diff options
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r-- | gdb/infrun.c | 86 |
1 files changed, 83 insertions, 3 deletions
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 } |