1 /* Ada Ravenscar thread support.
3 Copyright (C) 2004-2017 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
22 #include "gdbthread.h"
27 #include "ravenscar-thread.h"
34 /* If non-null, ravenscar task support is enabled. */
35 static int ravenscar_task_support = 1;
37 /* This module's target-specific operations. */
38 static struct target_ops ravenscar_ops;
40 /* Some base target uses a special value for the null PID (exempli gratia
42 static ptid_t base_magic_null_ptid;
44 /* Ptid of the inferior as seen by the process stratum. */
45 static ptid_t base_ptid;
47 static const char running_thread_name[] = "__gnat_running_thread_table";
49 static const char known_tasks_name[] = "system__tasking__debug__known_tasks";
50 static const char first_task_name[] = "system__tasking__debug__first_task";
52 static const char ravenscar_runtime_initializer[] =
53 "system__bb__threads__initialize";
55 static void ravenscar_update_thread_list (struct target_ops *ops);
56 static ptid_t ravenscar_running_thread (void);
57 static const char *ravenscar_extra_thread_info (struct target_ops *self,
58 struct thread_info *tp);
59 static int ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid);
60 static void ravenscar_fetch_registers (struct target_ops *ops,
61 struct regcache *regcache, int regnum);
62 static void ravenscar_store_registers (struct target_ops *ops,
63 struct regcache *regcache, int regnum);
64 static void ravenscar_prepare_to_store (struct target_ops *self,
65 struct regcache *regcache);
66 static void ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
67 enum gdb_signal siggnal);
68 static void ravenscar_mourn_inferior (struct target_ops *ops);
69 static void ravenscar_update_inferior_ptid (void);
70 static int has_ravenscar_runtime (void);
71 static int ravenscar_runtime_initialized (void);
72 static void ravenscar_inferior_created (struct target_ops *target,
75 /* Fetch the ravenscar running thread from target memory and
76 update inferior_ptid accordingly. */
79 ravenscar_update_inferior_ptid (void)
81 base_ptid = inferior_ptid;
83 /* If the runtime has not been initialized yet, the inferior_ptid is
84 the only ptid that there is. */
85 if (!ravenscar_runtime_initialized ())
88 /* Make sure we set base_ptid before calling ravenscar_running_thread
89 as the latter relies on it. */
90 inferior_ptid = ravenscar_running_thread ();
91 gdb_assert (!ptid_equal (inferior_ptid, null_ptid));
93 /* The running thread may not have been added to
94 system.tasking.debug's list yet; so ravenscar_update_thread_list
95 may not always add it to the thread list. Add it here. */
96 if (!find_thread_ptid (inferior_ptid))
97 add_thread (inferior_ptid);
100 /* The Ravenscar Runtime exports a symbol which contains the ID of
101 the thread that is currently running. Try to locate that symbol
102 and return its associated minimal symbol.
103 Return NULL if not found. */
105 static struct bound_minimal_symbol
106 get_running_thread_msymbol (void)
108 struct bound_minimal_symbol msym;
110 msym = lookup_minimal_symbol (running_thread_name, NULL, NULL);
112 /* Older versions of the GNAT runtime were using a different
113 (less ideal) name for the symbol where the active thread ID
114 is stored. If we couldn't find the symbol using the latest
115 name, then try the old one. */
116 msym = lookup_minimal_symbol ("running_thread", NULL, NULL);
121 /* Return True if the Ada Ravenscar run-time can be found in the
125 has_ravenscar_runtime (void)
127 struct bound_minimal_symbol msym_ravenscar_runtime_initializer =
128 lookup_minimal_symbol (ravenscar_runtime_initializer, NULL, NULL);
129 struct bound_minimal_symbol msym_known_tasks =
130 lookup_minimal_symbol (known_tasks_name, NULL, NULL);
131 struct bound_minimal_symbol msym_first_task =
132 lookup_minimal_symbol (first_task_name, NULL, NULL);
133 struct bound_minimal_symbol msym_running_thread
134 = get_running_thread_msymbol ();
136 return (msym_ravenscar_runtime_initializer.minsym
137 && (msym_known_tasks.minsym || msym_first_task.minsym)
138 && msym_running_thread.minsym);
141 /* Return True if the Ada Ravenscar run-time can be found in the
142 application, and if it has been initialized on target. */
145 ravenscar_runtime_initialized (void)
147 return (!(ptid_equal (ravenscar_running_thread (), null_ptid)));
150 /* Return the ID of the thread that is currently running.
151 Return 0 if the ID could not be determined. */
154 get_running_thread_id (void)
156 struct bound_minimal_symbol object_msym = get_running_thread_msymbol ();
160 CORE_ADDR object_addr;
161 struct type *builtin_type_void_data_ptr =
162 builtin_type (target_gdbarch ())->builtin_data_ptr;
164 if (!object_msym.minsym)
167 object_addr = BMSYMBOL_VALUE_ADDRESS (object_msym);
168 object_size = TYPE_LENGTH (builtin_type_void_data_ptr);
169 buf_size = object_size;
170 buf = (gdb_byte *) alloca (buf_size);
171 read_memory (object_addr, buf, buf_size);
172 return extract_typed_address (buf, builtin_type_void_data_ptr);
176 ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
177 enum gdb_signal siggnal)
179 struct target_ops *beneath = find_target_beneath (ops);
181 inferior_ptid = base_ptid;
182 beneath->to_resume (beneath, base_ptid, step, siggnal);
186 ravenscar_wait (struct target_ops *ops, ptid_t ptid,
187 struct target_waitstatus *status,
190 struct target_ops *beneath = find_target_beneath (ops);
192 inferior_ptid = base_ptid;
193 beneath->to_wait (beneath, base_ptid, status, 0);
194 /* Find any new threads that might have been created, and update
195 inferior_ptid to the active thread.
197 Only do it if the program is still alive, though. Otherwise,
198 this causes problems when debugging through the remote protocol,
199 because we might try switching threads (and thus sending packets)
200 after the remote has disconnected. */
201 if (status->kind != TARGET_WAITKIND_EXITED
202 && status->kind != TARGET_WAITKIND_SIGNALLED)
204 ravenscar_update_thread_list (ops);
205 ravenscar_update_inferior_ptid ();
207 return inferior_ptid;
210 /* Add the thread associated to the given TASK to the thread list
211 (if the thread has already been added, this is a no-op). */
214 ravenscar_add_thread (struct ada_task_info *task)
216 if (find_thread_ptid (task->ptid) == NULL)
217 add_thread (task->ptid);
221 ravenscar_update_thread_list (struct target_ops *ops)
223 ada_build_task_list ();
225 /* Do not clear the thread list before adding the Ada task, to keep
226 the thread that the process stratum has included into it
227 (base_ptid) and the running thread, that may not have been included
228 to system.tasking.debug's list yet. */
230 iterate_over_live_ada_tasks (ravenscar_add_thread);
234 ravenscar_running_thread (void)
236 CORE_ADDR tid = get_running_thread_id ();
241 return ptid_build (ptid_get_pid (base_ptid), 0, tid);
245 ravenscar_extra_thread_info (struct target_ops *self, struct thread_info *tp)
247 return "Ravenscar task";
251 ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid)
253 /* Ravenscar tasks are non-terminating. */
258 ravenscar_pid_to_str (struct target_ops *ops, ptid_t ptid)
262 snprintf (buf, sizeof (buf), "Thread %#x", (int) ptid_get_tid (ptid));
267 ravenscar_fetch_registers (struct target_ops *ops,
268 struct regcache *regcache, int regnum)
270 struct target_ops *beneath = find_target_beneath (ops);
271 ptid_t ptid = regcache_get_ptid (regcache);
273 if (!ravenscar_runtime_initialized ()
274 || ptid_equal (ptid, base_magic_null_ptid)
275 || ptid_equal (ptid, ravenscar_running_thread ()))
276 beneath->to_fetch_registers (beneath, regcache, regnum);
279 struct gdbarch *gdbarch = regcache->arch ();
280 struct ravenscar_arch_ops *arch_ops
281 = gdbarch_ravenscar_ops (gdbarch);
283 arch_ops->to_fetch_registers (regcache, regnum);
288 ravenscar_store_registers (struct target_ops *ops,
289 struct regcache *regcache, int regnum)
291 struct target_ops *beneath = find_target_beneath (ops);
292 ptid_t ptid = regcache_get_ptid (regcache);
294 if (!ravenscar_runtime_initialized ()
295 || ptid_equal (ptid, base_magic_null_ptid)
296 || ptid_equal (ptid, ravenscar_running_thread ()))
297 beneath->to_store_registers (beneath, regcache, regnum);
300 struct gdbarch *gdbarch = regcache->arch ();
301 struct ravenscar_arch_ops *arch_ops
302 = gdbarch_ravenscar_ops (gdbarch);
304 arch_ops->to_store_registers (regcache, regnum);
309 ravenscar_prepare_to_store (struct target_ops *self,
310 struct regcache *regcache)
312 struct target_ops *beneath = find_target_beneath (self);
313 ptid_t ptid = regcache_get_ptid (regcache);
315 if (!ravenscar_runtime_initialized ()
316 || ptid_equal (ptid, base_magic_null_ptid)
317 || ptid_equal (ptid, ravenscar_running_thread ()))
318 beneath->to_prepare_to_store (beneath, regcache);
321 struct gdbarch *gdbarch = regcache->arch ();
322 struct ravenscar_arch_ops *arch_ops
323 = gdbarch_ravenscar_ops (gdbarch);
325 arch_ops->to_prepare_to_store (regcache);
329 /* Implement the to_stopped_by_sw_breakpoint target_ops "method". */
332 ravenscar_stopped_by_sw_breakpoint (struct target_ops *ops)
334 ptid_t saved_ptid = inferior_ptid;
335 struct target_ops *beneath = find_target_beneath (ops);
338 inferior_ptid = base_ptid;
339 result = beneath->to_stopped_by_sw_breakpoint (beneath);
340 inferior_ptid = saved_ptid;
344 /* Implement the to_stopped_by_hw_breakpoint target_ops "method". */
347 ravenscar_stopped_by_hw_breakpoint (struct target_ops *ops)
349 ptid_t saved_ptid = inferior_ptid;
350 struct target_ops *beneath = find_target_beneath (ops);
353 inferior_ptid = base_ptid;
354 result = beneath->to_stopped_by_hw_breakpoint (beneath);
355 inferior_ptid = saved_ptid;
359 /* Implement the to_stopped_by_watchpoint target_ops "method". */
362 ravenscar_stopped_by_watchpoint (struct target_ops *ops)
364 ptid_t saved_ptid = inferior_ptid;
365 struct target_ops *beneath = find_target_beneath (ops);
368 inferior_ptid = base_ptid;
369 result = beneath->to_stopped_by_watchpoint (beneath);
370 inferior_ptid = saved_ptid;
374 /* Implement the to_stopped_data_address target_ops "method". */
377 ravenscar_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
379 ptid_t saved_ptid = inferior_ptid;
380 struct target_ops *beneath = find_target_beneath (ops);
383 inferior_ptid = base_ptid;
384 result = beneath->to_stopped_data_address (beneath, addr_p);
385 inferior_ptid = saved_ptid;
390 ravenscar_mourn_inferior (struct target_ops *ops)
392 struct target_ops *beneath = find_target_beneath (ops);
394 base_ptid = null_ptid;
395 beneath->to_mourn_inferior (beneath);
396 unpush_target (&ravenscar_ops);
399 /* Implement the to_core_of_thread target_ops "method". */
402 ravenscar_core_of_thread (struct target_ops *ops, ptid_t ptid)
404 ptid_t saved_ptid = inferior_ptid;
405 struct target_ops *beneath = find_target_beneath (ops);
408 inferior_ptid = base_ptid;
409 result = beneath->to_core_of_thread (beneath, inferior_ptid);
410 inferior_ptid = saved_ptid;
414 /* Observer on inferior_created: push ravenscar thread stratum if needed. */
417 ravenscar_inferior_created (struct target_ops *target, int from_tty)
420 if (!ravenscar_task_support
421 || gdbarch_ravenscar_ops (target_gdbarch ()) == NULL
422 || !has_ravenscar_runtime ())
425 base_magic_null_ptid = inferior_ptid;
426 ravenscar_update_inferior_ptid ();
427 push_target (&ravenscar_ops);
431 ravenscar_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
433 return ptid_build (ptid_get_pid (base_ptid), 0, thread);
437 init_ravenscar_thread_ops (void)
439 ravenscar_ops.to_shortname = "ravenscar";
440 ravenscar_ops.to_longname = "Ravenscar tasks.";
441 ravenscar_ops.to_doc = "Ravenscar tasks support.";
442 ravenscar_ops.to_resume = ravenscar_resume;
443 ravenscar_ops.to_wait = ravenscar_wait;
444 ravenscar_ops.to_fetch_registers = ravenscar_fetch_registers;
445 ravenscar_ops.to_store_registers = ravenscar_store_registers;
446 ravenscar_ops.to_prepare_to_store = ravenscar_prepare_to_store;
447 ravenscar_ops.to_stopped_by_sw_breakpoint
448 = ravenscar_stopped_by_sw_breakpoint;
449 ravenscar_ops.to_stopped_by_hw_breakpoint
450 = ravenscar_stopped_by_hw_breakpoint;
451 ravenscar_ops.to_stopped_by_watchpoint = ravenscar_stopped_by_watchpoint;
452 ravenscar_ops.to_stopped_data_address = ravenscar_stopped_data_address;
453 ravenscar_ops.to_thread_alive = ravenscar_thread_alive;
454 ravenscar_ops.to_update_thread_list = ravenscar_update_thread_list;
455 ravenscar_ops.to_pid_to_str = ravenscar_pid_to_str;
456 ravenscar_ops.to_extra_thread_info = ravenscar_extra_thread_info;
457 ravenscar_ops.to_get_ada_task_ptid = ravenscar_get_ada_task_ptid;
458 ravenscar_ops.to_mourn_inferior = ravenscar_mourn_inferior;
459 ravenscar_ops.to_has_all_memory = default_child_has_all_memory;
460 ravenscar_ops.to_has_memory = default_child_has_memory;
461 ravenscar_ops.to_has_stack = default_child_has_stack;
462 ravenscar_ops.to_has_registers = default_child_has_registers;
463 ravenscar_ops.to_has_execution = default_child_has_execution;
464 ravenscar_ops.to_stratum = thread_stratum;
465 ravenscar_ops.to_core_of_thread = ravenscar_core_of_thread;
466 ravenscar_ops.to_magic = OPS_MAGIC;
469 /* Command-list for the "set/show ravenscar" prefix command. */
470 static struct cmd_list_element *set_ravenscar_list;
471 static struct cmd_list_element *show_ravenscar_list;
473 /* Implement the "set ravenscar" prefix command. */
476 set_ravenscar_command (const char *arg, int from_tty)
478 printf_unfiltered (_(\
479 "\"set ravenscar\" must be followed by the name of a setting.\n"));
480 help_list (set_ravenscar_list, "set ravenscar ", all_commands, gdb_stdout);
483 /* Implement the "show ravenscar" prefix command. */
486 show_ravenscar_command (const char *args, int from_tty)
488 cmd_show_list (show_ravenscar_list, from_tty, "");
491 /* Implement the "show ravenscar task-switching" command. */
494 show_ravenscar_task_switching_command (struct ui_file *file, int from_tty,
495 struct cmd_list_element *c,
498 if (ravenscar_task_support)
499 fprintf_filtered (file, _("\
500 Support for Ravenscar task/thread switching is enabled\n"));
502 fprintf_filtered (file, _("\
503 Support for Ravenscar task/thread switching is disabled\n"));
506 /* Module startup initialization function, automagically called by
510 _initialize_ravenscar (void)
512 init_ravenscar_thread_ops ();
513 base_ptid = null_ptid;
515 /* Notice when the inferior is created in order to push the
516 ravenscar ops if needed. */
517 observer_attach_inferior_created (ravenscar_inferior_created);
519 complete_target_initialization (&ravenscar_ops);
521 add_prefix_cmd ("ravenscar", no_class, set_ravenscar_command,
522 _("Prefix command for changing Ravenscar-specific settings"),
523 &set_ravenscar_list, "set ravenscar ", 0, &setlist);
525 add_prefix_cmd ("ravenscar", no_class, show_ravenscar_command,
526 _("Prefix command for showing Ravenscar-specific settings"),
527 &show_ravenscar_list, "show ravenscar ", 0, &showlist);
529 add_setshow_boolean_cmd ("task-switching", class_obscure,
530 &ravenscar_task_support, _("\
531 Enable or disable support for GNAT Ravenscar tasks"), _("\
532 Show whether support for GNAT Ravenscar tasks is enabled"),
534 Enable or disable support for task/thread switching with the GNAT\n\
535 Ravenscar run-time library for bareboard configuration."),
536 NULL, show_ravenscar_task_switching_command,
537 &set_ravenscar_list, &show_ravenscar_list);