/* 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
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 */
{
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));
}
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;
+}
+
+/* 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);
+}
+#endif
+
/*
* Function: target_wait
*
#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);
}
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
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
}
/*
procfs_insert_watchpoint (CORE_ADDR addr, int len, int type)
{
if (!target_have_steppable_watchpoint
- && !gdbarch_have_nonsteppable_watchpoint (current_gdbarch))
+ && !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
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;
}
/*
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
*
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 ();
-
-#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
- procfs_use_watchpoints (t);
-#endif
-
- 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\
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;
}
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. */