#define MSYMBOL_IS_SPECIAL(msym) \
(((long) MSYMBOL_INFO (msym) & 0x80000000) != 0)
+/* Macros for swapping shorts and ints. In the unlikely case that anybody else needs these,
+ move to a general header. (A better solution might be to define memory read routines that
+ know whether they are reading code or data.) */
+
+#define SWAP_SHORT(x) \
+ ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8));
+
+#define SWAP_INT(x) \
+ ( ((x & 0xff000000) >> 24) \
+ | ((x & 0x00ff0000) >> 8) \
+ | ((x & 0x0000ff00) << 8) \
+ | ((x & 0x000000ff) << 24))
+
/* Per-objfile data used for mapping symbols. */
static const struct objfile_data *arm_objfile_data_key;
{
struct arm_per_objfile *data;
VEC(arm_mapping_symbol_s) *map;
- struct arm_mapping_symbol map_key = { memaddr - sec->addr, 0 };
+ struct arm_mapping_symbol map_key = { memaddr - obj_section_addr (sec),
+ 0 };
unsigned int idx;
data = objfile_data (sec->objfile, arm_objfile_data_key);
/* Remove useless bits from addresses in a running program. */
static CORE_ADDR
-arm_addr_bits_remove (CORE_ADDR val)
+arm_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR val)
{
if (arm_apcs_32)
return UNMAKE_THUMB_ADDR (val);
/* When reading symbols, we need to zap the low bit of the address,
which may be set to 1 for Thumb functions. */
static CORE_ADDR
-arm_smash_text_address (CORE_ADDR val)
+arm_smash_text_address (struct gdbarch *gdbarch, CORE_ADDR val)
{
return val & ~1;
}
insn = read_memory_unsigned_integer (start, 2);
+ if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch))
+ insn = SWAP_SHORT (insn);
+
if ((insn & 0xfe00) == 0xb400) /* push { rlist } */
{
int regno;
{
unsigned long inst;
CORE_ADDR skip_pc;
- CORE_ADDR func_addr, func_end = 0;
- char *func_name;
+ CORE_ADDR func_addr, limit_pc;
struct symtab_and_line sal;
/* If we're in a dummy frame, don't even try to skip the prologue. */
if (deprecated_pc_in_call_dummy (pc))
return pc;
- /* See what the symbol table says. */
-
- if (find_pc_partial_function (pc, &func_name, &func_addr, &func_end))
+ /* See if we can determine the end of the prologue via the symbol table.
+ If so, then return either PC, or the PC after the prologue, whichever
+ is greater. */
+ if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
{
- struct symbol *sym;
-
- /* Found a function. */
- sym = lookup_symbol (func_name, NULL, VAR_DOMAIN, NULL, NULL);
- if (sym && SYMBOL_LANGUAGE (sym) != language_asm)
- {
- /* Don't use this trick for assembly source files. */
- sal = find_pc_line (func_addr, 0);
- if ((sal.line != 0) && (sal.end < func_end))
- return sal.end;
- }
+ CORE_ADDR post_prologue_pc = skip_prologue_using_sal (func_addr);
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);
}
- /* Can't find the prologue end in the symbol table, try it the hard way
- by disassembling the instructions. */
+ /* Can't determine prologue from the symbol table, need to examine
+ instructions. */
+ /* Find an upper limit on the function prologue using the debug
+ information. If the debug information could not be used to provide
+ that bound, then use an arbitrary large number as the upper bound. */
/* Like arm_scan_prologue, stop no later than pc + 64. */
- if (func_end == 0 || func_end > pc + 64)
- func_end = pc + 64;
+ limit_pc = skip_prologue_using_sal (pc);
+ if (limit_pc == 0)
+ limit_pc = pc + 64; /* Magic. */
+
/* Check if this is Thumb code. */
if (arm_pc_is_thumb (pc))
- return thumb_analyze_prologue (gdbarch, pc, func_end, NULL);
+ return thumb_analyze_prologue (gdbarch, pc, limit_pc, NULL);
- for (skip_pc = pc; skip_pc < func_end; skip_pc += 4)
+ for (skip_pc = pc; skip_pc < limit_pc; skip_pc += 4)
{
inst = read_memory_unsigned_integer (skip_pc, 4);
+ if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch))
+ inst = SWAP_INT (inst);
+
/* "mov ip, sp" is no longer a required part of the prologue. */
if (inst == 0xe1a0c00d) /* mov ip, sp */
continue;
{
unsigned int insn = read_memory_unsigned_integer (current_pc, 4);
+ if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch))
+ insn = SWAP_INT (insn);
+
if (insn == 0xe1a0c00d) /* mov ip, sp */
{
regs[ARM_IP_REGNUM] = regs[ARM_SP_REGNUM];
void **this_cache,
int prev_regnum)
{
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
struct arm_prologue_cache *cache;
if (*this_cache == NULL)
lr = frame_unwind_register_unsigned (this_frame, ARM_LR_REGNUM);
return frame_unwind_got_constant (this_frame, prev_regnum,
- arm_addr_bits_remove (lr));
+ arm_addr_bits_remove (gdbarch, lr));
}
/* SP is generally not saved to the stack, but this frame is
{
CORE_ADDR pc;
pc = frame_unwind_register_unsigned (this_frame, ARM_PC_REGNUM);
- return arm_addr_bits_remove (pc);
+ return arm_addr_bits_remove (gdbarch, pc);
}
static CORE_ADDR
arm_dwarf2_prev_register (struct frame_info *this_frame, void **this_cache,
int regnum)
{
+ struct gdbarch * gdbarch = get_frame_arch (this_frame);
CORE_ADDR lr, cpsr;
switch (regnum)
part of the PC. */
lr = frame_unwind_register_unsigned (this_frame, ARM_LR_REGNUM);
return frame_unwind_got_constant (this_frame, regnum,
- arm_addr_bits_remove (lr));
+ arm_addr_bits_remove (gdbarch, lr));
case ARM_PS_REGNUM:
/* Reconstruct the T bit; see arm_prologue_prev_register for details. */
if (regnum >= ARM_F0_REGNUM && regnum < ARM_F0_REGNUM + NUM_FREGS)
return builtin_type_arm_ext;
else if (regnum == ARM_SP_REGNUM)
- return builtin_type_void_data_ptr;
+ return builtin_type (gdbarch)->builtin_data_ptr;
else if (regnum == ARM_PC_REGNUM)
- return builtin_type_void_func_ptr;
+ return builtin_type (gdbarch)->builtin_func_ptr;
else if (regnum >= ARRAY_SIZE (arm_register_names))
/* These registers are only supported on targets which supply
an XML description. */
CORE_ADDR nextpc = pc + 2; /* default is next instruction */
unsigned long offset;
+ if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch))
+ inst1 = SWAP_SHORT (inst1);
+
if ((inst1 & 0xff00) == 0xbd00) /* pop {rlist, pc} */
{
CORE_ADDR sp;
else if ((inst1 & 0xf800) == 0xf000) /* long branch with link, and blx */
{
unsigned short inst2 = read_memory_unsigned_integer (pc + 2, 2);
+ if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch))
+ inst2 = SWAP_SHORT (inst2);
offset = (sbits (inst1, 0, 10) << 12) + (bits (inst2, 0, 10) << 1);
nextpc = pc_val + offset;
/* For BLX make sure to clear the low bits. */
pc_val = (unsigned long) pc;
this_instr = read_memory_unsigned_integer (pc, 4);
+
+ if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch))
+ this_instr = SWAP_INT (this_instr);
+
status = get_frame_register_unsigned (frame, ARM_PS_REGNUM);
nextpc = (CORE_ADDR) (pc_val + 4); /* Default case */
struct gdbarch_info info;
/* If the current architecture is not ARM, we have nothing to do. */
- if (gdbarch_bfd_arch_info (current_gdbarch)->arch != bfd_arch_arm)
+ if (gdbarch_bfd_arch_info (target_gdbarch)->arch != bfd_arch_arm)
return;
/* Update the architecture. */
show_fp_model (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (target_gdbarch);
if (arm_fp_model == ARM_FLOAT_AUTO
- && gdbarch_bfd_arch_info (current_gdbarch)->arch == bfd_arch_arm)
+ && gdbarch_bfd_arch_info (target_gdbarch)->arch == bfd_arch_arm)
fprintf_filtered (file, _("\
The current ARM floating point model is \"auto\" (currently \"%s\").\n"),
fp_model_strings[tdep->fp_model]);
arm_show_abi (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (target_gdbarch);
if (arm_abi_global == ARM_ABI_AUTO
- && gdbarch_bfd_arch_info (current_gdbarch)->arch == bfd_arch_arm)
+ && gdbarch_bfd_arch_info (target_gdbarch)->arch == bfd_arch_arm)
fprintf_filtered (file, _("\
The current ARM ABI is \"auto\" (currently \"%s\").\n"),
arm_abi_strings[tdep->arm_abi]);
arm_show_fallback_mode (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (target_gdbarch);
fprintf_filtered (file, _("\
The current execution mode assumed (when symbols are unavailable) is \"%s\".\n"),
arm_show_force_mode (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (target_gdbarch);
fprintf_filtered (file, _("\
The current execution mode assumed (even when symbols are available) is \"%s\".\n"),
break;
}
}
+
+ if (e_flags & EF_ARM_BE8)
+ info.byte_order_for_code = BFD_ENDIAN_LITTLE;
+
break;
default:
tdep->have_fpa_registers = have_fpa_registers;
/* Breakpoints. */
- switch (info.byte_order)
+ switch (info.byte_order_for_code)
{
case BFD_ENDIAN_BIG:
tdep->arm_breakpoint = arm_default_arm_be_breakpoint;
set_gdbarch_print_float_info (gdbarch, arm_print_float_info);
/* Internal <-> external register number maps. */
- set_gdbarch_dwarf_reg_to_regnum (gdbarch, arm_dwarf_reg_to_regnum);
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, arm_dwarf_reg_to_regnum);
set_gdbarch_register_sim_regno (gdbarch, arm_register_sim_regno);