#include "defs.h"
#include "floatformat.h"
#include "frame.h"
#include "frame-unwind.h"
#include "osabi.h"
#include "solib-svr4.h"
#include "symtab.h"
#include "trad-frame.h"
#include "gdb_assert.h"
#include "sparc-tdep.h"
static const int sparc32obsd_page_size = 4096;
static int
sparc32obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
{
CORE_ADDR start_pc = (pc & ~(sparc32obsd_page_size - 1));
unsigned long insn;
if (name)
return 0;
insn = sparc_fetch_instruction (start_pc + 0xec);
if (insn != 0x83e82067)
return 0;
insn = sparc_fetch_instruction (start_pc + 0xf4);
if (insn != 0x91d02000)
return 0;
return 1;
}
static struct sparc_frame_cache *
sparc32obsd_frame_cache (struct frame_info *next_frame, void **this_cache)
{
struct sparc_frame_cache *cache;
CORE_ADDR addr;
if (*this_cache)
return *this_cache;
cache = sparc_frame_cache (next_frame, this_cache);
gdb_assert (cache == *this_cache);
if (cache->pc == 0)
{
cache->pc = frame_pc_unwind (next_frame);
cache->pc &= ~(sparc32obsd_page_size - 1);
cache->frameless_p = 0;
addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
cache->base = addr;
}
cache->saved_regs = sparc32nbsd_sigcontext_saved_regs (next_frame);
return cache;
}
static void
sparc32obsd_frame_this_id (struct frame_info *next_frame, void **this_cache,
struct frame_id *this_id)
{
struct sparc_frame_cache *cache =
sparc32obsd_frame_cache (next_frame, this_cache);
(*this_id) = frame_id_build (cache->base, cache->pc);
}
static void
sparc32obsd_frame_prev_register (struct frame_info *next_frame,
void **this_cache,
int regnum, int *optimizedp,
enum lval_type *lvalp, CORE_ADDR *addrp,
int *realnump, gdb_byte *valuep)
{
struct sparc_frame_cache *cache =
sparc32obsd_frame_cache (next_frame, this_cache);
trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum,
optimizedp, lvalp, addrp, realnump, valuep);
}
static const struct frame_unwind sparc32obsd_frame_unwind =
{
SIGTRAMP_FRAME,
sparc32obsd_frame_this_id,
sparc32obsd_frame_prev_register
};
static const struct frame_unwind *
sparc32obsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
{
CORE_ADDR pc = frame_pc_unwind (next_frame);
char *name;
find_pc_partial_function (pc, &name, NULL, NULL);
if (sparc32obsd_pc_in_sigtramp (pc, name))
return &sparc32obsd_frame_unwind;
return NULL;
}
static void
sparc32obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
sparc32nbsd_elf_init_abi (info, gdbarch);
frame_unwind_append_sniffer (gdbarch, sparc32obsd_sigtramp_frame_sniffer);
}
void _initialize_sparc32obsd_tdep (void);
void
_initialize_sparc32obsd_tdep (void)
{
gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_OPENBSD_ELF,
sparc32obsd_init_abi);
}