/* Machine independent support for SVR4 /proc (process file system) for GDB.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2006, 2007
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2006, 2007, 2008
Free Software Foundation, Inc.
Written by Michael Snyder at Cygnus Solutions.
Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others.
-This file is part of GDB.
+ This file is part of GDB.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "inferior.h"
static void procfs_detach (char *, int);
static void procfs_resume (ptid_t, int, enum target_signal);
static int procfs_can_run (void);
-static void procfs_stop (void);
+static void procfs_stop (ptid_t);
static void procfs_files_info (struct target_ops *);
static void procfs_fetch_registers (struct regcache *, int);
static void procfs_store_registers (struct regcache *, int);
struct target_ops procfs_ops; /* the target vector */
+#if defined (PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
+/* When GDB is built as 64-bit application on Solaris, the auxv data is
+ presented in 64-bit format. We need to provide a custom parser to handle
+ that. */
+static int
+procfs_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
+ gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
+{
+ const int pointer_size = TYPE_LENGTH (builtin_type_void_data_ptr);
+ gdb_byte *ptr = *readptr;
+
+ if (endptr == ptr)
+ return 0;
+
+ if (endptr - ptr < 8 * 2)
+ return -1;
+
+ *typep = extract_unsigned_integer (ptr, 4);
+ 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);
+ ptr += 8;
+
+ *readptr = ptr;
+ return 1;
+}
+#endif
+
static void
init_procfs_ops (void)
{
procfs_ops.to_find_memory_regions = proc_find_memory_regions;
procfs_ops.to_make_corefile_notes = procfs_make_note_section;
procfs_ops.to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
+
+#if defined(PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
+ procfs_ops.to_auxv_parse = procfs_auxv_parse;
+#endif
+
procfs_ops.to_magic = OPS_MAGIC;
}
char sinfo[sizeof (gdb_siginfo_t)];
} arg;
gdb_siginfo_t *mysinfo;
+ ptid_t wait_ptid;
+ struct target_waitstatus wait_status;
/*
* We should never have to apply this operation to any procinfo
/* The pointer is just a type alias. */
mysinfo = (gdb_siginfo_t *) &arg.sinfo;
- mysinfo->si_signo = signo;
- mysinfo->si_code = 0;
- mysinfo->si_pid = getpid (); /* ?why? */
- mysinfo->si_uid = getuid (); /* ?why? */
+ get_last_target_status (&wait_ptid, &wait_status);
+ if (ptid_equal (wait_ptid, inferior_ptid)
+ && wait_status.kind == TARGET_WAITKIND_STOPPED
+ && wait_status.value.sig == target_signal_from_host (signo)
+ && proc_get_status (pi)
+#ifdef NEW_PROC_API
+ && pi->prstatus.pr_lwp.pr_info.si_signo == signo
+#else
+ && pi->prstatus.pr_info.si_signo == signo
+#endif
+ )
+ /* 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));
+#else
+ memcpy (mysinfo, &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? */
+ }
#ifdef NEW_PROC_API
arg.cmd = PCSSIG;
void *ptr;
gdb_assert (sizeof (ptr) == TYPE_LENGTH (builtin_type_void_data_ptr));
- ADDRESS_TO_POINTER (builtin_type_void_data_ptr, &ptr, addr);
+ gdbarch_address_to_pointer (current_gdbarch, builtin_type_void_data_ptr,
+ &ptr, addr);
return ptr;
}
#endif
}
-#ifdef TM_I386SOL2_H /* Is it hokey to use this? */
+#if (defined(__i386__) || defined(__x86_64__)) && defined (sun)
#include <sys/sysi86.h>
#endif
}
-#endif /* TM_I386SOL2_H */
+/*
+ * Function: procfs_find_LDT_entry
+ *
+ * Input:
+ * ptid_t ptid; // The GDB-style pid-plus-LWP.
+ *
+ * Return:
+ * pointer to the corresponding LDT entry.
+ */
+
+struct ssd *
+procfs_find_LDT_entry (ptid_t ptid)
+{
+ gdb_gregset_t *gregs;
+ int key;
+ procinfo *pi;
+
+ /* Find procinfo for the lwp. */
+ if ((pi = find_procinfo (PIDGET (ptid), TIDGET (ptid))) == NULL)
+ {
+ warning (_("procfs_find_LDT_entry: could not find procinfo for %d:%d."),
+ PIDGET (ptid), TIDGET (ptid));
+ return NULL;
+ }
+ /* get its general registers. */
+ if ((gregs = proc_get_gregs (pi)) == NULL)
+ {
+ warning (_("procfs_find_LDT_entry: could not read gregs for %d:%d."),
+ PIDGET (ptid), TIDGET (ptid));
+ return NULL;
+ }
+ /* Now extract the GS register's lower 16 bits. */
+ key = (*gregs)[GS] & 0xffff;
+
+ /* Find the matching entry and return it. */
+ return proc_get_LDT_entry (pi, key);
+}
+
+#endif
/* =============== END, non-thread part of /proc "MODULE" =============== */
procinfo *pi;
int pid = PIDGET (inferior_ptid);
int tid = TIDGET (inferior_ptid);
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
/* First look up procinfo for the main process. */
pi = find_procinfo_or_die (pid, 0);
supply_gregset (regcache, (const gdb_gregset_t *) gregs);
- if (FP0_REGNUM >= 0) /* Do we have an FPU? */
+ if (gdbarch_fp0_regnum (gdbarch) >= 0) /* Do we have an FPU? */
{
gdb_fpregset_t *fpregs;
- if ((regnum >= 0 && regnum < FP0_REGNUM)
- || regnum == PC_REGNUM
- || regnum == SP_REGNUM)
+ if ((regnum >= 0 && regnum < gdbarch_fp0_regnum (gdbarch))
+ || regnum == gdbarch_pc_regnum (gdbarch)
+ || regnum == gdbarch_sp_regnum (gdbarch))
return; /* Not a floating point register. */
fpregs = proc_get_fpregs (pi);
procinfo *pi;
int pid = PIDGET (inferior_ptid);
int tid = TIDGET (inferior_ptid);
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
/* First find procinfo for main process. */
pi = find_procinfo_or_die (pid, 0);
if (!proc_set_gregs (pi))
proc_error (pi, "store_registers, set_gregs", __LINE__);
- if (FP0_REGNUM >= 0) /* Do we have an FPU? */
+ if (gdbarch_fp0_regnum (gdbarch) >= 0) /* Do we have an FPU? */
{
gdb_fpregset_t *fpregs;
- if ((regnum >= 0 && regnum < FP0_REGNUM)
- || regnum == PC_REGNUM
- || regnum == SP_REGNUM)
+ if ((regnum >= 0 && regnum < gdbarch_fp0_regnum (gdbarch))
+ || regnum == gdbarch_pc_regnum (gdbarch)
+ || regnum == gdbarch_sp_regnum (gdbarch))
return; /* Not a floating point register. */
fpregs = proc_get_fpregs (pi);
case PR_SYSENTRY:
if (syscall_is_lwp_exit (pi, what))
{
- printf_filtered (_("[%s exited]\n"),
- target_pid_to_str (retval));
+ if (print_thread_events)
+ printf_unfiltered (_("[%s exited]\n"),
+ target_pid_to_str (retval));
delete_thread (retval);
status->kind = TARGET_WAITKIND_SPURIOUS;
return retval;
temp_ptid = MERGEPID (pi->pid, temp_tid);
/* If not in GDB's thread list, add it. */
if (!in_thread_list (temp_ptid))
- {
- printf_filtered (_("[New %s]\n"),
- target_pid_to_str (temp_ptid));
- add_thread (temp_ptid);
- }
+ add_thread (temp_ptid);
+
/* Return to WFI, but tell it to immediately resume. */
status->kind = TARGET_WAITKIND_SPURIOUS;
return inferior_ptid;
}
else if (syscall_is_lwp_exit (pi, what))
{
- printf_filtered (_("[%s exited]\n"),
- target_pid_to_str (retval));
+ if (print_thread_events)
+ printf_unfiltered (_("[%s exited]\n"),
+ target_pid_to_str (retval));
delete_thread (retval);
status->kind = TARGET_WAITKIND_SPURIOUS;
return retval;
/* If not in GDB's thread list, add it. */
temp_ptid = MERGEPID (pi->pid, temp_tid);
if (!in_thread_list (temp_ptid))
- {
- printf_filtered (_("[New %s]\n"),
- target_pid_to_str (temp_ptid));
- add_thread (temp_ptid);
- }
+ add_thread (temp_ptid);
status->kind = TARGET_WAITKIND_STOPPED;
status->value.sig = 0;
* If we don't create a procinfo, resume may be unhappy
* later.
*/
- printf_filtered (_("[New %s]\n"), target_pid_to_str (retval));
add_thread (retval);
if (find_procinfo (PIDGET (retval), TIDGET (retval)) == NULL)
create_procinfo (PIDGET (retval), TIDGET (retval));
case TARGET_OBJECT_MEMORY:
if (readbuf)
return (*ops->deprecated_xfer_memory) (offset, readbuf, len,
- 0/*write*/, NULL, ops);
+ 0/*read*/, NULL, ops);
if (writebuf)
return (*ops->deprecated_xfer_memory) (offset, writebuf, len,
1/*write*/, NULL, ops);
if (!proc_set_gregs (pi)) /* flush gregs cache */
proc_warn (pi, "target_resume, set_gregs",
__LINE__);
- if (FP0_REGNUM >= 0)
+ if (gdbarch_fp0_regnum (current_gdbarch) >= 0)
if (pi->fpregs_dirty)
if (parent == NULL ||
proc_get_current_thread (parent) != pi->tid)
*/
static void
-procfs_stop (void)
+procfs_stop (ptid_t ptid)
{
kill (-inferior_process_group, SIGINT);
}
return 0;
}
-#ifdef TM_I386SOL2_H
-/*
- * Function: procfs_find_LDT_entry
- *
- * Input:
- * ptid_t ptid; // The GDB-style pid-plus-LWP.
- *
- * Return:
- * pointer to the corresponding LDT entry.
- */
-
-struct ssd *
-procfs_find_LDT_entry (ptid_t ptid)
-{
- gdb_gregset_t *gregs;
- int key;
- procinfo *pi;
-
- /* Find procinfo for the lwp. */
- if ((pi = find_procinfo (PIDGET (ptid), TIDGET (ptid))) == NULL)
- {
- warning (_("procfs_find_LDT_entry: could not find procinfo for %d:%d."),
- PIDGET (ptid), TIDGET (ptid));
- return NULL;
- }
- /* get its general registers. */
- if ((gregs = proc_get_gregs (pi)) == NULL)
- {
- warning (_("procfs_find_LDT_entry: could not read gregs for %d:%d."),
- PIDGET (ptid), TIDGET (ptid));
- return NULL;
- }
- /* Now extract the GS register's lower 16 bits. */
- key = (*gregs)[GS] & 0xffff;
-
- /* Find the matching entry and return it. */
- return proc_get_LDT_entry (pi, key);
-}
-#endif /* TM_I386SOL2_H */
-
/*
* Memory Mappings Functions:
*/
{
char *data_fmt_string;
- if (TARGET_ADDR_BIT == 32)
+ if (gdbarch_addr_bit (current_gdbarch) == 32)
data_fmt_string = "\t%#10lx %#10lx %#10x %#10x %7s\n";
else
data_fmt_string = " %#18lx %#18lx %#10x %#10x %7s\n";
{
char *header_fmt_string;
- if (TARGET_PTR_BIT == 32)
+ if (gdbarch_ptr_bit (current_gdbarch) == 32)
header_fmt_string = "\t%10s %10s %10s %10s %7s\n";
else
header_fmt_string = " %18s %18s %10s %10s %7s\n";
procfs_do_thread_registers (bfd *obfd, ptid_t ptid,
char *note_data, int *note_size)
{
+ struct regcache *regcache = get_thread_regcache (ptid);
gdb_gregset_t gregs;
gdb_fpregset_t fpregs;
unsigned long merged_pid;
merged_pid = TIDGET (ptid) << 16 | PIDGET (ptid);
- fill_gregset (current_regcache, &gregs, -1);
+ fill_gregset (regcache, &gregs, -1);
#if defined (UNIXWARE)
note_data = (char *) elfcore_write_lwpstatus (obfd,
note_data,
stop_signal,
&gregs);
#endif
- fill_fpregset (current_regcache, &fpregs, -1);
+ fill_fpregset (regcache, &fpregs, -1);
note_data = (char *) elfcore_write_prfpreg (obfd,
note_data,
note_size,
psargs);
#ifdef UNIXWARE
- fill_gregset (current_regcache, &gregs, -1);
+ fill_gregset (get_current_regcache (), &gregs, -1);
note_data = elfcore_write_pstatus (obfd, note_data, note_size,
PIDGET (inferior_ptid),
stop_signal, &gregs);