#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include "symtab.h"
#include "target.h"
#include "gdbcore.h"
#include "symfile.h"
#include "objfiles.h"
#include "gdbcmd.h"
#include "arch-utils.h"
#include "floatformat.h"
#include "gdbtypes.h"
#include "regcache.h"
#include "reggroups.h"
#include "frame-base.h"
#include "frame-unwind.h"
#include "dummy-frame.h"
#include "libbfd.h"
#include "arm-tdep.h"
#include "elf-bfd.h"
#include "dis-asm.h"
#include "gdbarch.h"
#include "osabi.h"
#include <mach-o/nlist.h>
#include <mach/mach.h>
#include "mach-o.h"
static enum gdb_osabi arm_mach_o_osabi_sniffer_use_dyld_hint (bfd *abfd);
static void arm_macosx_init_abi (struct gdbarch_info info,
struct gdbarch *gdbarch);
static void arm_macosx_init_abi_v6 (struct gdbarch_info info,
struct gdbarch *gdbarch);
int
arm_mach_o_query_v6 ()
{
host_basic_info_data_t info;
mach_msg_type_number_t count;
count = HOST_BASIC_INFO_COUNT;
host_info (mach_host_self (), HOST_BASIC_INFO, (host_info_t) & info,
&count);
return (info.cpu_type == BFD_MACH_O_CPU_TYPE_ARM &&
info.cpu_subtype == BFD_MACH_O_CPU_SUBTYPE_ARM_6);
}
static enum gdb_osabi
arm_mach_o_osabi_sniffer (bfd *abfd)
{
enum gdb_osabi ret;
if (strcmp (bfd_get_target (abfd), "mach-o-le") == 0)
{
bfd_arch_info_type *arch_info = bfd_get_arch_info (abfd);
if (arch_info->arch == bfd_arch_arm)
{
if (arch_info->mach == bfd_mach_arm_4T)
return GDB_OSABI_DARWIN;
else if (arch_info->mach == bfd_mach_arm_6)
return GDB_OSABI_DARWINV6;
}
}
ret = arm_mach_o_osabi_sniffer_use_dyld_hint (abfd);
if (ret == GDB_OSABI_DARWINV6 || ret == GDB_OSABI_DARWIN)
return ret;
if (bfd_check_format (abfd, bfd_archive))
{
enum gdb_osabi best = GDB_OSABI_UNKNOWN;
enum gdb_osabi cur = GDB_OSABI_UNKNOWN;
bfd *nbfd = NULL;
for (;;)
{
nbfd = bfd_openr_next_archived_file (abfd, nbfd);
if (nbfd == NULL)
break;
if (!bfd_check_format (nbfd, bfd_object))
continue;
cur = arm_mach_o_osabi_sniffer (nbfd);
if (cur == GDB_OSABI_DARWINV6 &&
best != GDB_OSABI_DARWINV6 && arm_mach_o_query_v6 ())
best = cur;
if (cur == GDB_OSABI_DARWIN &&
best != GDB_OSABI_DARWINV6 && best != GDB_OSABI_DARWIN)
best = cur;
}
return best;
}
if (!bfd_check_format (abfd, bfd_object))
return GDB_OSABI_UNKNOWN;
return GDB_OSABI_UNKNOWN;
}
static enum gdb_osabi
arm_mach_o_osabi_sniffer_use_dyld_hint (bfd *abfd)
{
if (osabi_seen_in_attached_dyld == GDB_OSABI_UNKNOWN)
return GDB_OSABI_UNKNOWN;
bfd *nbfd = NULL;
for (;;)
{
bfd_arch_info_type *arch_info;
nbfd = bfd_openr_next_archived_file (abfd, nbfd);
if (nbfd == NULL)
break;
if (!bfd_check_format (nbfd, bfd_object))
continue;
arch_info = bfd_get_arch_info (nbfd);
if (arch_info->arch == bfd_arch_arm)
{
if (arch_info->mach == bfd_mach_arm_4T
&& osabi_seen_in_attached_dyld == GDB_OSABI_DARWIN)
return GDB_OSABI_DARWIN;
if (arch_info->mach == bfd_mach_arm_6
&& osabi_seen_in_attached_dyld == GDB_OSABI_DARWINV6)
return GDB_OSABI_DARWINV6;
}
}
return GDB_OSABI_UNKNOWN;
}
CORE_ADDR
arm_fetch_pointer_argument (struct frame_info *frame, int argi,
struct type *type)
{
CORE_ADDR addr;
addr = get_frame_register_unsigned (frame, argi);
return addr;
}
static void
arm_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
int reg, gdb_byte *buf)
{
int s_reg_lsw = 2 * (reg - ARM_FIRST_VFP_PSEUDO_REGNUM)
+ ARM_FIRST_VFP_REGNUM;
int s_reg_msw = s_reg_lsw + 1;
regcache_cooked_read (regcache, s_reg_lsw, buf);
regcache_cooked_read (regcache, s_reg_msw, buf + 4);
}
static void
arm_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
int reg, const gdb_byte *buf)
{
int s_reg_lsw = 2 * (reg - ARM_FIRST_VFP_PSEUDO_REGNUM)
+ ARM_FIRST_VFP_REGNUM;
int s_reg_msw = s_reg_lsw + 1;
regcache_cooked_write (regcache, s_reg_lsw, buf);
regcache_cooked_write (regcache, s_reg_msw, buf + 4);
}
#define GDB_N_ARM_THUMB_DEF 0x0008
#define MSYMBOL_SET_SPECIAL(msym) \
MSYMBOL_INFO (msym) = (char *) (((long) MSYMBOL_INFO (msym)) \
| 0x80000000)
static void
arm_macosx_dbx_make_msymbol_special (int16_t desc, struct minimal_symbol *msym)
{
if (desc & GDB_N_ARM_THUMB_DEF)
MSYMBOL_SET_SPECIAL (msym);
}
int
arm_macosx_stab_reg_to_regnum (int num)
{
int regnum = num;
if (num >= ARM_MACOSX_FIRST_VFP_STABS_REGNUM
&& num <= ARM_MACOSX_LAST_VFP_STABS_REGNUM)
regnum = ARM_FIRST_VFP_REGNUM + num - ARM_MACOSX_FIRST_VFP_STABS_REGNUM;
else
regnum = num;
return regnum;
}
char *
arm_throw_catch_find_typeinfo (struct frame_info *curr_frame,
int exception_type)
{
struct minimal_symbol *typeinfo_sym = NULL;
ULONGEST typeinfo_ptr;
char *typeinfo_str;
if (exception_type == EX_EVENT_THROW)
{
frame_unwind_unsigned_register (curr_frame,
ARM_R0_REGNUM + 1,
&typeinfo_ptr);
typeinfo_sym = lookup_minimal_symbol_by_pc (typeinfo_ptr);
}
else
{
ULONGEST type_obj_addr = 0;
frame_unwind_unsigned_register (curr_frame,
ARM_R0_REGNUM,
&typeinfo_ptr);
if (safe_read_memory_unsigned_integer
(typeinfo_ptr - 44, 4, &type_obj_addr))
typeinfo_sym = lookup_minimal_symbol_by_pc (type_obj_addr);
}
if (!typeinfo_sym)
return NULL;
typeinfo_str =
typeinfo_sym->ginfo.language_specific.cplus_specific.demangled_name;
if ((typeinfo_str == NULL)
|| (strstr (typeinfo_str, "typeinfo for ") != typeinfo_str))
return NULL;
return typeinfo_str + strlen ("typeinfo for ");
}
static void
arm_macosx_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
(gdbarch_tdep (gdbarch))->fp_model = ARM_FLOAT_NONE;
set_gdbarch_print_float_info (gdbarch, NULL);
set_gdbarch_stab_reg_to_regnum (gdbarch, arm_macosx_stab_reg_to_regnum);
set_gdbarch_skip_trampoline_code (gdbarch, macosx_skip_trampoline_code);
set_gdbarch_in_solib_return_trampoline (gdbarch,
macosx_in_solib_return_trampoline);
set_gdbarch_fetch_pointer_argument (gdbarch, arm_fetch_pointer_argument);
set_gdbarch_num_regs (gdbarch, ARM_MACOSX_NUM_REGS);
set_gdbarch_dbx_make_msymbol_special (gdbarch, arm_macosx_dbx_make_msymbol_special);
}
static void
arm_macosx_init_abi_v6 (struct gdbarch_info info, struct gdbarch *gdbarch)
{
(gdbarch_tdep (gdbarch))->fp_model = ARM_FLOAT_VFP;
set_gdbarch_stab_reg_to_regnum (gdbarch, arm_macosx_stab_reg_to_regnum);
set_gdbarch_skip_trampoline_code (gdbarch, macosx_skip_trampoline_code);
set_gdbarch_in_solib_return_trampoline (gdbarch,
macosx_in_solib_return_trampoline);
set_gdbarch_fetch_pointer_argument (gdbarch, arm_fetch_pointer_argument);
set_gdbarch_num_regs (gdbarch, ARM_V6_MACOSX_NUM_REGS);
set_gdbarch_num_pseudo_regs (gdbarch, ARM_MACOSX_NUM_VFP_PSEUDO_REGS);
set_gdbarch_pseudo_register_read (gdbarch, arm_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch, arm_pseudo_register_write);
set_gdbarch_dbx_make_msymbol_special (gdbarch, arm_macosx_dbx_make_msymbol_special);
}
void
_initialize_arm_macosx_tdep ()
{
struct cmd_list_element *cmd = NULL;
gdbarch_register_osabi_sniffer (bfd_arch_unknown, bfd_target_mach_o_flavour,
arm_mach_o_osabi_sniffer);
gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_DARWIN,
arm_macosx_init_abi);
gdbarch_register_osabi ((bfd_lookup_arch (bfd_arch_arm, bfd_mach_arm_6))->arch, bfd_mach_arm_6,
GDB_OSABI_DARWINV6, arm_macosx_init_abi_v6);
}