mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-02-03 23:56:39 +00:00
* arm-tdep.c (thumb_expand_immediate): New function.
(thumb_instruction_changes_pc): Likewise. (thumb2_instruction_changes_pc): Likewise. (thumb_analyze_prologue): Handle 32-bit Thumb instructions during prologue parsing. Improved support for optimized code. (thumb_scan_prologue): Do not reply on line-number information, use same heuristics as arm_scan_prologue insead. (skip_prologue_function): Accept functions "__tls_get_addr" and "__aeabi_read_tp".
This commit is contained in:
parent
4024ca9964
commit
ec3d575a7a
@ -1,3 +1,15 @@
|
||||
2010-10-08 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* arm-tdep.c (thumb_expand_immediate): New function.
|
||||
(thumb_instruction_changes_pc): Likewise.
|
||||
(thumb2_instruction_changes_pc): Likewise.
|
||||
(thumb_analyze_prologue): Handle 32-bit Thumb instructions during
|
||||
prologue parsing. Improved support for optimized code.
|
||||
(thumb_scan_prologue): Do not reply on line-number information,
|
||||
use same heuristics as arm_scan_prologue insead.
|
||||
(skip_prologue_function): Accept functions
|
||||
"__tls_get_addr" and "__aeabi_read_tp".
|
||||
|
||||
2010-10-08 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
|
440
gdb/arm-tdep.c
440
gdb/arm-tdep.c
@ -476,6 +476,12 @@ skip_prologue_function (CORE_ADDR pc)
|
||||
if (strncmp (name, "__aeabi_d2f", strlen ("__aeabi_d2f")) == 0)
|
||||
return 1;
|
||||
|
||||
/* Internal functions related to thread-local storage. */
|
||||
if (strncmp (name, "__tls_get_addr", strlen ("__tls_get_addr")) == 0)
|
||||
return 1;
|
||||
if (strncmp (name, "__aeabi_read_tp", strlen ("__aeabi_read_tp")) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -488,6 +494,149 @@ skip_prologue_function (CORE_ADDR pc)
|
||||
#define BranchDest(addr,instr) \
|
||||
((CORE_ADDR) (((long) (addr)) + 8 + (sbits (instr, 0, 23) << 2)))
|
||||
|
||||
/* Decode immediate value; implements ThumbExpandImmediate pseudo-op. */
|
||||
|
||||
static unsigned int
|
||||
thumb_expand_immediate (unsigned int imm)
|
||||
{
|
||||
unsigned int count = imm >> 7;
|
||||
|
||||
if (count < 8)
|
||||
switch (count / 2)
|
||||
{
|
||||
case 0:
|
||||
return imm & 0xff;
|
||||
case 1:
|
||||
return (imm & 0xff) | ((imm & 0xff) << 16);
|
||||
case 2:
|
||||
return ((imm & 0xff) << 8) | ((imm & 0xff) << 24);
|
||||
case 3:
|
||||
return (imm & 0xff) | ((imm & 0xff) << 8)
|
||||
| ((imm & 0xff) << 16) | ((imm & 0xff) << 24);
|
||||
}
|
||||
|
||||
return (0x80 | (imm & 0x7f)) << (32 - count);
|
||||
}
|
||||
|
||||
/* Return 1 if the 16-bit Thumb instruction INST might change
|
||||
control flow, 0 otherwise. */
|
||||
|
||||
static int
|
||||
thumb_instruction_changes_pc (unsigned short inst)
|
||||
{
|
||||
if ((inst & 0xff00) == 0xbd00) /* pop {rlist, pc} */
|
||||
return 1;
|
||||
|
||||
if ((inst & 0xf000) == 0xd000) /* conditional branch */
|
||||
return 1;
|
||||
|
||||
if ((inst & 0xf800) == 0xe000) /* unconditional branch */
|
||||
return 1;
|
||||
|
||||
if ((inst & 0xff00) == 0x4700) /* bx REG, blx REG */
|
||||
return 1;
|
||||
|
||||
if ((inst & 0xf500) == 0xb100) /* CBNZ or CBZ. */
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return 1 if the 32-bit Thumb instruction in INST1 and INST2
|
||||
might change control flow, 0 otherwise. */
|
||||
|
||||
static int
|
||||
thumb2_instruction_changes_pc (unsigned short inst1, unsigned short inst2)
|
||||
{
|
||||
if ((inst1 & 0xf800) == 0xf000 && (inst2 & 0x8000) == 0x8000)
|
||||
{
|
||||
/* Branches and miscellaneous control instructions. */
|
||||
|
||||
if ((inst2 & 0x1000) != 0 || (inst2 & 0xd001) == 0xc000)
|
||||
{
|
||||
/* B, BL, BLX. */
|
||||
return 1;
|
||||
}
|
||||
else if (inst1 == 0xf3de && (inst2 & 0xff00) == 0x3f00)
|
||||
{
|
||||
/* SUBS PC, LR, #imm8. */
|
||||
return 1;
|
||||
}
|
||||
else if ((inst2 & 0xd000) == 0x8000 && (inst1 & 0x0380) != 0x0380)
|
||||
{
|
||||
/* Conditional branch. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((inst1 & 0xfe50) == 0xe810)
|
||||
{
|
||||
/* Load multiple or RFE. */
|
||||
|
||||
if (bit (inst1, 7) && !bit (inst1, 8))
|
||||
{
|
||||
/* LDMIA or POP */
|
||||
if (bit (inst2, 15))
|
||||
return 1;
|
||||
}
|
||||
else if (!bit (inst1, 7) && bit (inst1, 8))
|
||||
{
|
||||
/* LDMDB */
|
||||
if (bit (inst2, 15))
|
||||
return 1;
|
||||
}
|
||||
else if (bit (inst1, 7) && bit (inst1, 8))
|
||||
{
|
||||
/* RFEIA */
|
||||
return 1;
|
||||
}
|
||||
else if (!bit (inst1, 7) && !bit (inst1, 8))
|
||||
{
|
||||
/* RFEDB */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((inst1 & 0xffef) == 0xea4f && (inst2 & 0xfff0) == 0x0f00)
|
||||
{
|
||||
/* MOV PC or MOVS PC. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((inst1 & 0xff70) == 0xf850 && (inst2 & 0xf000) == 0xf000)
|
||||
{
|
||||
/* LDR PC. */
|
||||
if (bits (inst1, 0, 3) == 15)
|
||||
return 1;
|
||||
if (bit (inst1, 7))
|
||||
return 1;
|
||||
if (bit (inst2, 11))
|
||||
return 1;
|
||||
if ((inst2 & 0x0fc0) == 0x0000)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf000)
|
||||
{
|
||||
/* TBB. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf010)
|
||||
{
|
||||
/* TBH. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Analyze a Thumb prologue, looking for a recognizable stack frame
|
||||
and frame pointer. Scan until we encounter a store that could
|
||||
clobber the stack frame unexpectedly, or an unknown instruction.
|
||||
@ -506,6 +655,7 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
|
||||
struct pv_area *stack;
|
||||
struct cleanup *back_to;
|
||||
CORE_ADDR offset;
|
||||
CORE_ADDR unrecognized_pc = 0;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
regs[i] = pv_register (i, 0);
|
||||
@ -643,9 +793,8 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
|
||||
constant = read_memory_unsigned_integer (loc, 4, byte_order);
|
||||
regs[bits (insn, 8, 10)] = pv_constant (constant);
|
||||
}
|
||||
else if ((insn & 0xe000) == 0xe000 && cache == NULL)
|
||||
else if ((insn & 0xe000) == 0xe000)
|
||||
{
|
||||
/* Only recognize 32-bit instructions for prologue skipping. */
|
||||
unsigned short inst2;
|
||||
|
||||
inst2 = read_memory_unsigned_integer (start + 2, 2,
|
||||
@ -675,58 +824,256 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
|
||||
if (!skip_prologue_function (nextpc))
|
||||
break;
|
||||
}
|
||||
else if ((insn & 0xfe50) == 0xe800 /* stm{db,ia} Rn[!], { registers } */
|
||||
|
||||
else if ((insn & 0xffd0) == 0xe900 /* stmdb Rn{!}, { registers } */
|
||||
&& pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
|
||||
;
|
||||
else if ((insn & 0xfe50) == 0xe840 /* strd Rt, Rt2, [Rn, #imm] */
|
||||
{
|
||||
pv_t addr = regs[bits (insn, 0, 3)];
|
||||
int regno;
|
||||
|
||||
if (pv_area_store_would_trash (stack, addr))
|
||||
break;
|
||||
|
||||
/* Calculate offsets of saved registers. */
|
||||
for (regno = ARM_LR_REGNUM; regno >= 0; regno--)
|
||||
if (inst2 & (1 << regno))
|
||||
{
|
||||
addr = pv_add_constant (addr, -4);
|
||||
pv_area_store (stack, addr, 4, regs[regno]);
|
||||
}
|
||||
|
||||
if (insn & 0x0020)
|
||||
regs[bits (insn, 0, 3)] = addr;
|
||||
}
|
||||
|
||||
else if ((insn & 0xff50) == 0xe940 /* strd Rt, Rt2, [Rn, #+/-imm]{!} */
|
||||
&& pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
|
||||
{
|
||||
int regno1 = bits (inst2, 12, 15);
|
||||
int regno2 = bits (inst2, 8, 11);
|
||||
pv_t addr = regs[bits (insn, 0, 3)];
|
||||
|
||||
offset = inst2 & 0xff;
|
||||
if (insn & 0x0080)
|
||||
addr = pv_add_constant (addr, offset);
|
||||
else
|
||||
addr = pv_add_constant (addr, -offset);
|
||||
|
||||
if (pv_area_store_would_trash (stack, addr))
|
||||
break;
|
||||
|
||||
pv_area_store (stack, addr, 4, regs[regno1]);
|
||||
pv_area_store (stack, pv_add_constant (addr, 4),
|
||||
4, regs[regno2]);
|
||||
|
||||
if (insn & 0x0020)
|
||||
regs[bits (insn, 0, 3)] = addr;
|
||||
}
|
||||
|
||||
else if ((insn & 0xfff0) == 0xf8c0 /* str Rt,[Rn,+/-#imm]{!} */
|
||||
&& (inst2 & 0x0c00) == 0x0c00
|
||||
&& pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
|
||||
{
|
||||
int regno = bits (inst2, 12, 15);
|
||||
pv_t addr = regs[bits (insn, 0, 3)];
|
||||
|
||||
offset = inst2 & 0xff;
|
||||
if (inst2 & 0x0200)
|
||||
addr = pv_add_constant (addr, offset);
|
||||
else
|
||||
addr = pv_add_constant (addr, -offset);
|
||||
|
||||
if (pv_area_store_would_trash (stack, addr))
|
||||
break;
|
||||
|
||||
pv_area_store (stack, addr, 4, regs[regno]);
|
||||
|
||||
if (inst2 & 0x0100)
|
||||
regs[bits (insn, 0, 3)] = addr;
|
||||
}
|
||||
|
||||
else if ((insn & 0xfff0) == 0xf8c0 /* str.w Rt,[Rn,#imm] */
|
||||
&& pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
|
||||
{
|
||||
int regno = bits (inst2, 12, 15);
|
||||
pv_t addr;
|
||||
|
||||
offset = inst2 & 0xfff;
|
||||
addr = pv_add_constant (regs[bits (insn, 0, 3)], offset);
|
||||
|
||||
if (pv_area_store_would_trash (stack, addr))
|
||||
break;
|
||||
|
||||
pv_area_store (stack, addr, 4, regs[regno]);
|
||||
}
|
||||
|
||||
else if ((insn & 0xffd0) == 0xf880 /* str{bh}.w Rt,[Rn,#imm] */
|
||||
&& pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
|
||||
/* Ignore stores of argument registers to the stack. */
|
||||
;
|
||||
|
||||
else if ((insn & 0xffd0) == 0xf800 /* str{bh} Rt,[Rn,#+/-imm] */
|
||||
&& (inst2 & 0x0d00) == 0x0c00
|
||||
&& pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
|
||||
/* Ignore stores of argument registers to the stack. */
|
||||
;
|
||||
|
||||
else if ((insn & 0xffd0) == 0xe890 /* ldmia Rn[!], { registers } */
|
||||
&& (inst2 & 0x8000) == 0x0000
|
||||
&& pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
|
||||
&& (inst2 & 0x8000) == 0x0000
|
||||
&& pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
|
||||
/* Ignore block loads from the stack, potentially copying
|
||||
parameters from memory. */
|
||||
;
|
||||
|
||||
else if ((insn & 0xffb0) == 0xe950 /* ldrd Rt, Rt2, [Rn, #+/-imm] */
|
||||
&& pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
|
||||
/* Similarly ignore dual loads from the stack. */
|
||||
;
|
||||
|
||||
else if ((insn & 0xfff0) == 0xf850 /* ldr Rt,[Rn,#+/-imm] */
|
||||
&& (inst2 & 0x0d00) == 0x0c00
|
||||
&& pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
|
||||
/* Similarly ignore single loads from the stack. */
|
||||
;
|
||||
|
||||
else if ((insn & 0xfff0) == 0xf8d0 /* ldr.w Rt,[Rn,#imm] */
|
||||
&& pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
|
||||
/* Similarly ignore single loads from the stack. */
|
||||
;
|
||||
|
||||
else if ((insn & 0xfbf0) == 0xf100 /* add.w Rd, Rn, #imm */
|
||||
&& (inst2 & 0x8000) == 0x0000)
|
||||
/* Since we only recognize this for prologue skipping, do not bother
|
||||
to compute the constant. */
|
||||
regs[bits (inst2, 8, 11)] = regs[bits (insn, 0, 3)];
|
||||
else if ((insn & 0xfbf0) == 0xf1a0 /* sub.w Rd, Rn, #imm12 */
|
||||
{
|
||||
unsigned int imm = ((bits (insn, 10, 10) << 11)
|
||||
| (bits (inst2, 12, 14) << 8)
|
||||
| bits (inst2, 0, 7));
|
||||
|
||||
regs[bits (inst2, 8, 11)]
|
||||
= pv_add_constant (regs[bits (insn, 0, 3)],
|
||||
thumb_expand_immediate (imm));
|
||||
}
|
||||
|
||||
else if ((insn & 0xfbf0) == 0xf200 /* addw Rd, Rn, #imm */
|
||||
&& (inst2 & 0x8000) == 0x0000)
|
||||
/* Since we only recognize this for prologue skipping, do not bother
|
||||
to compute the constant. */
|
||||
regs[bits (inst2, 8, 11)] = regs[bits (insn, 0, 3)];
|
||||
else if ((insn & 0xfbf0) == 0xf2a0 /* sub.w Rd, Rn, #imm8 */
|
||||
{
|
||||
unsigned int imm = ((bits (insn, 10, 10) << 11)
|
||||
| (bits (inst2, 12, 14) << 8)
|
||||
| bits (inst2, 0, 7));
|
||||
|
||||
regs[bits (inst2, 8, 11)]
|
||||
= pv_add_constant (regs[bits (insn, 0, 3)], imm);
|
||||
}
|
||||
|
||||
else if ((insn & 0xfbf0) == 0xf1a0 /* sub.w Rd, Rn, #imm */
|
||||
&& (inst2 & 0x8000) == 0x0000)
|
||||
/* Since we only recognize this for prologue skipping, do not bother
|
||||
to compute the constant. */
|
||||
regs[bits (inst2, 8, 11)] = regs[bits (insn, 0, 3)];
|
||||
else if ((insn & 0xff50) == 0xf850 /* ldr.w Rd, [Rn, #imm]{!} */
|
||||
&& pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
|
||||
;
|
||||
else if ((insn & 0xff50) == 0xe950 /* ldrd Rt, Rt2, [Rn, #imm]{!} */
|
||||
&& pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
|
||||
;
|
||||
else if ((insn & 0xff50) == 0xf800 /* strb.w or strh.w */
|
||||
&& pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
|
||||
;
|
||||
{
|
||||
unsigned int imm = ((bits (insn, 10, 10) << 11)
|
||||
| (bits (inst2, 12, 14) << 8)
|
||||
| bits (inst2, 0, 7));
|
||||
|
||||
regs[bits (inst2, 8, 11)]
|
||||
= pv_add_constant (regs[bits (insn, 0, 3)],
|
||||
- (CORE_ADDR) thumb_expand_immediate (imm));
|
||||
}
|
||||
|
||||
else if ((insn & 0xfbf0) == 0xf2a0 /* subw Rd, Rn, #imm */
|
||||
&& (inst2 & 0x8000) == 0x0000)
|
||||
{
|
||||
unsigned int imm = ((bits (insn, 10, 10) << 11)
|
||||
| (bits (inst2, 12, 14) << 8)
|
||||
| bits (inst2, 0, 7));
|
||||
|
||||
regs[bits (inst2, 8, 11)]
|
||||
= pv_add_constant (regs[bits (insn, 0, 3)], - (CORE_ADDR) imm);
|
||||
}
|
||||
|
||||
else if ((insn & 0xfbff) == 0xf04f) /* mov.w Rd, #const */
|
||||
{
|
||||
unsigned int imm = ((bits (insn, 10, 10) << 11)
|
||||
| (bits (inst2, 12, 14) << 8)
|
||||
| bits (inst2, 0, 7));
|
||||
|
||||
regs[bits (inst2, 8, 11)]
|
||||
= pv_constant (thumb_expand_immediate (imm));
|
||||
}
|
||||
|
||||
else if ((insn & 0xfbf0) == 0xf240) /* movw Rd, #const */
|
||||
{
|
||||
unsigned int imm = ((bits (insn, 0, 3) << 12)
|
||||
| (bits (insn, 10, 10) << 11)
|
||||
| (bits (inst2, 12, 14) << 8)
|
||||
| bits (inst2, 0, 7));
|
||||
|
||||
regs[bits (inst2, 8, 11)] = pv_constant (imm);
|
||||
}
|
||||
|
||||
else if (insn == 0xea5f /* mov.w Rd,Rm */
|
||||
&& (inst2 & 0xf0f0) == 0)
|
||||
{
|
||||
int dst_reg = (inst2 & 0x0f00) >> 8;
|
||||
int src_reg = inst2 & 0xf;
|
||||
regs[dst_reg] = regs[src_reg];
|
||||
}
|
||||
|
||||
else if ((insn & 0xff7f) == 0xf85f) /* ldr.w Rt,<label> */
|
||||
{
|
||||
/* Constant pool loads. */
|
||||
unsigned int constant;
|
||||
CORE_ADDR loc;
|
||||
|
||||
offset = bits (insn, 0, 11);
|
||||
if (insn & 0x0080)
|
||||
loc = start + 4 + offset;
|
||||
else
|
||||
loc = start + 4 - offset;
|
||||
|
||||
constant = read_memory_unsigned_integer (loc, 4, byte_order);
|
||||
regs[bits (inst2, 12, 15)] = pv_constant (constant);
|
||||
}
|
||||
|
||||
else if ((insn & 0xff7f) == 0xe95f) /* ldrd Rt,Rt2,<label> */
|
||||
{
|
||||
/* Constant pool loads. */
|
||||
unsigned int constant;
|
||||
CORE_ADDR loc;
|
||||
|
||||
offset = bits (insn, 0, 7) << 2;
|
||||
if (insn & 0x0080)
|
||||
loc = start + 4 + offset;
|
||||
else
|
||||
loc = start + 4 - offset;
|
||||
|
||||
constant = read_memory_unsigned_integer (loc, 4, byte_order);
|
||||
regs[bits (inst2, 12, 15)] = pv_constant (constant);
|
||||
|
||||
constant = read_memory_unsigned_integer (loc + 4, 4, byte_order);
|
||||
regs[bits (inst2, 8, 11)] = pv_constant (constant);
|
||||
}
|
||||
|
||||
else if (thumb2_instruction_changes_pc (insn, inst2))
|
||||
{
|
||||
/* Don't scan past anything that might change control flow. */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We don't know what this instruction is. We're finished
|
||||
scanning. NOTE: Recognizing more safe-to-ignore
|
||||
instructions here will improve support for optimized
|
||||
code. */
|
||||
break;
|
||||
/* The optimizer might shove anything into the prologue,
|
||||
so we just skip what we don't recognize. */
|
||||
unrecognized_pc = start;
|
||||
}
|
||||
|
||||
start += 2;
|
||||
}
|
||||
else if (thumb_instruction_changes_pc (insn))
|
||||
{
|
||||
/* Don't scan past anything that might change control flow. */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We don't know what this instruction is. We're finished
|
||||
scanning. NOTE: Recognizing more safe-to-ignore
|
||||
instructions here will improve support for optimized
|
||||
code. */
|
||||
break;
|
||||
/* The optimizer might shove anything into the prologue,
|
||||
so we just skip what we don't recognize. */
|
||||
unrecognized_pc = start;
|
||||
}
|
||||
|
||||
start += 2;
|
||||
@ -736,10 +1083,13 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
|
||||
fprintf_unfiltered (gdb_stdlog, "Prologue scan stopped at %s\n",
|
||||
paddress (gdbarch, start));
|
||||
|
||||
if (unrecognized_pc == 0)
|
||||
unrecognized_pc = start;
|
||||
|
||||
if (cache == NULL)
|
||||
{
|
||||
do_cleanups (back_to);
|
||||
return start;
|
||||
return unrecognized_pc;
|
||||
}
|
||||
|
||||
if (pv_is_register (regs[ARM_FP_REGNUM], ARM_SP_REGNUM))
|
||||
@ -772,7 +1122,7 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
|
||||
cache->saved_regs[i].addr = offset;
|
||||
|
||||
do_cleanups (back_to);
|
||||
return start;
|
||||
return unrecognized_pc;
|
||||
}
|
||||
|
||||
/* Advance the PC across any function entry prologue instructions to
|
||||
@ -956,12 +1306,12 @@ thumb_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR prev_pc,
|
||||
if (find_pc_partial_function (block_addr, NULL, &prologue_start,
|
||||
&prologue_end))
|
||||
{
|
||||
struct symtab_and_line sal = find_pc_line (prologue_start, 0);
|
||||
|
||||
if (sal.line == 0) /* no line info, use current PC */
|
||||
prologue_end = prev_pc;
|
||||
else if (sal.end < prologue_end) /* next line begins after fn end */
|
||||
prologue_end = sal.end; /* (probably means no prologue) */
|
||||
/* See comment in arm_scan_prologue for an explanation of
|
||||
this heuristics. */
|
||||
if (prologue_end > prologue_start + 64)
|
||||
{
|
||||
prologue_end = prologue_start + 64;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* We're in the boondocks: we have no idea where the start of the
|
||||
|
Loading…
x
Reference in New Issue
Block a user