Provide the "Base CPU" in output of "info task" (if set by runtime).
[deliverable/binutils-gdb.git] / gdb / ravenscar-thread.c
CommitLineData
036b1ba8
JB
1/* Ada Ravenscar thread support.
2
61baf725 3 Copyright (C) 2004-2017 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"
036b1ba8
JB
29#include "gdbcmd.h"
30#include "top.h"
31#include "regcache.h"
77e371c0 32#include "objfiles.h"
036b1ba8
JB
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
e8032dde 55static void ravenscar_update_thread_list (struct target_ops *ops);
036b1ba8 56static ptid_t ravenscar_running_thread (void);
7a114964
PA
57static const char *ravenscar_extra_thread_info (struct target_ops *self,
58 struct thread_info *tp);
036b1ba8
JB
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);
f32dbf8c
MM
64static void ravenscar_prepare_to_store (struct target_ops *self,
65 struct regcache *regcache);
036b1ba8 66static void ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
2ea28649 67 enum gdb_signal siggnal);
036b1ba8
JB
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
e8032dde 94 system.tasking.debug's list yet; so ravenscar_update_thread_list
036b1ba8
JB
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
7f39f34a
JB
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
3b7344d5 105static struct bound_minimal_symbol
7f39f34a
JB
106get_running_thread_msymbol (void)
107{
3b7344d5 108 struct bound_minimal_symbol msym;
7f39f34a
JB
109
110 msym = lookup_minimal_symbol (running_thread_name, NULL, NULL);
3b7344d5 111 if (!msym.minsym)
7f39f34a
JB
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
036b1ba8
JB
121/* Return True if the Ada Ravenscar run-time can be found in the
122 application. */
123
124static int
125has_ravenscar_runtime (void)
126{
3b7344d5 127 struct bound_minimal_symbol msym_ravenscar_runtime_initializer =
036b1ba8 128 lookup_minimal_symbol (ravenscar_runtime_initializer, NULL, NULL);
3b7344d5 129 struct bound_minimal_symbol msym_known_tasks =
036b1ba8 130 lookup_minimal_symbol (known_tasks_name, NULL, NULL);
3b7344d5 131 struct bound_minimal_symbol msym_first_task =
6040a59d 132 lookup_minimal_symbol (first_task_name, NULL, NULL);
3b7344d5
TT
133 struct bound_minimal_symbol msym_running_thread
134 = get_running_thread_msymbol ();
036b1ba8 135
3b7344d5
TT
136 return (msym_ravenscar_runtime_initializer.minsym
137 && (msym_known_tasks.minsym || msym_first_task.minsym)
138 && msym_running_thread.minsym);
036b1ba8
JB
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
7f39f34a
JB
150/* Return the ID of the thread that is currently running.
151 Return 0 if the ID could not be determined. */
036b1ba8
JB
152
153static CORE_ADDR
7f39f34a 154get_running_thread_id (void)
036b1ba8 155{
3b7344d5 156 struct bound_minimal_symbol object_msym = get_running_thread_msymbol ();
036b1ba8
JB
157 int object_size;
158 int buf_size;
948f8e3d 159 gdb_byte *buf;
036b1ba8
JB
160 CORE_ADDR object_addr;
161 struct type *builtin_type_void_data_ptr =
f5656ead 162 builtin_type (target_gdbarch ())->builtin_data_ptr;
036b1ba8 163
3b7344d5 164 if (!object_msym.minsym)
036b1ba8
JB
165 return 0;
166
77e371c0 167 object_addr = BMSYMBOL_VALUE_ADDRESS (object_msym);
036b1ba8
JB
168 object_size = TYPE_LENGTH (builtin_type_void_data_ptr);
169 buf_size = object_size;
224c3ddb 170 buf = (gdb_byte *) alloca (buf_size);
036b1ba8
JB
171 read_memory (object_addr, buf, buf_size);
172 return extract_typed_address (buf, builtin_type_void_data_ptr);
173}
174
036b1ba8
JB
175static void
176ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
2ea28649 177 enum gdb_signal siggnal)
036b1ba8
JB
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);
bed0c243
JB
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 {
e8032dde 204 ravenscar_update_thread_list (ops);
bed0c243
JB
205 ravenscar_update_inferior_ptid ();
206 }
036b1ba8
JB
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
e8032dde 221ravenscar_update_thread_list (struct target_ops *ops)
036b1ba8 222{
79779fa9 223 ada_build_task_list ();
036b1ba8
JB
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{
7f39f34a 236 CORE_ADDR tid = get_running_thread_id ();
036b1ba8
JB
237
238 if (tid == 0)
239 return null_ptid;
240 else
241 return ptid_build (ptid_get_pid (base_ptid), 0, tid);
242}
243
7a114964 244static const char *
c15906d8 245ravenscar_extra_thread_info (struct target_ops *self, struct thread_info *tp)
036b1ba8
JB
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
7a114964 257static const char *
036b1ba8
JB
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);
bcc0c096 271 ptid_t ptid = regcache_get_ptid (regcache);
036b1ba8
JB
272
273 if (!ravenscar_runtime_initialized ()
bcc0c096
SM
274 || ptid_equal (ptid, base_magic_null_ptid)
275 || ptid_equal (ptid, ravenscar_running_thread ()))
036b1ba8
JB
276 beneath->to_fetch_registers (beneath, regcache, regnum);
277 else
7e35103a 278 {
ac7936df 279 struct gdbarch *gdbarch = regcache->arch ();
7e35103a
JB
280 struct ravenscar_arch_ops *arch_ops
281 = gdbarch_ravenscar_ops (gdbarch);
282
283 arch_ops->to_fetch_registers (regcache, regnum);
284 }
036b1ba8
JB
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);
bcc0c096 292 ptid_t ptid = regcache_get_ptid (regcache);
036b1ba8
JB
293
294 if (!ravenscar_runtime_initialized ()
bcc0c096
SM
295 || ptid_equal (ptid, base_magic_null_ptid)
296 || ptid_equal (ptid, ravenscar_running_thread ()))
036b1ba8
JB
297 beneath->to_store_registers (beneath, regcache, regnum);
298 else
7e35103a 299 {
ac7936df 300 struct gdbarch *gdbarch = regcache->arch ();
7e35103a
JB
301 struct ravenscar_arch_ops *arch_ops
302 = gdbarch_ravenscar_ops (gdbarch);
303
304 arch_ops->to_store_registers (regcache, regnum);
305 }
036b1ba8
JB
306}
307
308static void
f32dbf8c
MM
309ravenscar_prepare_to_store (struct target_ops *self,
310 struct regcache *regcache)
036b1ba8 311{
44e89118 312 struct target_ops *beneath = find_target_beneath (self);
bcc0c096 313 ptid_t ptid = regcache_get_ptid (regcache);
036b1ba8
JB
314
315 if (!ravenscar_runtime_initialized ()
bcc0c096
SM
316 || ptid_equal (ptid, base_magic_null_ptid)
317 || ptid_equal (ptid, ravenscar_running_thread ()))
f32dbf8c 318 beneath->to_prepare_to_store (beneath, regcache);
036b1ba8 319 else
7e35103a 320 {
ac7936df 321 struct gdbarch *gdbarch = regcache->arch ();
7e35103a
JB
322 struct ravenscar_arch_ops *arch_ops
323 = gdbarch_ravenscar_ops (gdbarch);
324
325 arch_ops->to_prepare_to_store (regcache);
326 }
036b1ba8
JB
327}
328
e02544b2
JB
329/* Implement the to_stopped_by_sw_breakpoint target_ops "method". */
330
331static int
332ravenscar_stopped_by_sw_breakpoint (struct target_ops *ops)
333{
334 ptid_t saved_ptid = inferior_ptid;
335 struct target_ops *beneath = find_target_beneath (ops);
336 int result;
337
338 inferior_ptid = base_ptid;
339 result = beneath->to_stopped_by_sw_breakpoint (beneath);
340 inferior_ptid = saved_ptid;
341 return result;
342}
343
344/* Implement the to_stopped_by_hw_breakpoint target_ops "method". */
345
346static int
347ravenscar_stopped_by_hw_breakpoint (struct target_ops *ops)
348{
349 ptid_t saved_ptid = inferior_ptid;
350 struct target_ops *beneath = find_target_beneath (ops);
351 int result;
352
353 inferior_ptid = base_ptid;
354 result = beneath->to_stopped_by_hw_breakpoint (beneath);
355 inferior_ptid = saved_ptid;
356 return result;
357}
358
359/* Implement the to_stopped_by_watchpoint target_ops "method". */
360
361static int
362ravenscar_stopped_by_watchpoint (struct target_ops *ops)
363{
364 ptid_t saved_ptid = inferior_ptid;
365 struct target_ops *beneath = find_target_beneath (ops);
366 int result;
367
368 inferior_ptid = base_ptid;
369 result = beneath->to_stopped_by_watchpoint (beneath);
370 inferior_ptid = saved_ptid;
371 return result;
372}
373
374/* Implement the to_stopped_data_address target_ops "method". */
375
376static int
377ravenscar_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
378{
379 ptid_t saved_ptid = inferior_ptid;
380 struct target_ops *beneath = find_target_beneath (ops);
381 int result;
382
383 inferior_ptid = base_ptid;
384 result = beneath->to_stopped_data_address (beneath, addr_p);
385 inferior_ptid = saved_ptid;
386 return result;
387}
388
036b1ba8
JB
389static void
390ravenscar_mourn_inferior (struct target_ops *ops)
391{
44e89118 392 struct target_ops *beneath = find_target_beneath (ops);
036b1ba8
JB
393
394 base_ptid = null_ptid;
395 beneath->to_mourn_inferior (beneath);
396 unpush_target (&ravenscar_ops);
397}
398
e02544b2
JB
399/* Implement the to_core_of_thread target_ops "method". */
400
401static int
402ravenscar_core_of_thread (struct target_ops *ops, ptid_t ptid)
403{
404 ptid_t saved_ptid = inferior_ptid;
405 struct target_ops *beneath = find_target_beneath (ops);
406 int result;
407
408 inferior_ptid = base_ptid;
409 result = beneath->to_core_of_thread (beneath, inferior_ptid);
410 inferior_ptid = saved_ptid;
411 return result;
412}
413
036b1ba8
JB
414/* Observer on inferior_created: push ravenscar thread stratum if needed. */
415
416static void
417ravenscar_inferior_created (struct target_ops *target, int from_tty)
418{
7e35103a
JB
419
420 if (!ravenscar_task_support
7dc7c195 421 || gdbarch_ravenscar_ops (target_gdbarch ()) == NULL
7e35103a 422 || !has_ravenscar_runtime ())
25abf4de
JB
423 return;
424
425 base_magic_null_ptid = inferior_ptid;
426 ravenscar_update_inferior_ptid ();
427 push_target (&ravenscar_ops);
036b1ba8
JB
428}
429
036b1ba8 430static ptid_t
1e6b91a4 431ravenscar_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
036b1ba8
JB
432{
433 return ptid_build (ptid_get_pid (base_ptid), 0, thread);
434}
435
436static void
437init_ravenscar_thread_ops (void)
438{
439 ravenscar_ops.to_shortname = "ravenscar";
440 ravenscar_ops.to_longname = "Ravenscar tasks.";
441 ravenscar_ops.to_doc = "Ravenscar tasks support.";
036b1ba8
JB
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;
e02544b2
JB
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;
036b1ba8 453 ravenscar_ops.to_thread_alive = ravenscar_thread_alive;
e8032dde 454 ravenscar_ops.to_update_thread_list = ravenscar_update_thread_list;
036b1ba8
JB
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;
e02544b2 465 ravenscar_ops.to_core_of_thread = ravenscar_core_of_thread;
036b1ba8
JB
466 ravenscar_ops.to_magic = OPS_MAGIC;
467}
468
469/* Command-list for the "set/show ravenscar" prefix command. */
470static struct cmd_list_element *set_ravenscar_list;
471static struct cmd_list_element *show_ravenscar_list;
472
473/* Implement the "set ravenscar" prefix command. */
474
475static void
981a3fb3 476set_ravenscar_command (const char *arg, int from_tty)
036b1ba8
JB
477{
478 printf_unfiltered (_(\
479"\"set ravenscar\" must be followed by the name of a setting.\n"));
635c7e8a 480 help_list (set_ravenscar_list, "set ravenscar ", all_commands, gdb_stdout);
036b1ba8
JB
481}
482
483/* Implement the "show ravenscar" prefix command. */
484
485static void
981a3fb3 486show_ravenscar_command (const char *args, int from_tty)
036b1ba8
JB
487{
488 cmd_show_list (show_ravenscar_list, from_tty, "");
489}
490
491/* Implement the "show ravenscar task-switching" command. */
492
493static void
494show_ravenscar_task_switching_command (struct ui_file *file, int from_tty,
495 struct cmd_list_element *c,
496 const char *value)
497{
498 if (ravenscar_task_support)
499 fprintf_filtered (file, _("\
b64edec4 500Support for Ravenscar task/thread switching is enabled\n"));
036b1ba8
JB
501 else
502 fprintf_filtered (file, _("\
b64edec4 503Support for Ravenscar task/thread switching is disabled\n"));
036b1ba8
JB
504}
505
506/* Module startup initialization function, automagically called by
507 init.c. */
508
509void
510_initialize_ravenscar (void)
511{
512 init_ravenscar_thread_ops ();
513 base_ptid = null_ptid;
514
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);
518
12070676 519 complete_target_initialization (&ravenscar_ops);
036b1ba8
JB
520
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);
524
525 add_prefix_cmd ("ravenscar", no_class, show_ravenscar_command,
526 _("Prefix command for showing Ravenscar-specific settings"),
04f9d4d0 527 &show_ravenscar_list, "show ravenscar ", 0, &showlist);
036b1ba8
JB
528
529 add_setshow_boolean_cmd ("task-switching", class_obscure,
530 &ravenscar_task_support, _("\
531Enable or disable support for GNAT Ravenscar tasks"), _("\
532Show whether support for GNAT Ravenscar tasks is enabled"),
533 _("\
534Enable or disable support for task/thread switching with the GNAT\n\
535Ravenscar run-time library for bareboard configuration."),
536 NULL, show_ravenscar_task_switching_command,
537 &set_ravenscar_list, &show_ravenscar_list);
538}
This page took 0.750546 seconds and 4 git commands to generate.