/* Machine independent support for SVR4 /proc (process file system) for GDB.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2006, 2007, 2008, 2009
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Written by Michael Snyder at Cygnus Solutions.
#include "gdb_assert.h"
#include "inflow.h"
#include "auxv.h"
+#include "procfs.h"
+#include "observer.h"
/*
* PROCFS.C
static void procfs_create_inferior (struct target_ops *, char *,
char *, char **, int);
static ptid_t procfs_wait (struct target_ops *,
- ptid_t, struct target_waitstatus *);
+ ptid_t, struct target_waitstatus *, int);
static int procfs_xfer_memory (CORE_ADDR, gdb_byte *, int, int,
struct mem_attrib *attrib,
struct target_ops *);
procfs_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
gdb_byte *ptr = *readptr;
if (endptr == ptr)
if (endptr - ptr < 8 * 2)
return -1;
- *typep = extract_unsigned_integer (ptr, 4);
+ *typep = extract_unsigned_integer (ptr, 4, byte_order);
ptr += 8;
/* The size of data is always 64-bit. If the application is 32-bit,
it will be zero extended, as expected. */
- *valp = extract_unsigned_integer (ptr, 8);
+ *valp = extract_unsigned_integer (ptr, 8, byte_order);
ptr += 8;
*readptr = ptr;
}
#endif
-static struct target_ops *
+struct target_ops *
procfs_target (void)
{
struct target_ops *t = inf_child_target ();
t->to_has_thread_control = tc_schedlock;
t->to_find_memory_regions = proc_find_memory_regions;
t->to_make_corefile_notes = procfs_make_note_section;
- t->to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
#if defined(PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
t->to_auxv_parse = procfs_auxv_parse;
typedef struct siginfo gdb_siginfo_t;
#endif
+/* On mips-irix, praddset and prdelset are defined in such a way that
+ they return a value, which causes GCC to emit a -Wunused error
+ because the returned value is not used. Prevent this warning
+ by casting the return value to void. On sparc-solaris, this issue
+ does not exist because the definition of these macros already include
+ that cast to void. */
+#define gdb_praddset(sp, flag) ((void) praddset (sp, flag))
+#define gdb_prdelset(sp, flag) ((void) prdelset (sp, flag))
+
/* gdb_premptysysset */
#ifdef premptysysset
#define gdb_premptysysset premptysysset
#ifdef praddsysset
#define gdb_praddsysset praddsysset
#else
-#define gdb_praddsysset praddset
+#define gdb_praddsysset gdb_praddset
#endif
/* prdelsysset */
#ifdef prdelsysset
#define gdb_prdelsysset prdelsysset
#else
-#define gdb_prdelsysset prdelset
+#define gdb_prdelsysset gdb_prdelset
#endif
/* prissyssetmember */
static int find_syscall (procinfo *pi, char *name);
#endif /* DYNAMIC_SYSCALLS */
+/* A function type used as a callback back iterate_over_mappings. */
+typedef int (iterate_over_mappings_cb_ftype)
+ (CORE_ADDR vaddr, unsigned long size, int read, int write, int execute,
+ void *data);
+
+static int iterate_over_mappings
+ (procinfo *pi,
+ iterate_over_mappings_cb_ftype *child_func,
+ void *data,
+ int (*func) (struct prmap *map,
+ iterate_over_mappings_cb_ftype *child_func,
+ void *data));
+
/* The head of the procinfo list: */
static procinfo * procinfo_list;
{
if (proc_get_traced_signals (pi, &temp))
{
- praddset (&temp, signo);
+ gdb_praddset (&temp, signo);
return proc_set_traced_signals (pi, &temp);
}
}
{
if (proc_get_traced_signals (pi, &temp))
{
- prdelset (&temp, signo);
+ gdb_prdelset (&temp, signo);
return proc_set_traced_signals (pi, &temp);
}
}
/* Use char array to avoid alignment issues. */
char sinfo[sizeof (gdb_siginfo_t)];
} arg;
- gdb_siginfo_t *mysinfo;
+ gdb_siginfo_t mysinfo;
ptid_t wait_ptid;
struct target_waitstatus wait_status;
#endif
/* The pointer is just a type alias. */
- mysinfo = (gdb_siginfo_t *) &arg.sinfo;
get_last_target_status (&wait_ptid, &wait_status);
if (ptid_equal (wait_ptid, inferior_ptid)
&& wait_status.kind == TARGET_WAITKIND_STOPPED
/* Use the siginfo associated with the signal being
redelivered. */
#ifdef NEW_PROC_API
- memcpy (mysinfo, &pi->prstatus.pr_lwp.pr_info, sizeof (gdb_siginfo_t));
+ memcpy (arg.sinfo, &pi->prstatus.pr_lwp.pr_info, sizeof (gdb_siginfo_t));
#else
- memcpy (mysinfo, &pi->prstatus.pr_info, sizeof (gdb_siginfo_t));
+ memcpy (arg.sinfo, &pi->prstatus.pr_info, sizeof (gdb_siginfo_t));
#endif
else
{
- mysinfo->si_signo = signo;
- mysinfo->si_code = 0;
- mysinfo->si_pid = getpid (); /* ?why? */
- mysinfo->si_uid = getuid (); /* ?why? */
+ mysinfo.si_signo = signo;
+ mysinfo.si_code = 0;
+ mysinfo.si_pid = getpid (); /* ?why? */
+ mysinfo.si_uid = getuid (); /* ?why? */
+ memcpy (arg.sinfo, &mysinfo, sizeof (gdb_siginfo_t));
}
#ifdef NEW_PROC_API
/* Use char array to avoid alignment issues. */
char sinfo[sizeof (gdb_siginfo_t)];
} arg;
- gdb_siginfo_t *mysinfo;
+ gdb_siginfo_t mysinfo;
arg.cmd = PCSSIG;
/* The pointer is just a type alias. */
- mysinfo = (gdb_siginfo_t *) &arg.sinfo;
- mysinfo->si_signo = 0;
- mysinfo->si_code = 0;
- mysinfo->si_errno = 0;
- mysinfo->si_pid = getpid (); /* ?why? */
- mysinfo->si_uid = getuid (); /* ?why? */
+ mysinfo.si_signo = 0;
+ mysinfo.si_code = 0;
+ mysinfo.si_errno = 0;
+ mysinfo.si_pid = getpid (); /* ?why? */
+ mysinfo.si_uid = getuid (); /* ?why? */
+ memcpy (arg.sinfo, &mysinfo, sizeof (gdb_siginfo_t));
win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg));
}
return pi->prstatus.pr_ppid;
}
-
/* Convert a target address (a.k.a. CORE_ADDR) into a host address
(a.k.a void pointer)! */
+#if (defined (PCWATCH) || defined (PIOCSWATCH)) \
+ && !(defined (PIOCOPENLWP) || defined (UNIXWARE))
static void *
procfs_address_to_host_pointer (CORE_ADDR addr)
{
(gdb_byte *) &ptr, addr);
return ptr;
}
+#endif
/*
* Function: proc_set_watchpoint
int
proc_set_watchpoint (procinfo *pi, CORE_ADDR addr, int len, int wflags)
{
-#if !defined (TARGET_HAS_HARDWARE_WATCHPOINTS)
+#if !defined (PCWATCH) && !defined (PIOCSWATCH)
+ /* If neither or these is defined, we can't support watchpoints.
+ This just avoids possibly failing to compile the below on such
+ systems. */
return 0;
#else
/* Horrible hack! Detect Solaris 2.5, because this doesn't work on 2.5 */
procfs_ctl_t cmd;
char watch[sizeof (prwatch_t)];
} arg;
- prwatch_t *pwatch;
+ prwatch_t pwatch;
- pwatch = (prwatch_t *) &arg.watch;
/* NOTE: cagney/2003-02-01: Even more horrible hack. Need to
convert a target address into something that can be stored in a
native data structure. */
#ifdef PCAGENT /* Horrible hack: only defined on Solaris 2.6+ */
- pwatch->pr_vaddr = (uintptr_t) procfs_address_to_host_pointer (addr);
+ pwatch.pr_vaddr = (uintptr_t) procfs_address_to_host_pointer (addr);
#else
- pwatch->pr_vaddr = (caddr_t) procfs_address_to_host_pointer (addr);
+ pwatch.pr_vaddr = (caddr_t) procfs_address_to_host_pointer (addr);
#endif
- pwatch->pr_size = len;
- pwatch->pr_wflags = wflags;
+ pwatch.pr_size = len;
+ pwatch.pr_wflags = wflags;
#if defined(NEW_PROC_API) && defined (PCWATCH)
arg.cmd = PCWATCH;
+ memcpy (arg.watch, &pwatch, sizeof (prwatch_t));
return (write (pi->ctl_fd, &arg, sizeof (arg)) == sizeof (arg));
#else
#if defined (PIOCSWATCH)
- return (ioctl (pi->ctl_fd, PIOCSWATCH, pwatch) >= 0);
+ return (ioctl (pi->ctl_fd, PIOCSWATCH, &pwatch) >= 0);
#else
return 0; /* Fail */
#endif
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
#else
/* Register to trace hardware faults in the child. */
prfillset (&traced_faults); /* trace all faults... */
- prdelset (&traced_faults, FLTPAGE); /* except page fault. */
+ gdb_prdelset (&traced_faults, FLTPAGE); /* except page fault. */
#endif
if (!proc_set_traced_faults (pi, &traced_faults))
return __LINE__;
char *exec_file;
int pid;
- if (!args)
- error_no_arg (_("process-id to attach"));
+ pid = parse_pid_to_attach (args);
- pid = atoi (args);
if (pid == getpid ())
error (_("Attaching GDB to itself is not a good idea..."));
if ((fail = procfs_debug_inferior (pi)) != 0)
dead_procinfo (pi, "do_attach: failed in procfs_debug_inferior", NOKILL);
- inf = add_inferior (pi->pid);
+ inf = current_inferior ();
+ inferior_appeared (inf, pi->pid);
/* Let GDB know that the inferior was attached. */
inf->attach_flag = 1;
return 0;
}
+/* 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 (deprecated_remove_raw_breakpoint (target_gdbarch, dbx_link_bpt) != 0)
+ warning (_("Unable to remove __dbx_link breakpoint."));
+
+ dbx_link_bpt_addr = 0;
+ dbx_link_bpt = NULL;
+}
+
+#ifdef SYS_syssgi
+/* 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."), 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;
+ dbx_link_bpt = deprecated_insert_raw_breakpoint (target_gdbarch, NULL,
+ sym_addr);
+ if (dbx_link_bpt == NULL)
+ {
+ warning (_("Failed to insert dbx_link breakpoint."));
+ bfd_close (abfd);
+ return 0;
+ }
+ bfd_close (abfd);
+ return 1;
+ }
+
+ bfd_close (abfd);
+ return 0;
+}
+
+/* Calls the supplied callback function once for each mapped address
+ space in the process. The callback function receives an open
+ file descriptor for the file corresponding to that mapped
+ address space (if there is one), and the base address of the
+ mapped space. Quit when the callback function returns a
+ nonzero value, or at teh end of the mappings.
+
+ Returns: the first non-zero return value of the callback function,
+ or zero. */
+
+static int
+solib_mappings_callback (struct prmap *map, int (*func) (int, CORE_ADDR),
+ void *data)
+{
+ procinfo *pi = data;
+ int fd;
+
+#ifdef NEW_PROC_API
+ char name[MAX_PROC_NAME_SIZE + sizeof (map->pr_mapname)];
+
+ if (map->pr_vaddr == 0 && map->pr_size == 0)
+ return -1; /* sanity */
+
+ if (map->pr_mapname[0] == 0)
+ {
+ fd = -1; /* no map file */
+ }
+ else
+ {
+ sprintf (name, "/proc/%d/object/%s", pi->pid, map->pr_mapname);
+ /* Note: caller's responsibility to close this fd! */
+ fd = open_with_retry (name, O_RDONLY);
+ /* Note: we don't test the above call for failure;
+ we just pass the FD on as given. Sometimes there is
+ no file, so the open may return failure, but that's
+ not a problem. */
+ }
+#else
+ fd = ioctl (pi->ctl_fd, PIOCOPENM, &map->pr_vaddr);
+ /* Note: we don't test the above call for failure;
+ we just pass the FD on as given. Sometimes there is
+ no file, so the ioctl may return failure, but that's
+ not a problem. */
+#endif
+ return (*func) (fd, (CORE_ADDR) map->pr_vaddr);
+}
+
+/* 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,
+ iterate_over_mappings_cb_ftype *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);
+}
+#endif
+
/*
* Function: target_wait
*
static ptid_t
procfs_wait (struct target_ops *ops,
- ptid_t ptid, struct target_waitstatus *status)
+ ptid_t ptid, struct target_waitstatus *status, int options)
{
/* First cut: loosely based on original version 2.1 */
procinfo *pi;
#ifdef NEW_PROC_API
case TARGET_OBJECT_AUXV:
- return procfs_xfer_auxv (ops, object, annex, readbuf, writebuf,
+ return memory_xfer_auxv (ops, object, annex, readbuf, writebuf,
offset, len);
#endif
if (!proc_set_gregs (pi)) /* flush gregs cache */
proc_warn (pi, "target_resume, set_gregs",
__LINE__);
- if (gdbarch_fp0_regnum (current_gdbarch) >= 0)
+ if (gdbarch_fp0_regnum (target_gdbarch) >= 0)
if (pi->fpregs_dirty)
if (parent == NULL ||
proc_get_current_thread (parent) != pi->tid)
if (signal_stop_state (target_signal_from_host (signo)) == 0 &&
signal_print_state (target_signal_from_host (signo)) == 0 &&
signal_pass_state (target_signal_from_host (signo)) == 1)
- prdelset (signals, signo);
+ gdb_prdelset (signals, signo);
else
- praddset (signals, signo);
+ gdb_praddset (signals, signo);
return proc_set_traced_signals (pi, signals);
}
static void
procfs_stop (ptid_t ptid)
{
- kill (-inferior_process_group, SIGINT);
+ kill (-inferior_process_group (), SIGINT);
}
/*
if (dbx_link_bpt != NULL)
{
- deprecated_remove_raw_breakpoint (dbx_link_bpt);
+ deprecated_remove_raw_breakpoint (target_gdbarch, dbx_link_bpt);
dbx_link_bpt_addr = 0;
dbx_link_bpt = NULL;
}
NULL, NULL, shell_file);
procfs_init_inferior (ops, pid);
+}
+/* An observer for the "inferior_created" event. */
+
+static void
+procfs_inferior_created (struct target_ops *ops, int from_tty)
+{
#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. */
+ See procfs_init_inferior() for more details.
+
+ Since these notifications are only ever enabled when we spawned
+ the inferior ourselves, there is nothing to do when the inferior
+ was created by attaching to an already running process, or when
+ debugging a core file. */
+ if (current_inferior ()->attach_flag || !target_can_run (¤t_target))
+ return;
+
proc_trace_syscalls_1 (find_procinfo_or_die (PIDGET (inferior_ptid), 0),
SYS_syssgi, PR_SYSEXIT, FLAG_RESET, 0);
#endif
Note: procfs_can_use_hw_breakpoint() is not yet used by all
procfs.c targets due to the fact that some of them still define
- TARGET_CAN_USE_HARDWARE_WATCHPOINT. */
+ target_can_use_hardware_watchpoint. */
static int
procfs_can_use_hw_breakpoint (int type, int cnt, int othertype)
{
-#ifndef TARGET_HAS_HARDWARE_WATCHPOINTS
- return 0;
-#else
/* Due to the way that proc_set_watchpoint() is implemented, host
and target pointers must be of the same size. If they are not,
we can't use hardware watchpoints. This limitation is due to the
/* Other tests here??? */
return 1;
-#endif
}
/*
* else returns zero.
*/
-int
-procfs_stopped_by_watchpoint (ptid_t ptid)
+static int
+procfs_stopped_by_watchpoint (void)
{
procinfo *pi;
- pi = find_procinfo_or_die (PIDGET (ptid) == -1 ?
- PIDGET (inferior_ptid) : PIDGET (ptid), 0);
+ pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
if (!pi) /* If no process, then not stopped by watchpoint! */
return 0;
return 0;
}
+static int
+procfs_insert_watchpoint (CORE_ADDR addr, int len, int type)
+{
+ if (!target_have_steppable_watchpoint
+ && !gdbarch_have_nonsteppable_watchpoint (target_gdbarch))
+ {
+ /* When a hardware watchpoint fires off the PC will be left at
+ the instruction following the one which caused the
+ watchpoint. It will *NOT* be necessary for GDB to step over
+ the watchpoint. */
+ return procfs_set_watchpoint (inferior_ptid, addr, len, type, 1);
+ }
+ else
+ {
+ /* When a hardware watchpoint fires off the PC will be left at
+ the instruction which caused the watchpoint. It will be
+ necessary for GDB to step over the watchpoint. */
+ return procfs_set_watchpoint (inferior_ptid, addr, len, type, 0);
+ }
+}
+
+static int
+procfs_remove_watchpoint (CORE_ADDR addr, int len, int type)
+{
+ return procfs_set_watchpoint (inferior_ptid, addr, 0, 0, 0);
+}
+
+static int
+procfs_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
+{
+ /* The man page for proc(4) on Solaris 2.6 and up says that the
+ system can support "thousands" of hardware watchpoints, but gives
+ no method for finding out how many; It doesn't say anything about
+ the allowed size for the watched area either. So we just tell
+ GDB 'yes'. */
+ return 1;
+}
+
+void
+procfs_use_watchpoints (struct target_ops *t)
+{
+ t->to_stopped_by_watchpoint = procfs_stopped_by_watchpoint;
+ t->to_insert_watchpoint = procfs_insert_watchpoint;
+ t->to_remove_watchpoint = procfs_remove_watchpoint;
+ t->to_region_ok_for_hw_watchpoint = procfs_region_ok_for_hw_watchpoint;
+ t->to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
+}
+
/*
* Memory Mappings Functions:
*/
*/
static int
-iterate_over_mappings (procinfo *pi, int (*child_func) (), void *data,
+iterate_over_mappings (procinfo *pi,
+ iterate_over_mappings_cb_ftype *child_func,
+ void *data,
int (*func) (struct prmap *map,
- int (*child_func) (),
+ iterate_over_mappings_cb_ftype *child_func,
void *data))
{
char pathname[MAX_PROC_NAME_SIZE];
return 0;
}
-/*
- * Function: solib_mappings_callback
- *
- * Calls the supplied callback function once for each mapped address
- * space in the process. The callback function receives an open
- * file descriptor for the file corresponding to that mapped
- * address space (if there is one), and the base address of the
- * mapped space. Quit when the callback function returns a
- * nonzero value, or at teh end of the mappings.
- *
- * Returns: the first non-zero return value of the callback function,
- * or zero.
- */
-
-int solib_mappings_callback (struct prmap *map,
- int (*func) (int, CORE_ADDR),
- void *data)
-{
- procinfo *pi = data;
- int fd;
-
-#ifdef NEW_PROC_API
- char name[MAX_PROC_NAME_SIZE + sizeof (map->pr_mapname)];
-
- if (map->pr_vaddr == 0 && map->pr_size == 0)
- return -1; /* sanity */
-
- if (map->pr_mapname[0] == 0)
- {
- fd = -1; /* no map file */
- }
- else
- {
- sprintf (name, "/proc/%d/object/%s", pi->pid, map->pr_mapname);
- /* Note: caller's responsibility to close this fd! */
- fd = open_with_retry (name, O_RDONLY);
- /* Note: we don't test the above call for failure;
- we just pass the FD on as given. Sometimes there is
- no file, so the open may return failure, but that's
- not a problem. */
- }
-#else
- fd = ioctl (pi->ctl_fd, PIOCOPENM, &map->pr_vaddr);
- /* Note: we don't test the above call for failure;
- we just pass the FD on as given. Sometimes there is
- no file, so the ioctl may return failure, but that's
- not a problem. */
-#endif
- return (*func) (fd, (CORE_ADDR) map->pr_vaddr);
-}
-
-/*
- * Function: proc_iterate_over_mappings
- *
- * Uses the unified "iterate_over_mappings" function
- * to implement the exported interface to solib-svr4.c.
- *
- * Given a pointer to a function, call that function once for every
- * mapped address space in the process. The callback function
- * receives an open file descriptor for the file corresponding to
- * that mapped address space (if there is one), and the base address
- * of the mapped space. Quit when the callback function returns a
- * nonzero value, or at teh end of the mappings.
- *
- * Returns: the first non-zero return value of the callback function,
- * or zero.
- */
-
-int
-proc_iterate_over_mappings (int (*func) (int, CORE_ADDR))
-{
- procinfo *pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
-
- return iterate_over_mappings (pi, func, pi, solib_mappings_callback);
-}
-
/*
* Function: 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 (deprecated_remove_raw_breakpoint (dbx_link_bpt) != 0)
- warning (_("Unable to remove __dbx_link breakpoint."));
-
- dbx_link_bpt_addr = 0;
- dbx_link_bpt = NULL;
-}
-
-/* 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."), 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;
- dbx_link_bpt = deprecated_insert_raw_breakpoint (sym_addr);
- if (dbx_link_bpt == NULL)
- {
- 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
*
*/
static int
-info_mappings_callback (struct prmap *map, int (*ignore) (), void *unused)
+info_mappings_callback (struct prmap *map,
+ iterate_over_mappings_cb_ftype *ignore,
+ void *unused)
{
unsigned int pr_off;
pr_off = map->pr_off;
#endif
- if (gdbarch_addr_bit (current_gdbarch) == 32)
+ if (gdbarch_addr_bit (target_gdbarch) == 32)
printf_filtered ("\t%#10lx %#10lx %#10lx %#10x %7s\n",
(unsigned long) map->pr_vaddr,
(unsigned long) map->pr_vaddr + map->pr_size - 1,
return; /* No output for summary mode. */
printf_filtered (_("Mapped address spaces:\n\n"));
- if (gdbarch_ptr_bit (current_gdbarch) == 32)
+ if (gdbarch_ptr_bit (target_gdbarch) == 32)
printf_filtered ("\t%10s %10s %10s %10s %7s\n",
"Start Addr",
" End Addr",
void
_initialize_procfs (void)
{
- struct target_ops * t;
-
- t = procfs_target ();
-
- add_target (t);
+ observer_attach_inferior_created (procfs_inferior_created);
add_info ("proc", info_proc_cmd, _("\
Show /proc process information about any running process.\n\
return pid_to_ptid (procinfo_list ? procinfo_list->pid : -1);
}
-static int
-find_signalled_thread (struct thread_info *info, void *data)
-{
- if (info->stop_signal != TARGET_SIGNAL_0
- && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid))
- return 1;
-
- return 0;
-}
-
-static enum target_signal
-find_stop_signal (void)
-{
- struct thread_info *info =
- iterate_over_threads (find_signalled_thread, NULL);
-
- if (info)
- return info->stop_signal;
- else
- return TARGET_SIGNAL_0;
-}
-
/* =================== GCORE .NOTE "MODULE" =================== */
#if defined (UNIXWARE) || defined (PIOCOPENLWP) || defined (PCAGENT)
/* gcore only implemented on solaris and unixware (so far) */
gdb_gregset_t gregs;
gdb_fpregset_t fpregs;
unsigned long merged_pid;
+ struct cleanup *old_chain;
merged_pid = TIDGET (ptid) << 16 | PIDGET (ptid);
+ /* This part is the old method for fetching registers.
+ It should be replaced by the newer one using regsets
+ once it is implemented in this platform:
+ gdbarch_regset_from_core_section() and regset->collect_regset(). */
+
+ old_chain = save_inferior_ptid ();
+ inferior_ptid = ptid;
+ target_fetch_registers (regcache, -1);
+
fill_gregset (regcache, &gregs, -1);
-#if defined (UNIXWARE)
+#if defined (NEW_PROC_API)
note_data = (char *) elfcore_write_lwpstatus (obfd,
note_data,
note_size,
note_size,
&fpregs,
sizeof (fpregs));
+
+ do_cleanups (old_chain);
+
return note_data;
}
if (pi != NULL)
{
- ptid_t saved_ptid = inferior_ptid;
- inferior_ptid = MERGEPID (pi->pid, thread->tid);
- args->note_data = procfs_do_thread_registers (args->obfd, inferior_ptid,
+ ptid_t ptid = MERGEPID (pi->pid, thread->tid);
+ args->note_data = procfs_do_thread_registers (args->obfd, ptid,
args->note_data,
args->note_size,
args->stop_signal);
- inferior_ptid = saved_ptid;
}
return 0;
}
+static int
+find_signalled_thread (struct thread_info *info, void *data)
+{
+ if (info->stop_signal != TARGET_SIGNAL_0
+ && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid))
+ return 1;
+
+ return 0;
+}
+
+static enum target_signal
+find_stop_signal (void)
+{
+ struct thread_info *info =
+ iterate_over_threads (find_signalled_thread, NULL);
+
+ if (info)
+ return info->stop_signal;
+ else
+ return TARGET_SIGNAL_0;
+}
+
static char *
procfs_make_note_section (bfd *obfd, int *note_size)
{
struct procfs_corefile_thread_data thread_args;
gdb_byte *auxv;
int auxv_len;
+ enum target_signal stop_signal;
if (get_exec_file (0))
{
fname,
psargs);
+ stop_signal = find_stop_signal ();
+
#ifdef UNIXWARE
fill_gregset (get_current_regcache (), &gregs, -1);
note_data = elfcore_write_pstatus (obfd, note_data, note_size,
thread_args.obfd = obfd;
thread_args.note_data = note_data;
thread_args.note_size = note_size;
- thread_args.stop_signal = find_stop_signal ();
+ thread_args.stop_signal = stop_signal;
proc_iterate_over_threads (pi, procfs_corefile_thread_callback, &thread_args);
/* There should be always at least one thread. */