Fix Nios II GDB epilogue detection to handle multiple stack adjustments.
2014-11-25 Sandra Loosemore <sandra@codesourcery.com> gdb/ * nios2-tdep.c (nios2_in_epilogue_p): Handle multiple stack adjustments.
This commit is contained in:
parent
d53c26c753
commit
7f1659b587
2 changed files with 47 additions and 17 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
2014-11-25 Sandra Loosemore <sandra@codesourcery.com>
|
||||||
|
|
||||||
|
* nios2-tdep.c (nios2_in_epilogue_p): Handle multiple stack
|
||||||
|
adjustments.
|
||||||
|
|
||||||
2014-11-25 Sandra Loosemore <sandra@codesourcery.com>
|
2014-11-25 Sandra Loosemore <sandra@codesourcery.com>
|
||||||
|
|
||||||
* nios2-tdep.c (nios2_fetch_insn): Move up in file. Disassemble
|
* nios2-tdep.c (nios2_fetch_insn): Move up in file. Disassemble
|
||||||
|
|
|
@ -589,26 +589,42 @@ nios2_in_epilogue_p (struct gdbarch *gdbarch,
|
||||||
CORE_ADDR start_pc)
|
CORE_ADDR start_pc)
|
||||||
{
|
{
|
||||||
unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
|
unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
|
||||||
|
/* Maximum number of possibly-epilogue instructions to check.
|
||||||
|
Note that this number should not be too large, else we can
|
||||||
|
potentially end up iterating through unmapped memory. */
|
||||||
|
int ninsns, max_insns = 5;
|
||||||
unsigned int insn;
|
unsigned int insn;
|
||||||
const struct nios2_opcode *op = NULL;
|
const struct nios2_opcode *op = NULL;
|
||||||
unsigned int uimm;
|
unsigned int uimm;
|
||||||
int imm;
|
int imm;
|
||||||
int ra, rb, rc;
|
int ra, rb, rc;
|
||||||
enum branch_condition cond;
|
enum branch_condition cond;
|
||||||
|
CORE_ADDR pc;
|
||||||
|
|
||||||
/* There has to be a previous instruction in the function. */
|
/* There has to be a previous instruction in the function. */
|
||||||
if (current_pc > start_pc)
|
if (current_pc <= start_pc)
|
||||||
{
|
return 0;
|
||||||
int ok = 0;
|
|
||||||
|
|
||||||
/* Check whether the previous instruction was a stack adjustment.
|
/* Find the previous instruction before current_pc.
|
||||||
|
For the moment we will assume that all instructions are the
|
||||||
|
same size here. */
|
||||||
|
pc = current_pc - NIOS2_OPCODE_SIZE;
|
||||||
|
|
||||||
|
/* Beginning with the previous instruction we just located, check whether
|
||||||
|
we are in a sequence of at least one stack adjustment instruction.
|
||||||
Possible instructions here include:
|
Possible instructions here include:
|
||||||
ADDI sp, sp, n
|
ADDI sp, sp, n
|
||||||
ADD sp, sp, rn
|
ADD sp, sp, rn
|
||||||
LDW sp, n(sp) */
|
LDW sp, n(sp) */
|
||||||
op = nios2_fetch_insn (gdbarch, current_pc - NIOS2_OPCODE_SIZE, &insn);
|
for (ninsns = 0; ninsns < max_insns; ninsns++)
|
||||||
|
{
|
||||||
|
int ok = 0;
|
||||||
|
|
||||||
|
/* Fetch the insn at pc. */
|
||||||
|
op = nios2_fetch_insn (gdbarch, pc, &insn);
|
||||||
if (op == NULL)
|
if (op == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
pc += op->size;
|
||||||
|
|
||||||
/* Was it a stack adjustment? */
|
/* Was it a stack adjustment? */
|
||||||
if (nios2_match_addi (insn, op, mach, &ra, &rb, &imm))
|
if (nios2_match_addi (insn, op, mach, &ra, &rb, &imm))
|
||||||
|
@ -618,18 +634,27 @@ nios2_in_epilogue_p (struct gdbarch *gdbarch,
|
||||||
else if (nios2_match_ldw (insn, op, mach, &ra, &rb, &imm))
|
else if (nios2_match_ldw (insn, op, mach, &ra, &rb, &imm))
|
||||||
ok = (rb == NIOS2_SP_REGNUM);
|
ok = (rb == NIOS2_SP_REGNUM);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No stack adjustments found. */
|
||||||
|
if (ninsns == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Then check if it's followed by a return or a tail call. */
|
/* We found more stack adjustments than we expect GCC to be generating.
|
||||||
op = nios2_fetch_insn (gdbarch, current_pc, &insn);
|
Since it looks like a stack unwind might be in progress tell GDB to
|
||||||
if (op == NULL)
|
treat it as such. */
|
||||||
return 0;
|
if (ninsns == max_insns)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* The next instruction following the stack adjustments must be a
|
||||||
|
return, jump, or unconditional branch. */
|
||||||
if (nios2_match_jmpr (insn, op, mach, &ra)
|
if (nios2_match_jmpr (insn, op, mach, &ra)
|
||||||
|| nios2_match_jmpi (insn, op, mach, &uimm)
|
|| nios2_match_jmpi (insn, op, mach, &uimm)
|
||||||
|| (nios2_match_branch (insn, op, mach, &ra, &rb, &imm, &cond)
|
|| (nios2_match_branch (insn, op, mach, &ra, &rb, &imm, &cond)
|
||||||
&& cond == branch_none))
|
&& cond == branch_none))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue