From 9d4fde7506bd543f837946511c7adf055148ff23 Mon Sep 17 00:00:00 2001 From: Stan Shebs Date: Mon, 11 Aug 2008 19:00:25 +0000 Subject: [PATCH] ARM BE8 support. * disasm.c (gdb_disassemble_info): Set endian_code. * gdbarch.sh (gdbarch_info): New field byte_order_for_code. * gdbarch.h, gdbarch.c: Regenerate. * arch-utils.c (initialize_current_architecture): Set the default byte_order_for_code. (gdbarch_info_init): Ditto. (gdbarch_info_fill): Ditto. * arm-tdep.c (SWAP_INT, SWAP_SHORT): New macros. (thumb_analyze_prologue): Swap halfword if code endianness is different from general endianness. (arm_skip_prologue): Similarly. (arm_scan_prologue): Ditto. (thumb_get_next_pc): Ditto. (arm_get_next_pc): Ditto. (arm_gdbarch_init): Set byte_order_for_code from BE8 flag, choose correct endianness for breakpoints. --- gdb/ChangeLog | 20 ++++++++++++++++++++ gdb/arch-utils.c | 3 +++ gdb/arm-tdep.c | 37 ++++++++++++++++++++++++++++++++++++- gdb/disasm.c | 1 + gdb/gdbarch.c | 15 +++++++++++++++ gdb/gdbarch.h | 5 +++++ gdb/gdbarch.sh | 3 +++ 7 files changed, 83 insertions(+), 1 deletion(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 73f6d2e137b..fbe50881bea 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,23 @@ +2008-08-11 Stan Shebs + + ARM BE8 support. + * disasm.c (gdb_disassemble_info): Set endian_code. + * gdbarch.sh (gdbarch_info): New field byte_order_for_code. + * gdbarch.h, gdbarch.c: Regenerate. + * arch-utils.c (initialize_current_architecture): Set the + default byte_order_for_code. + (gdbarch_info_init): Ditto. + (gdbarch_info_fill): Ditto. + * arm-tdep.c (SWAP_INT, SWAP_SHORT): New macros. + (thumb_analyze_prologue): Swap halfword if code endianness is + different from general endianness. + (arm_skip_prologue): Similarly. + (arm_scan_prologue): Ditto. + (thumb_get_next_pc): Ditto. + (arm_get_next_pc): Ditto. + (arm_gdbarch_init): Set byte_order_for_code from BE8 flag, + choose correct endianness for breakpoints. + 2008-08-10 Pedro Alves * bsd-kvm.c: Include "gdbthread.h". diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c index 259d1e3a5f4..a2fd7b65661 100644 --- a/gdb/arch-utils.c +++ b/gdb/arch-utils.c @@ -629,6 +629,7 @@ initialize_current_architecture (void) } info.byte_order = default_byte_order; + info.byte_order_for_code = info.byte_order; if (! gdbarch_update_p (info)) internal_error (__FILE__, __LINE__, @@ -667,6 +668,7 @@ gdbarch_info_init (struct gdbarch_info *info) { memset (info, 0, sizeof (struct gdbarch_info)); info->byte_order = BFD_ENDIAN_UNKNOWN; + info->byte_order_for_code = info->byte_order; info->osabi = GDB_OSABI_UNINITIALIZED; } @@ -708,6 +710,7 @@ gdbarch_info_fill (struct gdbarch_info *info) /* From the default. */ if (info->byte_order == BFD_ENDIAN_UNKNOWN) info->byte_order = default_byte_order; + info->byte_order_for_code = info->byte_order; /* "(gdb) set osabi ...". Handled by gdbarch_lookup_osabi. */ if (info->osabi == GDB_OSABI_UNINITIALIZED) diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index fd732a87e45..66add047d4b 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -69,6 +69,19 @@ static int arm_debug; #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; @@ -391,6 +404,9 @@ thumb_analyze_prologue (struct gdbarch *gdbarch, 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; @@ -559,6 +575,9 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) { 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; @@ -855,6 +874,9 @@ arm_scan_prologue (struct frame_info *this_frame, { 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]; @@ -1812,6 +1834,9 @@ thumb_get_next_pc (struct frame_info *frame, CORE_ADDR pc) 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; @@ -1839,6 +1864,8 @@ thumb_get_next_pc (struct frame_info *frame, CORE_ADDR pc) 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. */ @@ -1874,6 +1901,10 @@ arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc) 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 */ @@ -3150,6 +3181,10 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) break; } } + + if (e_flags & EF_ARM_BE8) + info.byte_order_for_code = BFD_ENDIAN_LITTLE; + break; default: @@ -3192,7 +3227,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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; diff --git a/gdb/disasm.c b/gdb/disasm.c index 64c0cbc5a7c..f9ff9b1c485 100644 --- a/gdb/disasm.c +++ b/gdb/disasm.c @@ -343,6 +343,7 @@ gdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file) di.arch = gdbarch_bfd_arch_info (gdbarch)->arch; di.mach = gdbarch_bfd_arch_info (gdbarch)->mach; di.endian = gdbarch_byte_order (gdbarch); + di.endian_code = gdbarch_byte_order_for_code (gdbarch); disassemble_init_for_target (&di); return di; } diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 6b173c2b80c..504cb774f1c 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -90,6 +90,7 @@ struct gdbarch /* basic architectural information */ const struct bfd_arch_info * bfd_arch_info; int byte_order; + int byte_order_for_code; enum gdb_osabi osabi; const struct target_desc * target_desc; @@ -254,6 +255,7 @@ struct gdbarch startup_gdbarch = /* basic architecture information */ &bfd_default_arch_struct, /* bfd_arch_info */ BFD_ENDIAN_BIG, /* byte_order */ + BFD_ENDIAN_BIG, /* byte_order_for_code */ GDB_OSABI_UNKNOWN, /* osabi */ 0, /* target_desc */ /* target specific vector and its dump routine */ @@ -398,6 +400,7 @@ gdbarch_alloc (const struct gdbarch_info *info, gdbarch->bfd_arch_info = info->bfd_arch_info; gdbarch->byte_order = info->byte_order; + gdbarch->byte_order_for_code = info->byte_order_for_code; gdbarch->osabi = info->osabi; gdbarch->target_desc = info->target_desc; @@ -692,6 +695,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) fprintf_unfiltered (file, "gdbarch_dump: byte_order = %s\n", paddr_d (gdbarch->byte_order)); + fprintf_unfiltered (file, + "gdbarch_dump: byte_order_for_code = %s\n", + paddr_d (gdbarch->byte_order_for_code)); fprintf_unfiltered (file, "gdbarch_dump: call_dummy_location = %s\n", paddr_d (gdbarch->call_dummy_location)); @@ -1122,6 +1128,15 @@ gdbarch_byte_order (struct gdbarch *gdbarch) return gdbarch->byte_order; } +int +gdbarch_byte_order_for_code (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_byte_order_for_code called\n"); + return gdbarch->byte_order_for_code; +} + enum gdb_osabi gdbarch_osabi (struct gdbarch *gdbarch) { diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 870b79b73d2..24d8c6bbc68 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -64,6 +64,9 @@ extern const struct bfd_arch_info * gdbarch_bfd_arch_info (struct gdbarch *gdbar extern int gdbarch_byte_order (struct gdbarch *gdbarch); /* set_gdbarch_byte_order() - not applicable - pre-initialized. */ +extern int gdbarch_byte_order_for_code (struct gdbarch *gdbarch); +/* set_gdbarch_byte_order_for_code() - not applicable - pre-initialized. */ + extern enum gdb_osabi gdbarch_osabi (struct gdbarch *gdbarch); /* set_gdbarch_osabi() - not applicable - pre-initialized. */ @@ -885,6 +888,8 @@ struct gdbarch_info /* Use default: BFD_ENDIAN_UNKNOWN (NB: is not ZERO). */ int byte_order; + int byte_order_for_code; + /* Use default: NULL (ZERO). */ bfd *abfd; diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index af7aea437b8..a9fcd80015a 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -339,6 +339,7 @@ function_list () i:const struct bfd_arch_info *:bfd_arch_info:::&bfd_default_arch_struct::::gdbarch_bfd_arch_info (gdbarch)->printable_name # i:int:byte_order:::BFD_ENDIAN_BIG +i:int:byte_order_for_code:::BFD_ENDIAN_BIG # i:enum gdb_osabi:osabi:::GDB_OSABI_UNKNOWN # @@ -962,6 +963,8 @@ struct gdbarch_info /* Use default: BFD_ENDIAN_UNKNOWN (NB: is not ZERO). */ int byte_order; + int byte_order_for_code; + /* Use default: NULL (ZERO). */ bfd *abfd; -- 2.39.2