summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/binutils/gdb
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2005-12-04 20:36:09 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2005-12-04 20:36:09 +0000
commit855285a7671aca79b64b58cc81aa4838bb4a8860 (patch)
tree371e92f52b1ea327c2526bb570aa68190e072d37 /gnu/usr.bin/binutils/gdb
parent8f92ccf32d35daa299b8702171a6c321de61556a (diff)
amd64 threads support.
Diffstat (limited to 'gnu/usr.bin/binutils/gdb')
-rw-r--r--gnu/usr.bin/binutils/gdb/amd64obsd-tdep.c190
-rw-r--r--gnu/usr.bin/binutils/gdb/valops.c47
2 files changed, 197 insertions, 40 deletions
diff --git a/gnu/usr.bin/binutils/gdb/amd64obsd-tdep.c b/gnu/usr.bin/binutils/gdb/amd64obsd-tdep.c
index 198c87e4a28..04589538ae2 100644
--- a/gnu/usr.bin/binutils/gdb/amd64obsd-tdep.c
+++ b/gnu/usr.bin/binutils/gdb/amd64obsd-tdep.c
@@ -22,7 +22,10 @@
#include "defs.h"
#include "frame.h"
#include "gdbcore.h"
+#include "symtab.h"
+#include "objfiles.h"
#include "osabi.h"
+#include "regcache.h"
#include "regset.h"
#include "target.h"
@@ -32,6 +35,7 @@
#include "amd64-tdep.h"
#include "i387-tdep.h"
#include "solib-svr4.h"
+#include "bsd-uthread.h"
/* Support for core dumps. */
@@ -40,7 +44,7 @@ amd64obsd_supply_regset (const struct regset *regset,
struct regcache *regcache, int regnum,
const void *regs, size_t len)
{
- const struct gdbarch_tdep *tdep = regset->descr;
+ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FXSAVE);
@@ -61,11 +65,7 @@ amd64obsd_regset_from_core_section (struct gdbarch *gdbarch,
&& sect_size >= tdep->sizeof_gregset + I387_SIZEOF_FXSAVE)
{
if (tdep->gregset == NULL)
- {
- tdep->gregset = XMALLOC (struct regset);
- tdep->gregset->descr = tdep;
- tdep->gregset->supply_regset = amd64obsd_supply_regset;
- }
+ tdep->gregset = regset_alloc (gdbarch, amd64obsd_supply_regset, NULL);
return tdep->gregset;
}
@@ -75,11 +75,16 @@ amd64obsd_regset_from_core_section (struct gdbarch *gdbarch,
/* Support for signal handlers. */
+/* Default page size. */
static const int amd64obsd_page_size = 4096;
+/* Return whether the frame preceding NEXT_FRAME corresponds to an
+ OpenBSD sigtramp routine. */
+
static int
-amd64obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
+amd64obsd_sigtramp_p (struct frame_info *next_frame)
{
+ CORE_ADDR pc = frame_pc_unwind (next_frame);
CORE_ADDR start_pc = (pc & ~(amd64obsd_page_size - 1));
const char sigreturn[] =
{
@@ -87,18 +92,30 @@ amd64obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
0x67, 0x00, 0x00, 0x00, /* movq $SYS_sigreturn, %rax */
0xcd, 0x80 /* int $0x80 */
};
- char *buf;
+ size_t buflen = (sizeof sigreturn) + 1;
+ char *name, *buf;
- if (name)
+ /* If the function has a valid symbol name, it isn't a
+ trampoline. */
+ find_pc_partial_function (pc, &name, NULL, NULL);
+ if (name != NULL)
+ return 0;
+
+ /* If the function lives in a valid section (even without a starting
+ point) it isn't a trampoline. */
+ if (find_pc_section (pc) != NULL)
return 0;
/* If we can't read the instructions at START_PC, return zero. */
- buf = alloca (sizeof sigreturn);
- if (target_read_memory (start_pc + 0x7, buf, sizeof sigreturn))
+ buf = alloca ((sizeof sigreturn) + 1);
+ if (!safe_frame_unwind_memory (next_frame, start_pc + 6, buf, buflen))
return 0;
- /* Check for sigreturn(2). */
- if (memcmp (buf, sigreturn, sizeof sigreturn))
+ /* Check for sigreturn(2). Depending on how the assembler encoded
+ the `movq %rsp, %rdi' instruction, the code starts at offset 6 or
+ 7. */
+ if (memcmp (buf, sigreturn, sizeof sigreturn)
+ && memcpy (buf + 1, sigreturn, sizeof sigreturn))
return 0;
return 1;
@@ -110,9 +127,25 @@ amd64obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
static CORE_ADDR
amd64obsd_sigcontext_addr (struct frame_info *next_frame)
{
+ CORE_ADDR pc = frame_pc_unwind (next_frame);
+ ULONGEST offset = (pc & (amd64obsd_page_size - 1));
+
/* The %rsp register points at `struct sigcontext' upon entry of a
- signal trampoline. */
- return frame_unwind_register_unsigned (next_frame, AMD64_RSP_REGNUM);
+ signal trampoline. The relevant part of the trampoline is
+
+ call *%rax
+ movq %rsp, %rdi
+ pushq %rdi
+ movq $SYS_sigreturn,%rax
+ int $0x80
+
+ (see /usr/src/sys/arch/amd64/amd64/locore.S). The `pushq'
+ instruction clobbers %rsp, but its value is saved in `%rdi'. */
+
+ if (offset > 5)
+ return frame_unwind_register_unsigned (next_frame, AMD64_RDI_REGNUM);
+ else
+ return frame_unwind_register_unsigned (next_frame, AMD64_RSP_REGNUM);
}
/* OpenBSD 3.5 or later. */
@@ -178,6 +211,127 @@ static int amd64obsd_sc_reg_offset[] =
15 * 8 /* %gs */
};
+/* From /usr/src/lib/libpthread/arch/amd64/uthread_machdep.c. */
+static int amd64obsd_uthread_reg_offset[] =
+{
+ 19 * 8, /* %rax */
+ 16 * 8, /* %rbx */
+ 18 * 8, /* %rcx */
+ 17 * 8, /* %rdx */
+ 14 * 8, /* %rsi */
+ 13 * 8, /* %rdi */
+ 15 * 8, /* %rbp */
+ -1, /* %rsp */
+ 12 * 8, /* %r8 ... */
+ 11 * 8,
+ 10 * 8,
+ 9 * 8,
+ 8 * 8,
+ 7 * 8,
+ 6 * 8,
+ 5 * 8, /* ... %r15 */
+ 20 * 8, /* %rip */
+ 4 * 8, /* %eflags */
+ 21 * 8, /* %cs */
+ -1, /* %ss */
+ 3 * 8, /* %ds */
+ 2 * 8, /* %es */
+ 1 * 8, /* %fs */
+ 0 * 8 /* %gs */
+};
+
+/* Offset within the thread structure where we can find the saved
+ stack pointer (%esp). */
+#define AMD64OBSD_UTHREAD_RSP_OFFSET 400
+
+static void
+amd64obsd_supply_uthread (struct regcache *regcache,
+ int regnum, CORE_ADDR addr)
+{
+ CORE_ADDR sp_addr = addr + AMD64OBSD_UTHREAD_RSP_OFFSET;
+ CORE_ADDR sp = 0;
+ char buf[8];
+ int i;
+
+ gdb_assert (regnum >= -1);
+
+ if (regnum == -1 || regnum == AMD64_RSP_REGNUM)
+ {
+ int offset;
+
+ /* Fetch stack pointer from thread structure. */
+ sp = read_memory_unsigned_integer (sp_addr, 8);
+
+ /* Adjust the stack pointer such that it looks as if we just
+ returned from _thread_machdep_switch. */
+ offset = amd64obsd_uthread_reg_offset[AMD64_RIP_REGNUM] + 8;
+ store_unsigned_integer (buf, 8, sp + offset);
+ regcache_raw_supply (regcache, AMD64_RSP_REGNUM, buf);
+ }
+
+ for (i = 0; i < ARRAY_SIZE (amd64obsd_uthread_reg_offset); i++)
+ {
+ if (amd64obsd_uthread_reg_offset[i] != -1
+ && (regnum == -1 || regnum == i))
+ {
+ /* Fetch stack pointer from thread structure (if we didn't
+ do so already). */
+ if (sp == 0)
+ sp = read_memory_unsigned_integer (sp_addr, 8);
+
+ /* Read the saved register from the stack frame. */
+ read_memory (sp + amd64obsd_uthread_reg_offset[i], buf, 8);
+ regcache_raw_supply (regcache, i, buf);
+ }
+ }
+}
+
+static void
+amd64obsd_collect_uthread (const struct regcache *regcache,
+ int regnum, CORE_ADDR addr)
+{
+ CORE_ADDR sp_addr = addr + AMD64OBSD_UTHREAD_RSP_OFFSET;
+ CORE_ADDR sp = 0;
+ char buf[8];
+ int i;
+
+ gdb_assert (regnum >= -1);
+
+ if (regnum == -1 || regnum == AMD64_RSP_REGNUM)
+ {
+ int offset;
+
+ /* Calculate the stack pointer (frame pointer) that will be
+ stored into the thread structure. */
+ offset = amd64obsd_uthread_reg_offset[AMD64_RIP_REGNUM] + 8;
+ regcache_raw_collect (regcache, AMD64_RSP_REGNUM, buf);
+ sp = extract_unsigned_integer (buf, 8) - offset;
+
+ /* Store the stack pointer. */
+ write_memory_unsigned_integer (sp_addr, 8, sp);
+
+ /* The stack pointer was (potentially) modified. Make sure we
+ build a proper stack frame. */
+ regnum = -1;
+ }
+
+ for (i = 0; i < ARRAY_SIZE (amd64obsd_uthread_reg_offset); i++)
+ {
+ if (amd64obsd_uthread_reg_offset[i] != -1
+ && (regnum == -1 || regnum == i))
+ {
+ /* Fetch stack pointer from thread structure (if we didn't
+ calculate it already). */
+ if (sp == 0)
+ sp = read_memory_unsigned_integer (sp_addr, 8);
+
+ /* Write the register into the stack frame. */
+ regcache_raw_collect (regcache, i, buf);
+ write_memory (sp + amd64obsd_uthread_reg_offset[i], buf, 8);
+ }
+ }
+}
+
static void
amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
@@ -195,11 +349,15 @@ amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tdep->jb_pc_offset = 7 * 8;
- set_gdbarch_pc_in_sigtramp (gdbarch, amd64obsd_pc_in_sigtramp);
+ tdep->sigtramp_p = amd64obsd_sigtramp_p;
tdep->sigcontext_addr = amd64obsd_sigcontext_addr;
tdep->sc_reg_offset = amd64obsd_sc_reg_offset;
tdep->sc_num_regs = ARRAY_SIZE (amd64obsd_sc_reg_offset);
+ /* OpenBSD provides a user-level threads implementation. */
+ bsd_uthread_set_supply_uthread (gdbarch, amd64obsd_supply_uthread);
+ bsd_uthread_set_collect_uthread (gdbarch, amd64obsd_collect_uthread);
+
/* OpenBSD uses SVR4-style shared libraries. */
set_solib_svr4_fetch_link_map_offsets
(gdbarch, svr4_lp64_fetch_link_map_offsets);
diff --git a/gnu/usr.bin/binutils/gdb/valops.c b/gnu/usr.bin/binutils/gdb/valops.c
index 575c9a335ea..13ad2b5548f 100644
--- a/gnu/usr.bin/binutils/gdb/valops.c
+++ b/gnu/usr.bin/binutils/gdb/valops.c
@@ -132,37 +132,36 @@ struct value *
find_function_in_inferior (const char *name)
{
struct symbol *sym;
+ struct minimal_symbol *msymbol;
+
sym = lookup_symbol (name, 0, VAR_DOMAIN, 0, NULL);
if (sym != NULL)
{
if (SYMBOL_CLASS (sym) != LOC_BLOCK)
- {
- error ("\"%s\" exists in this program but is not a function.",
- name);
- }
- return value_of_variable (sym, NULL);
+ error (_("\"%s\" exists in this program but is not a function."),
+ name);
+
+ if (TYPE_PROTOTYPED (SYMBOL_TYPE (sym)))
+ return value_of_variable (sym, NULL);
}
- else
+
+ msymbol = lookup_minimal_symbol (name, NULL, NULL);
+ if (msymbol != NULL)
{
- struct minimal_symbol *msymbol = lookup_minimal_symbol (name, NULL, NULL);
- if (msymbol != NULL)
- {
- struct type *type;
- CORE_ADDR maddr;
- type = lookup_pointer_type (builtin_type_char);
- type = lookup_function_type (type);
- type = lookup_pointer_type (type);
- maddr = SYMBOL_VALUE_ADDRESS (msymbol);
- return value_from_pointer (type, maddr);
- }
- else
- {
- if (!target_has_execution)
- error ("evaluation of this expression requires the target program to be active");
- else
- error ("evaluation of this expression requires the program to have a function \"%s\".", name);
- }
+ struct type *type;
+ CORE_ADDR maddr;
+
+ type = lookup_pointer_type (builtin_type_char);
+ type = lookup_function_type (type);
+ type = lookup_pointer_type (type);
+ maddr = SYMBOL_VALUE_ADDRESS (msymbol);
+ return value_from_pointer (type, maddr);
}
+
+ if (!target_has_execution)
+ error ("evaluation of this expression requires the target program to be active");
+ else
+ error ("evaluation of this expression requires the program to have a function \"%s\".", name);
}
/* Allocate NBYTES of space in the inferior using the inferior's malloc