i386-macosx-tdep.c [plain text]
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include "gdbcore.h"
#include "target.h"
#include "floatformat.h"
#include "symtab.h"
#include "regcache.h"
#include "i387-tdep.h"
#include "i386-tdep.h"
#include "osabi.h"
#include "i386-macosx-thread-status.h"
#include <mach/thread_status.h>
#include "i386-macosx-tdep.h"
enum gdb_osabi osabi_seen_in_attached_dyld = GDB_OSABI_UNKNOWN;
#define supply_unsigned_int(regnum, val)\
store_unsigned_integer (buf, 4, val); \
supply_register(regnum, buf);
#define collect_unsigned_int(regnum, addr)\
regcache_collect (regnum, buf); \
(* (addr)) = extract_unsigned_integer (buf, 4);
void
i386_macosx_fetch_gp_registers (gdb_i386_thread_state_t *sp_regs)
{
char buf[4];
supply_unsigned_int (0, sp_regs->eax);
supply_unsigned_int (1, sp_regs->ecx);
supply_unsigned_int (2, sp_regs->edx);
supply_unsigned_int (3, sp_regs->ebx);
supply_unsigned_int (4, sp_regs->esp);
supply_unsigned_int (5, sp_regs->ebp);
supply_unsigned_int (6, sp_regs->esi);
supply_unsigned_int (7, sp_regs->edi);
supply_unsigned_int (8, sp_regs->eip);
supply_unsigned_int (9, sp_regs->efl);
supply_unsigned_int (10, sp_regs->cs);
supply_unsigned_int (11, sp_regs->ss);
supply_unsigned_int (12, sp_regs->ds);
supply_unsigned_int (13, sp_regs->es);
supply_unsigned_int (14, sp_regs->fs);
supply_unsigned_int (15, sp_regs->gs);
}
void
i386_macosx_store_gp_registers (gdb_i386_thread_state_t *sp_regs)
{
unsigned char buf[4];
collect_unsigned_int (0, &sp_regs->eax);
collect_unsigned_int (1, &sp_regs->ecx);
collect_unsigned_int (2, &sp_regs->edx);
collect_unsigned_int (3, &sp_regs->ebx);
collect_unsigned_int (4, &sp_regs->esp);
collect_unsigned_int (5, &sp_regs->ebp);
collect_unsigned_int (6, &sp_regs->esi);
collect_unsigned_int (7, &sp_regs->edi);
collect_unsigned_int (8, &sp_regs->eip);
collect_unsigned_int (9, &sp_regs->efl);
collect_unsigned_int (10, &sp_regs->cs);
collect_unsigned_int (11, &sp_regs->ss);
collect_unsigned_int (12, &sp_regs->ds);
collect_unsigned_int (13, &sp_regs->es);
collect_unsigned_int (14, &sp_regs->fs);
collect_unsigned_int (15, &sp_regs->gs);
}
void
i386_macosx_fetch_fp_registers (gdb_i386_thread_fpstate_t *fp_regs)
{
i387_swap_fxsave (current_regcache, &fp_regs->hw_fu_state);
i387_supply_fxsave (current_regcache, -1, &fp_regs->hw_fu_state);
}
int
i386_macosx_store_fp_registers (gdb_i386_thread_fpstate_t *fp_regs)
{
memset (fp_regs, 0, sizeof (gdb_i386_thread_fpstate_t));
fp_regs->fpkind = GDB_i386_FP_SSE2;
fp_regs->initialized = 1;
fp_regs->exc_status = 0;
i387_fill_fxsave ((unsigned char *) &fp_regs->hw_fu_state, -1);
i387_swap_fxsave (current_regcache, &fp_regs->hw_fu_state);
return 1;
}
static CORE_ADDR
i386_macosx_sigcontext_addr (struct frame_info *frame)
{
CORE_ADDR start_of_func = get_frame_func (frame);
int offset = 0;
CORE_ADDR push_ebp_addr = 0;
CORE_ADDR mov_esp_ebp_addr = 0;
CORE_ADDR esp, ebp, pc;
CORE_ADDR address_of_pointer_to_struct_ucontext;
CORE_ADDR address_of_struct_ucontext;
CORE_ADDR address_of_struct_sigcontext;
char buf[4];
int limit;
pc = get_frame_pc (frame);
limit = min (pc - start_of_func + 1, 16);
while (offset < limit)
{
if (!push_ebp_addr)
{
if (read_memory_unsigned_integer (start_of_func + offset, 1) == 0x55)
{
push_ebp_addr = start_of_func + offset;
offset++;
}
else
{
offset++;
continue;
}
}
if (read_memory_unsigned_integer (start_of_func + offset, 2) == 0xe589
|| read_memory_unsigned_integer (start_of_func + offset, 2) == 0xec8b)
{
mov_esp_ebp_addr = start_of_func + offset;
break;
}
offset++;
}
if (!push_ebp_addr || !mov_esp_ebp_addr)
error ("Unable to analyze the prologue of _sigtramp(), giving up.");
frame_unwind_register (frame, I386_ESP_REGNUM, buf);
esp = extract_unsigned_integer (buf, 4);
frame_unwind_register (frame, I386_EBP_REGNUM, buf);
ebp = extract_unsigned_integer (buf, 4);
if (pc <= push_ebp_addr)
address_of_pointer_to_struct_ucontext = esp + 20;
if (pc > push_ebp_addr && pc <= mov_esp_ebp_addr)
address_of_pointer_to_struct_ucontext = esp + 24;
if (pc > mov_esp_ebp_addr)
address_of_pointer_to_struct_ucontext = ebp + 24;
address_of_struct_ucontext = read_memory_unsigned_integer
(address_of_pointer_to_struct_ucontext, 4);
address_of_struct_sigcontext = read_memory_unsigned_integer
(address_of_struct_ucontext + 28, 4);
return address_of_struct_sigcontext;
}
static int i386_macosx_sc_reg_offset[] =
{
2 * 4,
4 * 4,
5 * 4,
3 * 4,
9 * 4,
8 * 4,
7 * 4,
6 * 4,
12 * 4,
11 * 4,
13 * 4,
-1,
14 * 4,
15 * 4,
16 * 4,
17 * 4
};
static CORE_ADDR
i386_integer_to_address (struct type *type, void *buf)
{
char *tmp = alloca (TYPE_LENGTH (builtin_type_void_data_ptr));
LONGEST val = unpack_long (type, buf);
store_unsigned_integer (tmp, TYPE_LENGTH (builtin_type_void_data_ptr), val);
return extract_unsigned_integer (tmp,
TYPE_LENGTH (builtin_type_void_data_ptr));
}
static void
i386_macosx_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
tdep->num_xmm_regs = I386_NUM_XREGS - 1;
set_gdbarch_num_regs (gdbarch, I386_SSE_NUM_REGS);
set_gdbarch_skip_trampoline_code (gdbarch, macosx_skip_trampoline_code);
set_gdbarch_in_solib_call_trampoline (gdbarch,
macosx_in_solib_call_trampoline);
set_gdbarch_in_solib_return_trampoline (gdbarch,
macosx_in_solib_return_trampoline);
tdep->struct_return = reg_struct_return;
tdep->sigcontext_addr = i386_macosx_sigcontext_addr;
tdep->sc_reg_offset = i386_macosx_sc_reg_offset;
tdep->sc_num_regs = 16;
tdep->jb_pc_offset = 20;
set_gdbarch_integer_to_address (gdbarch, i386_integer_to_address);
}
static enum gdb_osabi
i386_mach_o_osabi_sniffer (bfd *abfd)
{
if (strcmp (bfd_get_target (abfd), "mach-o-le") == 0
|| strcmp (bfd_get_target (abfd), "mach-o-fat") == 0)
return GDB_OSABI_DARWIN;
return GDB_OSABI_UNKNOWN;
}
void
_initialize_i386_macosx_tdep (void)
{
gdbarch_register_osabi_sniffer (bfd_arch_unknown, bfd_target_mach_o_flavour,
i386_mach_o_osabi_sniffer);
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_DARWIN,
i386_macosx_init_abi);
}