diff options
author | Kevin Buettner <kevinb@redhat.com> | 2001-06-01 02:39:51 +0000 |
---|---|---|
committer | Kevin Buettner <kevinb@redhat.com> | 2001-06-01 02:39:51 +0000 |
commit | 58ab00f996277e5c3c5ad9e60d4b6039422b9988 (patch) | |
tree | 4eb1bfdb3b189f91353090116f52551a76c59c28 /gdb/ia64-tdep.c | |
parent | d469a809fae43c5d442b4089b67b722832812b3e (diff) | |
download | gdb-58ab00f996277e5c3c5ad9e60d4b6039422b9988.zip gdb-58ab00f996277e5c3c5ad9e60d4b6039422b9988.tar.gz gdb-58ab00f996277e5c3c5ad9e60d4b6039422b9988.tar.bz2 |
Prologue scanner modifications.
Diffstat (limited to 'gdb/ia64-tdep.c')
-rw-r--r-- | gdb/ia64-tdep.c | 72 |
1 files changed, 71 insertions, 1 deletions
diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c index 2a1b351..afa0e1c 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. */ |