]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/ravenscar-thread.c
make MSYMBOL_VALUE_ADDRESS an rvalue
[thirdparty/binutils-gdb.git] / gdb / ravenscar-thread.c
CommitLineData
036b1ba8
JB
1/* Ada Ravenscar thread support.
2
ecd75fc8 3 Copyright (C) 2004-2014 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"
0e9f083f 29#include <string.h>
036b1ba8
JB
30#include "gdbcmd.h"
31#include "top.h"
32#include "regcache.h"
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
036b1ba8
JB
55static void ravenscar_find_new_threads (struct target_ops *ops);
56static ptid_t ravenscar_running_thread (void);
c15906d8
TT
57static 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
94 system.tasking.debug's list yet; so ravenscar_find_new_threads
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
105static struct minimal_symbol *
106get_running_thread_msymbol (void)
107{
108 struct minimal_symbol *msym;
109
110 msym = lookup_minimal_symbol (running_thread_name, NULL, NULL);
111 if (!msym)
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{
127 struct minimal_symbol *msym_ravenscar_runtime_initializer =
128 lookup_minimal_symbol (ravenscar_runtime_initializer, NULL, NULL);
129 struct minimal_symbol *msym_known_tasks =
130 lookup_minimal_symbol (known_tasks_name, NULL, NULL);
6040a59d
JB
131 struct minimal_symbol *msym_first_task =
132 lookup_minimal_symbol (first_task_name, NULL, NULL);
7f39f34a 133 struct minimal_symbol *msym_running_thread = get_running_thread_msymbol ();
036b1ba8
JB
134
135 return (msym_ravenscar_runtime_initializer
6040a59d 136 && (msym_known_tasks || msym_first_task)
036b1ba8
JB
137 && msym_running_thread);
138}
139
140/* Return True if the Ada Ravenscar run-time can be found in the
141 application, and if it has been initialized on target. */
142
143static int
144ravenscar_runtime_initialized (void)
145{
146 return (!(ptid_equal (ravenscar_running_thread (), null_ptid)));
147}
148
7f39f34a
JB
149/* Return the ID of the thread that is currently running.
150 Return 0 if the ID could not be determined. */
036b1ba8
JB
151
152static CORE_ADDR
7f39f34a 153get_running_thread_id (void)
036b1ba8 154{
7f39f34a 155 const struct minimal_symbol *object_msym = get_running_thread_msymbol ();
036b1ba8
JB
156 int object_size;
157 int buf_size;
948f8e3d 158 gdb_byte *buf;
036b1ba8
JB
159 CORE_ADDR object_addr;
160 struct type *builtin_type_void_data_ptr =
f5656ead 161 builtin_type (target_gdbarch ())->builtin_data_ptr;
036b1ba8
JB
162
163 if (!object_msym)
164 return 0;
165
efd66ac6 166 object_addr = MSYMBOL_VALUE_ADDRESS (object_msym);
036b1ba8
JB
167 object_size = TYPE_LENGTH (builtin_type_void_data_ptr);
168 buf_size = object_size;
169 buf = alloca (buf_size);
170 read_memory (object_addr, buf, buf_size);
171 return extract_typed_address (buf, builtin_type_void_data_ptr);
172}
173
036b1ba8
JB
174static void
175ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
2ea28649 176 enum gdb_signal siggnal)
036b1ba8
JB
177{
178 struct target_ops *beneath = find_target_beneath (ops);
179
180 inferior_ptid = base_ptid;
181 beneath->to_resume (beneath, base_ptid, step, siggnal);
182}
183
184static ptid_t
185ravenscar_wait (struct target_ops *ops, ptid_t ptid,
186 struct target_waitstatus *status,
187 int options)
188{
189 struct target_ops *beneath = find_target_beneath (ops);
190
191 inferior_ptid = base_ptid;
192 beneath->to_wait (beneath, base_ptid, status, 0);
bed0c243
JB
193 /* Find any new threads that might have been created, and update
194 inferior_ptid to the active thread.
195
196 Only do it if the program is still alive, though. Otherwise,
197 this causes problems when debugging through the remote protocol,
198 because we might try switching threads (and thus sending packets)
199 after the remote has disconnected. */
200 if (status->kind != TARGET_WAITKIND_EXITED
201 && status->kind != TARGET_WAITKIND_SIGNALLED)
202 {
203 ravenscar_find_new_threads (ops);
204 ravenscar_update_inferior_ptid ();
205 }
036b1ba8
JB
206 return inferior_ptid;
207}
208
209/* Add the thread associated to the given TASK to the thread list
210 (if the thread has already been added, this is a no-op). */
211
212static void
213ravenscar_add_thread (struct ada_task_info *task)
214{
215 if (find_thread_ptid (task->ptid) == NULL)
216 add_thread (task->ptid);
217}
218
219static void
220ravenscar_find_new_threads (struct target_ops *ops)
221{
79779fa9 222 ada_build_task_list ();
036b1ba8
JB
223
224 /* Do not clear the thread list before adding the Ada task, to keep
225 the thread that the process stratum has included into it
226 (base_ptid) and the running thread, that may not have been included
227 to system.tasking.debug's list yet. */
228
229 iterate_over_live_ada_tasks (ravenscar_add_thread);
230}
231
232static ptid_t
233ravenscar_running_thread (void)
234{
7f39f34a 235 CORE_ADDR tid = get_running_thread_id ();
036b1ba8
JB
236
237 if (tid == 0)
238 return null_ptid;
239 else
240 return ptid_build (ptid_get_pid (base_ptid), 0, tid);
241}
242
243static char *
c15906d8 244ravenscar_extra_thread_info (struct target_ops *self, struct thread_info *tp)
036b1ba8
JB
245{
246 return "Ravenscar task";
247}
248
249static int
250ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid)
251{
252 /* Ravenscar tasks are non-terminating. */
253 return 1;
254}
255
256static char *
257ravenscar_pid_to_str (struct target_ops *ops, ptid_t ptid)
258{
259 static char buf[30];
260
261 snprintf (buf, sizeof (buf), "Thread %#x", (int) ptid_get_tid (ptid));
262 return buf;
263}
264
265static void
266ravenscar_fetch_registers (struct target_ops *ops,
267 struct regcache *regcache, int regnum)
268{
269 struct target_ops *beneath = find_target_beneath (ops);
270
271 if (!ravenscar_runtime_initialized ()
272 || ptid_equal (inferior_ptid, base_magic_null_ptid)
273 || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
274 beneath->to_fetch_registers (beneath, regcache, regnum);
275 else
7e35103a
JB
276 {
277 struct gdbarch *gdbarch = get_regcache_arch (regcache);
278 struct ravenscar_arch_ops *arch_ops
279 = gdbarch_ravenscar_ops (gdbarch);
280
281 arch_ops->to_fetch_registers (regcache, regnum);
282 }
036b1ba8
JB
283}
284
285static void
286ravenscar_store_registers (struct target_ops *ops,
287 struct regcache *regcache, int regnum)
288{
289 struct target_ops *beneath = find_target_beneath (ops);
290
291 if (!ravenscar_runtime_initialized ()
292 || ptid_equal (inferior_ptid, base_magic_null_ptid)
293 || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
294 beneath->to_store_registers (beneath, regcache, regnum);
295 else
7e35103a
JB
296 {
297 struct gdbarch *gdbarch = get_regcache_arch (regcache);
298 struct ravenscar_arch_ops *arch_ops
299 = gdbarch_ravenscar_ops (gdbarch);
300
301 arch_ops->to_store_registers (regcache, regnum);
302 }
036b1ba8
JB
303}
304
305static void
f32dbf8c
MM
306ravenscar_prepare_to_store (struct target_ops *self,
307 struct regcache *regcache)
036b1ba8
JB
308{
309 struct target_ops *beneath = find_target_beneath (&ravenscar_ops);
310
311 if (!ravenscar_runtime_initialized ()
312 || ptid_equal (inferior_ptid, base_magic_null_ptid)
313 || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
f32dbf8c 314 beneath->to_prepare_to_store (beneath, regcache);
036b1ba8 315 else
7e35103a
JB
316 {
317 struct gdbarch *gdbarch = get_regcache_arch (regcache);
318 struct ravenscar_arch_ops *arch_ops
319 = gdbarch_ravenscar_ops (gdbarch);
320
321 arch_ops->to_prepare_to_store (regcache);
322 }
036b1ba8
JB
323}
324
325static void
326ravenscar_mourn_inferior (struct target_ops *ops)
327{
328 struct target_ops *beneath = find_target_beneath (&ravenscar_ops);
329
330 base_ptid = null_ptid;
331 beneath->to_mourn_inferior (beneath);
332 unpush_target (&ravenscar_ops);
333}
334
335/* Observer on inferior_created: push ravenscar thread stratum if needed. */
336
337static void
338ravenscar_inferior_created (struct target_ops *target, int from_tty)
339{
7e35103a
JB
340 struct ravenscar_arch_ops *ops;
341
342 if (!ravenscar_task_support
343 || gdbarch_ravenscar_ops (current_inferior ()->gdbarch) == NULL
344 || !has_ravenscar_runtime ())
25abf4de
JB
345 return;
346
347 base_magic_null_ptid = inferior_ptid;
348 ravenscar_update_inferior_ptid ();
349 push_target (&ravenscar_ops);
036b1ba8
JB
350}
351
036b1ba8 352static ptid_t
1e6b91a4 353ravenscar_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
036b1ba8
JB
354{
355 return ptid_build (ptid_get_pid (base_ptid), 0, thread);
356}
357
358static void
359init_ravenscar_thread_ops (void)
360{
361 ravenscar_ops.to_shortname = "ravenscar";
362 ravenscar_ops.to_longname = "Ravenscar tasks.";
363 ravenscar_ops.to_doc = "Ravenscar tasks support.";
036b1ba8
JB
364 ravenscar_ops.to_resume = ravenscar_resume;
365 ravenscar_ops.to_wait = ravenscar_wait;
366 ravenscar_ops.to_fetch_registers = ravenscar_fetch_registers;
367 ravenscar_ops.to_store_registers = ravenscar_store_registers;
368 ravenscar_ops.to_prepare_to_store = ravenscar_prepare_to_store;
369 ravenscar_ops.to_thread_alive = ravenscar_thread_alive;
370 ravenscar_ops.to_find_new_threads = ravenscar_find_new_threads;
371 ravenscar_ops.to_pid_to_str = ravenscar_pid_to_str;
372 ravenscar_ops.to_extra_thread_info = ravenscar_extra_thread_info;
373 ravenscar_ops.to_get_ada_task_ptid = ravenscar_get_ada_task_ptid;
374 ravenscar_ops.to_mourn_inferior = ravenscar_mourn_inferior;
375 ravenscar_ops.to_has_all_memory = default_child_has_all_memory;
376 ravenscar_ops.to_has_memory = default_child_has_memory;
377 ravenscar_ops.to_has_stack = default_child_has_stack;
378 ravenscar_ops.to_has_registers = default_child_has_registers;
379 ravenscar_ops.to_has_execution = default_child_has_execution;
380 ravenscar_ops.to_stratum = thread_stratum;
381 ravenscar_ops.to_magic = OPS_MAGIC;
382}
383
384/* Command-list for the "set/show ravenscar" prefix command. */
385static struct cmd_list_element *set_ravenscar_list;
386static struct cmd_list_element *show_ravenscar_list;
387
388/* Implement the "set ravenscar" prefix command. */
389
390static void
391set_ravenscar_command (char *arg, int from_tty)
392{
393 printf_unfiltered (_(\
394"\"set ravenscar\" must be followed by the name of a setting.\n"));
395 help_list (set_ravenscar_list, "set ravenscar ", -1, gdb_stdout);
396}
397
398/* Implement the "show ravenscar" prefix command. */
399
400static void
401show_ravenscar_command (char *args, int from_tty)
402{
403 cmd_show_list (show_ravenscar_list, from_tty, "");
404}
405
406/* Implement the "show ravenscar task-switching" command. */
407
408static void
409show_ravenscar_task_switching_command (struct ui_file *file, int from_tty,
410 struct cmd_list_element *c,
411 const char *value)
412{
413 if (ravenscar_task_support)
414 fprintf_filtered (file, _("\
b64edec4 415Support for Ravenscar task/thread switching is enabled\n"));
036b1ba8
JB
416 else
417 fprintf_filtered (file, _("\
b64edec4 418Support for Ravenscar task/thread switching is disabled\n"));
036b1ba8
JB
419}
420
8d037db9
JB
421/* Provide a prototype to silence -Wmissing-prototypes. */
422extern void _initialize_ravenscar (void);
423
036b1ba8
JB
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
12070676 437 complete_target_initialization (&ravenscar_ops);
036b1ba8
JB
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"),
04f9d4d0 445 &show_ravenscar_list, "show ravenscar ", 0, &showlist);
036b1ba8
JB
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}