Replace clear_hook_in_cleanup with scoped_restore_hook_in
[deliverable/binutils-gdb.git] / gdb / ravenscar-thread.c
... / ...
CommitLineData
1/* Ada Ravenscar thread support.
2
3 Copyright (C) 2004-2017 Free Software Foundation, Inc.
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"
29#include "gdbcmd.h"
30#include "top.h"
31#include "regcache.h"
32#include "objfiles.h"
33
34/* If non-null, ravenscar task support is enabled. */
35static int ravenscar_task_support = 1;
36
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
47static const char running_thread_name[] = "__gnat_running_thread_table";
48
49static const char known_tasks_name[] = "system__tasking__debug__known_tasks";
50static const char first_task_name[] = "system__tasking__debug__first_task";
51
52static const char ravenscar_runtime_initializer[] =
53 "system__bb__threads__initialize";
54
55static void ravenscar_update_thread_list (struct target_ops *ops);
56static ptid_t ravenscar_running_thread (void);
57static const char *ravenscar_extra_thread_info (struct target_ops *self,
58 struct thread_info *tp);
59static int ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid);
60static void ravenscar_fetch_registers (struct target_ops *ops,
61 struct regcache *regcache, int regnum);
62static void ravenscar_store_registers (struct target_ops *ops,
63 struct regcache *regcache, int regnum);
64static void ravenscar_prepare_to_store (struct target_ops *self,
65 struct regcache *regcache);
66static void ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
67 enum gdb_signal siggnal);
68static void ravenscar_mourn_inferior (struct target_ops *ops);
69static void ravenscar_update_inferior_ptid (void);
70static int has_ravenscar_runtime (void);
71static int ravenscar_runtime_initialized (void);
72static void ravenscar_inferior_created (struct target_ops *target,
73 int from_tty);
74
75/* Fetch the ravenscar running thread from target memory and
76 update inferior_ptid accordingly. */
77
78static void
79ravenscar_update_inferior_ptid (void)
80{
81 base_ptid = inferior_ptid;
82
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 ())
86 return;
87
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));
92
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);
98}
99
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. */
104
105static struct bound_minimal_symbol
106get_running_thread_msymbol (void)
107{
108 struct bound_minimal_symbol msym;
109
110 msym = lookup_minimal_symbol (running_thread_name, NULL, NULL);
111 if (!msym.minsym)
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);
117
118 return msym;
119}
120
121/* Return True if the Ada Ravenscar run-time can be found in the
122 application. */
123
124static int
125has_ravenscar_runtime (void)
126{
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 ();
135
136 return (msym_ravenscar_runtime_initializer.minsym
137 && (msym_known_tasks.minsym || msym_first_task.minsym)
138 && msym_running_thread.minsym);
139}
140
141/* Return True if the Ada Ravenscar run-time can be found in the
142 application, and if it has been initialized on target. */
143
144static int
145ravenscar_runtime_initialized (void)
146{
147 return (!(ptid_equal (ravenscar_running_thread (), null_ptid)));
148}
149
150/* Return the ID of the thread that is currently running.
151 Return 0 if the ID could not be determined. */
152
153static CORE_ADDR
154get_running_thread_id (void)
155{
156 struct bound_minimal_symbol object_msym = get_running_thread_msymbol ();
157 int object_size;
158 int buf_size;
159 gdb_byte *buf;
160 CORE_ADDR object_addr;
161 struct type *builtin_type_void_data_ptr =
162 builtin_type (target_gdbarch ())->builtin_data_ptr;
163
164 if (!object_msym.minsym)
165 return 0;
166
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);
173}
174
175static void
176ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
177 enum gdb_signal siggnal)
178{
179 struct target_ops *beneath = find_target_beneath (ops);
180
181 inferior_ptid = base_ptid;
182 beneath->to_resume (beneath, base_ptid, step, siggnal);
183}
184
185static ptid_t
186ravenscar_wait (struct target_ops *ops, ptid_t ptid,
187 struct target_waitstatus *status,
188 int options)
189{
190 struct target_ops *beneath = find_target_beneath (ops);
191
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.
196
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)
203 {
204 ravenscar_update_thread_list (ops);
205 ravenscar_update_inferior_ptid ();
206 }
207 return inferior_ptid;
208}
209
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). */
212
213static void
214ravenscar_add_thread (struct ada_task_info *task)
215{
216 if (find_thread_ptid (task->ptid) == NULL)
217 add_thread (task->ptid);
218}
219
220static void
221ravenscar_update_thread_list (struct target_ops *ops)
222{
223 ada_build_task_list ();
224
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. */
229
230 iterate_over_live_ada_tasks (ravenscar_add_thread);
231}
232
233static ptid_t
234ravenscar_running_thread (void)
235{
236 CORE_ADDR tid = get_running_thread_id ();
237
238 if (tid == 0)
239 return null_ptid;
240 else
241 return ptid_build (ptid_get_pid (base_ptid), 0, tid);
242}
243
244static const char *
245ravenscar_extra_thread_info (struct target_ops *self, struct thread_info *tp)
246{
247 return "Ravenscar task";
248}
249
250static int
251ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid)
252{
253 /* Ravenscar tasks are non-terminating. */
254 return 1;
255}
256
257static const char *
258ravenscar_pid_to_str (struct target_ops *ops, ptid_t ptid)
259{
260 static char buf[30];
261
262 snprintf (buf, sizeof (buf), "Thread %#x", (int) ptid_get_tid (ptid));
263 return buf;
264}
265
266static void
267ravenscar_fetch_registers (struct target_ops *ops,
268 struct regcache *regcache, int regnum)
269{
270 struct target_ops *beneath = find_target_beneath (ops);
271 ptid_t ptid = regcache_get_ptid (regcache);
272
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);
277 else
278 {
279 struct gdbarch *gdbarch = get_regcache_arch (regcache);
280 struct ravenscar_arch_ops *arch_ops
281 = gdbarch_ravenscar_ops (gdbarch);
282
283 arch_ops->to_fetch_registers (regcache, regnum);
284 }
285}
286
287static void
288ravenscar_store_registers (struct target_ops *ops,
289 struct regcache *regcache, int regnum)
290{
291 struct target_ops *beneath = find_target_beneath (ops);
292 ptid_t ptid = regcache_get_ptid (regcache);
293
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);
298 else
299 {
300 struct gdbarch *gdbarch = get_regcache_arch (regcache);
301 struct ravenscar_arch_ops *arch_ops
302 = gdbarch_ravenscar_ops (gdbarch);
303
304 arch_ops->to_store_registers (regcache, regnum);
305 }
306}
307
308static void
309ravenscar_prepare_to_store (struct target_ops *self,
310 struct regcache *regcache)
311{
312 struct target_ops *beneath = find_target_beneath (self);
313 ptid_t ptid = regcache_get_ptid (regcache);
314
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);
319 else
320 {
321 struct gdbarch *gdbarch = get_regcache_arch (regcache);
322 struct ravenscar_arch_ops *arch_ops
323 = gdbarch_ravenscar_ops (gdbarch);
324
325 arch_ops->to_prepare_to_store (regcache);
326 }
327}
328
329static void
330ravenscar_mourn_inferior (struct target_ops *ops)
331{
332 struct target_ops *beneath = find_target_beneath (ops);
333
334 base_ptid = null_ptid;
335 beneath->to_mourn_inferior (beneath);
336 unpush_target (&ravenscar_ops);
337}
338
339/* Observer on inferior_created: push ravenscar thread stratum if needed. */
340
341static void
342ravenscar_inferior_created (struct target_ops *target, int from_tty)
343{
344
345 if (!ravenscar_task_support
346 || gdbarch_ravenscar_ops (target_gdbarch ()) == NULL
347 || !has_ravenscar_runtime ())
348 return;
349
350 base_magic_null_ptid = inferior_ptid;
351 ravenscar_update_inferior_ptid ();
352 push_target (&ravenscar_ops);
353}
354
355static ptid_t
356ravenscar_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
357{
358 return ptid_build (ptid_get_pid (base_ptid), 0, thread);
359}
360
361static void
362init_ravenscar_thread_ops (void)
363{
364 ravenscar_ops.to_shortname = "ravenscar";
365 ravenscar_ops.to_longname = "Ravenscar tasks.";
366 ravenscar_ops.to_doc = "Ravenscar tasks support.";
367 ravenscar_ops.to_resume = ravenscar_resume;
368 ravenscar_ops.to_wait = ravenscar_wait;
369 ravenscar_ops.to_fetch_registers = ravenscar_fetch_registers;
370 ravenscar_ops.to_store_registers = ravenscar_store_registers;
371 ravenscar_ops.to_prepare_to_store = ravenscar_prepare_to_store;
372 ravenscar_ops.to_thread_alive = ravenscar_thread_alive;
373 ravenscar_ops.to_update_thread_list = ravenscar_update_thread_list;
374 ravenscar_ops.to_pid_to_str = ravenscar_pid_to_str;
375 ravenscar_ops.to_extra_thread_info = ravenscar_extra_thread_info;
376 ravenscar_ops.to_get_ada_task_ptid = ravenscar_get_ada_task_ptid;
377 ravenscar_ops.to_mourn_inferior = ravenscar_mourn_inferior;
378 ravenscar_ops.to_has_all_memory = default_child_has_all_memory;
379 ravenscar_ops.to_has_memory = default_child_has_memory;
380 ravenscar_ops.to_has_stack = default_child_has_stack;
381 ravenscar_ops.to_has_registers = default_child_has_registers;
382 ravenscar_ops.to_has_execution = default_child_has_execution;
383 ravenscar_ops.to_stratum = thread_stratum;
384 ravenscar_ops.to_magic = OPS_MAGIC;
385}
386
387/* Command-list for the "set/show ravenscar" prefix command. */
388static struct cmd_list_element *set_ravenscar_list;
389static struct cmd_list_element *show_ravenscar_list;
390
391/* Implement the "set ravenscar" prefix command. */
392
393static void
394set_ravenscar_command (char *arg, int from_tty)
395{
396 printf_unfiltered (_(\
397"\"set ravenscar\" must be followed by the name of a setting.\n"));
398 help_list (set_ravenscar_list, "set ravenscar ", all_commands, gdb_stdout);
399}
400
401/* Implement the "show ravenscar" prefix command. */
402
403static void
404show_ravenscar_command (char *args, int from_tty)
405{
406 cmd_show_list (show_ravenscar_list, from_tty, "");
407}
408
409/* Implement the "show ravenscar task-switching" command. */
410
411static void
412show_ravenscar_task_switching_command (struct ui_file *file, int from_tty,
413 struct cmd_list_element *c,
414 const char *value)
415{
416 if (ravenscar_task_support)
417 fprintf_filtered (file, _("\
418Support for Ravenscar task/thread switching is enabled\n"));
419 else
420 fprintf_filtered (file, _("\
421Support for Ravenscar task/thread switching is disabled\n"));
422}
423
424/* Module startup initialization function, automagically called by
425 init.c. */
426
427void
428_initialize_ravenscar (void)
429{
430 init_ravenscar_thread_ops ();
431 base_ptid = null_ptid;
432
433 /* Notice when the inferior is created in order to push the
434 ravenscar ops if needed. */
435 observer_attach_inferior_created (ravenscar_inferior_created);
436
437 complete_target_initialization (&ravenscar_ops);
438
439 add_prefix_cmd ("ravenscar", no_class, set_ravenscar_command,
440 _("Prefix command for changing Ravenscar-specific settings"),
441 &set_ravenscar_list, "set ravenscar ", 0, &setlist);
442
443 add_prefix_cmd ("ravenscar", no_class, show_ravenscar_command,
444 _("Prefix command for showing Ravenscar-specific settings"),
445 &show_ravenscar_list, "show ravenscar ", 0, &showlist);
446
447 add_setshow_boolean_cmd ("task-switching", class_obscure,
448 &ravenscar_task_support, _("\
449Enable or disable support for GNAT Ravenscar tasks"), _("\
450Show whether support for GNAT Ravenscar tasks is enabled"),
451 _("\
452Enable or disable support for task/thread switching with the GNAT\n\
453Ravenscar run-time library for bareboard configuration."),
454 NULL, show_ravenscar_task_switching_command,
455 &set_ravenscar_list, &show_ravenscar_list);
456}
This page took 0.024215 seconds and 4 git commands to generate.