[RFA] Improve Sparc epilogue analysis

David S. Miller
2002-04-20T07:31:47Z

Unlike other ports, Sparc only had a manual prologue discovery
mechanism. Most other port have a manual prologue examiner, but they
also first try to use line number information.

To this end, we look for line number information (the first two ".loc"
entries for a function have the same line number, the second one
begins at the end of the prologue) and if found we use it. Else
we just drop into the existing code.

Also, in sparc_init_extra_frame_info we were using grotty code to find
out if the save instruction in the prologue had executed yet.
Firstly, this relied on the debugging info being there. Secondly
such things need to be done within the prologue range only, and
examine_prologue was created to figure this out.

Due to a bug in dwarf2 gas up until a week ago, gas would eliminate
these duplicate .loc entries used for prologue discovery by accident.

For those of you playing at home:

sparc32 sparc64
failures before 88 124
failures after 83 111

More to come.

2002-04-19 David S. Miller <davem@redhat.com>

* sparc-tdep.c (examine_prologue): Put forward declaration before
sparc_init_extra_frame_info.
(sparc_init_extra_frame_info): Use it to determine if the save
instruction has been executed yet instead of solely relying upon
line number information. Some versions of gas delete duplicates.
(examine_prologue): Use line number information to find end of
prologue, if available. Else, use existing by-hand insn
examination.

--- sparc-tdep.c.~1~ Fri Apr 19 23:03:54 2002
+++ sparc-tdep.c Fri Apr 19 23:53:57 2002
@@ -279,6 +279,9 @@ struct frame_extra_info
int sp_offset;
};

+static CORE_ADDR examine_prologue (CORE_ADDR, int, struct frame_info *,
+ CORE_ADDR *);
+
/* Call this for each newly created frame. For SPARC, we need to
calculate the bottom of the frame, and do some extra work if the
prologue has been generated via the -mflat option to GCC. In
@@ -393,25 +396,20 @@ sparc_init_extra_frame_info (int fromlea
to the current value of the stack pointer and set
the in_prologue flag. */
CORE_ADDR addr;
- struct symtab_and_line sal;

- sal = find_pc_line (prologue_start, 0);
- if (sal.line == 0) /* no line info, use PC */
- prologue_end = fi->pc;
- else if (sal.end < prologue_end)
- prologue_end = sal.end;
+ prologue_end = examine_prologue (prologue_start, 0, NULL, NULL);
if (fi->pc < prologue_end)
{
- for (addr = prologue_start; addr < fi->pc; addr += 4)
+ for (addr = fi->pc; addr < prologue_end; addr += 4)
{
insn = read_memory_integer (addr, 4);
if (X_OP (insn) == 2 && X_OP3 (insn) == 0x3c)
break; /* SAVE seen, stop searching */
}
- if (addr >= fi->pc)
+ if (addr < prologue_end)
{
fi->extra_info->in_prologue = 1;
- fi->frame = read_register (SP_REGNUM);
+ fi->frame = read_sp ();
}
}
}
@@ -546,9 +544,6 @@ setup_arbitrary_frame (int argc, CORE_AD
This routine should be more specific in its actions; making sure
that it uses the same register in the initial prologue section. */

-static CORE_ADDR examine_prologue (CORE_ADDR, int, struct frame_info *,
- CORE_ADDR *);
-
static CORE_ADDR
examine_prologue (CORE_ADDR start_pc, int frameless_p, struct frame_info *fi,
CORE_ADDR *saved_regs)
@@ -557,7 +552,21 @@ examine_prologue (CORE_ADDR start_pc, in
int dest = -1;
CORE_ADDR pc = start_pc;
int is_flat = 0;
+ struct symtab_and_line sal;
+ CORE_ADDR func_start, func_end;
+
+ /* This is the preferred method, find the end of the prologue by
+ using the debugging information. */
+ if (find_pc_partial_function (start_pc, NULL, &func_start, &func_end))
+ {
+ sal = find_pc_line (func_start, 0);
+
+ if (sal.end < func_end
+ && start_pc <= sal.end)
+ return sal.end;
+ }

+ /* Oh well, examine the code by hand. */
insn = fetch_instruction (pc);

/* Recognize the `sethi' insn and record its destination. */