* 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:
Joel Brobecker 2004-08-27 13:37:42 +00:00
parent e5b2549632
commit 9185ddce96
3 changed files with 266 additions and 34 deletions

View file

@ -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.

View file

@ -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,23 +5898,21 @@ 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 (char *args, int from_tty, int entry_or_exit, int mode)
proc_trace_syscalls_1 (procinfo *pi, int syscallnum, int entry_or_exit,
int mode, int from_tty)
{
procinfo *pi;
sysset_t *sysset;
int syscallnum = 0;
if (PIDGET (inferior_ptid) <= 0)
error ("you must be debugging a process to use this command.");
if (args == NULL || args[0] == 0)
error_no_arg ("system call to trace");
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
@ -5743,6 +5936,25 @@ proc_trace_syscalls (char *args, int from_tty, int entry_or_exit, int mode)
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;
if (PIDGET (inferior_ptid) <= 0)
error ("you must be debugging a process to use this command.");
if (args == NULL || args[0] == 0)
error_no_arg ("system call to trace");
pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
if (isdigit (args[0]))
{
const int syscallnum = atoi (args);
proc_trace_syscalls_1 (pi, syscallnum, entry_or_exit, mode, from_tty);
}
}

View file

@ -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);
}