aboutsummaryrefslogtreecommitdiff
path: root/gdb/infrun.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r--gdb/infrun.c86
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
}