summaryrefslogtreecommitdiff
path: root/gdb/ia64-tdep.c
diff options
context:
space:
mode:
authorKevin Buettner <kevinb@redhat.com>2001-06-01 02:39:51 +0000
committerKevin Buettner <kevinb@redhat.com>2001-06-01 02:39:51 +0000
commit2a7c026269805532c77a9366f38c6e9bb16e6147 (patch)
tree83a0cb41c84ce600a14d5061e19e82933b85300d /gdb/ia64-tdep.c
parent15cf8539ad3c330e5063b4ea95107c63340ca325 (diff)
downloadgdb-2a7c026269805532c77a9366f38c6e9bb16e6147.tar.gz
Prologue scanner modifications.
Diffstat (limited to 'gdb/ia64-tdep.c')
-rw-r--r--gdb/ia64-tdep.c72
1 files changed, 71 insertions, 1 deletions
diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c
index 2a1b351b865..afa0e1c76b9 100644
--- a/gdb/ia64-tdep.c
+++ b/gdb/ia64-tdep.c
@@ -717,6 +717,69 @@ ia64_frame_saved_pc (struct frame_info *frame)
}
}
+/* Limit the number of skipped non-prologue instructions since examining
+ of the prologue is expensive. */
+static int max_skip_non_prologue_insns = 10;
+
+/* Given PC representing the starting address of a function, and
+ LIM_PC which is the (sloppy) limit to which to scan when looking
+ for a prologue, attempt to further refine this limit by using
+ the line data in the symbol table. If successful, a better guess
+ on where the prologue ends is returned, otherwise the previous
+ value of lim_pc is returned. TRUST_LIMIT is a pointer to a flag
+ which will be set to indicate whether the returned limit may be
+ used with no further scanning in the event that the function is
+ frameless. */
+
+static CORE_ADDR
+refine_prologue_limit (CORE_ADDR pc, CORE_ADDR lim_pc, int *trust_limit)
+{
+ struct symtab_and_line prologue_sal;
+ CORE_ADDR start_pc = pc;
+
+ /* Start off not trusting the limit. */
+ *trust_limit = 0;
+
+ prologue_sal = find_pc_line (pc, 0);
+ if (prologue_sal.line != 0)
+ {
+ int i;
+ CORE_ADDR addr = prologue_sal.end;
+
+ /* Handle the case in which compiler's optimizer/scheduler
+ has moved instructions into the prologue. We scan ahead
+ in the function looking for address ranges whose corresponding
+ line number is less than or equal to the first one that we
+ found for the function. (It can be less than when the
+ scheduler puts a body instruction before the first prologue
+ instruction.) */
+ for (i = 2 * max_skip_non_prologue_insns;
+ i > 0 && (lim_pc == 0 || addr < lim_pc);
+ i--)
+ {
+ struct symtab_and_line sal;
+
+ sal = find_pc_line (addr, 0);
+ if (sal.line == 0)
+ break;
+ if (sal.line <= prologue_sal.line
+ && sal.symtab == prologue_sal.symtab)
+ {
+ prologue_sal = sal;
+ }
+ addr = sal.end;
+ }
+
+ if (lim_pc == 0 || prologue_sal.end < lim_pc)
+ {
+ lim_pc = prologue_sal.end;
+ if (start_pc == get_pc_function_start (lim_pc))
+ *trust_limit = 1;
+ }
+ }
+ return lim_pc;
+}
+
#define isScratch(_regnum_) ((_regnum_) == 2 || (_regnum_) == 3 \
|| (8 <= (_regnum_) && (_regnum_) <= 11) \
|| (14 <= (_regnum_) && (_regnum_) <= 31))
@@ -744,6 +807,7 @@ examine_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct frame_info *frame)
CORE_ADDR spill_addr = 0;
char instores[8];
char infpstores[8];
+ int trust_limit;
memset (instores, 0, sizeof instores);
memset (infpstores, 0, sizeof infpstores);
@@ -760,6 +824,8 @@ examine_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct frame_info *frame)
&& frame->extra_info->after_prologue <= lim_pc)
return frame->extra_info->after_prologue;
+ lim_pc = refine_prologue_limit (pc, lim_pc, &trust_limit);
+
/* Must start with an alloc instruction */
next_pc = fetch_instruction (pc, &it, &instr);
if (pc < lim_pc && next_pc
@@ -779,7 +845,11 @@ examine_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct frame_info *frame)
pc = next_pc;
}
else
- pc = lim_pc; /* We're done early */
+ {
+ pc = lim_pc; /* Frameless: We're done early. */
+ if (trust_limit)
+ last_prologue_pc = lim_pc;
+ }
/* Loop, looking for prologue instructions, keeping track of
where preserved registers were spilled. */