aboutsummaryrefslogtreecommitdiff
path: root/gdb/arm-tdep.c
diff options
context:
space:
mode:
authorYao Qi <yao@codesourcery.com>2014-11-28 15:19:12 +0800
committerYao Qi <yao@codesourcery.com>2014-12-12 08:46:25 +0800
commitf303bc3e6ca29f0413376e38164dc5cdc0893d4b (patch)
treecc07c14344717252229db9bba5ca43d38b8b1885 /gdb/arm-tdep.c
parent65840e31a7a7cd64c81ac47bcb17319536ce3ba2 (diff)
downloadgdb-f303bc3e6ca29f0413376e38164dc5cdc0893d4b.zip
gdb-f303bc3e6ca29f0413376e38164dc5cdc0893d4b.tar.gz
gdb-f303bc3e6ca29f0413376e38164dc5cdc0893d4b.tar.bz2
Don't scan prologue past epilogue
This patch is to stop prologue analysis past epilogue in for arm mode, while we've already had done the same to thumb mode (see thumb_instruction_restores_sp). This is useful to parse functions with empty body (epilogue follows prologue). gdb: 2014-12-12 Yao Qi <yao@codesourcery.com> * arm-tdep.c (arm_instruction_restores_sp): New function. (arm_analyze_prologue): Call arm_instruction_restores_sp. (arm_in_function_epilogue_p): Move code to arm_instruction_restores_sp.
Diffstat (limited to 'gdb/arm-tdep.c')
-rw-r--r--gdb/arm-tdep.c53
1 files changed, 31 insertions, 22 deletions
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 7ec3bff..3407045 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -1664,6 +1664,30 @@ arm_instruction_changes_pc (uint32_t this_instr)
}
}
+/* Return 1 if the ARM instruction INSN restores SP in epilogue, 0
+ otherwise. */
+
+static int
+arm_instruction_restores_sp (unsigned int insn)
+{
+ if (bits (insn, 28, 31) != INST_NV)
+ {
+ if ((insn & 0x0df0f000) == 0x0080d000
+ /* ADD SP (register or immediate). */
+ || (insn & 0x0df0f000) == 0x0040d000
+ /* SUB SP (register or immediate). */
+ || (insn & 0x0ffffff0) == 0x01a0d000
+ /* MOV SP. */
+ || (insn & 0x0fff0000) == 0x08bd0000
+ /* POP (LDMIA). */
+ || (insn & 0x0fff0000) == 0x049d0000)
+ /* POP of a single register. */
+ return 1;
+ }
+
+ return 0;
+}
+
/* Analyze an ARM mode prologue starting at PROLOGUE_START and
continuing no further than PROLOGUE_END. If CACHE is non-NULL,
fill it in. Return the first address not recognized as a prologue
@@ -1861,6 +1885,11 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
else if (arm_instruction_changes_pc (insn))
/* Don't scan past anything that might change control flow. */
break;
+ else if (arm_instruction_restores_sp (insn))
+ {
+ /* Don't scan past the epilogue. */
+ break;
+ }
else if ((insn & 0xfe500000) == 0xe8100000 /* ldm */
&& pv_is_register (regs[bits (insn, 16, 19)], ARM_SP_REGNUM))
/* Ignore block loads from the stack, potentially copying
@@ -3351,7 +3380,7 @@ arm_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
{
enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
unsigned int insn;
- int found_return, found_stack_adjust;
+ int found_return;
CORE_ADDR func_start, func_end;
if (arm_pc_is_thumb (gdbarch, pc))
@@ -3391,28 +3420,8 @@ arm_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
if (pc < func_start + 4)
return 0;
- found_stack_adjust = 0;
insn = read_memory_unsigned_integer (pc - 4, 4, byte_order_for_code);
- if (bits (insn, 28, 31) != INST_NV)
- {
- if ((insn & 0x0df0f000) == 0x0080d000)
- /* ADD SP (register or immediate). */
- found_stack_adjust = 1;
- else if ((insn & 0x0df0f000) == 0x0040d000)
- /* SUB SP (register or immediate). */
- found_stack_adjust = 1;
- else if ((insn & 0x0ffffff0) == 0x01a0d000)
- /* MOV SP. */
- found_stack_adjust = 1;
- else if ((insn & 0x0fff0000) == 0x08bd0000)
- /* POP (LDMIA). */
- found_stack_adjust = 1;
- else if ((insn & 0x0fff0000) == 0x049d0000)
- /* POP of a single register. */
- found_stack_adjust = 1;
- }
-
- if (found_stack_adjust)
+ if (arm_instruction_restores_sp (insn))
return 1;
return 0;