* 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.
This commit is contained in:
parent
e5b2549632
commit
9185ddce96
3 changed files with 266 additions and 34 deletions
|
@ -1,3 +1,27 @@
|
|||
2004-08-27 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.
|
||||
|
||||
2004-08-25 Jim Blandy <jimb@redhat.com>
|
||||
|
||||
* gdbtypes.h (TYPE_CODE_ARRAY): Doc fix.
|
||||
|
|
262
gdb/procfs.c
262
gdb/procfs.c
|
@ -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
|
||||
|
@ -4070,6 +4081,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))
|
||||
{
|
||||
/*
|
||||
|
@ -4196,6 +4223,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:
|
||||
|
@ -4847,6 +4881,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
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -5053,6 +5113,16 @@ procfs_create_inferior (char *exec_file, char *allargs, char **env,
|
|||
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... */
|
||||
|
||||
|
@ -5515,6 +5585,131 @@ proc_find_memory_regions (int (*func) (CORE_ADDR,
|
|||
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
|
||||
*
|
||||
|
@ -5703,12 +5898,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.");
|
||||
|
@ -5719,30 +5952,9 @@ proc_trace_syscalls (char *args, int from_tty, int entry_or_exit, int mode)
|
|||
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);
|
||||
const int syscallnum = atoi (args);
|
||||
|
||||
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__);
|
||||
}
|
||||
proc_trace_syscalls_1 (pi, syscallnum, entry_or_exit, mode, from_tty);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue