mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-03 05:12:28 +08:00
* 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:
@ -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>
|
2004-08-25 Jim Blandy <jimb@redhat.com>
|
||||||
|
|
||||||
* gdbtypes.h (TYPE_CODE_ARRAY): Doc fix.
|
* 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 ptid_t do_attach (ptid_t ptid);
|
||||||
static void do_detach (int signo);
|
static void do_detach (int signo);
|
||||||
static int register_gdb_signals (procinfo *, gdb_sigset_t *);
|
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
|
* Function: procfs_debug_inferior
|
||||||
@ -4070,6 +4081,22 @@ wait_again:
|
|||||||
address. */
|
address. */
|
||||||
wstat = (SIGTRAP << 8) | 0177;
|
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))
|
else if (syscall_is_lwp_create (pi, what))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -4196,6 +4223,13 @@ wait_again:
|
|||||||
#if (FLTTRACE != FLTBPT) /* avoid "duplicate case" error */
|
#if (FLTTRACE != FLTBPT) /* avoid "duplicate case" error */
|
||||||
case FLTTRACE:
|
case FLTTRACE:
|
||||||
#endif
|
#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;
|
wstat = (SIGTRAP << 8) | 0177;
|
||||||
break;
|
break;
|
||||||
case FLTSTACK:
|
case FLTSTACK:
|
||||||
@ -4847,6 +4881,32 @@ procfs_init_inferior (int pid)
|
|||||||
/* Typically two, one trap to exec the shell, one to exec the
|
/* Typically two, one trap to exec the shell, one to exec the
|
||||||
program being debugged. Defined by "inferior.h". */
|
program being debugged. Defined by "inferior.h". */
|
||||||
startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
|
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,
|
fork_inferior (exec_file, allargs, env, procfs_set_exec_trap,
|
||||||
procfs_init_inferior, NULL, shell_file);
|
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. */
|
/* We are at the first instruction we care about. */
|
||||||
/* Pedal to the metal... */
|
/* Pedal to the metal... */
|
||||||
|
|
||||||
@ -5515,6 +5585,131 @@ proc_find_memory_regions (int (*func) (CORE_ADDR,
|
|||||||
find_memory_regions_callback);
|
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
|
* Function: mappingflags
|
||||||
*
|
*
|
||||||
@ -5703,12 +5898,50 @@ info_proc_cmd (char *args, int from_tty)
|
|||||||
do_cleanups (old_chain);
|
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
|
static void
|
||||||
proc_trace_syscalls (char *args, int from_tty, int entry_or_exit, int mode)
|
proc_trace_syscalls (char *args, int from_tty, int entry_or_exit, int mode)
|
||||||
{
|
{
|
||||||
procinfo *pi;
|
procinfo *pi;
|
||||||
sysset_t *sysset;
|
|
||||||
int syscallnum = 0;
|
|
||||||
|
|
||||||
if (PIDGET (inferior_ptid) <= 0)
|
if (PIDGET (inferior_ptid) <= 0)
|
||||||
error ("you must be debugging a process to use this command.");
|
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);
|
pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
|
||||||
if (isdigit (args[0]))
|
if (isdigit (args[0]))
|
||||||
{
|
{
|
||||||
syscallnum = atoi (args);
|
const int 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_trace_syscalls_1 (pi, syscallnum, entry_or_exit, mode, from_tty);
|
||||||
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__);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,15 +324,11 @@ disable_break (void)
|
|||||||
status = 0;
|
status = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For the SVR4 version, we always know the breakpoint address. For the
|
/* Note that it is possible that we have stopped at a location that
|
||||||
SunOS version we don't know it until the above code is executed.
|
is different from the location where we inserted our breakpoint.
|
||||||
Grumble if we are stopped anywhere besides the breakpoint address. */
|
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
|
||||||
if (stop_pc != breakpoint_addr)
|
for more details. */
|
||||||
{
|
|
||||||
warning
|
|
||||||
("stopped at unknown breakpoint while handling shared libraries");
|
|
||||||
}
|
|
||||||
|
|
||||||
return (status);
|
return (status);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user