GDB (API)
/home/stan/gdb/src/gdb/ravenscar-thread.c
Go to the documentation of this file.
00001 /* Ada Ravenscar thread support.
00002 
00003    Copyright (C) 2004-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "gdbcore.h"
00022 #include "gdbthread.h"
00023 #include "ada-lang.h"
00024 #include "target.h"
00025 #include "inferior.h"
00026 #include "command.h"
00027 #include "ravenscar-thread.h"
00028 #include "observer.h"
00029 #include "gdb_string.h"
00030 #include "gdbcmd.h"
00031 #include "top.h"
00032 #include "regcache.h"
00033 
00034 /* If non-null, ravenscar task support is enabled.  */
00035 static int ravenscar_task_support = 1;
00036 
00037 /* This module's target-specific operations.  */
00038 static struct target_ops ravenscar_ops;
00039 
00040 /* Some base target uses a special value for the null PID (exempli gratia
00041    remote).  */
00042 static ptid_t base_magic_null_ptid;
00043 
00044 /* Ptid of the inferior as seen by the process stratum.  */
00045 static ptid_t base_ptid;
00046 
00047 static const char running_thread_name[] = "__gnat_running_thread_table";
00048 
00049 static const char known_tasks_name[] = "system__tasking__debug__known_tasks";
00050 static const char first_task_name[] = "system__tasking__debug__first_task";
00051 
00052 static const char ravenscar_runtime_initializer[] =
00053   "system__bb__threads__initialize";
00054 
00055 static struct observer *update_target_observer = NULL;
00056 
00057 static void ravenscar_find_new_threads (struct target_ops *ops);
00058 static ptid_t ravenscar_running_thread (void);
00059 static char *ravenscar_extra_thread_info (struct thread_info *tp);
00060 static int ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid);
00061 static void ravenscar_fetch_registers (struct target_ops *ops,
00062                                        struct regcache *regcache, int regnum);
00063 static void ravenscar_store_registers (struct target_ops *ops,
00064                                        struct regcache *regcache, int regnum);
00065 static void ravenscar_prepare_to_store (struct regcache *regcache);
00066 static void ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
00067                               enum gdb_signal siggnal);
00068 static void ravenscar_mourn_inferior (struct target_ops *ops);
00069 static void ravenscar_update_inferior_ptid (void);
00070 static int has_ravenscar_runtime (void);
00071 static int ravenscar_runtime_initialized (void);
00072 static void ravenscar_inferior_created (struct target_ops *target,
00073                                         int from_tty);
00074 
00075 /* Fetch the ravenscar running thread from target memory and
00076    update inferior_ptid accordingly.  */
00077 
00078 static void
00079 ravenscar_update_inferior_ptid (void)
00080 {
00081   base_ptid = inferior_ptid;
00082 
00083   /* If the runtime has not been initialized yet, the inferior_ptid is
00084      the only ptid that there is.  */
00085   if (!ravenscar_runtime_initialized ())
00086     return;
00087 
00088   /* Make sure we set base_ptid before calling ravenscar_running_thread
00089      as the latter relies on it.  */
00090   inferior_ptid = ravenscar_running_thread ();
00091   gdb_assert (!ptid_equal (inferior_ptid, null_ptid));
00092 
00093   /* The running thread may not have been added to
00094      system.tasking.debug's list yet; so ravenscar_find_new_threads
00095      may not always add it to the thread list.  Add it here.  */
00096   if (!find_thread_ptid (inferior_ptid))
00097     add_thread (inferior_ptid);
00098 }
00099 
00100 /* The Ravenscar Runtime exports a symbol which contains the ID of
00101    the thread that is currently running.  Try to locate that symbol
00102    and return its associated minimal symbol.
00103    Return NULL if not found.  */
00104 
00105 static struct minimal_symbol *
00106 get_running_thread_msymbol (void)
00107 {
00108   struct minimal_symbol *msym;
00109 
00110   msym = lookup_minimal_symbol (running_thread_name, NULL, NULL);
00111   if (!msym)
00112     /* Older versions of the GNAT runtime were using a different
00113        (less ideal) name for the symbol where the active thread ID
00114        is stored.  If we couldn't find the symbol using the latest
00115        name, then try the old one.  */
00116     msym = lookup_minimal_symbol ("running_thread", NULL, NULL);
00117 
00118   return msym;
00119 }
00120 
00121 /* Return True if the Ada Ravenscar run-time can be found in the
00122    application.  */
00123 
00124 static int
00125 has_ravenscar_runtime (void)
00126 {
00127   struct minimal_symbol *msym_ravenscar_runtime_initializer =
00128     lookup_minimal_symbol (ravenscar_runtime_initializer, NULL, NULL);
00129   struct minimal_symbol *msym_known_tasks =
00130     lookup_minimal_symbol (known_tasks_name, NULL, NULL);
00131   struct minimal_symbol *msym_first_task =
00132     lookup_minimal_symbol (first_task_name, NULL, NULL);
00133   struct minimal_symbol *msym_running_thread = get_running_thread_msymbol ();
00134 
00135   return (msym_ravenscar_runtime_initializer
00136           && (msym_known_tasks || msym_first_task)
00137           && msym_running_thread);
00138 }
00139 
00140 /* Return True if the Ada Ravenscar run-time can be found in the
00141    application, and if it has been initialized on target.  */
00142 
00143 static int
00144 ravenscar_runtime_initialized (void)
00145 {
00146   return (!(ptid_equal (ravenscar_running_thread (), null_ptid)));
00147 }
00148 
00149 /* Return the ID of the thread that is currently running.
00150    Return 0 if the ID could not be determined.  */
00151 
00152 static CORE_ADDR
00153 get_running_thread_id (void)
00154 {
00155   const struct minimal_symbol *object_msym = get_running_thread_msymbol ();
00156   int object_size;
00157   int buf_size;
00158   gdb_byte *buf;
00159   CORE_ADDR object_addr;
00160   struct type *builtin_type_void_data_ptr =
00161     builtin_type (target_gdbarch ())->builtin_data_ptr;
00162 
00163   if (!object_msym)
00164     return 0;
00165 
00166   object_addr = SYMBOL_VALUE_ADDRESS (object_msym);
00167   object_size = TYPE_LENGTH (builtin_type_void_data_ptr);
00168   buf_size = object_size;
00169   buf = alloca (buf_size);
00170   read_memory (object_addr, buf, buf_size);
00171   return extract_typed_address (buf, builtin_type_void_data_ptr);
00172 }
00173 
00174 static void
00175 ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
00176                   enum gdb_signal siggnal)
00177 {
00178   struct target_ops *beneath = find_target_beneath (ops);
00179 
00180   inferior_ptid = base_ptid;
00181   beneath->to_resume (beneath, base_ptid, step, siggnal);
00182 }
00183 
00184 static ptid_t
00185 ravenscar_wait (struct target_ops *ops, ptid_t ptid,
00186                 struct target_waitstatus *status,
00187                 int options)
00188 {
00189   struct target_ops *beneath = find_target_beneath (ops);
00190 
00191   inferior_ptid = base_ptid;
00192   beneath->to_wait (beneath, base_ptid, status, 0);
00193   /* Find any new threads that might have been created, and update
00194      inferior_ptid to the active thread.
00195 
00196      Only do it if the program is still alive, though.  Otherwise,
00197      this causes problems when debugging through the remote protocol,
00198      because we might try switching threads (and thus sending packets)
00199      after the remote has disconnected.  */
00200   if (status->kind != TARGET_WAITKIND_EXITED
00201       && status->kind != TARGET_WAITKIND_SIGNALLED)
00202     {
00203       ravenscar_find_new_threads (ops);
00204       ravenscar_update_inferior_ptid ();
00205     }
00206   return inferior_ptid;
00207 }
00208 
00209 /* Add the thread associated to the given TASK to the thread list
00210    (if the thread has already been added, this is a no-op).  */
00211 
00212 static void
00213 ravenscar_add_thread (struct ada_task_info *task)
00214 {
00215   if (find_thread_ptid (task->ptid) == NULL)
00216     add_thread (task->ptid);
00217 }
00218 
00219 static void
00220 ravenscar_find_new_threads (struct target_ops *ops)
00221 {
00222   ada_build_task_list ();
00223 
00224   /* Do not clear the thread list before adding the Ada task, to keep
00225      the thread that the process stratum has included into it
00226      (base_ptid) and the running thread, that may not have been included
00227      to system.tasking.debug's list yet.  */
00228 
00229   iterate_over_live_ada_tasks (ravenscar_add_thread);
00230 }
00231 
00232 static ptid_t
00233 ravenscar_running_thread (void)
00234 {
00235   CORE_ADDR tid = get_running_thread_id ();
00236 
00237   if (tid == 0)
00238     return null_ptid;
00239   else
00240     return ptid_build (ptid_get_pid (base_ptid), 0, tid);
00241 }
00242 
00243 static char *
00244 ravenscar_extra_thread_info (struct thread_info *tp)
00245 {
00246   return "Ravenscar task";
00247 }
00248 
00249 static int
00250 ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid)
00251 {
00252   /* Ravenscar tasks are non-terminating.  */
00253   return 1;
00254 }
00255 
00256 static char *
00257 ravenscar_pid_to_str (struct target_ops *ops, ptid_t ptid)
00258 {
00259   static char buf[30];
00260 
00261   snprintf (buf, sizeof (buf), "Thread %#x", (int) ptid_get_tid (ptid));
00262   return buf;
00263 }
00264 
00265 static void
00266 ravenscar_fetch_registers (struct target_ops *ops,
00267                            struct regcache *regcache, int regnum)
00268 {
00269   struct target_ops *beneath = find_target_beneath (ops);
00270 
00271   if (!ravenscar_runtime_initialized ()
00272       || ptid_equal (inferior_ptid, base_magic_null_ptid)
00273       || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
00274     beneath->to_fetch_registers (beneath, regcache, regnum);
00275   else
00276     {
00277       struct gdbarch *gdbarch = get_regcache_arch (regcache);
00278       struct ravenscar_arch_ops *arch_ops
00279         = gdbarch_ravenscar_ops (gdbarch);
00280 
00281       arch_ops->to_fetch_registers (regcache, regnum);
00282     }
00283 }
00284 
00285 static void
00286 ravenscar_store_registers (struct target_ops *ops,
00287                            struct regcache *regcache, int regnum)
00288 {
00289   struct target_ops *beneath = find_target_beneath (ops);
00290 
00291   if (!ravenscar_runtime_initialized ()
00292       || ptid_equal (inferior_ptid, base_magic_null_ptid)
00293       || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
00294     beneath->to_store_registers (beneath, regcache, regnum);
00295   else
00296     {
00297       struct gdbarch *gdbarch = get_regcache_arch (regcache);
00298       struct ravenscar_arch_ops *arch_ops
00299         = gdbarch_ravenscar_ops (gdbarch);
00300 
00301       arch_ops->to_store_registers (regcache, regnum);
00302     }
00303 }
00304 
00305 static void
00306 ravenscar_prepare_to_store (struct regcache *regcache)
00307 {
00308   struct target_ops *beneath = find_target_beneath (&ravenscar_ops);
00309 
00310   if (!ravenscar_runtime_initialized ()
00311       || ptid_equal (inferior_ptid, base_magic_null_ptid)
00312       || ptid_equal (inferior_ptid, ravenscar_running_thread ()))
00313     beneath->to_prepare_to_store (regcache);
00314   else
00315     {
00316       struct gdbarch *gdbarch = get_regcache_arch (regcache);
00317       struct ravenscar_arch_ops *arch_ops
00318         = gdbarch_ravenscar_ops (gdbarch);
00319 
00320       arch_ops->to_prepare_to_store (regcache);
00321     }
00322 }
00323 
00324 static void
00325 ravenscar_mourn_inferior (struct target_ops *ops)
00326 {
00327   struct target_ops *beneath = find_target_beneath (&ravenscar_ops);
00328 
00329   base_ptid = null_ptid;
00330   beneath->to_mourn_inferior (beneath);
00331   unpush_target (&ravenscar_ops);
00332 }
00333 
00334 /* Observer on inferior_created: push ravenscar thread stratum if needed.  */
00335 
00336 static void
00337 ravenscar_inferior_created (struct target_ops *target, int from_tty)
00338 {
00339   struct ravenscar_arch_ops *ops;
00340 
00341   if (!ravenscar_task_support
00342       || gdbarch_ravenscar_ops (current_inferior ()->gdbarch) == NULL
00343       || !has_ravenscar_runtime ())
00344     return;
00345 
00346   base_magic_null_ptid = inferior_ptid;
00347   ravenscar_update_inferior_ptid ();
00348   push_target (&ravenscar_ops);
00349 }
00350 
00351 static ptid_t
00352 ravenscar_get_ada_task_ptid (long lwp, long thread)
00353 {
00354   return ptid_build (ptid_get_pid (base_ptid), 0, thread);
00355 }
00356 
00357 static void
00358 init_ravenscar_thread_ops (void)
00359 {
00360   ravenscar_ops.to_shortname = "ravenscar";
00361   ravenscar_ops.to_longname = "Ravenscar tasks.";
00362   ravenscar_ops.to_doc = "Ravenscar tasks support.";
00363   ravenscar_ops.to_resume = ravenscar_resume;
00364   ravenscar_ops.to_wait = ravenscar_wait;
00365   ravenscar_ops.to_fetch_registers = ravenscar_fetch_registers;
00366   ravenscar_ops.to_store_registers = ravenscar_store_registers;
00367   ravenscar_ops.to_prepare_to_store = ravenscar_prepare_to_store;
00368   ravenscar_ops.to_thread_alive = ravenscar_thread_alive;
00369   ravenscar_ops.to_find_new_threads = ravenscar_find_new_threads;
00370   ravenscar_ops.to_pid_to_str = ravenscar_pid_to_str;
00371   ravenscar_ops.to_extra_thread_info = ravenscar_extra_thread_info;
00372   ravenscar_ops.to_get_ada_task_ptid = ravenscar_get_ada_task_ptid;
00373   ravenscar_ops.to_mourn_inferior = ravenscar_mourn_inferior;
00374   ravenscar_ops.to_has_all_memory = default_child_has_all_memory;
00375   ravenscar_ops.to_has_memory = default_child_has_memory;
00376   ravenscar_ops.to_has_stack = default_child_has_stack;
00377   ravenscar_ops.to_has_registers = default_child_has_registers;
00378   ravenscar_ops.to_has_execution = default_child_has_execution;
00379   ravenscar_ops.to_stratum = thread_stratum;
00380   ravenscar_ops.to_magic = OPS_MAGIC;
00381 }
00382 
00383 /* Command-list for the "set/show ravenscar" prefix command.  */
00384 static struct cmd_list_element *set_ravenscar_list;
00385 static struct cmd_list_element *show_ravenscar_list;
00386 
00387 /* Implement the "set ravenscar" prefix command.  */
00388 
00389 static void
00390 set_ravenscar_command (char *arg, int from_tty)
00391 {
00392   printf_unfiltered (_(\
00393 "\"set ravenscar\" must be followed by the name of a setting.\n"));
00394   help_list (set_ravenscar_list, "set ravenscar ", -1, gdb_stdout);
00395 }
00396 
00397 /* Implement the "show ravenscar" prefix command.  */
00398 
00399 static void
00400 show_ravenscar_command (char *args, int from_tty)
00401 {
00402   cmd_show_list (show_ravenscar_list, from_tty, "");
00403 }
00404 
00405 /* Implement the "show ravenscar task-switching" command.  */
00406 
00407 static void
00408 show_ravenscar_task_switching_command (struct ui_file *file, int from_tty,
00409                                        struct cmd_list_element *c,
00410                                        const char *value)
00411 {
00412   if (ravenscar_task_support)
00413     fprintf_filtered (file, _("\
00414 Support for Ravenscar task/thread switching is enabled\n"));
00415   else
00416     fprintf_filtered (file, _("\
00417 Support for Ravenscar task/thread switching is disabled\n"));
00418 }
00419 
00420 /* Provide a prototype to silence -Wmissing-prototypes.  */
00421 extern void _initialize_ravenscar (void);
00422 
00423 /* Module startup initialization function, automagically called by
00424    init.c.  */
00425 
00426 void
00427 _initialize_ravenscar (void)
00428 {
00429   init_ravenscar_thread_ops ();
00430   base_ptid = null_ptid;
00431 
00432   /* Notice when the inferior is created in order to push the
00433      ravenscar ops if needed.  */
00434   observer_attach_inferior_created (ravenscar_inferior_created);
00435 
00436   complete_target_initialization (&ravenscar_ops);
00437 
00438   add_prefix_cmd ("ravenscar", no_class, set_ravenscar_command,
00439                   _("Prefix command for changing Ravenscar-specific settings"),
00440                   &set_ravenscar_list, "set ravenscar ", 0, &setlist);
00441 
00442   add_prefix_cmd ("ravenscar", no_class, show_ravenscar_command,
00443                   _("Prefix command for showing Ravenscar-specific settings"),
00444                   &show_ravenscar_list, "show ravenscar ", 0, &showlist);
00445 
00446   add_setshow_boolean_cmd ("task-switching", class_obscure,
00447                            &ravenscar_task_support, _("\
00448 Enable or disable support for GNAT Ravenscar tasks"), _("\
00449 Show whether support for GNAT Ravenscar tasks is enabled"),
00450                            _("\
00451 Enable or disable support for task/thread switching with the GNAT\n\
00452 Ravenscar run-time library for bareboard configuration."),
00453                            NULL, show_ravenscar_task_switching_command,
00454                            &set_ravenscar_list, &show_ravenscar_list);
00455 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines