GDB (API)
|
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 }