gdb.base/sym-file.exp: clean up test messages a bit.
[deliverable/binutils-gdb.git] / gdb / ravenscar-thread.c
1 /* Ada Ravenscar thread support.
2
3 Copyright (C) 2004-2014 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 <string.h>
30 #include "gdbcmd.h"
31 #include "top.h"
32 #include "regcache.h"
33 #include "objfiles.h"
34
35 /* If non-null, ravenscar task support is enabled. */
36 static int ravenscar_task_support = 1;
37
38 /* This module's target-specific operations. */
39 static struct target_ops ravenscar_ops;
40
41 /* Some base target uses a special value for the null PID (exempli gratia
42 remote). */
43 static ptid_t base_magic_null_ptid;
44
45 /* Ptid of the inferior as seen by the process stratum. */
46 static ptid_t base_ptid;
47
48 static const char running_thread_name[] = "__gnat_running_thread_table";
49
50 static const char known_tasks_name[] = "system__tasking__debug__known_tasks";
51 static const char first_task_name[] = "system__tasking__debug__first_task";
52
53 static const char ravenscar_runtime_initializer[] =
54 "system__bb__threads__initialize";
55
56 static void ravenscar_find_new_threads (struct target_ops *ops);
57 static ptid_t ravenscar_running_thread (void);
58 static char *ravenscar_extra_thread_info (struct target_ops *self,
59 struct thread_info *tp);
60 static int ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid);
61 static void ravenscar_fetch_registers (struct target_ops *ops,
62 struct regcache *regcache, int regnum);
63 static void ravenscar_store_registers (struct target_ops *ops,
64 struct regcache *regcache, int regnum);
65 static void ravenscar_prepare_to_store (struct target_ops *self,
66 struct regcache *regcache);
67 static void ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
68 enum gdb_signal siggnal);
69 static void ravenscar_mourn_inferior (struct target_ops *ops);
70 static void ravenscar_update_inferior_ptid (void);
71 static int has_ravenscar_runtime (void);
72 static int ravenscar_runtime_initialized (void);
73 static 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
79 static void
80 ravenscar_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
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
106 static struct bound_minimal_symbol
107 get_running_thread_msymbol (void)
108 {
109 struct bound_minimal_symbol msym;
110
111 msym = lookup_minimal_symbol (running_thread_name, NULL, NULL);
112 if (!msym.minsym)
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
122 /* Return True if the Ada Ravenscar run-time can be found in the
123 application. */
124
125 static int
126 has_ravenscar_runtime (void)
127 {
128 struct bound_minimal_symbol msym_ravenscar_runtime_initializer =
129 lookup_minimal_symbol (ravenscar_runtime_initializer, NULL, NULL);
130 struct bound_minimal_symbol msym_known_tasks =
131 lookup_minimal_symbol (known_tasks_name, NULL, NULL);
132 struct bound_minimal_symbol msym_first_task =
133 lookup_minimal_symbol (first_task_name, NULL, NULL);
134 struct bound_minimal_symbol msym_running_thread
135 = get_running_thread_msymbol ();
136
137 return (msym_ravenscar_runtime_initializer.minsym
138 && (msym_known_tasks.minsym || msym_first_task.minsym)
139 && msym_running_thread.minsym);
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
145 static int
146 ravenscar_runtime_initialized (void)
147 {
148 return (!(ptid_equal (ravenscar_running_thread (), null_ptid)));
149 }
150
151 /* Return the ID of the thread that is currently running.
152 Return 0 if the ID could not be determined. */
153
154 static CORE_ADDR
155 get_running_thread_id (void)
156 {
157 struct bound_minimal_symbol object_msym = get_running_thread_msymbol ();
158 int object_size;
159 int buf_size;
160 gdb_byte *buf;
161 CORE_ADDR object_addr;
162 struct type *builtin_type_void_data_ptr =
163 builtin_type (target_gdbarch ())->builtin_data_ptr;
164
165 if (!object_msym.minsym)
166 return 0;
167
168 object_addr = BMSYMBOL_VALUE_ADDRESS (object_msym);
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
176 static void
177 ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
178 enum gdb_signal siggnal)
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
186 static ptid_t
187 ravenscar_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);
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 }
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
214 static void
215 ravenscar_add_thread (struct ada_task_info *task)
216 {
217 if (find_thread_ptid (task->ptid) == NULL)
218 add_thread (task->ptid);
219 }
220
221 static void
222 ravenscar_find_new_threads (struct target_ops *ops)
223 {
224 ada_build_task_list ();
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
234 static ptid_t
235 ravenscar_running_thread (void)
236 {
237 CORE_ADDR tid = get_running_thread_id ();
238
239 if (tid == 0)
240 return null_ptid;
241 else
242 return ptid_build (ptid_get_pid (base_ptid), 0, tid);
243 }
244
245 static char *
246 ravenscar_extra_thread_info (struct target_ops *self, struct thread_info *tp)
247 {
248 return "Ravenscar task";
249 }
250
251 static int
252 ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid)
253 {
254 /* Ravenscar tasks are non-terminating. */
255 return 1;
256 }
257
258 static char *
259 ravenscar_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
267 static void
268 ravenscar_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
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 }
285 }
286
287 static void
288 ravenscar_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
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 }
305 }
306
307 static void
308 ravenscar_prepare_to_store (struct target_ops *self,
309 struct regcache *regcache)
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 ()))
316 beneath->to_prepare_to_store (beneath, regcache);
317 else
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 }
325 }
326
327 static void
328 ravenscar_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
339 static void
340 ravenscar_inferior_created (struct target_ops *target, int from_tty)
341 {
342 struct ravenscar_arch_ops *ops;
343
344 if (!ravenscar_task_support
345 || gdbarch_ravenscar_ops (current_inferior ()->gdbarch) == NULL
346 || !has_ravenscar_runtime ())
347 return;
348
349 base_magic_null_ptid = inferior_ptid;
350 ravenscar_update_inferior_ptid ();
351 push_target (&ravenscar_ops);
352 }
353
354 static ptid_t
355 ravenscar_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
356 {
357 return ptid_build (ptid_get_pid (base_ptid), 0, thread);
358 }
359
360 static void
361 init_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.";
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. */
387 static struct cmd_list_element *set_ravenscar_list;
388 static struct cmd_list_element *show_ravenscar_list;
389
390 /* Implement the "set ravenscar" prefix command. */
391
392 static void
393 set_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
402 static void
403 show_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
410 static void
411 show_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, _("\
417 Support for Ravenscar task/thread switching is enabled\n"));
418 else
419 fprintf_filtered (file, _("\
420 Support for Ravenscar task/thread switching is disabled\n"));
421 }
422
423 /* Provide a prototype to silence -Wmissing-prototypes. */
424 extern void _initialize_ravenscar (void);
425
426 /* Module startup initialization function, automagically called by
427 init.c. */
428
429 void
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
439 complete_target_initialization (&ravenscar_ops);
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"),
447 &show_ravenscar_list, "show ravenscar ", 0, &showlist);
448
449 add_setshow_boolean_cmd ("task-switching", class_obscure,
450 &ravenscar_task_support, _("\
451 Enable or disable support for GNAT Ravenscar tasks"), _("\
452 Show whether support for GNAT Ravenscar tasks is enabled"),
453 _("\
454 Enable or disable support for task/thread switching with the GNAT\n\
455 Ravenscar 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.046055 seconds and 4 git commands to generate.