* [RFA] Enhance GDB to break inside DSO init code
@ 2004-07-23 20:24 Joel Brobecker
2004-07-24 7:56 ` Eli Zaretskii
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Joel Brobecker @ 2004-07-23 20:24 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 3409 bytes --]
(My many thanks to David Anderson of SGI for explain in great details
how the runtime loader works, and how to get this working in GDB)
We are running on mips-irix native.
Consider a small program using a DSO (shared library) which has
been compiled with the following switch: -Wl,-init,myinit. This
means that the function myinit() is called when the shared library
is loaded, and before the program is executed.
Now, consider the following sequence of GDB commands:
% gdb hello_sal
(gdb) start
(gdb) b myinit
(gdb) run
We need to start the program first, in order for GDB to read the DSO
symbols. The expected behavior after the run is for GDB to stop in
myinit. But a limitation in the current startup implementation for
mips-irix is such that we end up inserting the breakpoint in myinit
*after* the DSO -init code is executed, hence too late. As a consequence,
The program runs to completion, vis:
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /[...]/hello_sal
[...]
Program exited normally.
Current language: auto; currently asm
For more details, you can refer to:
http://sources.redhat.com/ml/gdb-patches/2004-07/msg00030.html
The trick, as explained in the message above, is to stop on syssgi()
exit notifications until we can detect that rld has been mapped in
memory by finding the __dbx_link symbol. Then insert a breakpoint
at its address and run until we reach this breakpoint. We then know
that all DSOs have been mapped at this point, and therefore compute
the list of DSOs and load their symbols. At which point we can finally
insert our shared-library breakpoints and let the program run as usual.
With the attached patch, we now stop at the breakpoint, as expected:
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /[...]/hello_sal
Breakpoint 2, myinit () at /[...]/pack1.adb:29
29 i := write (1, msg'address, msg'length);
2004-07-23 Joel Brobecker <brobecker@gnat.com>
* procfs.c (dbx_link_bpt_addr): New static global variable.
(dbx_link_shadow_contents): New static global variable.
(procfs_wait, case <PR_SYSEXIT>): Handle syssgi events.
(procfs_wait, case <FLTBPT>): Remove the __dbx_link brekapoint
if we just hit it.
(procfs_init_inferior): Enable syssgi() syscall trace if appropriate.
Reset dbx_link_bpt_addr as the address of __dbx_link() may change
from run to run.
(procfs_create_inferior): Remove syssgi syscall-exit notifications
after the inferior has been forked.
(remove_dbx_link_breakpoint): New function.
(dbx_link_addr): New function.
(insert_dbx_link_bpt_in_file): New function.
(insert_dbx_link_bpt_in_region): New function.
(insert_dbx_link_breakpoint): New function.
(proc_trace_syscalls_1): New function, extracted from
proc_trace_syscalls.
(proc_trace_syscalls): Replace extract code by call to
proc_trace_syscalls_1.
* solib-irix.c (disable_break): Remove stop_pc assertion, as it
is no longer valid.
Tested on mips-irix, no regression. OK to commit?
Thanks,
--
Joel
[-- Attachment #2: irix-rld.diff --]
[-- Type: text/plain, Size: 12238 bytes --]
Index: procfs.c
===================================================================
RCS file: /cvs/src/src/gdb/procfs.c,v
retrieving revision 1.54
diff -u -p -r1.54 procfs.c
--- procfs.c 25 May 2004 14:58:30 -0000 1.54
+++ procfs.c 23 Jul 2004 18:01:46 -0000
@@ -3382,6 +3382,17 @@ proc_iterate_over_threads (procinfo *pi,
static ptid_t do_attach (ptid_t ptid);
static void do_detach (int signo);
static int register_gdb_signals (procinfo *, gdb_sigset_t *);
+static void proc_trace_syscalls_1 (procinfo *pi, int syscallnum,
+ int entry_or_exit, int mode, int from_tty);
+static int insert_dbx_link_breakpoint (procinfo *pi);
+static void remove_dbx_link_breakpoint (void);
+
+/* On mips-irix, we need to insert a breakpoint at __dbx_link during
+ the startup phase. The following two variables are used to record
+ the address of the breakpoint, and the code that was replaced by
+ a breakpoint. */
+static int dbx_link_bpt_addr = 0;
+static char dbx_link_shadow_contents[BREAKPOINT_MAX];
/*
* Function: procfs_debug_inferior
@@ -4065,6 +4076,22 @@ wait_again:
address. */
wstat = (SIGTRAP << 8) | 0177;
}
+#ifdef SYS_syssgi
+ else if (what == SYS_syssgi)
+ {
+ /* see if we can break on dbx_link(). If yes, then
+ we no longer need the SYS_syssgi notifications. */
+ if (insert_dbx_link_breakpoint (pi))
+ proc_trace_syscalls_1 (pi, SYS_syssgi, PR_SYSEXIT,
+ FLAG_RESET, 0);
+
+ /* This is an internal event and should be transparent
+ to wfi, so resume the execution and wait again. See
+ comment in procfs_init_inferior() for more details. */
+ target_resume (ptid, 0, TARGET_SIGNAL_0);
+ goto wait_again;
+ }
+#endif
else if (syscall_is_lwp_create (pi, what))
{
/*
@@ -4191,6 +4218,13 @@ wait_again:
#if (FLTTRACE != FLTBPT) /* avoid "duplicate case" error */
case FLTTRACE:
#endif
+ /* If we hit our __dbx_link() internal breakpoint,
+ then remove it. See comments in procfs_init_inferior()
+ for more details. */
+ if (dbx_link_bpt_addr != 0
+ && dbx_link_bpt_addr == read_pc ())
+ remove_dbx_link_breakpoint ();
+
wstat = (SIGTRAP << 8) | 0177;
break;
case FLTSTACK:
@@ -4842,6 +4876,32 @@ procfs_init_inferior (int pid)
/* Typically two, one trap to exec the shell, one to exec the
program being debugged. Defined by "inferior.h". */
startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
+
+#ifdef SYS_syssgi
+ /* On mips-irix, we need to stop the inferior early enough during
+ the startup phase in order to be able to load the shared library
+ symbols and insert the breakpoints that are located in these shared
+ libraries. Stopping at the program entry point is not good enough
+ because the -init code is executed before the execution reaches
+ that point.
+
+ So what we need to do is to insert a breakpoint in the runtime
+ loader (rld), more precisely in __dbx_link(). This procedure is
+ called by rld once all shared libraries have been mapped, but before
+ the -init code is executed. Unfortuantely, this is not straightforward,
+ as rld is not part of the executable we are running, and thus we need
+ the inferior to run until rld itself has been mapped in memory.
+
+ For this, we trace all syssgi() syscall exit events. Each time
+ we detect such an event, we iterate over each text memory maps,
+ get its associated fd, and scan the symbol table for __dbx_link().
+ When found, we know that rld has been mapped, and that we can insert
+ the breakpoint at the symbol address. Once the dbx_link() breakpoint
+ has been inserted, the syssgi() notifications are no longer necessary,
+ so they should be canceled. */
+ proc_trace_syscalls_1 (pi, SYS_syssgi, PR_SYSEXIT, FLAG_SET, 0);
+ dbx_link_bpt_addr = 0;
+#endif
}
/*
@@ -5048,6 +5108,16 @@ procfs_create_inferior (char *exec_file,
fork_inferior (exec_file, allargs, env, procfs_set_exec_trap,
procfs_init_inferior, NULL, shell_file);
+#ifdef SYS_syssgi
+ /* Make sure to cancel the syssgi() syscall-exit notifications.
+ They should normally have been removed by now, but they may still
+ be activated if the inferior doesn't use shared libraries, or if
+ we didn't locate __dbx_link, or if we never stopped in __dbx_link.
+ See procfs_init_inferior() for more details. */
+ proc_trace_syscalls_1 (find_procinfo_or_die (PIDGET (inferior_ptid), 0),
+ SYS_syssgi, PR_SYSEXIT, FLAG_RESET, 0);
+#endif
+
/* We are at the first instruction we care about. */
/* Pedal to the metal... */
@@ -5520,6 +5590,131 @@ proc_find_memory_regions (int (*func) (C
find_memory_regions_callback);
}
+/* Remove the breakpoint that we inserted in __dbx_link().
+ Does nothing if the breakpoint hasn't been inserted or has already
+ been removed. */
+
+static void
+remove_dbx_link_breakpoint (void)
+{
+ if (dbx_link_bpt_addr == 0)
+ return;
+
+ if (memory_remove_breakpoint (dbx_link_bpt_addr,
+ dbx_link_shadow_contents) != 0)
+ warning ("Unable to remove __dbx_link breakpoint.");
+
+ dbx_link_bpt_addr = 0;
+}
+
+/* Return the address of the __dbx_link() function in the file
+ refernced by ABFD by scanning its symbol table. Return 0 if
+ the symbol was not found. */
+
+static CORE_ADDR
+dbx_link_addr (bfd *abfd)
+{
+ long storage_needed;
+ asymbol **symbol_table;
+ long number_of_symbols;
+ long i;
+
+ storage_needed = bfd_get_symtab_upper_bound (abfd);
+ if (storage_needed <= 0)
+ return 0;
+
+ symbol_table = (asymbol **) xmalloc (storage_needed);
+ make_cleanup (xfree, symbol_table);
+
+ number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
+
+ for (i = 0; i < number_of_symbols; i++)
+ {
+ asymbol *sym = symbol_table[i];
+
+ if ((sym->flags & BSF_GLOBAL)
+ && sym->name != NULL && strcmp (sym->name, "__dbx_link") == 0)
+ return (sym->value + sym->section->vma);
+ }
+
+ /* Symbol not found, return NULL. */
+ return 0;
+}
+
+/* Search the symbol table of the file referenced by FD for a symbol
+ named __dbx_link(). If found, then insert a breakpoint at this location,
+ and return nonzero. Return zero otherwise. */
+
+static int
+insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored)
+{
+ bfd *abfd;
+ long storage_needed;
+ CORE_ADDR sym_addr;
+
+ abfd = bfd_fdopenr ("unamed", 0, fd);
+ if (abfd == NULL)
+ {
+ warning ("Failed to create a bfd: %s.\n", bfd_errmsg (bfd_get_error ()));
+ return 0;
+ }
+
+ if (!bfd_check_format (abfd, bfd_object))
+ {
+ /* Not the correct format, so we can not possibly find the dbx_link
+ symbol in it. */
+ bfd_close (abfd);
+ return 0;
+ }
+
+ sym_addr = dbx_link_addr (abfd);
+ if (sym_addr != 0)
+ {
+ /* Insert the breakpoint. */
+ dbx_link_bpt_addr = sym_addr;
+ if (target_insert_breakpoint (sym_addr, dbx_link_shadow_contents) != 0)
+ {
+ warning ("Failed to insert dbx_link breakpoint.");
+ bfd_close (abfd);
+ return 0;
+ }
+ bfd_close (abfd);
+ return 1;
+ }
+
+ bfd_close (abfd);
+ return 0;
+}
+
+/* If the given memory region MAP contains a symbol named __dbx_link,
+ insert a breakpoint at this location and return nonzero. Return
+ zero otherwise. */
+
+static int
+insert_dbx_link_bpt_in_region (struct prmap *map,
+ int (*child_func) (),
+ void *data)
+{
+ procinfo *pi = (procinfo *) data;
+
+ /* We know the symbol we're looking for is in a text region, so
+ only look for it if the region is a text one. */
+ if (map->pr_mflags & MA_EXEC)
+ return solib_mappings_callback (map, insert_dbx_link_bpt_in_file, pi);
+
+ return 0;
+}
+
+/* Search all memory regions for a symbol named __dbx_link. If found,
+ insert a breakpoint at its location, and return nonzero. Return zero
+ otherwise. */
+
+static int
+insert_dbx_link_breakpoint (procinfo *pi)
+{
+ return iterate_over_mappings (pi, NULL, pi, insert_dbx_link_bpt_in_region);
+}
+
/*
* Function: mappingflags
*
@@ -5708,12 +5903,50 @@ info_proc_cmd (char *args, int from_tty)
do_cleanups (old_chain);
}
+/* Modify the status of the system call identified by SYSCALLNUM in
+ the set of syscalls that are currently traced/debugged.
+
+ If ENTRY_OR_EXIT is set to PR_SYSENTRY, then the entry syscalls set
+ will be updated. Otherwise, the exit syscalls set will be updated.
+
+ If MODE is FLAG_SET, then traces will be enabled. Otherwise, they
+ will be disabled. */
+
+static void
+proc_trace_syscalls_1 (procinfo *pi, int syscallnum, int entry_or_exit,
+ int mode, int from_tty)
+{
+ sysset_t *sysset;
+
+ if (entry_or_exit == PR_SYSENTRY)
+ sysset = proc_get_traced_sysentry (pi, NULL);
+ else
+ sysset = proc_get_traced_sysexit (pi, NULL);
+
+ if (sysset == NULL)
+ proc_error (pi, "proc-trace, get_traced_sysset", __LINE__);
+
+ if (mode == FLAG_SET)
+ gdb_praddsysset (sysset, syscallnum);
+ else
+ gdb_prdelsysset (sysset, syscallnum);
+
+ if (entry_or_exit == PR_SYSENTRY)
+ {
+ if (!proc_set_traced_sysentry (pi, sysset))
+ proc_error (pi, "proc-trace, set_traced_sysentry", __LINE__);
+ }
+ else
+ {
+ if (!proc_set_traced_sysexit (pi, sysset))
+ proc_error (pi, "proc-trace, set_traced_sysexit", __LINE__);
+ }
+}
+
static void
proc_trace_syscalls (char *args, int from_tty, int entry_or_exit, int mode)
{
procinfo *pi;
- sysset_t *sysset;
- int syscallnum = 0;
if (PIDGET (inferior_ptid) <= 0)
error ("you must be debugging a process to use this command.");
@@ -5724,30 +5957,9 @@ proc_trace_syscalls (char *args, int fro
pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
if (isdigit (args[0]))
{
- syscallnum = atoi (args);
- if (entry_or_exit == PR_SYSENTRY)
- sysset = proc_get_traced_sysentry (pi, NULL);
- else
- sysset = proc_get_traced_sysexit (pi, NULL);
-
- if (sysset == NULL)
- proc_error (pi, "proc-trace, get_traced_sysset", __LINE__);
-
- if (mode == FLAG_SET)
- gdb_praddsysset (sysset, syscallnum);
- else
- gdb_prdelsysset (sysset, syscallnum);
+ const int syscallnum = atoi (args);
- if (entry_or_exit == PR_SYSENTRY)
- {
- if (!proc_set_traced_sysentry (pi, sysset))
- proc_error (pi, "proc-trace, set_traced_sysentry", __LINE__);
- }
- else
- {
- if (!proc_set_traced_sysexit (pi, sysset))
- proc_error (pi, "proc-trace, set_traced_sysexit", __LINE__);
- }
+ proc_trace_syscalls_1 (pi, syscallnum, entry_or_exit, mode, from_tty);
}
}
Index: solib-irix.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-irix.c,v
retrieving revision 1.5
diff -u -p -r1.5 solib-irix.c
--- solib-irix.c 14 Feb 2004 15:46:33 -0000 1.5
+++ solib-irix.c 23 Jul 2004 18:01:46 -0000
@@ -324,15 +324,11 @@ disable_break (void)
status = 0;
}
- /* For the SVR4 version, we always know the breakpoint address. For the
- SunOS version we don't know it until the above code is executed.
- Grumble if we are stopped anywhere besides the breakpoint address. */
-
- if (stop_pc != breakpoint_addr)
- {
- warning
- ("stopped at unknown breakpoint while handling shared libraries");
- }
+ /* Note that it is possible that we have stopped at a location that
+ is different from the location where we inserted our breakpoint.
+ On mips-irix, we can actually land in __dbx_init(), so we should
+ not check the PC against our breakpoint address here. See procfs.c
+ for more details. */
return (status);
}
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFA] Enhance GDB to break inside DSO init code
2004-07-23 20:24 [RFA] Enhance GDB to break inside DSO init code Joel Brobecker
@ 2004-07-24 7:56 ` Eli Zaretskii
2004-07-24 15:01 ` Joel Brobecker
2004-08-06 18:31 ` Joel Brobecker
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Eli Zaretskii @ 2004-07-24 7:56 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
> Date: Fri, 23 Jul 2004 13:24:47 -0700
> From: Joel Brobecker <brobecker@gnat.com>
>
> For more details, you can refer to:
>
> http://sources.redhat.com/ml/gdb-patches/2004-07/msg00030.html
>
> The trick, as explained in the message above, is to stop on syssgi()
> exit notifications until we can detect that rld has been mapped in
> memory by finding the __dbx_link symbol. [...]
Why, oh why do people go to such great lengths to explain this in a
mail message and/or in the comments to the code, but not as a patch to
gdbint.texinfo? Why not invest a small additional effort (Texinfo
markup) to improve our documentation together with fixing a bug?
Sigh.
Thanks for the patch. (I cannot approve it, though.)
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFA] Enhance GDB to break inside DSO init code
2004-07-24 7:56 ` Eli Zaretskii
@ 2004-07-24 15:01 ` Joel Brobecker
2004-07-24 17:16 ` Eli Zaretskii
0 siblings, 1 reply; 8+ messages in thread
From: Joel Brobecker @ 2004-07-24 15:01 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
> Why, oh why do people go to such great lengths to explain this in a
> mail message and/or in the comments to the code, but not as a patch to
> gdbint.texinfo? Why not invest a small additional effort (Texinfo
> markup) to improve our documentation together with fixing a bug?
To me, explainations about the code belong in the code. When reading
some code I don't know about, I appreciate explainations located right
besides the code I'm trying to understand. I usually don't remember to
look into gdbint or any other document, and besides, it's incovenient
to have to search it, to see if there would be any additional info
there.
If I had to make a suggestion, I would embed all the information from
gdbint inside the code, and make gdbint a document generated from the
code.
--
Joel
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFA] Enhance GDB to break inside DSO init code
2004-07-24 15:01 ` Joel Brobecker
@ 2004-07-24 17:16 ` Eli Zaretskii
0 siblings, 0 replies; 8+ messages in thread
From: Eli Zaretskii @ 2004-07-24 17:16 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
> Date: Sat, 24 Jul 2004 08:01:04 -0700
> From: Joel Brobecker <brobecker@gnat.com>
>
> > Why, oh why do people go to such great lengths to explain this in a
> > mail message and/or in the comments to the code, but not as a patch to
> > gdbint.texinfo? Why not invest a small additional effort (Texinfo
> > markup) to improve our documentation together with fixing a bug?
>
> To me, explainations about the code belong in the code.
I didn't object to having them in the code as well.
The one significant drawback with having these explanations _only_ in
the code is that one cannot easily find them, unless one already knows
where and what to look for. An Info manual, by contrast, has powerful
search facilities.
> If I had to make a suggestion, I would embed all the information from
> gdbint inside the code, and make gdbint a document generated from the
> code.
I support this goal, but I don't have time to work on making this
happen. AFAIK, there's no GNU standard for embedding documentation in
code, and, apart of the chew thingy used by Binutils, I'm not aware of
any tools that can produce Texinfo.
Note that some background information doesn't belong to code comments,
so there will be a need for pure Texinfo somewhere even if we adopt
some self-documenting-code system.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFA] Enhance GDB to break inside DSO init code
2004-07-23 20:24 [RFA] Enhance GDB to break inside DSO init code Joel Brobecker
2004-07-24 7:56 ` Eli Zaretskii
@ 2004-08-06 18:31 ` Joel Brobecker
2004-08-19 7:55 ` Joel Brobecker
2004-08-24 23:45 ` Kevin Buettner
3 siblings, 0 replies; 8+ messages in thread
From: Joel Brobecker @ 2004-08-06 18:31 UTC (permalink / raw)
To: gdb-patches
Ping?
On Fri, Jul 23, 2004 at 01:24:47PM -0700, Joel Brobecker wrote:
> (My many thanks to David Anderson of SGI for explain in great details
> how the runtime loader works, and how to get this working in GDB)
>
> We are running on mips-irix native.
>
> Consider a small program using a DSO (shared library) which has
> been compiled with the following switch: -Wl,-init,myinit. This
> means that the function myinit() is called when the shared library
> is loaded, and before the program is executed.
>
> Now, consider the following sequence of GDB commands:
>
> % gdb hello_sal
> (gdb) start
> (gdb) b myinit
> (gdb) run
>
> We need to start the program first, in order for GDB to read the DSO
> symbols. The expected behavior after the run is for GDB to stop in
> myinit. But a limitation in the current startup implementation for
> mips-irix is such that we end up inserting the breakpoint in myinit
> *after* the DSO -init code is executed, hence too late. As a consequence,
> The program runs to completion, vis:
>
> The program being debugged has been started already.
> Start it from the beginning? (y or n) y
>
> Starting program: /[...]/hello_sal
> [...]
> Program exited normally.
> Current language: auto; currently asm
>
> For more details, you can refer to:
>
> http://sources.redhat.com/ml/gdb-patches/2004-07/msg00030.html
>
> The trick, as explained in the message above, is to stop on syssgi()
> exit notifications until we can detect that rld has been mapped in
> memory by finding the __dbx_link symbol. Then insert a breakpoint
> at its address and run until we reach this breakpoint. We then know
> that all DSOs have been mapped at this point, and therefore compute
> the list of DSOs and load their symbols. At which point we can finally
> insert our shared-library breakpoints and let the program run as usual.
> With the attached patch, we now stop at the breakpoint, as expected:
>
> (gdb) run
> The program being debugged has been started already.
> Start it from the beginning? (y or n) y
>
> Starting program: /[...]/hello_sal
>
> Breakpoint 2, myinit () at /[...]/pack1.adb:29
> 29 i := write (1, msg'address, msg'length);
>
> 2004-07-23 Joel Brobecker <brobecker@gnat.com>
>
> * procfs.c (dbx_link_bpt_addr): New static global variable.
> (dbx_link_shadow_contents): New static global variable.
> (procfs_wait, case <PR_SYSEXIT>): Handle syssgi events.
> (procfs_wait, case <FLTBPT>): Remove the __dbx_link brekapoint
> if we just hit it.
> (procfs_init_inferior): Enable syssgi() syscall trace if appropriate.
> Reset dbx_link_bpt_addr as the address of __dbx_link() may change
> from run to run.
> (procfs_create_inferior): Remove syssgi syscall-exit notifications
> after the inferior has been forked.
> (remove_dbx_link_breakpoint): New function.
> (dbx_link_addr): New function.
> (insert_dbx_link_bpt_in_file): New function.
> (insert_dbx_link_bpt_in_region): New function.
> (insert_dbx_link_breakpoint): New function.
> (proc_trace_syscalls_1): New function, extracted from
> proc_trace_syscalls.
> (proc_trace_syscalls): Replace extract code by call to
> proc_trace_syscalls_1.
> * solib-irix.c (disable_break): Remove stop_pc assertion, as it
> is no longer valid.
>
> Tested on mips-irix, no regression. OK to commit?
>
> Thanks,
> --
> Joel
> Index: procfs.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/procfs.c,v
> retrieving revision 1.54
> diff -u -p -r1.54 procfs.c
> --- procfs.c 25 May 2004 14:58:30 -0000 1.54
> +++ procfs.c 23 Jul 2004 18:01:46 -0000
> @@ -3382,6 +3382,17 @@ proc_iterate_over_threads (procinfo *pi,
> static ptid_t do_attach (ptid_t ptid);
> static void do_detach (int signo);
> static int register_gdb_signals (procinfo *, gdb_sigset_t *);
> +static void proc_trace_syscalls_1 (procinfo *pi, int syscallnum,
> + int entry_or_exit, int mode, int from_tty);
> +static int insert_dbx_link_breakpoint (procinfo *pi);
> +static void remove_dbx_link_breakpoint (void);
> +
> +/* On mips-irix, we need to insert a breakpoint at __dbx_link during
> + the startup phase. The following two variables are used to record
> + the address of the breakpoint, and the code that was replaced by
> + a breakpoint. */
> +static int dbx_link_bpt_addr = 0;
> +static char dbx_link_shadow_contents[BREAKPOINT_MAX];
>
> /*
> * Function: procfs_debug_inferior
> @@ -4065,6 +4076,22 @@ wait_again:
> address. */
> wstat = (SIGTRAP << 8) | 0177;
> }
> +#ifdef SYS_syssgi
> + else if (what == SYS_syssgi)
> + {
> + /* see if we can break on dbx_link(). If yes, then
> + we no longer need the SYS_syssgi notifications. */
> + if (insert_dbx_link_breakpoint (pi))
> + proc_trace_syscalls_1 (pi, SYS_syssgi, PR_SYSEXIT,
> + FLAG_RESET, 0);
> +
> + /* This is an internal event and should be transparent
> + to wfi, so resume the execution and wait again. See
> + comment in procfs_init_inferior() for more details. */
> + target_resume (ptid, 0, TARGET_SIGNAL_0);
> + goto wait_again;
> + }
> +#endif
> else if (syscall_is_lwp_create (pi, what))
> {
> /*
> @@ -4191,6 +4218,13 @@ wait_again:
> #if (FLTTRACE != FLTBPT) /* avoid "duplicate case" error */
> case FLTTRACE:
> #endif
> + /* If we hit our __dbx_link() internal breakpoint,
> + then remove it. See comments in procfs_init_inferior()
> + for more details. */
> + if (dbx_link_bpt_addr != 0
> + && dbx_link_bpt_addr == read_pc ())
> + remove_dbx_link_breakpoint ();
> +
> wstat = (SIGTRAP << 8) | 0177;
> break;
> case FLTSTACK:
> @@ -4842,6 +4876,32 @@ procfs_init_inferior (int pid)
> /* Typically two, one trap to exec the shell, one to exec the
> program being debugged. Defined by "inferior.h". */
> startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
> +
> +#ifdef SYS_syssgi
> + /* On mips-irix, we need to stop the inferior early enough during
> + the startup phase in order to be able to load the shared library
> + symbols and insert the breakpoints that are located in these shared
> + libraries. Stopping at the program entry point is not good enough
> + because the -init code is executed before the execution reaches
> + that point.
> +
> + So what we need to do is to insert a breakpoint in the runtime
> + loader (rld), more precisely in __dbx_link(). This procedure is
> + called by rld once all shared libraries have been mapped, but before
> + the -init code is executed. Unfortuantely, this is not straightforward,
> + as rld is not part of the executable we are running, and thus we need
> + the inferior to run until rld itself has been mapped in memory.
> +
> + For this, we trace all syssgi() syscall exit events. Each time
> + we detect such an event, we iterate over each text memory maps,
> + get its associated fd, and scan the symbol table for __dbx_link().
> + When found, we know that rld has been mapped, and that we can insert
> + the breakpoint at the symbol address. Once the dbx_link() breakpoint
> + has been inserted, the syssgi() notifications are no longer necessary,
> + so they should be canceled. */
> + proc_trace_syscalls_1 (pi, SYS_syssgi, PR_SYSEXIT, FLAG_SET, 0);
> + dbx_link_bpt_addr = 0;
> +#endif
> }
>
> /*
> @@ -5048,6 +5108,16 @@ procfs_create_inferior (char *exec_file,
> fork_inferior (exec_file, allargs, env, procfs_set_exec_trap,
> procfs_init_inferior, NULL, shell_file);
>
> +#ifdef SYS_syssgi
> + /* Make sure to cancel the syssgi() syscall-exit notifications.
> + They should normally have been removed by now, but they may still
> + be activated if the inferior doesn't use shared libraries, or if
> + we didn't locate __dbx_link, or if we never stopped in __dbx_link.
> + See procfs_init_inferior() for more details. */
> + proc_trace_syscalls_1 (find_procinfo_or_die (PIDGET (inferior_ptid), 0),
> + SYS_syssgi, PR_SYSEXIT, FLAG_RESET, 0);
> +#endif
> +
> /* We are at the first instruction we care about. */
> /* Pedal to the metal... */
>
> @@ -5520,6 +5590,131 @@ proc_find_memory_regions (int (*func) (C
> find_memory_regions_callback);
> }
>
> +/* Remove the breakpoint that we inserted in __dbx_link().
> + Does nothing if the breakpoint hasn't been inserted or has already
> + been removed. */
> +
> +static void
> +remove_dbx_link_breakpoint (void)
> +{
> + if (dbx_link_bpt_addr == 0)
> + return;
> +
> + if (memory_remove_breakpoint (dbx_link_bpt_addr,
> + dbx_link_shadow_contents) != 0)
> + warning ("Unable to remove __dbx_link breakpoint.");
> +
> + dbx_link_bpt_addr = 0;
> +}
> +
> +/* Return the address of the __dbx_link() function in the file
> + refernced by ABFD by scanning its symbol table. Return 0 if
> + the symbol was not found. */
> +
> +static CORE_ADDR
> +dbx_link_addr (bfd *abfd)
> +{
> + long storage_needed;
> + asymbol **symbol_table;
> + long number_of_symbols;
> + long i;
> +
> + storage_needed = bfd_get_symtab_upper_bound (abfd);
> + if (storage_needed <= 0)
> + return 0;
> +
> + symbol_table = (asymbol **) xmalloc (storage_needed);
> + make_cleanup (xfree, symbol_table);
> +
> + number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
> +
> + for (i = 0; i < number_of_symbols; i++)
> + {
> + asymbol *sym = symbol_table[i];
> +
> + if ((sym->flags & BSF_GLOBAL)
> + && sym->name != NULL && strcmp (sym->name, "__dbx_link") == 0)
> + return (sym->value + sym->section->vma);
> + }
> +
> + /* Symbol not found, return NULL. */
> + return 0;
> +}
> +
> +/* Search the symbol table of the file referenced by FD for a symbol
> + named __dbx_link(). If found, then insert a breakpoint at this location,
> + and return nonzero. Return zero otherwise. */
> +
> +static int
> +insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored)
> +{
> + bfd *abfd;
> + long storage_needed;
> + CORE_ADDR sym_addr;
> +
> + abfd = bfd_fdopenr ("unamed", 0, fd);
> + if (abfd == NULL)
> + {
> + warning ("Failed to create a bfd: %s.\n", bfd_errmsg (bfd_get_error ()));
> + return 0;
> + }
> +
> + if (!bfd_check_format (abfd, bfd_object))
> + {
> + /* Not the correct format, so we can not possibly find the dbx_link
> + symbol in it. */
> + bfd_close (abfd);
> + return 0;
> + }
> +
> + sym_addr = dbx_link_addr (abfd);
> + if (sym_addr != 0)
> + {
> + /* Insert the breakpoint. */
> + dbx_link_bpt_addr = sym_addr;
> + if (target_insert_breakpoint (sym_addr, dbx_link_shadow_contents) != 0)
> + {
> + warning ("Failed to insert dbx_link breakpoint.");
> + bfd_close (abfd);
> + return 0;
> + }
> + bfd_close (abfd);
> + return 1;
> + }
> +
> + bfd_close (abfd);
> + return 0;
> +}
> +
> +/* If the given memory region MAP contains a symbol named __dbx_link,
> + insert a breakpoint at this location and return nonzero. Return
> + zero otherwise. */
> +
> +static int
> +insert_dbx_link_bpt_in_region (struct prmap *map,
> + int (*child_func) (),
> + void *data)
> +{
> + procinfo *pi = (procinfo *) data;
> +
> + /* We know the symbol we're looking for is in a text region, so
> + only look for it if the region is a text one. */
> + if (map->pr_mflags & MA_EXEC)
> + return solib_mappings_callback (map, insert_dbx_link_bpt_in_file, pi);
> +
> + return 0;
> +}
> +
> +/* Search all memory regions for a symbol named __dbx_link. If found,
> + insert a breakpoint at its location, and return nonzero. Return zero
> + otherwise. */
> +
> +static int
> +insert_dbx_link_breakpoint (procinfo *pi)
> +{
> + return iterate_over_mappings (pi, NULL, pi, insert_dbx_link_bpt_in_region);
> +}
> +
> /*
> * Function: mappingflags
> *
> @@ -5708,12 +5903,50 @@ info_proc_cmd (char *args, int from_tty)
> do_cleanups (old_chain);
> }
>
> +/* Modify the status of the system call identified by SYSCALLNUM in
> + the set of syscalls that are currently traced/debugged.
> +
> + If ENTRY_OR_EXIT is set to PR_SYSENTRY, then the entry syscalls set
> + will be updated. Otherwise, the exit syscalls set will be updated.
> +
> + If MODE is FLAG_SET, then traces will be enabled. Otherwise, they
> + will be disabled. */
> +
> +static void
> +proc_trace_syscalls_1 (procinfo *pi, int syscallnum, int entry_or_exit,
> + int mode, int from_tty)
> +{
> + sysset_t *sysset;
> +
> + if (entry_or_exit == PR_SYSENTRY)
> + sysset = proc_get_traced_sysentry (pi, NULL);
> + else
> + sysset = proc_get_traced_sysexit (pi, NULL);
> +
> + if (sysset == NULL)
> + proc_error (pi, "proc-trace, get_traced_sysset", __LINE__);
> +
> + if (mode == FLAG_SET)
> + gdb_praddsysset (sysset, syscallnum);
> + else
> + gdb_prdelsysset (sysset, syscallnum);
> +
> + if (entry_or_exit == PR_SYSENTRY)
> + {
> + if (!proc_set_traced_sysentry (pi, sysset))
> + proc_error (pi, "proc-trace, set_traced_sysentry", __LINE__);
> + }
> + else
> + {
> + if (!proc_set_traced_sysexit (pi, sysset))
> + proc_error (pi, "proc-trace, set_traced_sysexit", __LINE__);
> + }
> +}
> +
> static void
> proc_trace_syscalls (char *args, int from_tty, int entry_or_exit, int mode)
> {
> procinfo *pi;
> - sysset_t *sysset;
> - int syscallnum = 0;
>
> if (PIDGET (inferior_ptid) <= 0)
> error ("you must be debugging a process to use this command.");
> @@ -5724,30 +5957,9 @@ proc_trace_syscalls (char *args, int fro
> pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
> if (isdigit (args[0]))
> {
> - syscallnum = atoi (args);
> - if (entry_or_exit == PR_SYSENTRY)
> - sysset = proc_get_traced_sysentry (pi, NULL);
> - else
> - sysset = proc_get_traced_sysexit (pi, NULL);
> -
> - if (sysset == NULL)
> - proc_error (pi, "proc-trace, get_traced_sysset", __LINE__);
> -
> - if (mode == FLAG_SET)
> - gdb_praddsysset (sysset, syscallnum);
> - else
> - gdb_prdelsysset (sysset, syscallnum);
> + const int syscallnum = atoi (args);
>
> - if (entry_or_exit == PR_SYSENTRY)
> - {
> - if (!proc_set_traced_sysentry (pi, sysset))
> - proc_error (pi, "proc-trace, set_traced_sysentry", __LINE__);
> - }
> - else
> - {
> - if (!proc_set_traced_sysexit (pi, sysset))
> - proc_error (pi, "proc-trace, set_traced_sysexit", __LINE__);
> - }
> + proc_trace_syscalls_1 (pi, syscallnum, entry_or_exit, mode, from_tty);
> }
> }
>
> Index: solib-irix.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/solib-irix.c,v
> retrieving revision 1.5
> diff -u -p -r1.5 solib-irix.c
> --- solib-irix.c 14 Feb 2004 15:46:33 -0000 1.5
> +++ solib-irix.c 23 Jul 2004 18:01:46 -0000
> @@ -324,15 +324,11 @@ disable_break (void)
> status = 0;
> }
>
> - /* For the SVR4 version, we always know the breakpoint address. For the
> - SunOS version we don't know it until the above code is executed.
> - Grumble if we are stopped anywhere besides the breakpoint address. */
> -
> - if (stop_pc != breakpoint_addr)
> - {
> - warning
> - ("stopped at unknown breakpoint while handling shared libraries");
> - }
> + /* Note that it is possible that we have stopped at a location that
> + is different from the location where we inserted our breakpoint.
> + On mips-irix, we can actually land in __dbx_init(), so we should
> + not check the PC against our breakpoint address here. See procfs.c
> + for more details. */
>
> return (status);
> }
--
Joel
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFA] Enhance GDB to break inside DSO init code
2004-07-23 20:24 [RFA] Enhance GDB to break inside DSO init code Joel Brobecker
2004-07-24 7:56 ` Eli Zaretskii
2004-08-06 18:31 ` Joel Brobecker
@ 2004-08-19 7:55 ` Joel Brobecker
2004-08-24 23:45 ` Kevin Buettner
3 siblings, 0 replies; 8+ messages in thread
From: Joel Brobecker @ 2004-08-19 7:55 UTC (permalink / raw)
To: gdb-patches
Double-ping?
Thanks,
--
Joel
On Fri, Jul 23, 2004 at 01:24:47PM -0700, Joel Brobecker wrote:
> (My many thanks to David Anderson of SGI for explain in great details
> how the runtime loader works, and how to get this working in GDB)
>
> We are running on mips-irix native.
>
> Consider a small program using a DSO (shared library) which has
> been compiled with the following switch: -Wl,-init,myinit. This
> means that the function myinit() is called when the shared library
> is loaded, and before the program is executed.
>
> Now, consider the following sequence of GDB commands:
>
> % gdb hello_sal
> (gdb) start
> (gdb) b myinit
> (gdb) run
>
> We need to start the program first, in order for GDB to read the DSO
> symbols. The expected behavior after the run is for GDB to stop in
> myinit. But a limitation in the current startup implementation for
> mips-irix is such that we end up inserting the breakpoint in myinit
> *after* the DSO -init code is executed, hence too late. As a consequence,
> The program runs to completion, vis:
>
> The program being debugged has been started already.
> Start it from the beginning? (y or n) y
>
> Starting program: /[...]/hello_sal
> [...]
> Program exited normally.
> Current language: auto; currently asm
>
> For more details, you can refer to:
>
> http://sources.redhat.com/ml/gdb-patches/2004-07/msg00030.html
>
> The trick, as explained in the message above, is to stop on syssgi()
> exit notifications until we can detect that rld has been mapped in
> memory by finding the __dbx_link symbol. Then insert a breakpoint
> at its address and run until we reach this breakpoint. We then know
> that all DSOs have been mapped at this point, and therefore compute
> the list of DSOs and load their symbols. At which point we can finally
> insert our shared-library breakpoints and let the program run as usual.
> With the attached patch, we now stop at the breakpoint, as expected:
>
> (gdb) run
> The program being debugged has been started already.
> Start it from the beginning? (y or n) y
>
> Starting program: /[...]/hello_sal
>
> Breakpoint 2, myinit () at /[...]/pack1.adb:29
> 29 i := write (1, msg'address, msg'length);
>
> 2004-07-23 Joel Brobecker <brobecker@gnat.com>
>
> * procfs.c (dbx_link_bpt_addr): New static global variable.
> (dbx_link_shadow_contents): New static global variable.
> (procfs_wait, case <PR_SYSEXIT>): Handle syssgi events.
> (procfs_wait, case <FLTBPT>): Remove the __dbx_link brekapoint
> if we just hit it.
> (procfs_init_inferior): Enable syssgi() syscall trace if appropriate.
> Reset dbx_link_bpt_addr as the address of __dbx_link() may change
> from run to run.
> (procfs_create_inferior): Remove syssgi syscall-exit notifications
> after the inferior has been forked.
> (remove_dbx_link_breakpoint): New function.
> (dbx_link_addr): New function.
> (insert_dbx_link_bpt_in_file): New function.
> (insert_dbx_link_bpt_in_region): New function.
> (insert_dbx_link_breakpoint): New function.
> (proc_trace_syscalls_1): New function, extracted from
> proc_trace_syscalls.
> (proc_trace_syscalls): Replace extract code by call to
> proc_trace_syscalls_1.
> * solib-irix.c (disable_break): Remove stop_pc assertion, as it
> is no longer valid.
>
> Tested on mips-irix, no regression. OK to commit?
>
> Thanks,
> --
> Joel
> Index: procfs.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/procfs.c,v
> retrieving revision 1.54
> diff -u -p -r1.54 procfs.c
> --- procfs.c 25 May 2004 14:58:30 -0000 1.54
> +++ procfs.c 23 Jul 2004 18:01:46 -0000
> @@ -3382,6 +3382,17 @@ proc_iterate_over_threads (procinfo *pi,
> static ptid_t do_attach (ptid_t ptid);
> static void do_detach (int signo);
> static int register_gdb_signals (procinfo *, gdb_sigset_t *);
> +static void proc_trace_syscalls_1 (procinfo *pi, int syscallnum,
> + int entry_or_exit, int mode, int from_tty);
> +static int insert_dbx_link_breakpoint (procinfo *pi);
> +static void remove_dbx_link_breakpoint (void);
> +
> +/* On mips-irix, we need to insert a breakpoint at __dbx_link during
> + the startup phase. The following two variables are used to record
> + the address of the breakpoint, and the code that was replaced by
> + a breakpoint. */
> +static int dbx_link_bpt_addr = 0;
> +static char dbx_link_shadow_contents[BREAKPOINT_MAX];
>
> /*
> * Function: procfs_debug_inferior
> @@ -4065,6 +4076,22 @@ wait_again:
> address. */
> wstat = (SIGTRAP << 8) | 0177;
> }
> +#ifdef SYS_syssgi
> + else if (what == SYS_syssgi)
> + {
> + /* see if we can break on dbx_link(). If yes, then
> + we no longer need the SYS_syssgi notifications. */
> + if (insert_dbx_link_breakpoint (pi))
> + proc_trace_syscalls_1 (pi, SYS_syssgi, PR_SYSEXIT,
> + FLAG_RESET, 0);
> +
> + /* This is an internal event and should be transparent
> + to wfi, so resume the execution and wait again. See
> + comment in procfs_init_inferior() for more details. */
> + target_resume (ptid, 0, TARGET_SIGNAL_0);
> + goto wait_again;
> + }
> +#endif
> else if (syscall_is_lwp_create (pi, what))
> {
> /*
> @@ -4191,6 +4218,13 @@ wait_again:
> #if (FLTTRACE != FLTBPT) /* avoid "duplicate case" error */
> case FLTTRACE:
> #endif
> + /* If we hit our __dbx_link() internal breakpoint,
> + then remove it. See comments in procfs_init_inferior()
> + for more details. */
> + if (dbx_link_bpt_addr != 0
> + && dbx_link_bpt_addr == read_pc ())
> + remove_dbx_link_breakpoint ();
> +
> wstat = (SIGTRAP << 8) | 0177;
> break;
> case FLTSTACK:
> @@ -4842,6 +4876,32 @@ procfs_init_inferior (int pid)
> /* Typically two, one trap to exec the shell, one to exec the
> program being debugged. Defined by "inferior.h". */
> startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
> +
> +#ifdef SYS_syssgi
> + /* On mips-irix, we need to stop the inferior early enough during
> + the startup phase in order to be able to load the shared library
> + symbols and insert the breakpoints that are located in these shared
> + libraries. Stopping at the program entry point is not good enough
> + because the -init code is executed before the execution reaches
> + that point.
> +
> + So what we need to do is to insert a breakpoint in the runtime
> + loader (rld), more precisely in __dbx_link(). This procedure is
> + called by rld once all shared libraries have been mapped, but before
> + the -init code is executed. Unfortuantely, this is not straightforward,
> + as rld is not part of the executable we are running, and thus we need
> + the inferior to run until rld itself has been mapped in memory.
> +
> + For this, we trace all syssgi() syscall exit events. Each time
> + we detect such an event, we iterate over each text memory maps,
> + get its associated fd, and scan the symbol table for __dbx_link().
> + When found, we know that rld has been mapped, and that we can insert
> + the breakpoint at the symbol address. Once the dbx_link() breakpoint
> + has been inserted, the syssgi() notifications are no longer necessary,
> + so they should be canceled. */
> + proc_trace_syscalls_1 (pi, SYS_syssgi, PR_SYSEXIT, FLAG_SET, 0);
> + dbx_link_bpt_addr = 0;
> +#endif
> }
>
> /*
> @@ -5048,6 +5108,16 @@ procfs_create_inferior (char *exec_file,
> fork_inferior (exec_file, allargs, env, procfs_set_exec_trap,
> procfs_init_inferior, NULL, shell_file);
>
> +#ifdef SYS_syssgi
> + /* Make sure to cancel the syssgi() syscall-exit notifications.
> + They should normally have been removed by now, but they may still
> + be activated if the inferior doesn't use shared libraries, or if
> + we didn't locate __dbx_link, or if we never stopped in __dbx_link.
> + See procfs_init_inferior() for more details. */
> + proc_trace_syscalls_1 (find_procinfo_or_die (PIDGET (inferior_ptid), 0),
> + SYS_syssgi, PR_SYSEXIT, FLAG_RESET, 0);
> +#endif
> +
> /* We are at the first instruction we care about. */
> /* Pedal to the metal... */
>
> @@ -5520,6 +5590,131 @@ proc_find_memory_regions (int (*func) (C
> find_memory_regions_callback);
> }
>
> +/* Remove the breakpoint that we inserted in __dbx_link().
> + Does nothing if the breakpoint hasn't been inserted or has already
> + been removed. */
> +
> +static void
> +remove_dbx_link_breakpoint (void)
> +{
> + if (dbx_link_bpt_addr == 0)
> + return;
> +
> + if (memory_remove_breakpoint (dbx_link_bpt_addr,
> + dbx_link_shadow_contents) != 0)
> + warning ("Unable to remove __dbx_link breakpoint.");
> +
> + dbx_link_bpt_addr = 0;
> +}
> +
> +/* Return the address of the __dbx_link() function in the file
> + refernced by ABFD by scanning its symbol table. Return 0 if
> + the symbol was not found. */
> +
> +static CORE_ADDR
> +dbx_link_addr (bfd *abfd)
> +{
> + long storage_needed;
> + asymbol **symbol_table;
> + long number_of_symbols;
> + long i;
> +
> + storage_needed = bfd_get_symtab_upper_bound (abfd);
> + if (storage_needed <= 0)
> + return 0;
> +
> + symbol_table = (asymbol **) xmalloc (storage_needed);
> + make_cleanup (xfree, symbol_table);
> +
> + number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
> +
> + for (i = 0; i < number_of_symbols; i++)
> + {
> + asymbol *sym = symbol_table[i];
> +
> + if ((sym->flags & BSF_GLOBAL)
> + && sym->name != NULL && strcmp (sym->name, "__dbx_link") == 0)
> + return (sym->value + sym->section->vma);
> + }
> +
> + /* Symbol not found, return NULL. */
> + return 0;
> +}
> +
> +/* Search the symbol table of the file referenced by FD for a symbol
> + named __dbx_link(). If found, then insert a breakpoint at this location,
> + and return nonzero. Return zero otherwise. */
> +
> +static int
> +insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored)
> +{
> + bfd *abfd;
> + long storage_needed;
> + CORE_ADDR sym_addr;
> +
> + abfd = bfd_fdopenr ("unamed", 0, fd);
> + if (abfd == NULL)
> + {
> + warning ("Failed to create a bfd: %s.\n", bfd_errmsg (bfd_get_error ()));
> + return 0;
> + }
> +
> + if (!bfd_check_format (abfd, bfd_object))
> + {
> + /* Not the correct format, so we can not possibly find the dbx_link
> + symbol in it. */
> + bfd_close (abfd);
> + return 0;
> + }
> +
> + sym_addr = dbx_link_addr (abfd);
> + if (sym_addr != 0)
> + {
> + /* Insert the breakpoint. */
> + dbx_link_bpt_addr = sym_addr;
> + if (target_insert_breakpoint (sym_addr, dbx_link_shadow_contents) != 0)
> + {
> + warning ("Failed to insert dbx_link breakpoint.");
> + bfd_close (abfd);
> + return 0;
> + }
> + bfd_close (abfd);
> + return 1;
> + }
> +
> + bfd_close (abfd);
> + return 0;
> +}
> +
> +/* If the given memory region MAP contains a symbol named __dbx_link,
> + insert a breakpoint at this location and return nonzero. Return
> + zero otherwise. */
> +
> +static int
> +insert_dbx_link_bpt_in_region (struct prmap *map,
> + int (*child_func) (),
> + void *data)
> +{
> + procinfo *pi = (procinfo *) data;
> +
> + /* We know the symbol we're looking for is in a text region, so
> + only look for it if the region is a text one. */
> + if (map->pr_mflags & MA_EXEC)
> + return solib_mappings_callback (map, insert_dbx_link_bpt_in_file, pi);
> +
> + return 0;
> +}
> +
> +/* Search all memory regions for a symbol named __dbx_link. If found,
> + insert a breakpoint at its location, and return nonzero. Return zero
> + otherwise. */
> +
> +static int
> +insert_dbx_link_breakpoint (procinfo *pi)
> +{
> + return iterate_over_mappings (pi, NULL, pi, insert_dbx_link_bpt_in_region);
> +}
> +
> /*
> * Function: mappingflags
> *
> @@ -5708,12 +5903,50 @@ info_proc_cmd (char *args, int from_tty)
> do_cleanups (old_chain);
> }
>
> +/* Modify the status of the system call identified by SYSCALLNUM in
> + the set of syscalls that are currently traced/debugged.
> +
> + If ENTRY_OR_EXIT is set to PR_SYSENTRY, then the entry syscalls set
> + will be updated. Otherwise, the exit syscalls set will be updated.
> +
> + If MODE is FLAG_SET, then traces will be enabled. Otherwise, they
> + will be disabled. */
> +
> +static void
> +proc_trace_syscalls_1 (procinfo *pi, int syscallnum, int entry_or_exit,
> + int mode, int from_tty)
> +{
> + sysset_t *sysset;
> +
> + if (entry_or_exit == PR_SYSENTRY)
> + sysset = proc_get_traced_sysentry (pi, NULL);
> + else
> + sysset = proc_get_traced_sysexit (pi, NULL);
> +
> + if (sysset == NULL)
> + proc_error (pi, "proc-trace, get_traced_sysset", __LINE__);
> +
> + if (mode == FLAG_SET)
> + gdb_praddsysset (sysset, syscallnum);
> + else
> + gdb_prdelsysset (sysset, syscallnum);
> +
> + if (entry_or_exit == PR_SYSENTRY)
> + {
> + if (!proc_set_traced_sysentry (pi, sysset))
> + proc_error (pi, "proc-trace, set_traced_sysentry", __LINE__);
> + }
> + else
> + {
> + if (!proc_set_traced_sysexit (pi, sysset))
> + proc_error (pi, "proc-trace, set_traced_sysexit", __LINE__);
> + }
> +}
> +
> static void
> proc_trace_syscalls (char *args, int from_tty, int entry_or_exit, int mode)
> {
> procinfo *pi;
> - sysset_t *sysset;
> - int syscallnum = 0;
>
> if (PIDGET (inferior_ptid) <= 0)
> error ("you must be debugging a process to use this command.");
> @@ -5724,30 +5957,9 @@ proc_trace_syscalls (char *args, int fro
> pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
> if (isdigit (args[0]))
> {
> - syscallnum = atoi (args);
> - if (entry_or_exit == PR_SYSENTRY)
> - sysset = proc_get_traced_sysentry (pi, NULL);
> - else
> - sysset = proc_get_traced_sysexit (pi, NULL);
> -
> - if (sysset == NULL)
> - proc_error (pi, "proc-trace, get_traced_sysset", __LINE__);
> -
> - if (mode == FLAG_SET)
> - gdb_praddsysset (sysset, syscallnum);
> - else
> - gdb_prdelsysset (sysset, syscallnum);
> + const int syscallnum = atoi (args);
>
> - if (entry_or_exit == PR_SYSENTRY)
> - {
> - if (!proc_set_traced_sysentry (pi, sysset))
> - proc_error (pi, "proc-trace, set_traced_sysentry", __LINE__);
> - }
> - else
> - {
> - if (!proc_set_traced_sysexit (pi, sysset))
> - proc_error (pi, "proc-trace, set_traced_sysexit", __LINE__);
> - }
> + proc_trace_syscalls_1 (pi, syscallnum, entry_or_exit, mode, from_tty);
> }
> }
>
> Index: solib-irix.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/solib-irix.c,v
> retrieving revision 1.5
> diff -u -p -r1.5 solib-irix.c
> --- solib-irix.c 14 Feb 2004 15:46:33 -0000 1.5
> +++ solib-irix.c 23 Jul 2004 18:01:46 -0000
> @@ -324,15 +324,11 @@ disable_break (void)
> status = 0;
> }
>
> - /* For the SVR4 version, we always know the breakpoint address. For the
> - SunOS version we don't know it until the above code is executed.
> - Grumble if we are stopped anywhere besides the breakpoint address. */
> -
> - if (stop_pc != breakpoint_addr)
> - {
> - warning
> - ("stopped at unknown breakpoint while handling shared libraries");
> - }
> + /* Note that it is possible that we have stopped at a location that
> + is different from the location where we inserted our breakpoint.
> + On mips-irix, we can actually land in __dbx_init(), so we should
> + not check the PC against our breakpoint address here. See procfs.c
> + for more details. */
>
> return (status);
> }
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFA] Enhance GDB to break inside DSO init code
2004-07-23 20:24 [RFA] Enhance GDB to break inside DSO init code Joel Brobecker
` (2 preceding siblings ...)
2004-08-19 7:55 ` Joel Brobecker
@ 2004-08-24 23:45 ` Kevin Buettner
2004-08-27 13:39 ` Joel Brobecker
3 siblings, 1 reply; 8+ messages in thread
From: Kevin Buettner @ 2004-08-24 23:45 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
On Fri, 23 Jul 2004 13:24:47 -0700
Joel Brobecker <brobecker@gnat.com> wrote:
> 2004-07-23 Joel Brobecker <brobecker@gnat.com>
>
> * procfs.c (dbx_link_bpt_addr): New static global variable.
> (dbx_link_shadow_contents): New static global variable.
> (procfs_wait, case <PR_SYSEXIT>): Handle syssgi events.
> (procfs_wait, case <FLTBPT>): Remove the __dbx_link brekapoint
> if we just hit it.
> (procfs_init_inferior): Enable syssgi() syscall trace if appropriate.
> Reset dbx_link_bpt_addr as the address of __dbx_link() may change
> from run to run.
> (procfs_create_inferior): Remove syssgi syscall-exit notifications
> after the inferior has been forked.
> (remove_dbx_link_breakpoint): New function.
> (dbx_link_addr): New function.
> (insert_dbx_link_bpt_in_file): New function.
> (insert_dbx_link_bpt_in_region): New function.
> (insert_dbx_link_breakpoint): New function.
> (proc_trace_syscalls_1): New function, extracted from
> proc_trace_syscalls.
> (proc_trace_syscalls): Replace extract code by call to
> proc_trace_syscalls_1.
> * solib-irix.c (disable_break): Remove stop_pc assertion, as it
> is no longer valid.
>
> Tested on mips-irix, no regression. OK to commit?
Do you have access to a Solaris box? If so, could you test for
regressions there as well?
If all goes well, I have no objection to this patch going in. (Consider
it approved unless someone else says otherwise.)
Kevin
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFA] Enhance GDB to break inside DSO init code
2004-08-24 23:45 ` Kevin Buettner
@ 2004-08-27 13:39 ` Joel Brobecker
0 siblings, 0 replies; 8+ messages in thread
From: Joel Brobecker @ 2004-08-27 13:39 UTC (permalink / raw)
To: Kevin Buettner; +Cc: gdb-patches
Hello Kevin,
> Do you have access to a Solaris box? If so, could you test for
> regressions there as well?
That's a good idea. So I tested the patch on sparc-solaris2.8 as well,
without any regression.
> If all goes well, I have no objection to this patch going in. (Consider
> it approved unless someone else says otherwise.)
I didn't see any objection, so I checked the patch in. Thank you for
the review!
> > 2004-07-23 Joel Brobecker <brobecker@gnat.com>
> >
> > * procfs.c (dbx_link_bpt_addr): New static global variable.
> > (dbx_link_shadow_contents): New static global variable.
> > (procfs_wait, case <PR_SYSEXIT>): Handle syssgi events.
> > (procfs_wait, case <FLTBPT>): Remove the __dbx_link brekapoint
> > if we just hit it.
> > (procfs_init_inferior): Enable syssgi() syscall trace if appropriate.
> > Reset dbx_link_bpt_addr as the address of __dbx_link() may change
> > from run to run.
> > (procfs_create_inferior): Remove syssgi syscall-exit notifications
> > after the inferior has been forked.
> > (remove_dbx_link_breakpoint): New function.
> > (dbx_link_addr): New function.
> > (insert_dbx_link_bpt_in_file): New function.
> > (insert_dbx_link_bpt_in_region): New function.
> > (insert_dbx_link_breakpoint): New function.
> > (proc_trace_syscalls_1): New function, extracted from
> > proc_trace_syscalls.
> > (proc_trace_syscalls): Replace extract code by call to
> > proc_trace_syscalls_1.
> > * solib-irix.c (disable_break): Remove stop_pc assertion, as it
> > is no longer valid.
> >
> > Tested on mips-irix, no regression. OK to commit?
--
Joel
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2004-08-27 13:39 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-07-23 20:24 [RFA] Enhance GDB to break inside DSO init code Joel Brobecker
2004-07-24 7:56 ` Eli Zaretskii
2004-07-24 15:01 ` Joel Brobecker
2004-07-24 17:16 ` Eli Zaretskii
2004-08-06 18:31 ` Joel Brobecker
2004-08-19 7:55 ` Joel Brobecker
2004-08-24 23:45 ` Kevin Buettner
2004-08-27 13:39 ` Joel Brobecker
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox