X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fravenscar-thread.c;h=0ce712f896863f2fb8af181f477f151ab5d2cc3f;hb=a12ac51333cf97f4da0597d049cc694b4535e7dd;hp=7a80dcf9add19ac44dbfab1954768d090c1355f6;hpb=036b1ba8ec8e194f8772ed00ec6b1126e7dce710;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/ravenscar-thread.c b/gdb/ravenscar-thread.c index 7a80dcf9ad..0ce712f896 100644 --- a/gdb/ravenscar-thread.c +++ b/gdb/ravenscar-thread.c @@ -1,6 +1,6 @@ /* Ada Ravenscar thread support. - Copyright 2004, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2004-2016 Free Software Foundation, Inc. This file is part of GDB. @@ -26,18 +26,14 @@ #include "command.h" #include "ravenscar-thread.h" #include "observer.h" -#include "gdb_string.h" #include "gdbcmd.h" #include "top.h" #include "regcache.h" +#include "objfiles.h" /* If non-null, ravenscar task support is enabled. */ static int ravenscar_task_support = 1; -/* Non-null if the ravenscar thread layer has been pushed on the target - stack. */ -static int ravenscar_is_open = 0; - /* This module's target-specific operations. */ static struct target_ops ravenscar_ops; @@ -48,31 +44,27 @@ static ptid_t base_magic_null_ptid; /* Ptid of the inferior as seen by the process stratum. */ static ptid_t base_ptid; -static const char running_thread_name[] = "running_thread"; +static const char running_thread_name[] = "__gnat_running_thread_table"; static const char known_tasks_name[] = "system__tasking__debug__known_tasks"; +static const char first_task_name[] = "system__tasking__debug__first_task"; -static const char ravenscar_runtime_initializer[] = "system__bb__threads__initialize"; - -static struct observer *update_target_observer = NULL; - -/* Architecture-specific hooks. */ -static struct ravenscar_arch_ops* current_arch_ops; - -static CORE_ADDR read_thread_id (const char *symbol_name); +static const char ravenscar_runtime_initializer[] = + "system__bb__threads__initialize"; -static void ravenscar_find_new_threads (struct target_ops *ops); +static void ravenscar_update_thread_list (struct target_ops *ops); static ptid_t ravenscar_running_thread (void); -static char *ravenscar_extra_thread_info (struct thread_info *tp); +static char *ravenscar_extra_thread_info (struct target_ops *self, + struct thread_info *tp); static int ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid); static void ravenscar_fetch_registers (struct target_ops *ops, struct regcache *regcache, int regnum); static void ravenscar_store_registers (struct target_ops *ops, struct regcache *regcache, int regnum); -static void ravenscar_prepare_to_store (struct regcache *regcache); -static void ravenscar_initialize (char *name, int from_tty); +static void ravenscar_prepare_to_store (struct target_ops *self, + struct regcache *regcache); static void ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step, - enum target_signal siggnal); + enum gdb_signal siggnal); static void ravenscar_mourn_inferior (struct target_ops *ops); static void ravenscar_update_inferior_ptid (void); static int has_ravenscar_runtime (void); @@ -99,28 +91,51 @@ ravenscar_update_inferior_ptid (void) gdb_assert (!ptid_equal (inferior_ptid, null_ptid)); /* The running thread may not have been added to - system.tasking.debug's list yet; so ravenscar_find_new_threads + system.tasking.debug's list yet; so ravenscar_update_thread_list may not always add it to the thread list. Add it here. */ if (!find_thread_ptid (inferior_ptid)) add_thread (inferior_ptid); } +/* The Ravenscar Runtime exports a symbol which contains the ID of + the thread that is currently running. Try to locate that symbol + and return its associated minimal symbol. + Return NULL if not found. */ + +static struct bound_minimal_symbol +get_running_thread_msymbol (void) +{ + struct bound_minimal_symbol msym; + + msym = lookup_minimal_symbol (running_thread_name, NULL, NULL); + if (!msym.minsym) + /* Older versions of the GNAT runtime were using a different + (less ideal) name for the symbol where the active thread ID + is stored. If we couldn't find the symbol using the latest + name, then try the old one. */ + msym = lookup_minimal_symbol ("running_thread", NULL, NULL); + + return msym; +} + /* Return True if the Ada Ravenscar run-time can be found in the application. */ static int has_ravenscar_runtime (void) { - struct minimal_symbol *msym_ravenscar_runtime_initializer = + struct bound_minimal_symbol msym_ravenscar_runtime_initializer = lookup_minimal_symbol (ravenscar_runtime_initializer, NULL, NULL); - struct minimal_symbol *msym_known_tasks = + struct bound_minimal_symbol msym_known_tasks = lookup_minimal_symbol (known_tasks_name, NULL, NULL); - struct minimal_symbol *msym_running_thread = - lookup_minimal_symbol (running_thread_name, NULL, NULL); - - return (msym_ravenscar_runtime_initializer - && msym_known_tasks - && msym_running_thread); + struct bound_minimal_symbol msym_first_task = + lookup_minimal_symbol (first_task_name, NULL, NULL); + struct bound_minimal_symbol msym_running_thread + = get_running_thread_msymbol (); + + return (msym_ravenscar_runtime_initializer.minsym + && (msym_known_tasks.minsym || msym_first_task.minsym) + && msym_running_thread.minsym); } /* Return True if the Ada Ravenscar run-time can be found in the @@ -132,40 +147,34 @@ ravenscar_runtime_initialized (void) return (!(ptid_equal (ravenscar_running_thread (), null_ptid))); } -/* Read the thread ID whose symbol name is SYMBOL_NAME. */ +/* Return the ID of the thread that is currently running. + Return 0 if the ID could not be determined. */ static CORE_ADDR -read_thread_id (const char *symbol_name) +get_running_thread_id (void) { - const struct minimal_symbol *object_msym = - lookup_minimal_symbol (symbol_name, NULL, NULL); + struct bound_minimal_symbol object_msym = get_running_thread_msymbol (); int object_size; int buf_size; - char *buf; + gdb_byte *buf; CORE_ADDR object_addr; struct type *builtin_type_void_data_ptr = - builtin_type (target_gdbarch)->builtin_data_ptr; + builtin_type (target_gdbarch ())->builtin_data_ptr; - if (!object_msym) + if (!object_msym.minsym) return 0; - object_addr = SYMBOL_VALUE_ADDRESS (object_msym); + object_addr = BMSYMBOL_VALUE_ADDRESS (object_msym); object_size = TYPE_LENGTH (builtin_type_void_data_ptr); buf_size = object_size; - buf = alloca (buf_size); + buf = (gdb_byte *) alloca (buf_size); read_memory (object_addr, buf, buf_size); return extract_typed_address (buf, builtin_type_void_data_ptr); } -static void -ravenscar_close (int quitting) -{ - ravenscar_is_open = 0; -} - static void ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step, - enum target_signal siggnal) + enum gdb_signal siggnal) { struct target_ops *beneath = find_target_beneath (ops); @@ -182,8 +191,19 @@ ravenscar_wait (struct target_ops *ops, ptid_t ptid, inferior_ptid = base_ptid; beneath->to_wait (beneath, base_ptid, status, 0); - ravenscar_find_new_threads (ops); - ravenscar_update_inferior_ptid (); + /* Find any new threads that might have been created, and update + inferior_ptid to the active thread. + + Only do it if the program is still alive, though. Otherwise, + this causes problems when debugging through the remote protocol, + because we might try switching threads (and thus sending packets) + after the remote has disconnected. */ + if (status->kind != TARGET_WAITKIND_EXITED + && status->kind != TARGET_WAITKIND_SIGNALLED) + { + ravenscar_update_thread_list (ops); + ravenscar_update_inferior_ptid (); + } return inferior_ptid; } @@ -198,9 +218,9 @@ ravenscar_add_thread (struct ada_task_info *task) } static void -ravenscar_find_new_threads (struct target_ops *ops) +ravenscar_update_thread_list (struct target_ops *ops) { - ada_build_task_list (0); + ada_build_task_list (); /* Do not clear the thread list before adding the Ada task, to keep the thread that the process stratum has included into it @@ -213,7 +233,7 @@ ravenscar_find_new_threads (struct target_ops *ops) static ptid_t ravenscar_running_thread (void) { - CORE_ADDR tid = read_thread_id (running_thread_name); + CORE_ADDR tid = get_running_thread_id (); if (tid == 0) return null_ptid; @@ -222,7 +242,7 @@ ravenscar_running_thread (void) } static char * -ravenscar_extra_thread_info (struct thread_info *tp) +ravenscar_extra_thread_info (struct target_ops *self, struct thread_info *tp) { return "Ravenscar task"; } @@ -254,7 +274,13 @@ ravenscar_fetch_registers (struct target_ops *ops, || ptid_equal (inferior_ptid, ravenscar_running_thread ())) beneath->to_fetch_registers (beneath, regcache, regnum); else - current_arch_ops->to_fetch_registers (regcache, regnum); + { + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct ravenscar_arch_ops *arch_ops + = gdbarch_ravenscar_ops (gdbarch); + + arch_ops->to_fetch_registers (regcache, regnum); + } } static void @@ -268,26 +294,39 @@ ravenscar_store_registers (struct target_ops *ops, || ptid_equal (inferior_ptid, ravenscar_running_thread ())) beneath->to_store_registers (beneath, regcache, regnum); else - current_arch_ops->to_store_registers (regcache, regnum); + { + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct ravenscar_arch_ops *arch_ops + = gdbarch_ravenscar_ops (gdbarch); + + arch_ops->to_store_registers (regcache, regnum); + } } static void -ravenscar_prepare_to_store (struct regcache *regcache) +ravenscar_prepare_to_store (struct target_ops *self, + struct regcache *regcache) { - struct target_ops *beneath = find_target_beneath (&ravenscar_ops); + struct target_ops *beneath = find_target_beneath (self); if (!ravenscar_runtime_initialized () || ptid_equal (inferior_ptid, base_magic_null_ptid) || ptid_equal (inferior_ptid, ravenscar_running_thread ())) - beneath->to_prepare_to_store (regcache); + beneath->to_prepare_to_store (beneath, regcache); else - current_arch_ops->to_prepare_to_store (regcache); + { + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct ravenscar_arch_ops *arch_ops + = gdbarch_ravenscar_ops (gdbarch); + + arch_ops->to_prepare_to_store (regcache); + } } static void ravenscar_mourn_inferior (struct target_ops *ops) { - struct target_ops *beneath = find_target_beneath (&ravenscar_ops); + struct target_ops *beneath = find_target_beneath (ops); base_ptid = null_ptid; beneath->to_mourn_inferior (beneath); @@ -299,38 +338,20 @@ ravenscar_mourn_inferior (struct target_ops *ops) static void ravenscar_inferior_created (struct target_ops *target, int from_tty) { - if (ravenscar_task_support - && has_ravenscar_runtime ()) - ravenscar_initialize (NULL, 0); -} - -void -ravenscar_register_arch_ops (struct ravenscar_arch_ops *ops) -{ - /* FIXME: To be clean, we would need to handle a list of - architectures, just like in remote-wtx-hw.c. However, for now the - only Ravenscar run-time for bare board that is implemented in - GNAT is for only one architecture: erc32-elf. So no need to care about - that for now...*/ - current_arch_ops = ops; -} - -/* Initialize Ravenscar support. */ + struct ravenscar_arch_ops *ops; -static void -ravenscar_initialize (char *name, int from_tty) -{ - if (ravenscar_is_open) + if (!ravenscar_task_support + || gdbarch_ravenscar_ops (target_gdbarch ()) == NULL + || !has_ravenscar_runtime ()) return; base_magic_null_ptid = inferior_ptid; ravenscar_update_inferior_ptid (); push_target (&ravenscar_ops); - ravenscar_is_open = 1; } static ptid_t -ravenscar_get_ada_task_ptid (long lwp, long thread) +ravenscar_get_ada_task_ptid (struct target_ops *self, long lwp, long thread) { return ptid_build (ptid_get_pid (base_ptid), 0, thread); } @@ -341,14 +362,13 @@ init_ravenscar_thread_ops (void) ravenscar_ops.to_shortname = "ravenscar"; ravenscar_ops.to_longname = "Ravenscar tasks."; ravenscar_ops.to_doc = "Ravenscar tasks support."; - ravenscar_ops.to_close = ravenscar_close; ravenscar_ops.to_resume = ravenscar_resume; ravenscar_ops.to_wait = ravenscar_wait; ravenscar_ops.to_fetch_registers = ravenscar_fetch_registers; ravenscar_ops.to_store_registers = ravenscar_store_registers; ravenscar_ops.to_prepare_to_store = ravenscar_prepare_to_store; ravenscar_ops.to_thread_alive = ravenscar_thread_alive; - ravenscar_ops.to_find_new_threads = ravenscar_find_new_threads; + ravenscar_ops.to_update_thread_list = ravenscar_update_thread_list; ravenscar_ops.to_pid_to_str = ravenscar_pid_to_str; ravenscar_ops.to_extra_thread_info = ravenscar_extra_thread_info; ravenscar_ops.to_get_ada_task_ptid = ravenscar_get_ada_task_ptid; @@ -373,7 +393,7 @@ set_ravenscar_command (char *arg, int from_tty) { printf_unfiltered (_(\ "\"set ravenscar\" must be followed by the name of a setting.\n")); - help_list (set_ravenscar_list, "set ravenscar ", -1, gdb_stdout); + help_list (set_ravenscar_list, "set ravenscar ", all_commands, gdb_stdout); } /* Implement the "show ravenscar" prefix command. */ @@ -393,12 +413,15 @@ show_ravenscar_task_switching_command (struct ui_file *file, int from_tty, { if (ravenscar_task_support) fprintf_filtered (file, _("\ -Support for Ravenscar task/thread switching is enabled")); +Support for Ravenscar task/thread switching is enabled\n")); else fprintf_filtered (file, _("\ -Support for Ravenscar task/thread switching is disabled")); +Support for Ravenscar task/thread switching is disabled\n")); } +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern void _initialize_ravenscar (void); + /* Module startup initialization function, automagically called by init.c. */ @@ -412,7 +435,7 @@ _initialize_ravenscar (void) ravenscar ops if needed. */ observer_attach_inferior_created (ravenscar_inferior_created); - add_target (&ravenscar_ops); + complete_target_initialization (&ravenscar_ops); add_prefix_cmd ("ravenscar", no_class, set_ravenscar_command, _("Prefix command for changing Ravenscar-specific settings"), @@ -420,7 +443,7 @@ _initialize_ravenscar (void) add_prefix_cmd ("ravenscar", no_class, show_ravenscar_command, _("Prefix command for showing Ravenscar-specific settings"), - &show_ravenscar_list, "set ravenscar ", 0, &showlist); + &show_ravenscar_list, "show ravenscar ", 0, &showlist); add_setshow_boolean_cmd ("task-switching", class_obscure, &ravenscar_task_support, _("\