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