Update mn10300 dwarf register map
[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"
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
JB
54
55static struct observer *update_target_observer = NULL;
56
036b1ba8
JB
57static void ravenscar_find_new_threads (struct target_ops *ops);
58static ptid_t ravenscar_running_thread (void);
59static char *ravenscar_extra_thread_info (struct thread_info *tp);
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
106static struct minimal_symbol *
107get_running_thread_msymbol (void)
108{
109 struct minimal_symbol *msym;
110
111 msym = lookup_minimal_symbol (running_thread_name, NULL, NULL);
112 if (!msym)
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{
128 struct minimal_symbol *msym_ravenscar_runtime_initializer =
129 lookup_minimal_symbol (ravenscar_runtime_initializer, NULL, NULL);
130 struct minimal_symbol *msym_known_tasks =
131 lookup_minimal_symbol (known_tasks_name, NULL, NULL);
6040a59d
JB
132 struct minimal_symbol *msym_first_task =
133 lookup_minimal_symbol (first_task_name, NULL, NULL);
7f39f34a 134 struct minimal_symbol *msym_running_thread = get_running_thread_msymbol ();
036b1ba8
JB
135
136 return (msym_ravenscar_runtime_initializer
6040a59d 137 && (msym_known_tasks || msym_first_task)
036b1ba8
JB
138 && msym_running_thread);
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
144static int
145ravenscar_runtime_initialized (void)
146{
147 return (!(ptid_equal (ravenscar_running_thread (), null_ptid)));
148}
149
7f39f34a
JB
150/* Return the ID of the thread that is currently running.
151 Return 0 if the ID could not be determined. */
036b1ba8
JB
152
153static CORE_ADDR
7f39f34a 154get_running_thread_id (void)
036b1ba8 155{
7f39f34a 156 const struct minimal_symbol *object_msym = get_running_thread_msymbol ();
036b1ba8
JB
157 int object_size;
158 int buf_size;
948f8e3d 159 gdb_byte *buf;
036b1ba8
JB
160 CORE_ADDR object_addr;
161 struct type *builtin_type_void_data_ptr =
f5656ead 162 builtin_type (target_gdbarch ())->builtin_data_ptr;
036b1ba8
JB
163
164 if (!object_msym)
165 return 0;
166
167 object_addr = SYMBOL_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
036b1ba8
JB
175static void
176ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
2ea28649 177 enum gdb_signal siggnal)
036b1ba8
JB
178{
179 struct target_ops *beneath = find_target_beneath (ops);
180
181 inferior_ptid = base_ptid;
182 beneath->to_resume (beneath, base_ptid, step, siggnal);
183}
184
185static ptid_t
186ravenscar_wait (struct target_ops *ops, ptid_t ptid,
187 struct target_waitstatus *status,
188 int options)
189{
190 struct target_ops *beneath = find_target_beneath (ops);
191
192 inferior_ptid = base_ptid;
193 beneath->to_wait (beneath, base_ptid, status, 0);
bed0c243
JB
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 {
204 ravenscar_find_new_threads (ops);
205 ravenscar_update_inferior_ptid ();
206 }
036b1ba8
JB
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
213static void
214ravenscar_add_thread (struct ada_task_info *task)
215{
216 if (find_thread_ptid (task->ptid) == NULL)
217 add_thread (task->ptid);
218}
219
220static void
221ravenscar_find_new_threads (struct target_ops *ops)
222{
79779fa9 223 ada_build_task_list ();
036b1ba8
JB
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
230 iterate_over_live_ada_tasks (ravenscar_add_thread);
231}
232
233static ptid_t
234ravenscar_running_thread (void)
235{
7f39f34a 236 CORE_ADDR tid = get_running_thread_id ();
036b1ba8
JB
237
238 if (tid == 0)
239 return null_ptid;
240 else
241 return ptid_build (ptid_get_pid (base_ptid), 0, tid);
242}
243
244static char *
245ravenscar_extra_thread_info (struct thread_info *tp)
246{
247 return "Ravenscar task";
248}
249
250static int
251ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid)
252{
253 /* Ravenscar tasks are non-terminating. */
254 return 1;
255}
256
257static char *
258ravenscar_pid_to_str (struct target_ops *ops, ptid_t ptid)
259{
260 static char buf[30];
261
262 snprintf (buf, sizeof (buf), "Thread %#x", (int) ptid_get_tid (ptid));
263 return buf;
264}
265
266static void
267ravenscar_fetch_registers (struct target_ops *ops,
268 struct regcache *regcache, int regnum)
269{
270 struct target_ops *beneath = find_target_beneath (ops);
271
272 if (!ravenscar_runtime_initialized ()
273 || ptid_equal (inferior_ptid, base_magic_null_ptid)
274 || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
275 beneath->to_fetch_registers (beneath, regcache, regnum);
276 else
7e35103a
JB
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 }
036b1ba8
JB
284}
285
286static void
287ravenscar_store_registers (struct target_ops *ops,
288 struct regcache *regcache, int regnum)
289{
290 struct target_ops *beneath = find_target_beneath (ops);
291
292 if (!ravenscar_runtime_initialized ()
293 || ptid_equal (inferior_ptid, base_magic_null_ptid)
294 || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
295 beneath->to_store_registers (beneath, regcache, regnum);
296 else
7e35103a
JB
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 }
036b1ba8
JB
304}
305
306static void
f32dbf8c
MM
307ravenscar_prepare_to_store (struct target_ops *self,
308 struct regcache *regcache)
036b1ba8
JB
309{
310 struct target_ops *beneath = find_target_beneath (&ravenscar_ops);
311
312 if (!ravenscar_runtime_initialized ()
313 || ptid_equal (inferior_ptid, base_magic_null_ptid)
314 || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
f32dbf8c 315 beneath->to_prepare_to_store (beneath, regcache);
036b1ba8 316 else
7e35103a
JB
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 }
036b1ba8
JB
324}
325
326static void
327ravenscar_mourn_inferior (struct target_ops *ops)
328{
329 struct target_ops *beneath = find_target_beneath (&ravenscar_ops);
330
331 base_ptid = null_ptid;
332 beneath->to_mourn_inferior (beneath);
333 unpush_target (&ravenscar_ops);
334}
335
336/* Observer on inferior_created: push ravenscar thread stratum if needed. */
337
338static void
339ravenscar_inferior_created (struct target_ops *target, int from_tty)
340{
7e35103a
JB
341 struct ravenscar_arch_ops *ops;
342
343 if (!ravenscar_task_support
344 || gdbarch_ravenscar_ops (current_inferior ()->gdbarch) == NULL
345 || !has_ravenscar_runtime ())
25abf4de
JB
346 return;
347
348 base_magic_null_ptid = inferior_ptid;
349 ravenscar_update_inferior_ptid ();
350 push_target (&ravenscar_ops);
036b1ba8
JB
351}
352
036b1ba8
JB
353static ptid_t
354ravenscar_get_ada_task_ptid (long lwp, long thread)
355{
356 return ptid_build (ptid_get_pid (base_ptid), 0, thread);
357}
358
359static void
360init_ravenscar_thread_ops (void)
361{
362 ravenscar_ops.to_shortname = "ravenscar";
363 ravenscar_ops.to_longname = "Ravenscar tasks.";
364 ravenscar_ops.to_doc = "Ravenscar tasks support.";
036b1ba8
JB
365 ravenscar_ops.to_resume = ravenscar_resume;
366 ravenscar_ops.to_wait = ravenscar_wait;
367 ravenscar_ops.to_fetch_registers = ravenscar_fetch_registers;
368 ravenscar_ops.to_store_registers = ravenscar_store_registers;
369 ravenscar_ops.to_prepare_to_store = ravenscar_prepare_to_store;
370 ravenscar_ops.to_thread_alive = ravenscar_thread_alive;
371 ravenscar_ops.to_find_new_threads = ravenscar_find_new_threads;
372 ravenscar_ops.to_pid_to_str = ravenscar_pid_to_str;
373 ravenscar_ops.to_extra_thread_info = ravenscar_extra_thread_info;
374 ravenscar_ops.to_get_ada_task_ptid = ravenscar_get_ada_task_ptid;
375 ravenscar_ops.to_mourn_inferior = ravenscar_mourn_inferior;
376 ravenscar_ops.to_has_all_memory = default_child_has_all_memory;
377 ravenscar_ops.to_has_memory = default_child_has_memory;
378 ravenscar_ops.to_has_stack = default_child_has_stack;
379 ravenscar_ops.to_has_registers = default_child_has_registers;
380 ravenscar_ops.to_has_execution = default_child_has_execution;
381 ravenscar_ops.to_stratum = thread_stratum;
382 ravenscar_ops.to_magic = OPS_MAGIC;
383}
384
385/* Command-list for the "set/show ravenscar" prefix command. */
386static struct cmd_list_element *set_ravenscar_list;
387static struct cmd_list_element *show_ravenscar_list;
388
389/* Implement the "set ravenscar" prefix command. */
390
391static void
392set_ravenscar_command (char *arg, int from_tty)
393{
394 printf_unfiltered (_(\
395"\"set ravenscar\" must be followed by the name of a setting.\n"));
396 help_list (set_ravenscar_list, "set ravenscar ", -1, gdb_stdout);
397}
398
399/* Implement the "show ravenscar" prefix command. */
400
401static void
402show_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
409static void
410show_ravenscar_task_switching_command (struct ui_file *file, int from_tty,
411 struct cmd_list_element *c,
412 const char *value)
413{
414 if (ravenscar_task_support)
415 fprintf_filtered (file, _("\
b64edec4 416Support for Ravenscar task/thread switching is enabled\n"));
036b1ba8
JB
417 else
418 fprintf_filtered (file, _("\
b64edec4 419Support for Ravenscar task/thread switching is disabled\n"));
036b1ba8
JB
420}
421
8d037db9
JB
422/* Provide a prototype to silence -Wmissing-prototypes. */
423extern void _initialize_ravenscar (void);
424
036b1ba8
JB
425/* Module startup initialization function, automagically called by
426 init.c. */
427
428void
429_initialize_ravenscar (void)
430{
431 init_ravenscar_thread_ops ();
432 base_ptid = null_ptid;
433
434 /* Notice when the inferior is created in order to push the
435 ravenscar ops if needed. */
436 observer_attach_inferior_created (ravenscar_inferior_created);
437
12070676 438 complete_target_initialization (&ravenscar_ops);
036b1ba8
JB
439
440 add_prefix_cmd ("ravenscar", no_class, set_ravenscar_command,
441 _("Prefix command for changing Ravenscar-specific settings"),
442 &set_ravenscar_list, "set ravenscar ", 0, &setlist);
443
444 add_prefix_cmd ("ravenscar", no_class, show_ravenscar_command,
445 _("Prefix command for showing Ravenscar-specific settings"),
04f9d4d0 446 &show_ravenscar_list, "show ravenscar ", 0, &showlist);
036b1ba8
JB
447
448 add_setshow_boolean_cmd ("task-switching", class_obscure,
449 &ravenscar_task_support, _("\
450Enable or disable support for GNAT Ravenscar tasks"), _("\
451Show whether support for GNAT Ravenscar tasks is enabled"),
452 _("\
453Enable or disable support for task/thread switching with the GNAT\n\
454Ravenscar run-time library for bareboard configuration."),
455 NULL, show_ravenscar_task_switching_command,
456 &set_ravenscar_list, &show_ravenscar_list);
457}
This page took 0.35971 seconds and 4 git commands to generate.