aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog20
-rw-r--r--gdb/arch-utils.c3
-rw-r--r--gdb/arm-tdep.c37
-rw-r--r--gdb/disasm.c1
-rw-r--r--gdb/gdbarch.c15
-rw-r--r--gdb/gdbarch.h5
-rwxr-xr-xgdb/gdbarch.sh3
7 files changed, 83 insertions, 1 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 73f6d2e..fbe5088 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,23 @@
+2008-08-11 Stan Shebs <stan@codesourcery.com>
+
+ 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 <pedro@codesourcery.com>
* bsd-kvm.c: Include "gdbthread.h".
diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c
index 259d1e3..a2fd7b6 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 fd732a8..66add04 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 64c0cbc..f9ff9b1 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 6b173c2..504cb77 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;
@@ -693,6 +696,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *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));
fprintf_unfiltered (file,
@@ -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 870b79b..24d8c6b 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 af7aea4..a9fcd80 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;