From 87273c713f0e22999692252d3dcdbb5613ab5729 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Tue, 23 Jan 1996 21:06:34 +0000 Subject: [PATCH] * symfile.c (auto_solib_add): Renamed from auto_solib_add_at_startup. All references changed. * breakpoint.c (bpstat_what): Add shlib_event to the class types. Update state table. Reformat so that it's still readable. When we hit the shlib_event breakpoint, set the calss of shlib_event. (breakpoint_1): Add "shlib events" as a breakpoint type. Print the shlib_event breakpoint like other breakpoints. (create_solib_event_breakpoint): New function. (breakpoint_re_set_one): Handle solib_event breakpoints. * breakpoint.h (enum bytype): Add bp_shlib_event breakpoint type. (enum bpstat_what_main_action): Add BPSTAT_WHAT_CHECK_SHLIBS action. (create_solib_event_breakpoint): Declare. * infrun.c (wait_for_inferior): Handle CHECK_SHLIBS bpstat. (normal_stop): Inform the user when the inferior stoped due to a shared library event. (_initialize_infrun): Add new set/show variable "stop_on-solib-events" to control whether or not gdb continues the inferior or stops it when a shared library event occurs. * minsyms.c (lookup_minimal_symbol_solib_trampoline): New function. * somsolib.c (TODO list): Update. (som_solib_create_inferior_hook): Arrange for gdb to be notified when significant shared library events occur. * hppa-tdep.c (find_unwind_entry): No longer static. First cut at the machine independent changes for 7363. Also includes code to automatically track shl_load/shl_unload calls on hpux. --- gdb/ChangeLog | 27 ++++++++++++ gdb/NEWS | 13 ++++++ gdb/hppa-tdep.c | 4 +- gdb/infrun.c | 86 +++++++++++++++++++++++++++++++++++++-- gdb/irix5-nat.c | 11 ++--- gdb/minsyms.c | 52 +++++++++++++++++++++++- gdb/osfsolib.c | 11 ++--- gdb/somsolib.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 8 files changed, 300 insertions(+), 28 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 861c03d..a0c947f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,30 @@ +Tue Jan 23 13:08:26 1996 Jeffrey A Law (law@cygnus.com) + + * symfile.c (auto_solib_add): Renamed from auto_solib_add_at_startup. + All references changed. + * breakpoint.c (bpstat_what): Add shlib_event to the class types. + Update state table. Reformat so that it's still readable. + When we hit the shlib_event breakpoint, set the calss of shlib_event. + (breakpoint_1): Add "shlib events" as a breakpoint type. + Print the shlib_event breakpoint like other breakpoints. + (create_solib_event_breakpoint): New function. + (breakpoint_re_set_one): Handle solib_event breakpoints. + * breakpoint.h (enum bytype): Add bp_shlib_event breakpoint type. + (enum bpstat_what_main_action): Add BPSTAT_WHAT_CHECK_SHLIBS + action. + (create_solib_event_breakpoint): Declare. + * infrun.c (wait_for_inferior): Handle CHECK_SHLIBS bpstat. + (normal_stop): Inform the user when the inferior stoped due + to a shared library event. + (_initialize_infrun): Add new set/show variable "stop_on-solib-events" + to control whether or not gdb continues the inferior or stops it when + a shared library event occurs. + * minsyms.c (lookup_minimal_symbol_solib_trampoline): New function. + * somsolib.c (TODO list): Update. + (som_solib_create_inferior_hook): Arrange for gdb to be notified + when significant shared library events occur. + * hppa-tdep.c (find_unwind_entry): No longer static. + Tue Jan 23 09:00:48 1996 Doug Evans * gdbtk.c (gdb_disassemble): Rework disassemble_info initialization. diff --git a/gdb/NEWS b/gdb/NEWS index 1d754cd..0867bde 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -19,6 +19,19 @@ The standard remote protocol now includes an option to send a break rather than a ^C to the target in order to interrupt it. By default, GDB will send ^C; to send a break, set the variable `remotebreak' to 1. +* Automatic tracking of dynamic object loading (HPUX only at the moment). + +By default GDB will automatically keep track of objects as they are +loaded and unloaded by the dynamic linker. By using the command +"set stop-on-solib-events 1" you can arrange for GDB to stop the +inferior when shared library events occur, thus allowing you to +set breakpoints in shared libraries which are explicitly loaded by +the inferior. + +Note this feature does not work on hpux8. On hpux9 you must link +/usr/lib/end.o into your program. This feature should work automatically +on hpux10. + *** Changes in GDB-4.15: * Psymtabs for XCOFF diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index 4fee8b0..544d726 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -1,5 +1,5 @@ /* Target-dependent code for the HP PA architecture, for GDB. - Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995 + Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. Contributed by the Center for Software Science at the @@ -487,7 +487,7 @@ read_unwind_info (objfile) contains a sorted list of struct unwind_table_entry. Since we do a binary search of the unwind tables, we depend upon them to be sorted. */ -static struct unwind_table_entry * +struct unwind_table_entry * find_unwind_entry(pc) CORE_ADDR pc; { diff --git a/gdb/infrun.c b/gdb/infrun.c index 73647aa..19ff2d3 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -1,5 +1,5 @@ /* Target-struct-independent code to start (run) and stop an inferior process. - Copyright 1986, 1987, 1988, 1989, 1991, 1992, 1993, 1994 + Copyright 1986, 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. This file is part of GDB. @@ -72,6 +72,21 @@ static int hook_stop_stub PARAMS ((char *)); #define SKIP_TRAMPOLINE_CODE(pc) 0 #endif +/* Dynamic function trampolines are similar to solib trampolines in that they + are between the caller and the callee. The difference is that when you + enter a dynamic trampoline, you can't determine the callee's address. Some + (usually complex) code needs to run in the dynamic trampoline to figure out + the callee's address. This macro is usually called twice. First, when we + enter the trampoline (looks like a normal function call at that point). It + should return the PC of a point within the trampoline where the callee's + address is known. Second, when we hit the breakpoint, this routine returns + the callee's address. At that point, things proceed as per a step resume + breakpoint. */ + +#ifndef DYNAMIC_TRAMPOLINE_NEXTPC +#define DYNAMIC_TRAMPOLINE_NEXTPC(pc) 0 +#endif + /* For SVR4 shared libraries, each call goes through a small piece of trampoline code in the ".plt" section. IN_SOLIB_CALL_TRAMPOLINE evaluates to nonzero if we are current stopped in one of these. */ @@ -136,6 +151,10 @@ static struct symbol *step_start_function; static int trap_expected; +/* Nonzero if we want to give control to the user when we're notified + of shared library events by the dynamic linker. */ +static int stop_on_solib_events; + #ifdef HP_OS_BUG /* Nonzero if the next time we try to continue the inferior, it will step one instruction and generate a spurious trace trap. @@ -1015,6 +1034,35 @@ wait_for_inferior () another_trap = 1; break; +#ifdef SOLIB_ADD + case BPSTAT_WHAT_CHECK_SHLIBS: + { + extern int auto_solib_add; + + /* Check for any newly added shared libraries if we're + supposed to be adding them automatically. */ + if (auto_solib_add) + SOLIB_ADD (NULL, 0, NULL); + + /* If requested, stop when the dynamic linker notifies + gdb of events. This allows the user to get control + and place breakpoints in initializer routines for + dynamically loaded objects (among other things). */ + if (stop_on_solib_events) + { + stop_print_frame = 0; + goto stop_stepping; + } + else + { + /* We want to step over this breakpoint, then keep going. */ + another_trap = 1; + remove_breakpoints_on_following_step = 1; + break; + } + } +#endif + case BPSTAT_WHAT_LAST: /* Not a real code, but listed here to shut up gcc -Wall. */ @@ -1208,8 +1256,9 @@ wait_for_inferior () handling_longjmp stuff is working. */ )) #else -/* This is experimental code which greatly simplifies the subroutine call - test. I've actually tested on the Alpha, and it works great. -Stu */ + /* This test is a much more streamlined, (but hopefully correct) + replacement for the code above. It's been tested on the Sparc, + Mips, PA, and Power architectures with good results. */ if (stop_pc == stop_func_start /* Quick test */ || in_prologue (stop_pc, stop_func_start) @@ -1241,6 +1290,22 @@ wait_for_inferior () tmp = SKIP_TRAMPOLINE_CODE (stop_pc); if (tmp != 0) stop_func_start = tmp; + else + { + tmp = DYNAMIC_TRAMPOLINE_NEXTPC (stop_pc); + if (tmp) + { + struct symtab_and_line xxx; + + xxx.pc = tmp; + xxx.symtab = NULL; + xxx.line = 0; + step_resume_breakpoint = + set_momentary_breakpoint (xxx, NULL, bp_step_resume); + insert_breakpoints (); + goto keep_going; + } + } /* If we have line number information for the function we are thinking of stepping into, step into it. @@ -1593,6 +1658,9 @@ Further execution is probably impossible.\n"); target_terminal_ours (); + if (stop_bpstat && stop_bpstat->breakpoint_at->type == bp_shlib_event) + printf_filtered ("Stopped due to shared library event\n"); + /* Look up the hook_stop and run it if it exists. */ if (stop_command->hook) @@ -2121,4 +2189,16 @@ of the program stops.", &cmdlist); signal_print[TARGET_SIGNAL_POLL] = 0; signal_stop[TARGET_SIGNAL_URG] = 0; signal_print[TARGET_SIGNAL_URG] = 0; + +#ifdef SOLIB_ADD + add_show_from_set + (add_set_cmd ("stop-on-solib-events", class_support, var_zinteger, + (char *) &stop_on_solib_events, + "Set stopping for shared library events.\n\ +If nonzero, gdb will give control to the user when the dynamic linker\n\ +notifies gdb of shared library events. The most common event of interest\n\ +to the user would be loading/unloading of a new library.\n", + &setlist), + &showlist); +#endif } diff --git a/gdb/irix5-nat.c b/gdb/irix5-nat.c index 1be5d4d..fc4c8cb 100644 --- a/gdb/irix5-nat.c +++ b/gdb/irix5-nat.c @@ -1,5 +1,5 @@ /* Native support for the SGI Iris running IRIX version 5, for GDB. - Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995 + Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin. @@ -1001,7 +1001,7 @@ solib_create_inferior_hook() and will put out an annoying warning. Delaying the resetting of stop_soon_quietly until after symbol loading suppresses the warning. */ - if (auto_solib_add_at_startup) + if (auto_solib_add) solib_add ((char *) 0, 0, (struct target_ops *) 0); stop_soon_quietly = 0; } @@ -1039,10 +1039,11 @@ _initialize_solib() add_show_from_set (add_set_cmd ("auto-solib-add", class_support, var_zinteger, - (char *) &auto_solib_add_at_startup, - "Set autoloading of shared library symbols at startup.\n\ + (char *) &auto_solib_add, + "Set autoloading of shared library symbols.\n\ If nonzero, symbols from all shared object libraries will be loaded\n\ -automatically when the inferior begins execution. Otherwise, symbols\n\ +automatically when the inferior begins execution or when the dynamic linker\n\ +informs gdb that a new library has been loaded. Otherwise, symbols\n\ must be loaded manually, using `sharedlibrary'.", &setlist), &showlist); diff --git a/gdb/minsyms.c b/gdb/minsyms.c index e36302e..6ef709a 100644 --- a/gdb/minsyms.c +++ b/gdb/minsyms.c @@ -1,5 +1,5 @@ /* GDB routines for manipulating the minimal symbol tables. - Copyright 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + Copyright 1992, 1993, 1994, 1996, 1996 Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules. This file is part of GDB. @@ -253,6 +253,56 @@ lookup_minimal_symbol_text (name, sfile, objf) return NULL; } +/* Look through all the current minimal symbol tables and find the + first minimal symbol that matches NAME and of solib trampoline type. + If OBJF is non-NULL, limit + the search to that objfile. If SFILE is non-NULL, limit the search + to that source file. Returns a pointer to the minimal symbol that + matches, or NULL if no match is found. +*/ + +struct minimal_symbol * +lookup_minimal_symbol_solib_trampoline (name, sfile, objf) + register const char *name; + const char *sfile; + struct objfile *objf; +{ + struct objfile *objfile; + struct minimal_symbol *msymbol; + struct minimal_symbol *found_symbol = NULL; + struct minimal_symbol *found_file_symbol = NULL; + +#ifdef SOFUN_ADDRESS_MAYBE_MISSING + if (sfile != NULL) + { + char *p = strrchr (sfile, '/'); + if (p != NULL) + sfile = p + 1; + } +#endif + + for (objfile = object_files; + objfile != NULL && found_symbol == NULL; + objfile = objfile -> next) + { + if (objf == NULL || objf == objfile) + { + for (msymbol = objfile -> msymbols; + msymbol != NULL && SYMBOL_NAME (msymbol) != NULL && + found_symbol == NULL; + msymbol++) + { + if (SYMBOL_MATCHES_NAME (msymbol, name) && + MSYMBOL_TYPE (msymbol) == mst_solib_trampoline) + return msymbol; + } + } + } + + return NULL; +} + + /* Search through the minimal symbol table for each objfile and find the symbol whose address is the largest address that is still less than or equal to PC. Returns a pointer to the minimal symbol if such a symbol diff --git a/gdb/osfsolib.c b/gdb/osfsolib.c index b97e683..85afa24 100644 --- a/gdb/osfsolib.c +++ b/gdb/osfsolib.c @@ -1,5 +1,5 @@ /* Handle OSF/1 shared libraries for GDB, the GNU Debugger. - Copyright 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc. This file is part of GDB. @@ -905,7 +905,7 @@ solib_create_inferior_hook() and will put out an annoying warning. Delaying the resetting of stop_soon_quietly until after symbol loading suppresses the warning. */ - if (auto_solib_add_at_startup) + if (auto_solib_add) solib_add ((char *) 0, 0, (struct target_ops *) 0); stop_soon_quietly = 0; } @@ -944,10 +944,11 @@ _initialize_solib() add_show_from_set (add_set_cmd ("auto-solib-add", class_support, var_zinteger, - (char *) &auto_solib_add_at_startup, - "Set autoloading of shared library symbols at startup.\n\ + (char *) &auto_solib_add, + "Set autoloading of shared library symbols.\n\ If nonzero, symbols from all shared object libraries will be loaded\n\ -automatically when the inferior begins execution. Otherwise, symbols\n\ +automatically when the inferior begins execution or when the dynamic linker\n\ +informs gdb that a new library has been loaded. Otherwise, symbols\n\ must be loaded manually, using `sharedlibrary'.", &setlist), &showlist); diff --git a/gdb/somsolib.c b/gdb/somsolib.c index 595752c..2d232b3 100644 --- a/gdb/somsolib.c +++ b/gdb/somsolib.c @@ -1,5 +1,5 @@ /* Handle HP SOM shared libraries for GDB, the GNU Debugger. - Copyright 1993 Free Software Foundation, Inc. + Copyright 1993, 1996 Free Software Foundation, Inc. This file is part of GDB. @@ -41,11 +41,7 @@ and by Cygnus Support. */ * Most of this code should work for hp300 shared libraries. Does anyone care enough to weed out any SOM-isms. - * Do we need/want a command to load a shared library? - - * Support for hpux8 dynamic linker. - - * Support for tracking user calls to dld_load, dld_unload. */ + * Support for hpux8 dynamic linker. */ /* The basic structure which describes a dynamically loaded object. This data structure is private to the dynamic linker and isn't found in @@ -499,9 +495,10 @@ void som_solib_create_inferior_hook() { struct minimal_symbol *msymbol; - unsigned int dld_flags, status; + unsigned int dld_flags, status, have_endo; asection *shlib_info; char shadow_contents[BREAKPOINT_MAX], buf[4]; + struct objfile *objfile; CORE_ADDR anaddr; if (symfile_objfile == NULL) @@ -516,12 +513,106 @@ som_solib_create_inferior_hook() if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0) return; + have_endo = 0; + /* Slam the pid of the process into __d_pid; failing is only a warning! */ + msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile); + if (msymbol == NULL) + { + warning ("Unable to find __d_pid symbol in object file.\n"); + warning ("Suggest linking with /usr/lib/end.o.\n"); + warning ("GDB will be unable to track shl_load/shl_unload calls\n"); + goto keep_going; + } + + anaddr = SYMBOL_VALUE_ADDRESS (msymbol); + store_unsigned_integer (buf, 4, inferior_pid); + status = target_write_memory (anaddr, buf, 4); + if (status != 0) + { + warning ("Unable to write __d_pid\n"); + warning ("Suggest linking with /usr/lib/end.o.\n"); + warning ("GDB will be unable to track shl_load/shl_unload calls\n"); + goto keep_going; + } + + /* Get the value of _DLD_HOOK (an export stub) and put it in __dld_hook; + This will force the dynamic linker to call __d_trap when significant + events occur. */ + msymbol = lookup_minimal_symbol ("_DLD_HOOK", NULL, symfile_objfile); + if (msymbol == NULL) + { + warning ("Unable to find _DLD_HOOK symbol in object file.\n"); + warning ("Suggest linking with /usr/lib/end.o.\n"); + warning ("GDB will be unable to track shl_load/shl_unload calls\n"); + goto keep_going; + } + anaddr = SYMBOL_VALUE_ADDRESS (msymbol); + + /* Grrr, this might not be an export symbol! We have to find the + export stub. */ + ALL_OBJFILES (objfile) + { + struct unwind_table_entry *u; + + /* What a crock. */ + msymbol = lookup_minimal_symbol_solib_trampoline (SYMBOL_NAME (msymbol), + NULL, objfile); + /* Found a symbol with the right name. */ + if (msymbol) + { + struct unwind_table_entry *u; + /* It must be a shared library trampoline. */ + if (SYMBOL_TYPE (msymbol) != mst_solib_trampoline) + continue; + + /* It must also be an export stub. */ + u = find_unwind_entry (SYMBOL_VALUE (msymbol)); + if (!u || u->stub_type != EXPORT) + continue; + + /* OK. Looks like the correct import stub. */ + anaddr = SYMBOL_VALUE (msymbol); + break; + } + } + store_unsigned_integer (buf, 4, anaddr); + + msymbol = lookup_minimal_symbol ("__dld_hook", NULL, symfile_objfile); + if (msymbol == NULL) + { + warning ("Unable to find __dld_hook symbol in object file.\n"); + warning ("Suggest linking with /usr/lib/end.o.\n"); + warning ("GDB will be unable to track shl_load/shl_unload calls\n"); + goto keep_going; + } + anaddr = SYMBOL_VALUE_ADDRESS (msymbol); + status = target_write_memory (anaddr, buf, 4); + + /* Now set a shlib_event breakpoint at __d_trap so we can track + significant shared library events. */ + msymbol = lookup_minimal_symbol ("__d_trap", NULL, symfile_objfile); + if (msymbol == NULL) + { + warning ("Unable to find __dld_d_trap symbol in object file.\n"); + warning ("Suggest linking with /usr/lib/end.o.\n"); + warning ("GDB will be unable to track shl_load/shl_unload calls\n"); + goto keep_going; + } + create_solib_event_breakpoint (SYMBOL_VALUE_ADDRESS (msymbol)); + + /* We have all the support usually found in end.o, so we can track + shl_load and shl_unload calls. */ + have_endo = 1; + +keep_going: + /* Get the address of __dld_flags, if no such symbol exists, then we can not debug the shared code. */ msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL); if (msymbol == NULL) { error ("Unable to find __dld_flags symbol in object file.\n"); + goto keep_going; return; } @@ -536,7 +627,7 @@ som_solib_create_inferior_hook() dld_flags = extract_unsigned_integer (buf, 4); /* Turn on the flags we care about. */ - dld_flags |= 0x5; + dld_flags |= (0x5 | (have_endo << 1)); store_unsigned_integer (buf, 4, dld_flags); status = target_write_memory (anaddr, buf, 4); if (status != 0) @@ -545,7 +636,15 @@ som_solib_create_inferior_hook() return; } - /* Now find the address of _start and set a breakpoint there. */ + /* Now find the address of _start and set a breakpoint there. + We still need this code for two reasons: + + * Not all sites have /usr/lib/end.o, so it's not always + possible to track the dynamic linker's events. + + * At this time no events are triggered for shared libraries + loaded at startup time (what a crock). */ + msymbol = lookup_minimal_symbol ("_start", NULL, symfile_objfile); if (msymbol == NULL) { @@ -592,7 +691,7 @@ som_solib_create_inferior_hook() return; } - if (auto_solib_add_at_startup) + if (auto_solib_add) som_solib_add ((char *) 0, 0, (struct target_ops *) 0); } @@ -728,10 +827,11 @@ _initialize_som_solib () "Status of loaded shared object libraries."); add_show_from_set (add_set_cmd ("auto-solib-add", class_support, var_zinteger, - (char *) &auto_solib_add_at_startup, + (char *) &auto_solib_add, "Set autoloading of shared library symbols at startup.\n\ If nonzero, symbols from all shared object libraries will be loaded\n\ -automatically when the inferior begins execution. Otherwise, symbols\n\ +automatically when the inferior begins execution or when the dynamic linker\n\ +informs gdb that a new library has been loaded. Otherwise, symbols\n\ must be loaded manually, using `sharedlibrary'.", &setlist), &showlist); -- 2.7.4