1 /* Ada Ravenscar thread support.
3 Copyright (C) 2004-2014 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"
35 /* If non-null, ravenscar task support is enabled. */
36 static int ravenscar_task_support = 1;
38 /* This module's target-specific operations. */
39 static struct target_ops ravenscar_ops;
41 /* Some base target uses a special value for the null PID (exempli gratia
43 static ptid_t base_magic_null_ptid;
45 /* Ptid of the inferior as seen by the process stratum. */
46 static ptid_t base_ptid;
48 static const char running_thread_name[] = "__gnat_running_thread_table";
50 static const char known_tasks_name[] = "system__tasking__debug__known_tasks";
51 static const char first_task_name[] = "system__tasking__debug__first_task";
53 static const char ravenscar_runtime_initializer[] =
54 "system__bb__threads__initialize";
56 static void ravenscar_find_new_threads (struct target_ops *ops);
57 static ptid_t ravenscar_running_thread (void);
58 static char *ravenscar_extra_thread_info (struct target_ops *self,
59 struct thread_info *tp);
60 static int ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid);
61 static void ravenscar_fetch_registers (struct target_ops *ops,
62 struct regcache *regcache, int regnum);
63 static void ravenscar_store_registers (struct target_ops *ops,
64 struct regcache *regcache, int regnum);
65 static void ravenscar_prepare_to_store (struct target_ops *self,
66 struct regcache *regcache);
67 static void ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
68 enum gdb_signal siggnal);
69 static void ravenscar_mourn_inferior (struct target_ops *ops);
70 static void ravenscar_update_inferior_ptid (void);
71 static int has_ravenscar_runtime (void);
72 static int ravenscar_runtime_initialized (void);
73 static void ravenscar_inferior_created (struct target_ops *target,
76 /* Fetch the ravenscar running thread from target memory and
77 update inferior_ptid accordingly. */
80 ravenscar_update_inferior_ptid (void)
82 base_ptid = inferior_ptid;
84 /* If the runtime has not been initialized yet, the inferior_ptid is
85 the only ptid that there is. */
86 if (!ravenscar_runtime_initialized ())
89 /* Make sure we set base_ptid before calling ravenscar_running_thread
90 as the latter relies on it. */
91 inferior_ptid = ravenscar_running_thread ();
92 gdb_assert (!ptid_equal (inferior_ptid, null_ptid));
94 /* The running thread may not have been added to
95 system.tasking.debug's list yet; so ravenscar_find_new_threads
96 may not always add it to the thread list. Add it here. */
97 if (!find_thread_ptid (inferior_ptid))
98 add_thread (inferior_ptid);
101 /* The Ravenscar Runtime exports a symbol which contains the ID of
102 the thread that is currently running. Try to locate that symbol
103 and return its associated minimal symbol.
104 Return NULL if not found. */
106 static struct bound_minimal_symbol
107 get_running_thread_msymbol (void)
109 struct bound_minimal_symbol msym;
111 msym = lookup_minimal_symbol (running_thread_name, NULL, NULL);
113 /* Older versions of the GNAT runtime were using a different
114 (less ideal) name for the symbol where the active thread ID
115 is stored. If we couldn't find the symbol using the latest
116 name, then try the old one. */
117 msym = lookup_minimal_symbol ("running_thread", NULL, NULL);
122 /* Return True if the Ada Ravenscar run-time can be found in the
126 has_ravenscar_runtime (void)
128 struct bound_minimal_symbol msym_ravenscar_runtime_initializer =
129 lookup_minimal_symbol (ravenscar_runtime_initializer, NULL, NULL);
130 struct bound_minimal_symbol msym_known_tasks =
131 lookup_minimal_symbol (known_tasks_name, NULL, NULL);
132 struct bound_minimal_symbol msym_first_task =
133 lookup_minimal_symbol (first_task_name, NULL, NULL);
134 struct bound_minimal_symbol msym_running_thread
135 = get_running_thread_msymbol ();
137 return (msym_ravenscar_runtime_initializer.minsym
138 && (msym_known_tasks.minsym || msym_first_task.minsym)
139 && msym_running_thread.minsym);
142 /* Return True if the Ada Ravenscar run-time can be found in the
143 application, and if it has been initialized on target. */
146 ravenscar_runtime_initialized (void)
148 return (!(ptid_equal (ravenscar_running_thread (), null_ptid)));
151 /* Return the ID of the thread that is currently running.
152 Return 0 if the ID could not be determined. */
155 get_running_thread_id (void)
157 struct bound_minimal_symbol object_msym = get_running_thread_msymbol ();
161 CORE_ADDR object_addr;
162 struct type *builtin_type_void_data_ptr =
163 builtin_type (target_gdbarch ())->builtin_data_ptr;
165 if (!object_msym.minsym)
168 object_addr = BMSYMBOL_VALUE_ADDRESS (object_msym);
169 object_size = TYPE_LENGTH (builtin_type_void_data_ptr);
170 buf_size = object_size;
171 buf = alloca (buf_size);
172 read_memory (object_addr, buf, buf_size);
173 return extract_typed_address (buf, builtin_type_void_data_ptr);
177 ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
178 enum gdb_signal siggnal)
180 struct target_ops *beneath = find_target_beneath (ops);
182 inferior_ptid = base_ptid;
183 beneath->to_resume (beneath, base_ptid, step, siggnal);
187 ravenscar_wait (struct target_ops *ops, ptid_t ptid,
188 struct target_waitstatus *status,
191 struct target_ops *beneath = find_target_beneath (ops);
193 inferior_ptid = base_ptid;
194 beneath->to_wait (beneath, base_ptid, status, 0);
195 /* Find any new threads that might have been created, and update
196 inferior_ptid to the active thread.
198 Only do it if the program is still alive, though. Otherwise,
199 this causes problems when debugging through the remote protocol,
200 because we might try switching threads (and thus sending packets)
201 after the remote has disconnected. */
202 if (status->kind != TARGET_WAITKIND_EXITED
203 && status->kind != TARGET_WAITKIND_SIGNALLED)
205 ravenscar_find_new_threads (ops);
206 ravenscar_update_inferior_ptid ();
208 return inferior_ptid;
211 /* Add the thread associated to the given TASK to the thread list
212 (if the thread has already been added, this is a no-op). */
215 ravenscar_add_thread (struct ada_task_info *task)
217 if (find_thread_ptid (task->ptid) == NULL)
218 add_thread (task->ptid);
222 ravenscar_find_new_threads (struct target_ops *ops)
224 ada_build_task_list ();
226 /* Do not clear the thread list before adding the Ada task, to keep
227 the thread that the process stratum has included into it
228 (base_ptid) and the running thread, that may not have been included
229 to system.tasking.debug's list yet. */
231 iterate_over_live_ada_tasks (ravenscar_add_thread);
235 ravenscar_running_thread (void)
237 CORE_ADDR tid = get_running_thread_id ();
242 return ptid_build (ptid_get_pid (base_ptid), 0, tid);
246 ravenscar_extra_thread_info (struct target_ops *self, struct thread_info *tp)
248 return "Ravenscar task";
252 ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid)
254 /* Ravenscar tasks are non-terminating. */
259 ravenscar_pid_to_str (struct target_ops *ops, ptid_t ptid)
263 snprintf (buf, sizeof (buf), "Thread %#x", (int) ptid_get_tid (ptid));
268 ravenscar_fetch_registers (struct target_ops *ops,
269 struct regcache *regcache, int regnum)
271 struct target_ops *beneath = find_target_beneath (ops);
273 if (!ravenscar_runtime_initialized ()
274 || ptid_equal (inferior_ptid, base_magic_null_ptid)
275 || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
276 beneath->to_fetch_registers (beneath, regcache, regnum);
279 struct gdbarch *gdbarch = get_regcache_arch (regcache);
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);
293 if (!ravenscar_runtime_initialized ()
294 || ptid_equal (inferior_ptid, base_magic_null_ptid)
295 || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
296 beneath->to_store_registers (beneath, regcache, regnum);
299 struct gdbarch *gdbarch = get_regcache_arch (regcache);
300 struct ravenscar_arch_ops *arch_ops
301 = gdbarch_ravenscar_ops (gdbarch);
303 arch_ops->to_store_registers (regcache, regnum);
308 ravenscar_prepare_to_store (struct target_ops *self,
309 struct regcache *regcache)
311 struct target_ops *beneath = find_target_beneath (&ravenscar_ops);
313 if (!ravenscar_runtime_initialized ()
314 || ptid_equal (inferior_ptid, base_magic_null_ptid)
315 || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
316 beneath->to_prepare_to_store (beneath, regcache);
319 struct gdbarch *gdbarch = get_regcache_arch (regcache);
320 struct ravenscar_arch_ops *arch_ops
321 = gdbarch_ravenscar_ops (gdbarch);
323 arch_ops->to_prepare_to_store (regcache);
328 ravenscar_mourn_inferior (struct target_ops *ops)
330 struct target_ops *beneath = find_target_beneath (&ravenscar_ops);
332 base_ptid = null_ptid;
333 beneath->to_mourn_inferior (beneath);
334 unpush_target (&ravenscar_ops);
337 /* Observer on inferior_created: push ravenscar thread stratum if needed. */
340 ravenscar_inferior_created (struct target_ops *target, int from_tty)
342 struct ravenscar_arch_ops *ops;
344 if (!ravenscar_task_support
345 || gdbarch_ravenscar_ops (current_inferior ()->gdbarch) == NULL
346 || !has_ravenscar_runtime ())
349 base_magic_null_ptid = inferior_ptid;
350 ravenscar_update_inferior_ptid ();
351 push_target (&ravenscar_ops);
355 ravenscar_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
357 return ptid_build (ptid_get_pid (base_ptid), 0, thread);
361 init_ravenscar_thread_ops (void)
363 ravenscar_ops.to_shortname = "ravenscar";
364 ravenscar_ops.to_longname = "Ravenscar tasks.";
365 ravenscar_ops.to_doc = "Ravenscar tasks support.";
366 ravenscar_ops.to_resume = ravenscar_resume;
367 ravenscar_ops.to_wait = ravenscar_wait;
368 ravenscar_ops.to_fetch_registers = ravenscar_fetch_registers;
369 ravenscar_ops.to_store_registers = ravenscar_store_registers;
370 ravenscar_ops.to_prepare_to_store = ravenscar_prepare_to_store;
371 ravenscar_ops.to_thread_alive = ravenscar_thread_alive;
372 ravenscar_ops.to_find_new_threads = ravenscar_find_new_threads;
373 ravenscar_ops.to_pid_to_str = ravenscar_pid_to_str;
374 ravenscar_ops.to_extra_thread_info = ravenscar_extra_thread_info;
375 ravenscar_ops.to_get_ada_task_ptid = ravenscar_get_ada_task_ptid;
376 ravenscar_ops.to_mourn_inferior = ravenscar_mourn_inferior;
377 ravenscar_ops.to_has_all_memory = default_child_has_all_memory;
378 ravenscar_ops.to_has_memory = default_child_has_memory;
379 ravenscar_ops.to_has_stack = default_child_has_stack;
380 ravenscar_ops.to_has_registers = default_child_has_registers;
381 ravenscar_ops.to_has_execution = default_child_has_execution;
382 ravenscar_ops.to_stratum = thread_stratum;
383 ravenscar_ops.to_magic = OPS_MAGIC;
386 /* Command-list for the "set/show ravenscar" prefix command. */
387 static struct cmd_list_element *set_ravenscar_list;
388 static struct cmd_list_element *show_ravenscar_list;
390 /* Implement the "set ravenscar" prefix command. */
393 set_ravenscar_command (char *arg, int from_tty)
395 printf_unfiltered (_(\
396 "\"set ravenscar\" must be followed by the name of a setting.\n"));
397 help_list (set_ravenscar_list, "set ravenscar ", all_commands, gdb_stdout);
400 /* Implement the "show ravenscar" prefix command. */
403 show_ravenscar_command (char *args, int from_tty)
405 cmd_show_list (show_ravenscar_list, from_tty, "");
408 /* Implement the "show ravenscar task-switching" command. */
411 show_ravenscar_task_switching_command (struct ui_file *file, int from_tty,
412 struct cmd_list_element *c,
415 if (ravenscar_task_support)
416 fprintf_filtered (file, _("\
417 Support for Ravenscar task/thread switching is enabled\n"));
419 fprintf_filtered (file, _("\
420 Support for Ravenscar task/thread switching is disabled\n"));
423 /* Provide a prototype to silence -Wmissing-prototypes. */
424 extern void _initialize_ravenscar (void);
426 /* Module startup initialization function, automagically called by
430 _initialize_ravenscar (void)
432 init_ravenscar_thread_ops ();
433 base_ptid = null_ptid;
435 /* Notice when the inferior is created in order to push the
436 ravenscar ops if needed. */
437 observer_attach_inferior_created (ravenscar_inferior_created);
439 complete_target_initialization (&ravenscar_ops);
441 add_prefix_cmd ("ravenscar", no_class, set_ravenscar_command,
442 _("Prefix command for changing Ravenscar-specific settings"),
443 &set_ravenscar_list, "set ravenscar ", 0, &setlist);
445 add_prefix_cmd ("ravenscar", no_class, show_ravenscar_command,
446 _("Prefix command for showing Ravenscar-specific settings"),
447 &show_ravenscar_list, "show ravenscar ", 0, &showlist);
449 add_setshow_boolean_cmd ("task-switching", class_obscure,
450 &ravenscar_task_support, _("\
451 Enable or disable support for GNAT Ravenscar tasks"), _("\
452 Show whether support for GNAT Ravenscar tasks is enabled"),
454 Enable or disable support for task/thread switching with the GNAT\n\
455 Ravenscar run-time library for bareboard configuration."),
456 NULL, show_ravenscar_task_switching_command,
457 &set_ravenscar_list, &show_ravenscar_list);