minor ravenscar-thread cleanup
[external/binutils.git] / gdb / ravenscar-thread.c
1 /* Ada Ravenscar thread support.
2
3    Copyright 2004, 2009-2012 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 "gdb_string.h"
30 #include "gdbcmd.h"
31 #include "top.h"
32 #include "regcache.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).  */
42 static ptid_t base_magic_null_ptid;
43
44 /* Ptid of the inferior as seen by the process stratum.  */
45 static ptid_t base_ptid;
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 struct observer *update_target_observer = NULL;
56
57 /* Architecture-specific hooks.  */
58 static struct ravenscar_arch_ops* current_arch_ops;
59
60 static void ravenscar_find_new_threads (struct target_ops *ops);
61 static ptid_t ravenscar_running_thread (void);
62 static char *ravenscar_extra_thread_info (struct thread_info *tp);
63 static int ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid);
64 static void ravenscar_fetch_registers (struct target_ops *ops,
65                                        struct regcache *regcache, int regnum);
66 static void ravenscar_store_registers (struct target_ops *ops,
67                                        struct regcache *regcache, int regnum);
68 static void ravenscar_prepare_to_store (struct regcache *regcache);
69 static void ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
70                               enum gdb_signal siggnal);
71 static void ravenscar_mourn_inferior (struct target_ops *ops);
72 static void ravenscar_update_inferior_ptid (void);
73 static int has_ravenscar_runtime (void);
74 static int ravenscar_runtime_initialized (void);
75 static void ravenscar_inferior_created (struct target_ops *target,
76                                         int from_tty);
77
78 /* Fetch the ravenscar running thread from target memory and
79    update inferior_ptid accordingly.  */
80
81 static void
82 ravenscar_update_inferior_ptid (void)
83 {
84   base_ptid = inferior_ptid;
85
86   /* If the runtime has not been initialized yet, the inferior_ptid is
87      the only ptid that there is.  */
88   if (!ravenscar_runtime_initialized ())
89     return;
90
91   /* Make sure we set base_ptid before calling ravenscar_running_thread
92      as the latter relies on it.  */
93   inferior_ptid = ravenscar_running_thread ();
94   gdb_assert (!ptid_equal (inferior_ptid, null_ptid));
95
96   /* The running thread may not have been added to
97      system.tasking.debug's list yet; so ravenscar_find_new_threads
98      may not always add it to the thread list.  Add it here.  */
99   if (!find_thread_ptid (inferior_ptid))
100     add_thread (inferior_ptid);
101 }
102
103 /* The Ravenscar Runtime exports a symbol which contains the ID of
104    the thread that is currently running.  Try to locate that symbol
105    and return its associated minimal symbol.
106    Return NULL if not found.  */
107
108 static struct minimal_symbol *
109 get_running_thread_msymbol (void)
110 {
111   struct minimal_symbol *msym;
112
113   msym = lookup_minimal_symbol (running_thread_name, NULL, NULL);
114   if (!msym)
115     /* Older versions of the GNAT runtime were using a different
116        (less ideal) name for the symbol where the active thread ID
117        is stored.  If we couldn't find the symbol using the latest
118        name, then try the old one.  */
119     msym = lookup_minimal_symbol ("running_thread", NULL, NULL);
120
121   return msym;
122 }
123
124 /* Return True if the Ada Ravenscar run-time can be found in the
125    application.  */
126
127 static int
128 has_ravenscar_runtime (void)
129 {
130   struct minimal_symbol *msym_ravenscar_runtime_initializer =
131     lookup_minimal_symbol (ravenscar_runtime_initializer, NULL, NULL);
132   struct minimal_symbol *msym_known_tasks =
133     lookup_minimal_symbol (known_tasks_name, NULL, NULL);
134   struct minimal_symbol *msym_first_task =
135     lookup_minimal_symbol (first_task_name, NULL, NULL);
136   struct minimal_symbol *msym_running_thread = get_running_thread_msymbol ();
137
138   return (msym_ravenscar_runtime_initializer
139           && (msym_known_tasks || msym_first_task)
140           && msym_running_thread);
141 }
142
143 /* Return True if the Ada Ravenscar run-time can be found in the
144    application, and if it has been initialized on target.  */
145
146 static int
147 ravenscar_runtime_initialized (void)
148 {
149   return (!(ptid_equal (ravenscar_running_thread (), null_ptid)));
150 }
151
152 /* Return the ID of the thread that is currently running.
153    Return 0 if the ID could not be determined.  */
154
155 static CORE_ADDR
156 get_running_thread_id (void)
157 {
158   const struct minimal_symbol *object_msym = get_running_thread_msymbol ();
159   int object_size;
160   int buf_size;
161   char *buf;
162   CORE_ADDR object_addr;
163   struct type *builtin_type_void_data_ptr =
164     builtin_type (target_gdbarch ())->builtin_data_ptr;
165
166   if (!object_msym)
167     return 0;
168
169   object_addr = SYMBOL_VALUE_ADDRESS (object_msym);
170   object_size = TYPE_LENGTH (builtin_type_void_data_ptr);
171   buf_size = object_size;
172   buf = alloca (buf_size);
173   read_memory (object_addr, buf, buf_size);
174   return extract_typed_address (buf, builtin_type_void_data_ptr);
175 }
176
177 static void
178 ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
179                   enum gdb_signal siggnal)
180 {
181   struct target_ops *beneath = find_target_beneath (ops);
182
183   inferior_ptid = base_ptid;
184   beneath->to_resume (beneath, base_ptid, step, siggnal);
185 }
186
187 static ptid_t
188 ravenscar_wait (struct target_ops *ops, ptid_t ptid,
189                 struct target_waitstatus *status,
190                 int options)
191 {
192   struct target_ops *beneath = find_target_beneath (ops);
193
194   inferior_ptid = base_ptid;
195   beneath->to_wait (beneath, base_ptid, status, 0);
196   /* Find any new threads that might have been created, and update
197      inferior_ptid to the active thread.
198
199      Only do it if the program is still alive, though.  Otherwise,
200      this causes problems when debugging through the remote protocol,
201      because we might try switching threads (and thus sending packets)
202      after the remote has disconnected.  */
203   if (status->kind != TARGET_WAITKIND_EXITED
204       && status->kind != TARGET_WAITKIND_SIGNALLED)
205     {
206       ravenscar_find_new_threads (ops);
207       ravenscar_update_inferior_ptid ();
208     }
209   return inferior_ptid;
210 }
211
212 /* Add the thread associated to the given TASK to the thread list
213    (if the thread has already been added, this is a no-op).  */
214
215 static void
216 ravenscar_add_thread (struct ada_task_info *task)
217 {
218   if (find_thread_ptid (task->ptid) == NULL)
219     add_thread (task->ptid);
220 }
221
222 static void
223 ravenscar_find_new_threads (struct target_ops *ops)
224 {
225   ada_build_task_list ();
226
227   /* Do not clear the thread list before adding the Ada task, to keep
228      the thread that the process stratum has included into it
229      (base_ptid) and the running thread, that may not have been included
230      to system.tasking.debug's list yet.  */
231
232   iterate_over_live_ada_tasks (ravenscar_add_thread);
233 }
234
235 static ptid_t
236 ravenscar_running_thread (void)
237 {
238   CORE_ADDR tid = get_running_thread_id ();
239
240   if (tid == 0)
241     return null_ptid;
242   else
243     return ptid_build (ptid_get_pid (base_ptid), 0, tid);
244 }
245
246 static char *
247 ravenscar_extra_thread_info (struct thread_info *tp)
248 {
249   return "Ravenscar task";
250 }
251
252 static int
253 ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid)
254 {
255   /* Ravenscar tasks are non-terminating.  */
256   return 1;
257 }
258
259 static char *
260 ravenscar_pid_to_str (struct target_ops *ops, ptid_t ptid)
261 {
262   static char buf[30];
263
264   snprintf (buf, sizeof (buf), "Thread %#x", (int) ptid_get_tid (ptid));
265   return buf;
266 }
267
268 static void
269 ravenscar_fetch_registers (struct target_ops *ops,
270                            struct regcache *regcache, int regnum)
271 {
272   struct target_ops *beneath = find_target_beneath (ops);
273
274   if (!ravenscar_runtime_initialized ()
275       || ptid_equal (inferior_ptid, base_magic_null_ptid)
276       || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
277     beneath->to_fetch_registers (beneath, regcache, regnum);
278   else
279     current_arch_ops->to_fetch_registers (regcache, regnum);
280 }
281
282 static void
283 ravenscar_store_registers (struct target_ops *ops,
284                            struct regcache *regcache, int regnum)
285 {
286   struct target_ops *beneath = find_target_beneath (ops);
287
288   if (!ravenscar_runtime_initialized ()
289       || ptid_equal (inferior_ptid, base_magic_null_ptid)
290       || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
291     beneath->to_store_registers (beneath, regcache, regnum);
292   else
293     current_arch_ops->to_store_registers (regcache, regnum);
294 }
295
296 static void
297 ravenscar_prepare_to_store (struct regcache *regcache)
298 {
299   struct target_ops *beneath = find_target_beneath (&ravenscar_ops);
300
301   if (!ravenscar_runtime_initialized ()
302       || ptid_equal (inferior_ptid, base_magic_null_ptid)
303       || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
304     beneath->to_prepare_to_store (regcache);
305   else
306     current_arch_ops->to_prepare_to_store (regcache);
307 }
308
309 static void
310 ravenscar_mourn_inferior (struct target_ops *ops)
311 {
312   struct target_ops *beneath = find_target_beneath (&ravenscar_ops);
313
314   base_ptid = null_ptid;
315   beneath->to_mourn_inferior (beneath);
316   unpush_target (&ravenscar_ops);
317 }
318
319 /* Observer on inferior_created: push ravenscar thread stratum if needed.  */
320
321 static void
322 ravenscar_inferior_created (struct target_ops *target, int from_tty)
323 {
324   if (!ravenscar_task_support || !has_ravenscar_runtime ())
325     return;
326
327   base_magic_null_ptid = inferior_ptid;
328   ravenscar_update_inferior_ptid ();
329   push_target (&ravenscar_ops);
330 }
331
332 void
333 ravenscar_register_arch_ops (struct ravenscar_arch_ops *ops)
334 {
335   /* FIXME: To be clean, we would need to handle a list of
336      architectures, just like in remote-wtx-hw.c.  However, for now the
337      only Ravenscar run-time for bare board that is implemented in
338      GNAT is for only one architecture: erc32-elf.  So no need to care about
339      that for now...  */
340   current_arch_ops = ops;
341 }
342
343 static ptid_t
344 ravenscar_get_ada_task_ptid (long lwp, long thread)
345 {
346   return ptid_build (ptid_get_pid (base_ptid), 0, thread);
347 }
348
349 static void
350 init_ravenscar_thread_ops (void)
351 {
352   ravenscar_ops.to_shortname = "ravenscar";
353   ravenscar_ops.to_longname = "Ravenscar tasks.";
354   ravenscar_ops.to_doc = "Ravenscar tasks support.";
355   ravenscar_ops.to_resume = ravenscar_resume;
356   ravenscar_ops.to_wait = ravenscar_wait;
357   ravenscar_ops.to_fetch_registers = ravenscar_fetch_registers;
358   ravenscar_ops.to_store_registers = ravenscar_store_registers;
359   ravenscar_ops.to_prepare_to_store = ravenscar_prepare_to_store;
360   ravenscar_ops.to_thread_alive = ravenscar_thread_alive;
361   ravenscar_ops.to_find_new_threads = ravenscar_find_new_threads;
362   ravenscar_ops.to_pid_to_str = ravenscar_pid_to_str;
363   ravenscar_ops.to_extra_thread_info = ravenscar_extra_thread_info;
364   ravenscar_ops.to_get_ada_task_ptid = ravenscar_get_ada_task_ptid;
365   ravenscar_ops.to_mourn_inferior = ravenscar_mourn_inferior;
366   ravenscar_ops.to_has_all_memory = default_child_has_all_memory;
367   ravenscar_ops.to_has_memory = default_child_has_memory;
368   ravenscar_ops.to_has_stack = default_child_has_stack;
369   ravenscar_ops.to_has_registers = default_child_has_registers;
370   ravenscar_ops.to_has_execution = default_child_has_execution;
371   ravenscar_ops.to_stratum = thread_stratum;
372   ravenscar_ops.to_magic = OPS_MAGIC;
373 }
374
375 /* Command-list for the "set/show ravenscar" prefix command.  */
376 static struct cmd_list_element *set_ravenscar_list;
377 static struct cmd_list_element *show_ravenscar_list;
378
379 /* Implement the "set ravenscar" prefix command.  */
380
381 static void
382 set_ravenscar_command (char *arg, int from_tty)
383 {
384   printf_unfiltered (_(\
385 "\"set ravenscar\" must be followed by the name of a setting.\n"));
386   help_list (set_ravenscar_list, "set ravenscar ", -1, gdb_stdout);
387 }
388
389 /* Implement the "show ravenscar" prefix command.  */
390
391 static void
392 show_ravenscar_command (char *args, int from_tty)
393 {
394   cmd_show_list (show_ravenscar_list, from_tty, "");
395 }
396
397 /* Implement the "show ravenscar task-switching" command.  */
398
399 static void
400 show_ravenscar_task_switching_command (struct ui_file *file, int from_tty,
401                                        struct cmd_list_element *c,
402                                        const char *value)
403 {
404   if (ravenscar_task_support)
405     fprintf_filtered (file, _("\
406 Support for Ravenscar task/thread switching is enabled\n"));
407   else
408     fprintf_filtered (file, _("\
409 Support for Ravenscar task/thread switching is disabled\n"));
410 }
411
412 /* Provide a prototype to silence -Wmissing-prototypes.  */
413 extern void _initialize_ravenscar (void);
414
415 /* Module startup initialization function, automagically called by
416    init.c.  */
417
418 void
419 _initialize_ravenscar (void)
420 {
421   init_ravenscar_thread_ops ();
422   base_ptid = null_ptid;
423
424   /* Notice when the inferior is created in order to push the
425      ravenscar ops if needed.  */
426   observer_attach_inferior_created (ravenscar_inferior_created);
427
428   add_target (&ravenscar_ops);
429
430   add_prefix_cmd ("ravenscar", no_class, set_ravenscar_command,
431                   _("Prefix command for changing Ravenscar-specific settings"),
432                   &set_ravenscar_list, "set ravenscar ", 0, &setlist);
433
434   add_prefix_cmd ("ravenscar", no_class, show_ravenscar_command,
435                   _("Prefix command for showing Ravenscar-specific settings"),
436                   &show_ravenscar_list, "show ravenscar ", 0, &showlist);
437
438   add_setshow_boolean_cmd ("task-switching", class_obscure,
439                            &ravenscar_task_support, _("\
440 Enable or disable support for GNAT Ravenscar tasks"), _("\
441 Show whether support for GNAT Ravenscar tasks is enabled"),
442                            _("\
443 Enable or disable support for task/thread switching with the GNAT\n\
444 Ravenscar run-time library for bareboard configuration."),
445                            NULL, show_ravenscar_task_switching_command,
446                            &set_ravenscar_list, &show_ravenscar_list);
447 }