Add target_ops argument to to_program_signals
[deliverable/binutils-gdb.git] / gdb / ravenscar-thread.c
CommitLineData
036b1ba8
JB
1/* Ada Ravenscar thread support.
2
ecd75fc8 3 Copyright (C) 2004-2014 Free Software Foundation, Inc.
036b1ba8
JB
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20#include "defs.h"
21#include "gdbcore.h"
22#include "gdbthread.h"
23#include "ada-lang.h"
24#include "target.h"
25#include "inferior.h"
26#include "command.h"
27#include "ravenscar-thread.h"
28#include "observer.h"
0e9f083f 29#include <string.h>
036b1ba8
JB
30#include "gdbcmd.h"
31#include "top.h"
32#include "regcache.h"
33
34/* If non-null, ravenscar task support is enabled. */
35static int ravenscar_task_support = 1;
36
036b1ba8
JB
37/* This module's target-specific operations. */
38static struct target_ops ravenscar_ops;
39
40/* Some base target uses a special value for the null PID (exempli gratia
41 remote). */
42static ptid_t base_magic_null_ptid;
43
44/* Ptid of the inferior as seen by the process stratum. */
45static ptid_t base_ptid;
46
7f39f34a 47static const char running_thread_name[] = "__gnat_running_thread_table";
036b1ba8
JB
48
49static const char known_tasks_name[] = "system__tasking__debug__known_tasks";
6040a59d 50static const char first_task_name[] = "system__tasking__debug__first_task";
036b1ba8 51
0df8b418
MS
52static const char ravenscar_runtime_initializer[] =
53 "system__bb__threads__initialize";
036b1ba8 54
036b1ba8
JB
55static void ravenscar_find_new_threads (struct target_ops *ops);
56static ptid_t ravenscar_running_thread (void);
57static char *ravenscar_extra_thread_info (struct thread_info *tp);
58static int ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid);
59static void ravenscar_fetch_registers (struct target_ops *ops,
60 struct regcache *regcache, int regnum);
61static void ravenscar_store_registers (struct target_ops *ops,
62 struct regcache *regcache, int regnum);
f32dbf8c
MM
63static void ravenscar_prepare_to_store (struct target_ops *self,
64 struct regcache *regcache);
036b1ba8 65static void ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
2ea28649 66 enum gdb_signal siggnal);
036b1ba8
JB
67static void ravenscar_mourn_inferior (struct target_ops *ops);
68static void ravenscar_update_inferior_ptid (void);
69static int has_ravenscar_runtime (void);
70static int ravenscar_runtime_initialized (void);
71static void ravenscar_inferior_created (struct target_ops *target,
72 int from_tty);
73
74/* Fetch the ravenscar running thread from target memory and
75 update inferior_ptid accordingly. */
76
77static void
78ravenscar_update_inferior_ptid (void)
79{
80 base_ptid = inferior_ptid;
81
82 /* If the runtime has not been initialized yet, the inferior_ptid is
83 the only ptid that there is. */
84 if (!ravenscar_runtime_initialized ())
85 return;
86
87 /* Make sure we set base_ptid before calling ravenscar_running_thread
88 as the latter relies on it. */
89 inferior_ptid = ravenscar_running_thread ();
90 gdb_assert (!ptid_equal (inferior_ptid, null_ptid));
91
92 /* The running thread may not have been added to
93 system.tasking.debug's list yet; so ravenscar_find_new_threads
94 may not always add it to the thread list. Add it here. */
95 if (!find_thread_ptid (inferior_ptid))
96 add_thread (inferior_ptid);
97}
98
7f39f34a
JB
99/* The Ravenscar Runtime exports a symbol which contains the ID of
100 the thread that is currently running. Try to locate that symbol
101 and return its associated minimal symbol.
102 Return NULL if not found. */
103
104static struct minimal_symbol *
105get_running_thread_msymbol (void)
106{
107 struct minimal_symbol *msym;
108
109 msym = lookup_minimal_symbol (running_thread_name, NULL, NULL);
110 if (!msym)
111 /* Older versions of the GNAT runtime were using a different
112 (less ideal) name for the symbol where the active thread ID
113 is stored. If we couldn't find the symbol using the latest
114 name, then try the old one. */
115 msym = lookup_minimal_symbol ("running_thread", NULL, NULL);
116
117 return msym;
118}
119
036b1ba8
JB
120/* Return True if the Ada Ravenscar run-time can be found in the
121 application. */
122
123static int
124has_ravenscar_runtime (void)
125{
126 struct minimal_symbol *msym_ravenscar_runtime_initializer =
127 lookup_minimal_symbol (ravenscar_runtime_initializer, NULL, NULL);
128 struct minimal_symbol *msym_known_tasks =
129 lookup_minimal_symbol (known_tasks_name, NULL, NULL);
6040a59d
JB
130 struct minimal_symbol *msym_first_task =
131 lookup_minimal_symbol (first_task_name, NULL, NULL);
7f39f34a 132 struct minimal_symbol *msym_running_thread = get_running_thread_msymbol ();
036b1ba8
JB
133
134 return (msym_ravenscar_runtime_initializer
6040a59d 135 && (msym_known_tasks || msym_first_task)
036b1ba8
JB
136 && msym_running_thread);
137}
138
139/* Return True if the Ada Ravenscar run-time can be found in the
140 application, and if it has been initialized on target. */
141
142static int
143ravenscar_runtime_initialized (void)
144{
145 return (!(ptid_equal (ravenscar_running_thread (), null_ptid)));
146}
147
7f39f34a
JB
148/* Return the ID of the thread that is currently running.
149 Return 0 if the ID could not be determined. */
036b1ba8
JB
150
151static CORE_ADDR
7f39f34a 152get_running_thread_id (void)
036b1ba8 153{
7f39f34a 154 const struct minimal_symbol *object_msym = get_running_thread_msymbol ();
036b1ba8
JB
155 int object_size;
156 int buf_size;
948f8e3d 157 gdb_byte *buf;
036b1ba8
JB
158 CORE_ADDR object_addr;
159 struct type *builtin_type_void_data_ptr =
f5656ead 160 builtin_type (target_gdbarch ())->builtin_data_ptr;
036b1ba8
JB
161
162 if (!object_msym)
163 return 0;
164
165 object_addr = SYMBOL_VALUE_ADDRESS (object_msym);
166 object_size = TYPE_LENGTH (builtin_type_void_data_ptr);
167 buf_size = object_size;
168 buf = alloca (buf_size);
169 read_memory (object_addr, buf, buf_size);
170 return extract_typed_address (buf, builtin_type_void_data_ptr);
171}
172
036b1ba8
JB
173static void
174ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
2ea28649 175 enum gdb_signal siggnal)
036b1ba8
JB
176{
177 struct target_ops *beneath = find_target_beneath (ops);
178
179 inferior_ptid = base_ptid;
180 beneath->to_resume (beneath, base_ptid, step, siggnal);
181}
182
183static ptid_t
184ravenscar_wait (struct target_ops *ops, ptid_t ptid,
185 struct target_waitstatus *status,
186 int options)
187{
188 struct target_ops *beneath = find_target_beneath (ops);
189
190 inferior_ptid = base_ptid;
191 beneath->to_wait (beneath, base_ptid, status, 0);
bed0c243
JB
192 /* Find any new threads that might have been created, and update
193 inferior_ptid to the active thread.
194
195 Only do it if the program is still alive, though. Otherwise,
196 this causes problems when debugging through the remote protocol,
197 because we might try switching threads (and thus sending packets)
198 after the remote has disconnected. */
199 if (status->kind != TARGET_WAITKIND_EXITED
200 && status->kind != TARGET_WAITKIND_SIGNALLED)
201 {
202 ravenscar_find_new_threads (ops);
203 ravenscar_update_inferior_ptid ();
204 }
036b1ba8
JB
205 return inferior_ptid;
206}
207
208/* Add the thread associated to the given TASK to the thread list
209 (if the thread has already been added, this is a no-op). */
210
211static void
212ravenscar_add_thread (struct ada_task_info *task)
213{
214 if (find_thread_ptid (task->ptid) == NULL)
215 add_thread (task->ptid);
216}
217
218static void
219ravenscar_find_new_threads (struct target_ops *ops)
220{
79779fa9 221 ada_build_task_list ();
036b1ba8
JB
222
223 /* Do not clear the thread list before adding the Ada task, to keep
224 the thread that the process stratum has included into it
225 (base_ptid) and the running thread, that may not have been included
226 to system.tasking.debug's list yet. */
227
228 iterate_over_live_ada_tasks (ravenscar_add_thread);
229}
230
231static ptid_t
232ravenscar_running_thread (void)
233{
7f39f34a 234 CORE_ADDR tid = get_running_thread_id ();
036b1ba8
JB
235
236 if (tid == 0)
237 return null_ptid;
238 else
239 return ptid_build (ptid_get_pid (base_ptid), 0, tid);
240}
241
242static char *
243ravenscar_extra_thread_info (struct thread_info *tp)
244{
245 return "Ravenscar task";
246}
247
248static int
249ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid)
250{
251 /* Ravenscar tasks are non-terminating. */
252 return 1;
253}
254
255static char *
256ravenscar_pid_to_str (struct target_ops *ops, ptid_t ptid)
257{
258 static char buf[30];
259
260 snprintf (buf, sizeof (buf), "Thread %#x", (int) ptid_get_tid (ptid));
261 return buf;
262}
263
264static void
265ravenscar_fetch_registers (struct target_ops *ops,
266 struct regcache *regcache, int regnum)
267{
268 struct target_ops *beneath = find_target_beneath (ops);
269
270 if (!ravenscar_runtime_initialized ()
271 || ptid_equal (inferior_ptid, base_magic_null_ptid)
272 || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
273 beneath->to_fetch_registers (beneath, regcache, regnum);
274 else
7e35103a
JB
275 {
276 struct gdbarch *gdbarch = get_regcache_arch (regcache);
277 struct ravenscar_arch_ops *arch_ops
278 = gdbarch_ravenscar_ops (gdbarch);
279
280 arch_ops->to_fetch_registers (regcache, regnum);
281 }
036b1ba8
JB
282}
283
284static void
285ravenscar_store_registers (struct target_ops *ops,
286 struct regcache *regcache, int regnum)
287{
288 struct target_ops *beneath = find_target_beneath (ops);
289
290 if (!ravenscar_runtime_initialized ()
291 || ptid_equal (inferior_ptid, base_magic_null_ptid)
292 || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
293 beneath->to_store_registers (beneath, regcache, regnum);
294 else
7e35103a
JB
295 {
296 struct gdbarch *gdbarch = get_regcache_arch (regcache);
297 struct ravenscar_arch_ops *arch_ops
298 = gdbarch_ravenscar_ops (gdbarch);
299
300 arch_ops->to_store_registers (regcache, regnum);
301 }
036b1ba8
JB
302}
303
304static void
f32dbf8c
MM
305ravenscar_prepare_to_store (struct target_ops *self,
306 struct regcache *regcache)
036b1ba8
JB
307{
308 struct target_ops *beneath = find_target_beneath (&ravenscar_ops);
309
310 if (!ravenscar_runtime_initialized ()
311 || ptid_equal (inferior_ptid, base_magic_null_ptid)
312 || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
f32dbf8c 313 beneath->to_prepare_to_store (beneath, regcache);
036b1ba8 314 else
7e35103a
JB
315 {
316 struct gdbarch *gdbarch = get_regcache_arch (regcache);
317 struct ravenscar_arch_ops *arch_ops
318 = gdbarch_ravenscar_ops (gdbarch);
319
320 arch_ops->to_prepare_to_store (regcache);
321 }
036b1ba8
JB
322}
323
324static void
325ravenscar_mourn_inferior (struct target_ops *ops)
326{
327 struct target_ops *beneath = find_target_beneath (&ravenscar_ops);
328
329 base_ptid = null_ptid;
330 beneath->to_mourn_inferior (beneath);
331 unpush_target (&ravenscar_ops);
332}
333
334/* Observer on inferior_created: push ravenscar thread stratum if needed. */
335
336static void
337ravenscar_inferior_created (struct target_ops *target, int from_tty)
338{
7e35103a
JB
339 struct ravenscar_arch_ops *ops;
340
341 if (!ravenscar_task_support
342 || gdbarch_ravenscar_ops (current_inferior ()->gdbarch) == NULL
343 || !has_ravenscar_runtime ())
25abf4de
JB
344 return;
345
346 base_magic_null_ptid = inferior_ptid;
347 ravenscar_update_inferior_ptid ();
348 push_target (&ravenscar_ops);
036b1ba8
JB
349}
350
036b1ba8
JB
351static ptid_t
352ravenscar_get_ada_task_ptid (long lwp, long thread)
353{
354 return ptid_build (ptid_get_pid (base_ptid), 0, thread);
355}
356
357static void
358init_ravenscar_thread_ops (void)
359{
360 ravenscar_ops.to_shortname = "ravenscar";
361 ravenscar_ops.to_longname = "Ravenscar tasks.";
362 ravenscar_ops.to_doc = "Ravenscar tasks support.";
036b1ba8
JB
363 ravenscar_ops.to_resume = ravenscar_resume;
364 ravenscar_ops.to_wait = ravenscar_wait;
365 ravenscar_ops.to_fetch_registers = ravenscar_fetch_registers;
366 ravenscar_ops.to_store_registers = ravenscar_store_registers;
367 ravenscar_ops.to_prepare_to_store = ravenscar_prepare_to_store;
368 ravenscar_ops.to_thread_alive = ravenscar_thread_alive;
369 ravenscar_ops.to_find_new_threads = ravenscar_find_new_threads;
370 ravenscar_ops.to_pid_to_str = ravenscar_pid_to_str;
371 ravenscar_ops.to_extra_thread_info = ravenscar_extra_thread_info;
372 ravenscar_ops.to_get_ada_task_ptid = ravenscar_get_ada_task_ptid;
373 ravenscar_ops.to_mourn_inferior = ravenscar_mourn_inferior;
374 ravenscar_ops.to_has_all_memory = default_child_has_all_memory;
375 ravenscar_ops.to_has_memory = default_child_has_memory;
376 ravenscar_ops.to_has_stack = default_child_has_stack;
377 ravenscar_ops.to_has_registers = default_child_has_registers;
378 ravenscar_ops.to_has_execution = default_child_has_execution;
379 ravenscar_ops.to_stratum = thread_stratum;
380 ravenscar_ops.to_magic = OPS_MAGIC;
381}
382
383/* Command-list for the "set/show ravenscar" prefix command. */
384static struct cmd_list_element *set_ravenscar_list;
385static struct cmd_list_element *show_ravenscar_list;
386
387/* Implement the "set ravenscar" prefix command. */
388
389static void
390set_ravenscar_command (char *arg, int from_tty)
391{
392 printf_unfiltered (_(\
393"\"set ravenscar\" must be followed by the name of a setting.\n"));
394 help_list (set_ravenscar_list, "set ravenscar ", -1, gdb_stdout);
395}
396
397/* Implement the "show ravenscar" prefix command. */
398
399static void
400show_ravenscar_command (char *args, int from_tty)
401{
402 cmd_show_list (show_ravenscar_list, from_tty, "");
403}
404
405/* Implement the "show ravenscar task-switching" command. */
406
407static void
408show_ravenscar_task_switching_command (struct ui_file *file, int from_tty,
409 struct cmd_list_element *c,
410 const char *value)
411{
412 if (ravenscar_task_support)
413 fprintf_filtered (file, _("\
b64edec4 414Support for Ravenscar task/thread switching is enabled\n"));
036b1ba8
JB
415 else
416 fprintf_filtered (file, _("\
b64edec4 417Support for Ravenscar task/thread switching is disabled\n"));
036b1ba8
JB
418}
419
8d037db9
JB
420/* Provide a prototype to silence -Wmissing-prototypes. */
421extern void _initialize_ravenscar (void);
422
036b1ba8
JB
423/* Module startup initialization function, automagically called by
424 init.c. */
425
426void
427_initialize_ravenscar (void)
428{
429 init_ravenscar_thread_ops ();
430 base_ptid = null_ptid;
431
432 /* Notice when the inferior is created in order to push the
433 ravenscar ops if needed. */
434 observer_attach_inferior_created (ravenscar_inferior_created);
435
12070676 436 complete_target_initialization (&ravenscar_ops);
036b1ba8
JB
437
438 add_prefix_cmd ("ravenscar", no_class, set_ravenscar_command,
439 _("Prefix command for changing Ravenscar-specific settings"),
440 &set_ravenscar_list, "set ravenscar ", 0, &setlist);
441
442 add_prefix_cmd ("ravenscar", no_class, show_ravenscar_command,
443 _("Prefix command for showing Ravenscar-specific settings"),
04f9d4d0 444 &show_ravenscar_list, "show ravenscar ", 0, &showlist);
036b1ba8
JB
445
446 add_setshow_boolean_cmd ("task-switching", class_obscure,
447 &ravenscar_task_support, _("\
448Enable or disable support for GNAT Ravenscar tasks"), _("\
449Show whether support for GNAT Ravenscar tasks is enabled"),
450 _("\
451Enable or disable support for task/thread switching with the GNAT\n\
452Ravenscar run-time library for bareboard configuration."),
453 NULL, show_ravenscar_task_switching_command,
454 &set_ravenscar_list, &show_ravenscar_list);
455}
This page took 0.358628 seconds and 4 git commands to generate.