#include "defs.h"
#include "frame.h"
#include "gdbcore.h"
#include "symtab.h"
#include "objfiles.h"
#include "osabi.h"
#include "regset.h"
#include "target.h"
#include "gdb_assert.h"
#include "gdb_string.h"
#include "amd64-tdep.h"
#include "i387-tdep.h"
#include "solib-svr4.h"
static void
amd64obsd_supply_regset (const struct regset *regset,
struct regcache *regcache, int regnum,
const void *regs, size_t len)
{
const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FXSAVE);
i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset);
amd64_supply_fxsave (regcache, regnum,
((const gdb_byte *)regs) + tdep->sizeof_gregset);
}
static const struct regset *
amd64obsd_regset_from_core_section (struct gdbarch *gdbarch,
const char *sect_name, size_t sect_size)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
if (strcmp (sect_name, ".reg") == 0
&& sect_size >= tdep->sizeof_gregset + I387_SIZEOF_FXSAVE)
{
if (tdep->gregset == NULL)
tdep->gregset = regset_alloc (gdbarch, amd64obsd_supply_regset, NULL);
return tdep->gregset;
}
return NULL;
}
static const int amd64obsd_page_size = 4096;
static int
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 gdb_byte sigreturn[] =
{
0x48, 0xc7, 0xc0,
0x67, 0x00, 0x00, 0x00,
0xcd, 0x80
};
size_t buflen = (sizeof sigreturn) + 1;
gdb_byte *buf;
char *name;
find_pc_partial_function (pc, &name, NULL, NULL);
if (name != NULL)
return 0;
if (find_pc_section (pc) != NULL)
return 0;
buf = alloca ((sizeof sigreturn) + 1);
if (!safe_frame_unwind_memory (next_frame, start_pc + 6, buf, buflen))
return 0;
if (memcmp (buf, sigreturn, sizeof sigreturn)
&& memcpy (buf + 1, sigreturn, sizeof sigreturn))
return 0;
return 1;
}
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));
if (offset > 5)
return frame_unwind_register_unsigned (next_frame, AMD64_RDI_REGNUM);
else
return frame_unwind_register_unsigned (next_frame, AMD64_RSP_REGNUM);
}
int amd64obsd_r_reg_offset[] =
{
14 * 8,
13 * 8,
3 * 8,
2 * 8,
1 * 8,
0 * 8,
12 * 8,
15 * 8,
4 * 8,
5 * 8,
6 * 8,
7 * 8,
8 * 8,
9 * 8,
10 * 8,
11 * 8,
16 * 8,
17 * 8,
18 * 8,
19 * 8,
20 * 8,
21 * 8,
22 * 8,
23 * 8
};
static int amd64obsd_sc_reg_offset[] =
{
14 * 8,
13 * 8,
3 * 8,
2 * 8,
1 * 8,
0 * 8,
12 * 8,
24 * 8,
4 * 8,
5 * 8,
6 * 8,
7 * 8,
8 * 8,
9 * 8,
10 * 8,
11 * 8,
21 * 8,
23 * 8,
22 * 8,
25 * 8,
18 * 8,
17 * 8,
16 * 8,
15 * 8
};
static void
amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
amd64_init_abi (info, gdbarch);
tdep->gregset_reg_offset = amd64obsd_r_reg_offset;
tdep->gregset_num_regs = ARRAY_SIZE (amd64obsd_r_reg_offset);
tdep->sizeof_gregset = 24 * 8;
set_gdbarch_regset_from_core_section (gdbarch,
amd64obsd_regset_from_core_section);
tdep->jb_pc_offset = 7 * 8;
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);
set_solib_svr4_fetch_link_map_offsets
(gdbarch, svr4_lp64_fetch_link_map_offsets);
}
void _initialize_amd64obsd_tdep (void);
void
_initialize_amd64obsd_tdep (void)
{
gdb_assert (ARRAY_SIZE (amd64obsd_r_reg_offset) == AMD64_NUM_GREGS);
gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
GDB_OSABI_OPENBSD_ELF, amd64obsd_init_abi);
gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
GDB_OSABI_NETBSD_AOUT, amd64obsd_init_abi);
}