#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 <sys/types.h>
#include <sys/sysctl.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);
struct type *builtin_type_arm_psr = NULL;
struct type *builtin_type_arm_fpscr = NULL;
static register_info_t g_reginfo_arm_vfpv1[] =
{
{ "r0", 0, &builtin_type_int32 },
{ "r1", 0, &builtin_type_int32 },
{ "r2", 0, &builtin_type_int32 },
{ "r3", 0, &builtin_type_int32 },
{ "r4", 0, &builtin_type_int32 },
{ "r5", 0, &builtin_type_int32 },
{ "r6", 0, &builtin_type_int32 },
{ "r7", 0, &builtin_type_int32 },
{ "r8", 0, &builtin_type_int32 },
{ "r9", 0, &builtin_type_int32 },
{ "r10", 0, &builtin_type_int32 },
{ "r11", 0, &builtin_type_int32 },
{ "r12", 0, &builtin_type_int32 },
{ "sp", 0, &builtin_type_int32 },
{ "lr", 0, &builtin_type_int32 },
{ "pc", 0, &builtin_type_int32 },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "cpsr", 0, &builtin_type_arm_psr },
{ "s0", 0, &builtin_type_ieee_single_little },
{ "s1", 0, &builtin_type_ieee_single_little },
{ "s2", 0, &builtin_type_ieee_single_little },
{ "s3", 0, &builtin_type_ieee_single_little },
{ "s4", 0, &builtin_type_ieee_single_little },
{ "s5", 0, &builtin_type_ieee_single_little },
{ "s6", 0, &builtin_type_ieee_single_little },
{ "s7", 0, &builtin_type_ieee_single_little },
{ "s8", 0, &builtin_type_ieee_single_little },
{ "s9", 0, &builtin_type_ieee_single_little },
{ "s10", 0, &builtin_type_ieee_single_little },
{ "s11", 0, &builtin_type_ieee_single_little },
{ "s12", 0, &builtin_type_ieee_single_little },
{ "s13", 0, &builtin_type_ieee_single_little },
{ "s14", 0, &builtin_type_ieee_single_little },
{ "s15", 0, &builtin_type_ieee_single_little },
{ "s16", 0, &builtin_type_ieee_single_little },
{ "s17", 0, &builtin_type_ieee_single_little },
{ "s18", 0, &builtin_type_ieee_single_little },
{ "s19", 0, &builtin_type_ieee_single_little },
{ "s20", 0, &builtin_type_ieee_single_little },
{ "s21", 0, &builtin_type_ieee_single_little },
{ "s22", 0, &builtin_type_ieee_single_little },
{ "s23", 0, &builtin_type_ieee_single_little },
{ "s24", 0, &builtin_type_ieee_single_little },
{ "s25", 0, &builtin_type_ieee_single_little },
{ "s26", 0, &builtin_type_ieee_single_little },
{ "s27", 0, &builtin_type_ieee_single_little },
{ "s28", 0, &builtin_type_ieee_single_little },
{ "s29", 0, &builtin_type_ieee_single_little },
{ "s30", 0, &builtin_type_ieee_single_little },
{ "s31", 0, &builtin_type_ieee_single_little },
{ "fpscr",0, &builtin_type_arm_fpscr },
{ "d0", 0, &builtin_type_ieee_double_little },
{ "d1", 0, &builtin_type_ieee_double_little },
{ "d2", 0, &builtin_type_ieee_double_little },
{ "d3", 0, &builtin_type_ieee_double_little },
{ "d4", 0, &builtin_type_ieee_double_little },
{ "d5", 0, &builtin_type_ieee_double_little },
{ "d6", 0, &builtin_type_ieee_double_little },
{ "d7", 0, &builtin_type_ieee_double_little },
{ "d8", 0, &builtin_type_ieee_double_little },
{ "d9", 0, &builtin_type_ieee_double_little },
{ "d10", 0, &builtin_type_ieee_double_little },
{ "d11", 0, &builtin_type_ieee_double_little },
{ "d12", 0, &builtin_type_ieee_double_little },
{ "d13", 0, &builtin_type_ieee_double_little },
{ "d14", 0, &builtin_type_ieee_double_little },
{ "d15", 0, &builtin_type_ieee_double_little }
};
const uint32_t g_reginfo_arm_vfpv1_count = sizeof(g_reginfo_arm_vfpv1)/
sizeof(register_info_t);
static register_info_t g_reginfo_arm_vfpv3[] =
{
{ "r0", 0, &builtin_type_int32 },
{ "r1", 0, &builtin_type_int32 },
{ "r2", 0, &builtin_type_int32 },
{ "r3", 0, &builtin_type_int32 },
{ "r4", 0, &builtin_type_int32 },
{ "r5", 0, &builtin_type_int32 },
{ "r6", 0, &builtin_type_int32 },
{ "r7", 0, &builtin_type_int32 },
{ "r8", 0, &builtin_type_int32 },
{ "r9", 0, &builtin_type_int32 },
{ "r10", 0, &builtin_type_int32 },
{ "r11", 0, &builtin_type_int32 },
{ "r12", 0, &builtin_type_int32 },
{ "sp", 0, &builtin_type_int32 },
{ "lr", 0, &builtin_type_int32 },
{ "pc", 0, &builtin_type_int32 },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "", 0, &builtin_type_arm_ext_littlebyte_bigword },
{ "cpsr", 0, &builtin_type_arm_psr },
{ "s0", 0, &builtin_type_ieee_single_little },
{ "s1", 0, &builtin_type_ieee_single_little },
{ "s2", 0, &builtin_type_ieee_single_little },
{ "s3", 0, &builtin_type_ieee_single_little },
{ "s4", 0, &builtin_type_ieee_single_little },
{ "s5", 0, &builtin_type_ieee_single_little },
{ "s6", 0, &builtin_type_ieee_single_little },
{ "s7", 0, &builtin_type_ieee_single_little },
{ "s8", 0, &builtin_type_ieee_single_little },
{ "s9", 0, &builtin_type_ieee_single_little },
{ "s10", 0, &builtin_type_ieee_single_little },
{ "s11", 0, &builtin_type_ieee_single_little },
{ "s12", 0, &builtin_type_ieee_single_little },
{ "s13", 0, &builtin_type_ieee_single_little },
{ "s14", 0, &builtin_type_ieee_single_little },
{ "s15", 0, &builtin_type_ieee_single_little },
{ "s16", 0, &builtin_type_ieee_single_little },
{ "s17", 0, &builtin_type_ieee_single_little },
{ "s18", 0, &builtin_type_ieee_single_little },
{ "s19", 0, &builtin_type_ieee_single_little },
{ "s20", 0, &builtin_type_ieee_single_little },
{ "s21", 0, &builtin_type_ieee_single_little },
{ "s22", 0, &builtin_type_ieee_single_little },
{ "s23", 0, &builtin_type_ieee_single_little },
{ "s24", 0, &builtin_type_ieee_single_little },
{ "s25", 0, &builtin_type_ieee_single_little },
{ "s26", 0, &builtin_type_ieee_single_little },
{ "s27", 0, &builtin_type_ieee_single_little },
{ "s28", 0, &builtin_type_ieee_single_little },
{ "s29", 0, &builtin_type_ieee_single_little },
{ "s30", 0, &builtin_type_ieee_single_little },
{ "s31", 0, &builtin_type_ieee_single_little },
{ "fpscr",0, &builtin_type_arm_fpscr },
{ "d16", 0, &builtin_type_ieee_double_little },
{ "d17", 0, &builtin_type_ieee_double_little },
{ "d18", 0, &builtin_type_ieee_double_little },
{ "d19", 0, &builtin_type_ieee_double_little },
{ "d20", 0, &builtin_type_ieee_double_little },
{ "d21", 0, &builtin_type_ieee_double_little },
{ "d22", 0, &builtin_type_ieee_double_little },
{ "d23", 0, &builtin_type_ieee_double_little },
{ "d24", 0, &builtin_type_ieee_double_little },
{ "d25", 0, &builtin_type_ieee_double_little },
{ "d26", 0, &builtin_type_ieee_double_little },
{ "d27", 0, &builtin_type_ieee_double_little },
{ "d28", 0, &builtin_type_ieee_double_little },
{ "d29", 0, &builtin_type_ieee_double_little },
{ "d30", 0, &builtin_type_ieee_double_little },
{ "d31", 0, &builtin_type_ieee_double_little },
{ "d0", 0, &builtin_type_ieee_double_little },
{ "d1", 0, &builtin_type_ieee_double_little },
{ "d2", 0, &builtin_type_ieee_double_little },
{ "d3", 0, &builtin_type_ieee_double_little },
{ "d4", 0, &builtin_type_ieee_double_little },
{ "d5", 0, &builtin_type_ieee_double_little },
{ "d6", 0, &builtin_type_ieee_double_little },
{ "d7", 0, &builtin_type_ieee_double_little },
{ "d8", 0, &builtin_type_ieee_double_little },
{ "d9", 0, &builtin_type_ieee_double_little },
{ "d10", 0, &builtin_type_ieee_double_little },
{ "d11", 0, &builtin_type_ieee_double_little },
{ "d12", 0, &builtin_type_ieee_double_little },
{ "d13", 0, &builtin_type_ieee_double_little },
{ "d14", 0, &builtin_type_ieee_double_little },
{ "d15", 0, &builtin_type_ieee_double_little },
{ "q0", 0, &builtin_type_vec128 },
{ "q1", 0, &builtin_type_vec128 },
{ "q2", 0, &builtin_type_vec128 },
{ "q3", 0, &builtin_type_vec128 },
{ "q4", 0, &builtin_type_vec128 },
{ "q5", 0, &builtin_type_vec128 },
{ "q6", 0, &builtin_type_vec128 },
{ "q7", 0, &builtin_type_vec128 },
{ "q8", 0, &builtin_type_vec128 },
{ "q9", 0, &builtin_type_vec128 },
{ "q10", 0, &builtin_type_vec128 },
{ "q11", 0, &builtin_type_vec128 },
{ "q12", 0, &builtin_type_vec128 },
{ "q13", 0, &builtin_type_vec128 },
{ "q14", 0, &builtin_type_vec128 },
{ "q15", 0, &builtin_type_vec128 }
};
const uint32_t g_reginfo_arm_vfpv3_count = sizeof(g_reginfo_arm_vfpv3)/
sizeof(register_info_t);
static struct type *
build_builtin_type_arm_psr_mode_enum (void)
{
static struct gdbtypes_enum_info mode_enums[] = {
{"usr", 0x10 },
{"fiq", 0x11 },
{"irq", 0x12 },
{"svc", 0x13 },
{"dbg", 0x15 },
{"abt", 0x17 },
{"und", 0x1d },
{"sys", 0x1f }
};
uint32_t num_mode_enums = sizeof (mode_enums)/sizeof (mode_enums[0]);
return build_builtin_enum ("_arm_ext_psr_mode_enum", 4,
TYPE_FLAG_UNSIGNED, mode_enums, num_mode_enums);
}
static struct type *
build_builtin_type_arm_psr (void)
{
struct gdbtypes_bitfield_info psr_bitfields[] = {
{"", builtin_type_void_data_ptr, 31, 0 },
{"n", builtin_type_uint32, 31, 31 },
{"z", builtin_type_uint32, 30, 30 },
{"c", builtin_type_uint32, 29, 29 },
{"v", builtin_type_uint32, 28, 28 },
{"q", builtin_type_uint32, 27, 27 },
{"j", builtin_type_uint32, 24, 24 },
{"ge", builtin_type_uint32, 19, 16 },
{"e", builtin_type_uint32, 9, 9 },
{"a", builtin_type_uint32, 8, 8 },
{"i", builtin_type_uint32, 7, 7 },
{"f", builtin_type_uint32, 6, 6 },
{"t", builtin_type_uint32, 5, 5 },
{"mode", build_builtin_type_arm_psr_mode_enum (), 4, 0 },
};
uint32_t num_psr_bitfields = sizeof (psr_bitfields)/sizeof (psr_bitfields[0]);
return build_builtin_bitfield ("_arm_ext_psr", 4,
psr_bitfields, num_psr_bitfields);
}
static struct type *
build_builtin_type_arm_fpscr (void)
{
struct gdbtypes_bitfield_info fpscr_bitfields[] = {
{"", builtin_type_void_data_ptr, 31, 0 },
{"n", builtin_type_uint32, 31, 31 },
{"z", builtin_type_uint32, 30, 30 },
{"c", builtin_type_uint32, 29, 29 },
{"v", builtin_type_uint32, 28, 28 },
{"dn", builtin_type_uint32, 25, 25 },
{"fz", builtin_type_uint32, 24, 24 },
{"rmode", builtin_type_uint32, 23, 22 },
{"stride", builtin_type_uint32, 21, 20 },
{"len", builtin_type_uint32, 18, 16 },
{"ide", builtin_type_uint32, 15, 15 },
{"ixe", builtin_type_uint32, 12, 12 },
{"ufe", builtin_type_uint32, 11, 11 },
{"ofe", builtin_type_uint32, 10, 10 },
{"dze", builtin_type_uint32, 9, 9 },
{"ioe", builtin_type_uint32, 8, 8 },
{"idc", builtin_type_uint32, 7, 7 },
{"ixc", builtin_type_uint32, 4, 4 },
{"ufc", builtin_type_uint32, 3, 3 },
{"ofc", builtin_type_uint32, 2, 2 },
{"dzc", builtin_type_uint32, 1, 1 },
{"ioc", builtin_type_uint32, 0, 0 }
};
uint32_t num_fpscr_bitfields = sizeof (fpscr_bitfields)/
sizeof (fpscr_bitfields[0]);
return build_builtin_bitfield ("_arm_ext_fpscr", 4,
fpscr_bitfields, num_fpscr_bitfields);
}
enum gdb_osabi
arm_host_osabi ()
{
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);
if (info.cpu_type == BFD_MACH_O_CPU_TYPE_ARM)
{
if (info.cpu_subtype == BFD_MACH_O_CPU_SUBTYPE_ARM_6)
return GDB_OSABI_DARWINV6;
if (info.cpu_subtype == BFD_MACH_O_CPU_SUBTYPE_ARM_7)
return GDB_OSABI_DARWINV7;
else
return GDB_OSABI_DARWIN;
}
return GDB_OSABI_UNKNOWN;
}
enum gdb_osabi
arm_set_osabi_from_host_info ()
{
struct gdbarch_info info;
gdbarch_info_init (&info);
gdbarch_info_fill (current_gdbarch, &info);
info.byte_order = gdbarch_byte_order (current_gdbarch);
info.osabi = arm_host_osabi ();
if (info.osabi == GDB_OSABI_DARWINV7)
info.bfd_arch_info = bfd_lookup_arch (bfd_arch_arm, bfd_mach_arm_7);
else if (info.osabi == GDB_OSABI_DARWINV6)
info.bfd_arch_info = bfd_lookup_arch (bfd_arch_arm, bfd_mach_arm_6);
else if (info.osabi == GDB_OSABI_DARWIN)
info.bfd_arch_info = bfd_lookup_arch (bfd_arch_arm, 0);
if (info.osabi != GDB_OSABI_UNKNOWN)
gdbarch_update_p (info);
return TARGET_OSABI;
}
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)
{
const 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;
else if (arch_info->mach == bfd_mach_arm_7)
return GDB_OSABI_DARWINV7;
else
return GDB_OSABI_DARWIN;
}
}
ret = arm_mach_o_osabi_sniffer_use_dyld_hint (abfd);
if (ret == GDB_OSABI_DARWINV6 || ret == GDB_OSABI_DARWIN ||
ret == GDB_OSABI_DARWINV7)
return ret;
if (bfd_check_format (abfd, bfd_archive))
{
enum gdb_osabi best = GDB_OSABI_UNKNOWN;
enum gdb_osabi cur = GDB_OSABI_UNKNOWN;
const enum gdb_osabi host_osabi = arm_host_osabi ();
bfd *nbfd = NULL;
while ((nbfd = bfd_openr_next_archived_file (abfd, nbfd)) != NULL)
{
if (!bfd_check_format (nbfd, bfd_object))
continue;
cur = arm_mach_o_osabi_sniffer (nbfd);
if (cur == host_osabi)
return cur;
else if (cur > best && cur < host_osabi)
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 (;;)
{
const 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;
if (arch_info->mach == bfd_mach_arm_7
&& osabi_seen_in_attached_dyld == GDB_OSABI_DARWINV7)
return GDB_OSABI_DARWINV7;
}
}
return GDB_OSABI_UNKNOWN;
}
int
arm_macosx_in_switch_glue (CORE_ADDR pc)
{
int retval;
char *name;
retval = find_pc_partial_function (pc, &name, NULL, NULL);
if (retval)
{
if (strstr (name, "__switch") == name)
{
char *end = name + strlen ("__switch");
int len = strlen (end);
if ((len == 1 && *end == '8')
|| (len == 2
&& ((*end == 'u' && *(end + 1) == '8')
|| (*end == '1' && *(end + 1) == '6')
|| (*end == '3' && *(end + 1) == '2'))))
{
return 1;
}
}
}
return 0;
}
arm_macosx_tdep_inf_status_t arm_macosx_tdep_inf_status = { (CORE_ADDR)-1 };
int
arm_macosx_keep_going (CORE_ADDR stop_pc)
{
int result = 0;
if (stop_pc == arm_macosx_tdep_inf_status.macosx_half_step_pc)
{
result = 1;
}
else if (step_over_calls != STEP_OVER_NONE)
{
if (arm_macosx_in_switch_glue (stop_pc))
result = 1;
}
return result;
}
void *
arm_macosx_save_thread_inferior_status ()
{
if (arm_macosx_tdep_inf_status.macosx_half_step_pc == (CORE_ADDR)-1)
return NULL;
arm_macosx_tdep_inf_status_t *tdep_inf_status;
tdep_inf_status = XMALLOC (arm_macosx_tdep_inf_status_t);
if (tdep_inf_status)
tdep_inf_status->macosx_half_step_pc =
arm_macosx_tdep_inf_status.macosx_half_step_pc;
return tdep_inf_status;
}
void
arm_macosx_restore_thread_inferior_status (void *tdep_inf_status)
{
if (tdep_inf_status != NULL)
{
arm_macosx_tdep_inf_status.macosx_half_step_pc =
((arm_macosx_tdep_inf_status_t *)tdep_inf_status)->macosx_half_step_pc;
}
}
void
arm_macosx_free_thread_inferior_status (void *tdep_inf_status)
{
xfree (tdep_inf_status);
}
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;
}
#define submask(x) ((1L << ((x) + 1)) - 1)
#define bit(obj,st) ((((uint32_t)obj) >> ((uint32_t)st)) & (uint32_t)1)
#define bits(obj,st,fn) ((uint32_t)((((uint32_t)obj) >> ((uint32_t)st)) & submask (((uint32_t)fn) - ((uint32_t)st))))
static void
arm_macosx_print_float_info_vfp (struct gdbarch *gdbarch,
struct ui_file *file,
struct frame_info *frame, const char *args)
{
static const char* enabled_strings[2] = {"disabled", "enabled"};
static const char* Rmode_strings[4] = {
"Round to nearest (RN) mode",
"Round towards plus infinity (RP) mode",
"Round towards minus infinity (RM) mode",
"Round towards zero (RZ) mode"
};
uint32_t fpscr = read_register (ARM_VFP_REGNUM_FPSCR);
uint32_t b;
printf (_("VFP fpscr = 0x%8.8x\n"), fpscr);
printf (_(" N = %u Set if comparison produces a less than result\n"),
bit (fpscr, 31));
printf (_(" Z = %u Set if comparison produces an equal result\n"),
bit (fpscr, 30));
printf (_(" C = %u Set if comparison produces an equal, greater "
"than, or unordered result\n"),
bit (fpscr, 29));
printf (_(" V = %u Set if comparison produces an unordered result\n"),
bit (fpscr, 28));
b = bit (fpscr, 25);
printf (_(" DN = %u default NaN mode %s\n"), b, enabled_strings[b]);
b = bit (fpscr, 24);
printf (_(" Fz = %u flush-to-zero mode %s\n"), b, enabled_strings[b]);
b = bits (fpscr, 22, 23);
printf (_(" Rmode = %u %s\n"), b, Rmode_strings[b]);
printf (_("Stride = %u\n"), bits (fpscr, 20, 21));
printf (_(" LEN = %u\n"), bits (fpscr, 16, 18));
printf (_(" IDE = %u Input Subnormal exception\n"), bit (fpscr, 15));
printf (_(" IXE = %u Inexact exception\n"), bit (fpscr, 12));
printf (_(" UFE = %u Underflow exception\n"), bit (fpscr, 11));
printf (_(" OFE = %u Overflow exception\n"), bit (fpscr, 10));
printf (_(" DZE = %u Division by Zero exception\n"), bit (fpscr, 9));
printf (_(" IOE = %u Invalid Operation exception\n"), bit (fpscr, 8));
printf (_(" IDC = %u Input Subnormal cumulative\n"), bit (fpscr, 7));
printf (_(" IXC = %u Inexact cumulative\n"), bit (fpscr, 4));
printf (_(" UFC = %u Underflow cumulative\n"), bit (fpscr, 3));
printf (_(" OFC = %u Overflow cumulative\n"), bit (fpscr, 2));
printf (_(" DZC = %u Division by Zero cumulative\n"), bit (fpscr, 1));
printf (_(" IOC = %u Invalid Operation cumulative\n"), bit (fpscr, 0));
}
static void
arm_macosx_pseudo_register_read_vfpv1 (struct gdbarch *gdbarch,
struct regcache *regcache, int reg,
gdb_byte *buf)
{
int s_reg_lsw = 2 * (reg - ARM_VFPV1_PSEUDO_REGNUM_D0) + ARM_VFP_REGNUM_S0;
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_macosx_pseudo_register_write_vfpv1 (struct gdbarch *gdbarch,
struct regcache *regcache, int reg,
const gdb_byte *buf)
{
int s_reg_lsw = 2 * (reg - ARM_VFPV1_PSEUDO_REGNUM_D0) + ARM_VFP_REGNUM_S0;
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);
}
static void
arm_macosx_pseudo_register_read_vfpv3 (struct gdbarch *gdbarch,
struct regcache *regcache, int reg,
gdb_byte *buf)
{
int s_reg_lsw = 0;
int s_reg_msw = 0;
int regno;
int stride_byte_size = 0;
if (reg >= ARM_VFPV3_PSEUDO_REGNUM_D0 && reg <= ARM_VFPV3_PSEUDO_REGNUM_D15)
{
int d = reg - ARM_VFPV3_PSEUDO_REGNUM_D0;
s_reg_lsw = 2 * d + ARM_VFP_REGNUM_S0;
s_reg_msw = s_reg_lsw + 1;
stride_byte_size = 4;
}
else if (reg >= ARM_SIMD_PSEUDO_REGNUM_Q0 &&
reg <= ARM_SIMD_PSEUDO_REGNUM_Q15)
{
int q = reg - ARM_SIMD_PSEUDO_REGNUM_Q0;
if (q < 8)
{
s_reg_lsw = 4 * q + ARM_VFP_REGNUM_S0;
s_reg_msw = s_reg_lsw + 3;
stride_byte_size = 4;
}
else
{
s_reg_lsw = 2 * (q - 8) + ARM_VFPV3_REGNUM_D16;
s_reg_msw = s_reg_lsw + 1;
stride_byte_size = 8;
}
}
for (regno=s_reg_lsw; regno<=s_reg_msw; regno++)
regcache_cooked_read (regcache, regno,
buf + (stride_byte_size * (regno - s_reg_lsw)));
}
static void
arm_macosx_pseudo_register_write_vfpv3 (struct gdbarch *gdbarch,
struct regcache *regcache, int reg,
const gdb_byte *buf)
{
int s_reg_lsw = 0;
int s_reg_msw = 0;
int regno;
int stride_byte_size = 0;
if (reg >= ARM_VFPV3_PSEUDO_REGNUM_D0 && reg <= ARM_VFPV3_PSEUDO_REGNUM_D15)
{
int d = reg - ARM_VFPV3_PSEUDO_REGNUM_D0;
s_reg_lsw = 2 * d + ARM_VFP_REGNUM_S0;
s_reg_msw = s_reg_lsw + 1;
stride_byte_size = 4;
}
else if (reg >= ARM_SIMD_PSEUDO_REGNUM_Q0 &&
reg <= ARM_SIMD_PSEUDO_REGNUM_Q15)
{
int q = reg - ARM_SIMD_PSEUDO_REGNUM_Q0;
if (q < 8)
{
s_reg_lsw = 4 * q + ARM_VFP_REGNUM_S0;
s_reg_msw = s_reg_lsw + 3;
stride_byte_size = 4;
}
else
{
s_reg_lsw = 2 * (q - 8) + ARM_VFPV3_REGNUM_D16;
s_reg_msw = s_reg_lsw + 1;
stride_byte_size = 8;
}
}
for (regno=s_reg_lsw; regno<=s_reg_msw; regno++)
regcache_cooked_write (regcache, regno,
buf + (stride_byte_size * (regno - s_reg_lsw)));
}
#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_VFP_REGNUM_S0 + 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)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
tdep->fp_model = ARM_FLOAT_NONE;
tdep->vfp_version = ARM_VFP_UNSUPPORTED;
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);
if (get_arm_single_step_mode () == arm_single_step_mode_auto)
{
}
}
static struct type *
arm_macosx_register_type_vfpv1 (struct gdbarch *gdbarch, int regnum)
{
if (regnum < g_reginfo_arm_vfpv1_count && g_reginfo_arm_vfpv1[regnum].type)
return *g_reginfo_arm_vfpv1[regnum].type;
return builtin_type_int32;
}
static struct type *
arm_macosx_register_type_vfpv3 (struct gdbarch *gdbarch, int regnum)
{
if (regnum < g_reginfo_arm_vfpv3_count && g_reginfo_arm_vfpv3[regnum].type)
return *g_reginfo_arm_vfpv3[regnum].type;
return builtin_type_int32;
}
static const char *
arm_macosx_register_name_vfpv1 (int regnum)
{
if (regnum < g_reginfo_arm_vfpv1_count)
return g_reginfo_arm_vfpv1[regnum].name;
return NULL;
}
static const char *
arm_macosx_register_name_vfpv3 (int regnum)
{
if (regnum < g_reginfo_arm_vfpv3_count)
return g_reginfo_arm_vfpv3[regnum].name;
return NULL;
}
static int
arm_macosx_register_byte_vfpv1 (int regnum)
{
if (regnum < g_reginfo_arm_vfpv1_count)
return g_reginfo_arm_vfpv1[regnum].offset;
return 0;
}
static int
arm_macosx_register_byte_vfpv3 (int regnum)
{
if (regnum < g_reginfo_arm_vfpv3_count)
return g_reginfo_arm_vfpv3[regnum].offset;
return 0;
}
static void
arm_macosx_init_abi_v6 (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
tdep->fp_model = ARM_FLOAT_VFP;
tdep->vfp_version = ARM_VFP_VERSION_1;
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_deprecated_fp_regnum (gdbarch, ARM_FP_REGNUM);
set_gdbarch_print_float_info (gdbarch, arm_macosx_print_float_info_vfp);
set_gdbarch_sp_regnum (gdbarch, ARM_SP_REGNUM);
set_gdbarch_pc_regnum (gdbarch, ARM_PC_REGNUM);
set_gdbarch_register_name (gdbarch, arm_macosx_register_name_vfpv1);
set_gdbarch_deprecated_register_byte (gdbarch,
arm_macosx_register_byte_vfpv1);
set_gdbarch_num_regs (gdbarch, ARM_V6_MACOSX_NUM_REGS);
set_gdbarch_num_pseudo_regs (gdbarch, ARM_MACOSX_NUM_VFPV1_PSEUDO_REGS);
set_gdbarch_pseudo_register_read (gdbarch,
arm_macosx_pseudo_register_read_vfpv1);
set_gdbarch_pseudo_register_write (gdbarch,
arm_macosx_pseudo_register_write_vfpv1);
set_gdbarch_register_type (gdbarch, arm_macosx_register_type_vfpv1);
set_gdbarch_dbx_make_msymbol_special (gdbarch,
arm_macosx_dbx_make_msymbol_special);
if (get_arm_single_step_mode () == arm_single_step_mode_auto)
{
#ifdef NM_NEXTSTEP
uint32_t num_hw_bkpts = 0;
size_t num_hw_bkpts_len = sizeof(num_hw_bkpts);
if (sysctlbyname("hw.optional.breakpoint", &num_hw_bkpts,
&num_hw_bkpts_len, NULL, 0) == 0)
{
if (num_hw_bkpts > 0)
set_gdbarch_software_single_step (gdbarch, NULL);
}
else
{
set_gdbarch_software_single_step (gdbarch, NULL);
}
#else
set_gdbarch_software_single_step (gdbarch, NULL);
#endif
}
}
static void
arm_macosx_init_abi_v7 (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
tdep->fp_model = ARM_FLOAT_VFP;
tdep->vfp_version = ARM_VFP_VERSION_3;
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_deprecated_fp_regnum (gdbarch, ARM_FP_REGNUM);
set_gdbarch_print_float_info (gdbarch, arm_macosx_print_float_info_vfp);
set_gdbarch_sp_regnum (gdbarch, ARM_SP_REGNUM);
set_gdbarch_pc_regnum (gdbarch, ARM_PC_REGNUM);
set_gdbarch_register_name (gdbarch, arm_macosx_register_name_vfpv3);
set_gdbarch_deprecated_register_byte (gdbarch,
arm_macosx_register_byte_vfpv3);
set_gdbarch_num_regs (gdbarch, ARM_V7_MACOSX_NUM_REGS);
set_gdbarch_num_pseudo_regs (gdbarch, ARM_MACOSX_NUM_VFPV3_PSEUDO_REGS);
set_gdbarch_pseudo_register_read (gdbarch,
arm_macosx_pseudo_register_read_vfpv3);
set_gdbarch_pseudo_register_write (gdbarch,
arm_macosx_pseudo_register_write_vfpv3);
set_gdbarch_register_type (gdbarch, arm_macosx_register_type_vfpv3);
set_gdbarch_dbx_make_msymbol_special (gdbarch,
arm_macosx_dbx_make_msymbol_special);
if (get_arm_single_step_mode () == arm_single_step_mode_auto)
{
#ifdef NM_NEXTSTEP
uint32_t num_hw_bkpts = 0;
size_t num_hw_bkpts_len = sizeof(num_hw_bkpts);
if (sysctlbyname("hw.optional.breakpoint", &num_hw_bkpts,
&num_hw_bkpts_len, NULL, 0) == 0)
{
if (num_hw_bkpts > 0)
set_gdbarch_software_single_step (gdbarch, NULL);
}
else
{
}
#else
set_gdbarch_software_single_step (gdbarch, NULL);
#endif
}
}
void
_initialize_arm_macosx_tdep ()
{
uint32_t i;
builtin_type_arm_psr = build_builtin_type_arm_psr ();
builtin_type_arm_fpscr = build_builtin_type_arm_fpscr ();
g_reginfo_arm_vfpv1[0].offset = 0;
for (i=1; i<g_reginfo_arm_vfpv1_count; i++)
{
if (g_reginfo_arm_vfpv1[i-1].type)
g_reginfo_arm_vfpv1[i].offset = g_reginfo_arm_vfpv1[i-1].offset +
TYPE_LENGTH (*g_reginfo_arm_vfpv1[i-1].type);
}
g_reginfo_arm_vfpv3[0].offset = 0;
for (i=1; i<g_reginfo_arm_vfpv3_count; i++)
{
if (g_reginfo_arm_vfpv3[i-1].type)
g_reginfo_arm_vfpv3[i].offset = g_reginfo_arm_vfpv3[i-1].offset +
TYPE_LENGTH (*g_reginfo_arm_vfpv3[i-1].type);
}
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_4T))->arch,
bfd_mach_arm_4T,
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);
gdbarch_register_osabi ((bfd_lookup_arch (bfd_arch_arm, bfd_mach_arm_7))->arch,
bfd_mach_arm_7,
GDB_OSABI_DARWINV7,
arm_macosx_init_abi_v7);
}