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