From: Yao Qi Date: Fri, 28 Nov 2014 07:19:12 +0000 (+0800) Subject: Don't scan prologue past epilogue X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f303bc3e6ca29f0413376e38164dc5cdc0893d4b;p=binutils-gdb.git 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 * 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index bdbe56b10ac..c444ce77c07 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2014-12-12 Yao Qi + + * 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. + 2014-12-11 Doug Evans * cp-namespace.c (cp_lookup_nested_symbol): Fix comments. diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 7ec3bff5007..34070452e17 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;