GDB (xrefs)
/tmp/gdb-7.10/gdb/ravenscar-thread.c
Go to the documentation of this file.
1 /* Ada Ravenscar thread support.
2 
3  Copyright (C) 2004-2015 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. */
35 static int ravenscar_task_support = 1;
36 
37 /* This module's target-specific operations. */
38 static struct target_ops ravenscar_ops;
39 
40 /* Some base target uses a special value for the null PID (exempli gratia
41  remote). */
43 
44 /* Ptid of the inferior as seen by the process stratum. */
46 
47 static const char running_thread_name[] = "__gnat_running_thread_table";
48 
49 static const char known_tasks_name[] = "system__tasking__debug__known_tasks";
50 static const char first_task_name[] = "system__tasking__debug__first_task";
51 
52 static const char ravenscar_runtime_initializer[] =
53  "system__bb__threads__initialize";
54 
55 static void ravenscar_update_thread_list (struct target_ops *ops);
56 static ptid_t ravenscar_running_thread (void);
57 static 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,
73  int from_tty);
74 
75 /* Fetch the ravenscar running thread from target memory and
76  update inferior_ptid accordingly. */
77 
78 static 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. */
86  return;
87 
88  /* Make sure we set base_ptid before calling ravenscar_running_thread
89  as the latter relies on it. */
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. */
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 
105 static struct bound_minimal_symbol
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 
124 static int
126 {
127  struct bound_minimal_symbol msym_ravenscar_runtime_initializer =
129  struct bound_minimal_symbol msym_known_tasks =
131  struct bound_minimal_symbol msym_first_task =
133  struct bound_minimal_symbol msym_running_thread
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 
144 static int
146 {
148 }
149 
150 /* Return the ID of the thread that is currently running.
151  Return 0 if the ID could not be determined. */
152 
153 static CORE_ADDR
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 =
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 = alloca (buf_size);
171  read_memory (object_addr, buf, buf_size);
172  return extract_typed_address (buf, builtin_type_void_data_ptr);
173 }
174 
175 static void
176 ravenscar_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 
182  beneath->to_resume (beneath, base_ptid, step, siggnal);
183 }
184 
185 static ptid_t
187  struct target_waitstatus *status,
188  int options)
189 {
190  struct target_ops *beneath = find_target_beneath (ops);
191 
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  {
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 
213 static void
215 {
216  if (find_thread_ptid (task->ptid) == NULL)
217  add_thread (task->ptid);
218 }
219 
220 static void
222 {
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 
231 }
232 
233 static ptid_t
235 {
237 
238  if (tid == 0)
239  return null_ptid;
240  else
241  return ptid_build (ptid_get_pid (base_ptid), 0, tid);
242 }
243 
244 static char *
246 {
247  return "Ravenscar task";
248 }
249 
250 static int
252 {
253  /* Ravenscar tasks are non-terminating. */
254  return 1;
255 }
256 
257 static char *
259 {
260  static char buf[30];
261 
262  snprintf (buf, sizeof (buf), "Thread %#x", (int) ptid_get_tid (ptid));
263  return buf;
264 }
265 
266 static void
268  struct regcache *regcache, int regnum)
269 {
270  struct target_ops *beneath = find_target_beneath (ops);
271 
273  || ptid_equal (inferior_ptid, base_magic_null_ptid)
275  beneath->to_fetch_registers (beneath, regcache, regnum);
276  else
277  {
278  struct gdbarch *gdbarch = get_regcache_arch (regcache);
279  struct ravenscar_arch_ops *arch_ops
280  = gdbarch_ravenscar_ops (gdbarch);
281 
282  arch_ops->to_fetch_registers (regcache, regnum);
283  }
284 }
285 
286 static void
288  struct regcache *regcache, int regnum)
289 {
290  struct target_ops *beneath = find_target_beneath (ops);
291 
293  || ptid_equal (inferior_ptid, base_magic_null_ptid)
295  beneath->to_store_registers (beneath, regcache, regnum);
296  else
297  {
298  struct gdbarch *gdbarch = get_regcache_arch (regcache);
299  struct ravenscar_arch_ops *arch_ops
300  = gdbarch_ravenscar_ops (gdbarch);
301 
302  arch_ops->to_store_registers (regcache, regnum);
303  }
304 }
305 
306 static void
308  struct regcache *regcache)
309 {
310  struct target_ops *beneath = find_target_beneath (self);
311 
313  || ptid_equal (inferior_ptid, base_magic_null_ptid)
315  beneath->to_prepare_to_store (beneath, regcache);
316  else
317  {
318  struct gdbarch *gdbarch = get_regcache_arch (regcache);
319  struct ravenscar_arch_ops *arch_ops
320  = gdbarch_ravenscar_ops (gdbarch);
321 
322  arch_ops->to_prepare_to_store (regcache);
323  }
324 }
325 
326 static void
328 {
329  struct target_ops *beneath = find_target_beneath (ops);
330 
331  base_ptid = null_ptid;
332  beneath->to_mourn_inferior (beneath);
334 }
335 
336 /* Observer on inferior_created: push ravenscar thread stratum if needed. */
337 
338 static void
339 ravenscar_inferior_created (struct target_ops *target, int from_tty)
340 {
341  struct ravenscar_arch_ops *ops;
342 
345  || !has_ravenscar_runtime ())
346  return;
347 
348  base_magic_null_ptid = inferior_ptid;
351 }
352 
353 static ptid_t
354 ravenscar_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
355 {
356  return ptid_build (ptid_get_pid (base_ptid), 0, thread);
357 }
358 
359 static void
361 {
362  ravenscar_ops.to_shortname = "ravenscar";
363  ravenscar_ops.to_longname = "Ravenscar tasks.";
364  ravenscar_ops.to_doc = "Ravenscar tasks support.";
383 }
384 
385 /* Command-list for the "set/show ravenscar" prefix command. */
388 
389 /* Implement the "set ravenscar" prefix command. */
390 
391 static void
392 set_ravenscar_command (char *arg, int from_tty)
393 {
395 "\"set ravenscar\" must be followed by the name of a setting.\n"));
396  help_list (set_ravenscar_list, "set ravenscar ", all_commands, gdb_stdout);
397 }
398 
399 /* Implement the "show ravenscar" prefix command. */
400 
401 static void
402 show_ravenscar_command (char *args, int from_tty)
403 {
404  cmd_show_list (show_ravenscar_list, from_tty, "");
405 }
406 
407 /* Implement the "show ravenscar task-switching" command. */
408 
409 static void
410 show_ravenscar_task_switching_command (struct ui_file *file, int from_tty,
411  struct cmd_list_element *c,
412  const char *value)
413 {
415  fprintf_filtered (file, _("\
416 Support for Ravenscar task/thread switching is enabled\n"));
417  else
418  fprintf_filtered (file, _("\
419 Support for Ravenscar task/thread switching is disabled\n"));
420 }
421 
422 /* Provide a prototype to silence -Wmissing-prototypes. */
423 extern void _initialize_ravenscar (void);
424 
425 /* Module startup initialization function, automagically called by
426  init.c. */
427 
428 void
430 {
432  base_ptid = null_ptid;
433 
434  /* Notice when the inferior is created in order to push the
435  ravenscar ops if needed. */
437 
439 
441  _("Prefix command for changing Ravenscar-specific settings"),
442  &set_ravenscar_list, "set ravenscar ", 0, &setlist);
443 
445  _("Prefix command for showing Ravenscar-specific settings"),
446  &show_ravenscar_list, "show ravenscar ", 0, &showlist);
447 
448  add_setshow_boolean_cmd ("task-switching", class_obscure,
450 Enable or disable support for GNAT Ravenscar tasks"), _("\
451 Show whether support for GNAT Ravenscar tasks is enabled"),
452  _("\
453 Enable or disable support for task/thread switching with the GNAT\n\
454 Ravenscar run-time library for bareboard configuration."),
456  &set_ravenscar_list, &show_ravenscar_list);
457 }
static char * ravenscar_extra_thread_info(struct target_ops *self, struct thread_info *tp)
struct gdbarch * target_gdbarch(void)
Definition: gdbarch.c:5143
void _initialize_ravenscar(void)
int default_child_has_stack(struct target_ops *ops)
Definition: target.c:216
struct cmd_list_element * add_prefix_cmd(const char *name, enum command_class theclass, cmd_cfunc_ftype *fun, const char *doc, struct cmd_list_element **prefixlist, const char *prefixname, int allow_unknown, struct cmd_list_element **list)
Definition: cli-decode.c:338
struct thread_info * add_thread(ptid_t ptid)
Definition: thread.c:305
struct thread_info * find_thread_ptid(ptid_t ptid)
Definition: thread.c:393
CORE_ADDR extract_typed_address(const gdb_byte *buf, struct type *type)
Definition: findvar.c:169
static int has_ravenscar_runtime(void)
const char * to_longname
Definition: target.h:433
int ptid_equal(ptid_t ptid1, ptid_t ptid2)
Definition: ptid.c:76
bfd_vma CORE_ADDR
Definition: common-types.h:41
static ptid_t ravenscar_running_thread(void)
struct gdbarch * get_regcache_arch(const struct regcache *regcache)
Definition: regcache.c:297
#define BMSYMBOL_VALUE_ADDRESS(symbol)
Definition: symtab.h:393
int(* to_has_memory)(struct target_ops *)
Definition: target.h:652
char *(* to_pid_to_str)(struct target_ops *, ptid_t) TARGET_DEFAULT_FUNC(default_pid_to_str)
Definition: target.h:631
void(* to_fetch_registers)(struct regcache *, int)
int(* to_has_stack)(struct target_ops *)
Definition: target.h:653
void push_target(struct target_ops *t)
Definition: target.c:664
char *(* to_extra_thread_info)(struct target_ops *, struct thread_info *) TARGET_DEFAULT_RETURN(NULL)
Definition: target.h:633
struct ravenscar_arch_ops * gdbarch_ravenscar_ops(struct gdbarch *gdbarch)
Definition: gdbarch.c:4563
struct ui_file * gdb_stdout
Definition: main.c:71
const struct builtin_type * builtin_type(struct gdbarch *gdbarch)
Definition: gdbtypes.c:4766
static int ravenscar_task_support
int unpush_target(struct target_ops *t)
Definition: target.c:711
static CORE_ADDR get_running_thread_id(void)
static void show_ravenscar_task_switching_command(struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value)
static ptid_t base_ptid
static void ravenscar_update_thread_list(struct target_ops *ops)
static ptid_t ravenscar_get_ada_task_ptid(struct target_ops *self, long lwp, long thread)
static int ravenscar_runtime_initialized(void)
ptid_t(* to_wait)(struct target_ops *, ptid_t, struct target_waitstatus *, int TARGET_DEBUG_PRINTER(target_debug_print_options)) TARGET_DEFAULT_NORETURN(noprocess())
Definition: target.h:468
#define _(String)
Definition: gdb_locale.h:40
int default_child_has_execution(struct target_ops *ops, ptid_t the_ptid)
Definition: target.c:236
static struct cmd_list_element * set_ravenscar_list
static struct target_ops ravenscar_ops
Definition: ptid.h:35
ptid_t ptid_build(int pid, long lwp, long tid)
Definition: ptid.c:31
struct observer * observer_attach_inferior_created(observer_inferior_created_ftype *f)
static void set_ravenscar_command(char *arg, int from_tty)
int default_child_has_memory(struct target_ops *ops)
Definition: target.c:206
static void init_ravenscar_thread_ops(void)
struct cmd_list_element * setlist
Definition: cli-cmds.c:135
#define OPS_MAGIC
Definition: target.h:1233
static void ravenscar_prepare_to_store(struct target_ops *self, struct regcache *regcache)
static ptid_t ravenscar_wait(struct target_ops *ops, ptid_t ptid, struct target_waitstatus *status, int options)
void complete_target_initialization(struct target_ops *t)
Definition: target.c:317
void fprintf_filtered(struct ui_file *stream, const char *format,...)
Definition: utils.c:2351
mach_port_t mach_port_t name mach_port_t mach_port_t name error_t int status
Definition: gnu-nat.c:1816
void(* to_resume)(struct target_ops *, ptid_t, int TARGET_DEBUG_PRINTER(target_debug_print_step), enum gdb_signal) TARGET_DEFAULT_NORETURN(noprocess())
Definition: target.h:464
static char * ravenscar_pid_to_str(struct target_ops *ops, ptid_t ptid)
struct cmd_list_element * showlist
Definition: cli-cmds.c:143
int default_child_has_all_memory(struct target_ops *ops)
Definition: target.c:196
int(* to_has_execution)(struct target_ops *, ptid_t)
Definition: target.h:655
Definition: gdbtypes.h:749
static const char running_thread_name[]
static void ravenscar_mourn_inferior(struct target_ops *ops)
#define gdb_assert(expr)
Definition: gdb_assert.h:33
const char * to_doc
Definition: target.h:434
static void show_ravenscar_command(char *args, int from_tty)
struct target_ops * find_target_beneath(struct target_ops *t)
Definition: target.c:3148
int regnum
Definition: aarch64-tdep.c:69
void printf_unfiltered(const char *format,...)
Definition: utils.c:2399
void read_memory(CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
Definition: corefile.c:244
static void ravenscar_inferior_created(struct target_ops *target, int from_tty)
static const char known_tasks_name[]
void cmd_show_list(struct cmd_list_element *list, int from_tty, const char *prefix)
Definition: cli-setshow.c:672
static void ravenscar_add_thread(struct ada_task_info *task)
Definition: value.c:172
int ptid_get_pid(ptid_t ptid)
Definition: ptid.c:52
static const char first_task_name[]
bfd_byte gdb_byte
Definition: common-types.h:38
void help_list(struct cmd_list_element *list, const char *cmdtype, enum command_class theclass, struct ui_file *stream)
Definition: cli-decode.c:1023
static void ravenscar_store_registers(struct target_ops *ops, struct regcache *regcache, int regnum)
static ptid_t base_magic_null_ptid
ptid_t null_ptid
Definition: ptid.c:25
void(* to_fetch_registers)(struct target_ops *, struct regcache *, int) TARGET_DEFAULT_IGNORE()
Definition: target.h:472
long ptid_get_tid(ptid_t ptid)
Definition: ptid.c:68
ptid_t ptid
Definition: ada-lang.h:131
void(* to_mourn_inferior)(struct target_ops *) TARGET_DEFAULT_FUNC(default_mourn_inferior)
Definition: target.h:607
int default_child_has_registers(struct target_ops *ops)
Definition: target.c:226
enum target_waitkind kind
Definition: waitstatus.h:100
ptid_t inferior_ptid
Definition: infcmd.c:124
struct type * builtin_data_ptr
Definition: gdbtypes.h:1533
struct minimal_symbol * minsym
Definition: minsyms.h:32
static int ravenscar_thread_alive(struct target_ops *ops, ptid_t ptid)
enum strata to_stratum
Definition: target.h:650
static struct cmd_list_element * show_ravenscar_list
void iterate_over_live_ada_tasks(ada_task_list_iterator_ftype *iterator)
Definition: ada-tasks.c:357
struct inferior * current_inferior(void)
Definition: inferior.c:57
const char * to_shortname
Definition: target.h:432
int to_magic
Definition: target.h:1224
static void ravenscar_fetch_registers(struct target_ops *ops, struct regcache *regcache, int regnum)
int(* to_has_all_memory)(struct target_ops *)
Definition: target.h:651
static struct bound_minimal_symbol get_running_thread_msymbol(void)
#define TYPE_LENGTH(thistype)
Definition: gdbtypes.h:1237
static void ravenscar_update_inferior_ptid(void)
int(* to_thread_alive)(struct target_ops *, ptid_t ptid) TARGET_DEFAULT_RETURN(0)
Definition: target.h:627
int ada_build_task_list(void)
Definition: ada-tasks.c:981
void(* to_update_thread_list)(struct target_ops *) TARGET_DEFAULT_IGNORE()
Definition: target.h:629
void(* to_prepare_to_store)(struct target_ops *, struct regcache *) TARGET_DEFAULT_NORETURN(noprocess())
Definition: target.h:476
void(* to_store_registers)(struct target_ops *, struct regcache *, int) TARGET_DEFAULT_NORETURN(noprocess())
Definition: target.h:474
struct bound_minimal_symbol lookup_minimal_symbol(const char *name, const char *sfile, struct objfile *objf)
Definition: minsyms.c:163
int(* to_has_registers)(struct target_ops *)
Definition: target.h:654
ptid_t(* to_get_ada_task_ptid)(struct target_ops *, long lwp, long thread) TARGET_DEFAULT_FUNC(default_get_ada_task_ptid)
Definition: target.h:776
void(* to_store_registers)(struct regcache *, int)
static void ravenscar_resume(struct target_ops *ops, ptid_t ptid, int step, enum gdb_signal siggnal)
void(* to_prepare_to_store)(struct regcache *)
struct target_ops * beneath
Definition: target.h:431
void add_setshow_boolean_cmd(const char *name, enum command_class theclass, int *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_sfunc_ftype *set_func, show_value_ftype *show_func, struct cmd_list_element **set_list, struct cmd_list_element **show_list)
Definition: cli-decode.c:541
static const char ravenscar_runtime_initializer[]