#include "gdb_string.h"
#include "gdb_assert.h"
#include "inflow.h"
+#include "auxv.h"
/*
* PROCFS.C
static void procfs_prepare_to_store (void);
static void procfs_kill_inferior (void);
static void procfs_mourn_inferior (void);
-static void procfs_create_inferior (char *, char *, char **);
+static void procfs_create_inferior (char *, char *, char **, int);
static ptid_t procfs_wait (ptid_t, struct target_waitstatus *);
static int procfs_xfer_memory (CORE_ADDR, char *, int, int,
struct mem_attrib *attrib,
struct target_ops *);
+static LONGEST procfs_xfer_partial (struct target_ops *ops,
+ enum target_object object,
+ const char *annex,
+ void *readbuf, const void *writebuf,
+ ULONGEST offset, LONGEST len);
static int procfs_thread_alive (ptid_t);
procfs_ops.to_prepare_to_store = procfs_prepare_to_store;
procfs_ops.to_fetch_registers = procfs_fetch_registers;
procfs_ops.to_store_registers = procfs_store_registers;
- procfs_ops.to_xfer_memory = procfs_xfer_memory;
+ procfs_ops.to_xfer_partial = procfs_xfer_partial;
+ procfs_ops.deprecated_xfer_memory = procfs_xfer_memory;
procfs_ops.to_insert_breakpoint = memory_insert_breakpoint;
procfs_ops.to_remove_breakpoint = memory_remove_breakpoint;
procfs_ops.to_notice_signals = procfs_notice_signals;
return win;
}
-/*
- * Function: proc_get_gregs
- *
- * Get the general registers for the process or LWP.
- * Returns non-zero for success, zero for failure.
- */
+/* Return the general-purpose registers for the process or LWP
+ corresponding to PI. Upon failure, return NULL. */
gdb_gregset_t *
proc_get_gregs (procinfo *pi)
if (!proc_get_status (pi))
return NULL;
- /*
- * OK, sorry about the ifdef's.
- * There's three cases instead of two, because
- * in this instance Unixware and Solaris/RW differ.
- */
+ /* OK, sorry about the ifdef's. There's three cases instead of two,
+ because in this case Unixware and Solaris/RW differ. */
#ifdef NEW_PROC_API
-#ifdef UNIXWARE /* ugh, a true architecture dependency */
+# ifdef UNIXWARE /* FIXME: Should be autoconfigured. */
return &pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs;
-#else /* not Unixware */
+# else
return &pi->prstatus.pr_lwp.pr_reg;
-#endif /* Unixware */
-#else /* not NEW_PROC_API */
+# endif
+#else
return &pi->prstatus.pr_reg;
-#endif /* NEW_PROC_API */
+#endif
}
-/*
- * Function: proc_get_fpregs
- *
- * Get the floating point registers for the process or LWP.
- * Returns non-zero for success, zero for failure.
- */
+/* Return the general-purpose registers for the process or LWP
+ corresponding to PI. Upon failure, return NULL. */
gdb_fpregset_t *
proc_get_fpregs (procinfo *pi)
if (!proc_get_status (pi))
return NULL;
-#ifdef UNIXWARE /* a true architecture dependency */
+# ifdef UNIXWARE /* FIXME: Should be autoconfigured. */
return &pi->prstatus.pr_lwp.pr_context.uc_mcontext.fpregs;
-#else
+# else
return &pi->prstatus.pr_lwp.pr_fpreg;
-#endif /* Unixware */
+# endif
-#else /* not NEW_PROC_API */
+#else /* not NEW_PROC_API */
if (pi->fpregs_valid)
- return &pi->fpregset; /* already got 'em */
+ return &pi->fpregset; /* Already got 'em. */
else
{
- if (pi->ctl_fd == 0 &&
- open_procinfo_files (pi, FD_CTL) == 0)
+ if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0)
{
return NULL;
}
else
{
-#ifdef PIOCTGFPREG
+# ifdef PIOCTGFPREG
struct {
long pr_count;
tid_t pr_error_thread;
thread_fpregs.pr_count = 1;
thread_fpregs.thread_1.tid = pi->tid;
- if (pi->tid == 0 &&
- ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset) >= 0)
+ if (pi->tid == 0
+ && ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset) >= 0)
{
pi->fpregs_valid = 1;
- return &pi->fpregset; /* got 'em now! */
+ return &pi->fpregset; /* Got 'em now! */
}
- else if (pi->tid != 0 &&
- ioctl (pi->ctl_fd, PIOCTGFPREG, &thread_fpregs) >= 0)
+ else if (pi->tid != 0
+ && ioctl (pi->ctl_fd, PIOCTGFPREG, &thread_fpregs) >= 0)
{
memcpy (&pi->fpregset, &thread_fpregs.thread_1.pr_fpregs,
sizeof (pi->fpregset));
pi->fpregs_valid = 1;
- return &pi->fpregset; /* got 'em now! */
+ return &pi->fpregset; /* Got 'em now! */
}
else
{
return NULL;
}
-#else
+# else
if (ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset) >= 0)
{
pi->fpregs_valid = 1;
- return &pi->fpregset; /* got 'em now! */
+ return &pi->fpregset; /* Got 'em now! */
}
else
{
return NULL;
}
-#endif
+# endif
}
}
-#endif
+#endif /* NEW_PROC_API */
}
-/*
- * Function: proc_set_gregs
- *
- * Write the general registers back to the process or LWP.
- * Returns non-zero for success, zero for failure.
- */
+/* Write the general-purpose registers back to the process or LWP
+ corresponding to PI. Return non-zero for success, zero for
+ failure. */
int
proc_set_gregs (procinfo *pi)
gdb_gregset_t *gregs;
int win;
- if ((gregs = proc_get_gregs (pi)) == NULL)
- return 0; /* get_regs has already warned */
+ gregs = proc_get_gregs (pi);
+ if (gregs == NULL)
+ return 0; /* proc_get_regs has already warned. */
- if (pi->ctl_fd == 0 &&
- open_procinfo_files (pi, FD_CTL) == 0)
+ if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0)
{
return 0;
}
char gregs[sizeof (gdb_gregset_t)];
} arg;
- arg.cmd = PCSREG;
+ arg.cmd = PCSREG;
memcpy (&arg.gregs, gregs, sizeof (arg.gregs));
win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg));
#else
#endif
}
- /* Policy: writing the regs invalidates our cache. */
+ /* Policy: writing the registers invalidates our cache. */
pi->gregs_valid = 0;
return win;
}
-/*
- * Function: proc_set_fpregs
- *
- * Modify the floating point register set of the process or LWP.
- * Returns non-zero for success, zero for failure.
- */
+/* Write the floating-pointer registers back to the process or LWP
+ corresponding to PI. Return non-zero for success, zero for
+ failure. */
int
proc_set_fpregs (procinfo *pi)
gdb_fpregset_t *fpregs;
int win;
- if ((fpregs = proc_get_fpregs (pi)) == NULL)
- return 0; /* get_fpregs has already warned */
+ fpregs = proc_get_fpregs (pi);
+ if (fpregs == NULL)
+ return 0; /* proc_get_fpregs has already warned. */
- if (pi->ctl_fd == 0 &&
- open_procinfo_files (pi, FD_CTL) == 0)
+ if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0)
{
return 0;
}
char fpregs[sizeof (gdb_fpregset_t)];
} arg;
- arg.cmd = PCSFPREG;
+ arg.cmd = PCSFPREG;
memcpy (&arg.fpregs, fpregs, sizeof (arg.fpregs));
win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg));
#else
-#ifdef PIOCTSFPREG
+# ifdef PIOCTSFPREG
if (pi->tid == 0)
win = (ioctl (pi->ctl_fd, PIOCSFPREG, fpregs) >= 0);
else
sizeof (*fpregs));
win = (ioctl (pi->ctl_fd, PIOCTSFPREG, &thread_fpregs) >= 0);
}
-#else
+# else
win = (ioctl (pi->ctl_fd, PIOCSFPREG, fpregs) >= 0);
-#endif /* osf PIOCTSFPREG */
-#endif /* NEW_PROC_API */
+# endif
+#endif /* NEW_PROC_API */
}
- /* Policy: writing the regs invalidates our cache. */
+ /* Policy: writing the registers invalidates our cache. */
pi->fpregs_valid = 0;
return win;
}
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
static void
procfs_detach (char *args, int from_tty)
{
- char *exec_file;
- int signo = 0;
+ int sig = 0;
+
+ if (args)
+ sig = atoi (args);
if (from_tty)
{
+ int pid = PIDGET (inferior_ptid);
+ char *exec_file;
+
exec_file = get_exec_file (0);
- if (exec_file == 0)
+ if (exec_file == NULL)
exec_file = "";
- printf_filtered ("Detaching from program: %s %s\n",
- exec_file, target_pid_to_str (inferior_ptid));
- fflush (stdout);
+
+ printf_filtered ("Detaching from program: %s, %s\n", exec_file,
+ target_pid_to_str (pid_to_ptid (pid)));
+ gdb_flush (gdb_stdout);
}
- if (args)
- signo = atoi (args);
- do_detach (signo);
+ do_detach (sig);
+
inferior_ptid = null_ptid;
- unpush_target (&procfs_ops); /* Pop out of handling an inferior */
+ unpush_target (&procfs_ops);
}
static ptid_t
destroy_procinfo (pi);
}
-/*
- * fetch_registers
- *
- * Since the /proc interface cannot give us individual registers,
- * we pay no attention to the (regno) argument, and just fetch them all.
- * This results in the possibility that we will do unnecessarily many
- * fetches, since we may be called repeatedly for individual registers.
- * So we cache the results, and mark the cache invalid when the process
- * is resumed.
- */
+/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
+ for all registers.
+
+ ??? Is the following note still relevant? We can't get individual
+ registers with the PT_GETREGS ptrace(2) request either, yet we
+ don't bother with caching at all in that case.
+
+ NOTE: Since the /proc interface cannot give us individual
+ registers, we pay no attention to REGNUM, and just fetch them all.
+ This results in the possibility that we will do unnecessarily many
+ fetches, since we may be called repeatedly for individual
+ registers. So we cache the results, and mark the cache invalid
+ when the process is resumed. */
static void
-procfs_fetch_registers (int regno)
+procfs_fetch_registers (int regnum)
{
- gdb_fpregset_t *fpregs;
- gdb_gregset_t *gregs;
- procinfo *pi;
- int pid;
- int tid;
-
- pid = PIDGET (inferior_ptid);
- tid = TIDGET (inferior_ptid);
+ gdb_gregset_t *gregs;
+ procinfo *pi;
+ int pid = PIDGET (inferior_ptid);
+ int tid = TIDGET (inferior_ptid);
- /* First look up procinfo for the main process. */
- pi = find_procinfo_or_die (pid, 0);
+ /* First look up procinfo for the main process. */
+ pi = find_procinfo_or_die (pid, 0);
/* If the event thread is not the same as GDB's requested thread
(ie. inferior_ptid), then look up procinfo for the requested
thread. */
- if ((tid != 0) &&
- (tid != proc_get_current_thread (pi)))
+ if (tid != 0 && tid != proc_get_current_thread (pi))
pi = find_procinfo_or_die (pid, tid);
if (pi == NULL)
error ("procfs: fetch_registers failed to find procinfo for %s",
target_pid_to_str (inferior_ptid));
- if ((gregs = proc_get_gregs (pi)) == NULL)
+ gregs = proc_get_gregs (pi);
+ if (gregs == NULL)
proc_error (pi, "fetch_registers, get_gregs", __LINE__);
supply_gregset (gregs);
- if (FP0_REGNUM >= 0) /* need floating point? */
+ if (FP0_REGNUM >= 0) /* Do we have an FPU? */
{
- if ((regno >= 0 && regno < FP0_REGNUM)
- || regno == PC_REGNUM
- || regno == DEPRECATED_FP_REGNUM
- || regno == SP_REGNUM)
- return; /* not a floating point register */
+ gdb_fpregset_t *fpregs;
- if ((fpregs = proc_get_fpregs (pi)) == NULL)
+ if ((regnum >= 0 && regnum < FP0_REGNUM)
+ || regnum == PC_REGNUM
+ || regnum == SP_REGNUM)
+ return; /* Not a floating point register. */
+
+ fpregs = proc_get_fpregs (pi);
+ if (fpregs == NULL)
proc_error (pi, "fetch_registers, get_fpregs", __LINE__);
supply_fpregset (fpregs);
#endif
}
-/*
- * store_registers
- *
- * Since the /proc interface will not read individual registers,
- * we will cache these requests until the process is resumed, and
- * only then write them back to the inferior process.
- *
- * FIXME: is that a really bad idea? Have to think about cases
- * where writing one register might affect the value of others, etc.
- */
+/* Store register REGNUM back into the inferior. If REGNUM is -1, do
+ this for all registers.
+
+ NOTE: Since the /proc interface will not read individual registers,
+ we will cache these requests until the process is resumed, and only
+ then write them back to the inferior process.
+
+ FIXME: is that a really bad idea? Have to think about cases where
+ writing one register might affect the value of others, etc. */
static void
-procfs_store_registers (int regno)
+procfs_store_registers (int regnum)
{
- gdb_fpregset_t *fpregs;
- gdb_gregset_t *gregs;
- procinfo *pi;
- int pid;
- int tid;
-
- pid = PIDGET (inferior_ptid);
- tid = TIDGET (inferior_ptid);
-
- /* First find procinfo for main process */
- pi = find_procinfo_or_die (pid, 0);
+ gdb_gregset_t *gregs;
+ procinfo *pi;
+ int pid = PIDGET (inferior_ptid);
+ int tid = TIDGET (inferior_ptid);
- /* If current lwp for process is not the same as requested thread
- (ie. inferior_ptid), then find procinfo for the requested thread. */
+ /* First find procinfo for main process. */
+ pi = find_procinfo_or_die (pid, 0);
- if ((tid != 0) &&
- (tid != proc_get_current_thread (pi)))
+ /* If the event thread is not the same as GDB's requested thread
+ (ie. inferior_ptid), then look up procinfo for the requested
+ thread. */
+ if (tid != 0 && tid != proc_get_current_thread (pi))
pi = find_procinfo_or_die (pid, tid);
if (pi == NULL)
error ("procfs: store_registers: failed to find procinfo for %s",
target_pid_to_str (inferior_ptid));
- if ((gregs = proc_get_gregs (pi)) == NULL)
+ gregs = proc_get_gregs (pi);
+ if (gregs == NULL)
proc_error (pi, "store_registers, get_gregs", __LINE__);
- fill_gregset (gregs, regno);
+ fill_gregset (gregs, regnum);
if (!proc_set_gregs (pi))
proc_error (pi, "store_registers, set_gregs", __LINE__);
- if (FP0_REGNUM >= 0) /* need floating point? */
+ if (FP0_REGNUM >= 0) /* Do we have an FPU? */
{
- if ((regno >= 0 && regno < FP0_REGNUM)
- || regno == PC_REGNUM
- || regno == DEPRECATED_FP_REGNUM
- || regno == SP_REGNUM)
- return; /* not a floating point register */
+ gdb_fpregset_t *fpregs;
+
+ if ((regnum >= 0 && regnum < FP0_REGNUM)
+ || regnum == PC_REGNUM
+ || regnum == SP_REGNUM)
+ return; /* Not a floating point register. */
- if ((fpregs = proc_get_fpregs (pi)) == NULL)
+ fpregs = proc_get_fpregs (pi);
+ if (fpregs == NULL)
proc_error (pi, "store_registers, get_fpregs", __LINE__);
- fill_fpregset (fpregs, regno);
+ fill_fpregset (fpregs, regnum);
if (!proc_set_fpregs (pi))
proc_error (pi, "store_registers, set_fpregs", __LINE__);
}
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))
{
/*
#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:
return retval;
}
+/* Perform a partial transfer to/from the specified object. For
+ memory transfers, fall back to the old memory xfer functions. */
+
+static LONGEST
+procfs_xfer_partial (struct target_ops *ops, enum target_object object,
+ const char *annex, void *readbuf,
+ const void *writebuf, ULONGEST offset, LONGEST len)
+{
+ switch (object)
+ {
+ case TARGET_OBJECT_MEMORY:
+ if (readbuf)
+ return (*ops->deprecated_xfer_memory) (offset, readbuf, len,
+ 0/*write*/, NULL, ops);
+ if (writebuf)
+ return (*ops->deprecated_xfer_memory) (offset, writebuf, len,
+ 1/*write*/, NULL, ops);
+ return -1;
+
+#ifdef NEW_PROC_API
+ case TARGET_OBJECT_AUXV:
+ return procfs_xfer_auxv (ops, object, annex, readbuf, writebuf,
+ offset, len);
+#endif
+
+ default:
+ if (ops->beneath != NULL)
+ return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
+ readbuf, writebuf, offset, len);
+ return -1;
+ }
+}
+
+
/* Transfer LEN bytes between GDB address MYADDR and target address
MEMADDR. If DOWRITE is non-zero, transfer them to the target,
otherwise transfer them from the target. TARGET is unused.
the actual process ID plus the lwp ID. */
inferior_ptid = MERGEPID (pi->pid, proc_get_current_thread (pi));
-#ifdef START_INFERIOR_TRAPS_EXPECTED
+ /* 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);
-#else
- /* One trap to exec the shell, one to exec the program being debugged. */
- startup_inferior (2);
-#endif /* 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
}
/*
*/
static void
-procfs_create_inferior (char *exec_file, char *allargs, char **env)
+procfs_create_inferior (char *exec_file, char *allargs, char **env,
+ int from_tty)
{
char *shell_file = getenv ("SHELL");
char *tryname;
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... */
return 1;
}
-/*
- * Function: target_pid_to_str
- *
- * Return a string to be used to identify the thread in
- * the "info threads" display.
- */
+/* Convert PTID to a string. Returns the string in a static buffer. */
char *
procfs_pid_to_str (ptid_t ptid)
{
static char buf[80];
- int proc, thread;
- procinfo *pi;
-
- proc = PIDGET (ptid);
- thread = TIDGET (ptid);
- pi = find_procinfo (proc, thread);
- if (thread == 0)
- sprintf (buf, "Process %d", proc);
+ if (TIDGET (ptid) == 0)
+ sprintf (buf, "process %d", PIDGET (ptid));
else
- sprintf (buf, "LWP %d", thread);
- return &buf[0];
+ sprintf (buf, "LWP %ld", TIDGET (ptid));
+
+ return buf;
}
/*
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
*
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.");
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);
}
}
char *note_data = NULL;
char *inf_args;
struct procfs_corefile_thread_data thread_args;
+ char *auxv;
+ int auxv_len;
if (get_exec_file (0))
{
note_data = thread_args.note_data;
}
+ auxv_len = target_auxv_read (¤t_target, &auxv);
+ if (auxv_len > 0)
+ {
+ note_data = elfcore_write_note (obfd, note_data, note_size,
+ "CORE", NT_AUXV, auxv, auxv_len);
+ xfree (auxv);
+ }
+
make_cleanup (xfree, note_data);
return note_data;
}