diff options
author | Joel Brobecker <brobecker@gnat.com> | 2004-10-14 22:34:25 +0000 |
---|---|---|
committer | Joel Brobecker <brobecker@gnat.com> | 2004-10-14 22:34:25 +0000 |
commit | 98b4dd94014d814101527d41dc092fbd93e28e76 (patch) | |
tree | d54a6ab2f8b339acbd7ad92aed172ce2779658f5 /gdb/mips-tdep.c | |
parent | dfaf8edb15328188dd17e23ace958e6d043da41b (diff) | |
download | binutils-98b4dd94014d814101527d41dc092fbd93e28e76.zip binutils-98b4dd94014d814101527d41dc092fbd93e28e76.tar.gz binutils-98b4dd94014d814101527d41dc092fbd93e28e76.tar.bz2 |
* mips-tdep.c (mips32_scan_prologue): Merge code from
mips32_skip_prologue. Now return the address of the first
instruction past the function prologue.
(mips32_skip_prologue): Remove. No longer necessary.
(mips16_skip_prologue): Add parameter end_pc instead of
computing it.
(mips_skip_prologue): Compute the upper limit for the
prologue scanning. Update call to mips16_skip_prologue.
Replace call to mips32_skip_prologue by call to
mips32_scan_prologue.
Diffstat (limited to 'gdb/mips-tdep.c')
-rw-r--r-- | gdb/mips-tdep.c | 183 |
1 files changed, 76 insertions, 107 deletions
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index bb436f5..313b8b1 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -2419,9 +2419,10 @@ reset_saved_regs (struct mips_frame_cache *this_cache) } /* Analyze the function prologue from START_PC to LIMIT_PC. Builds - the associated FRAME_CACHE if not null. */ + the associated FRAME_CACHE if not null. + Return the address of the first instruction past the prologue. */ -static void +static CORE_ADDR mips32_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc, CORE_ADDR sp, struct frame_info *next_frame, struct mips_frame_cache *this_cache) @@ -2431,6 +2432,10 @@ mips32_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc, CORE_ADDR sp, long frame_offset; int frame_reg = MIPS_SP_REGNUM; + CORE_ADDR end_prologue_addr = 0; + int seen_sp_adjust = 0; + int load_immediate_bytes = 0; + restart: frame_offset = 0; @@ -2458,6 +2463,7 @@ restart: usually means that the stack cleanup code in the function epilogue is reached. */ break; + seen_sp_adjust = 1; } else if ((high_word & 0xFFE0) == 0xafa0) /* sw reg,offset($sp) */ { @@ -2465,8 +2471,7 @@ restart: } else if ((high_word & 0xFFE0) == 0xffa0) /* sd reg,offset($sp) */ { - /* Irix 6.2 N32 ABI uses sd instructions for saving $gp and - $ra. */ + /* Irix 6.2 N32 ABI uses sd instructions for saving $gp and $ra. */ set_reg_offset (this_cache, reg, sp + low_word); } else if (high_word == 0x27be) /* addiu $30,$sp,size */ @@ -2528,6 +2533,45 @@ restart: { set_reg_offset (this_cache, reg, frame_addr + low_word); } + else if ((high_word & 0xFFE0) == 0xE7A0 /* swc1 freg,n($sp) */ + || (high_word & 0xF3E0) == 0xA3C0 /* sx reg,n($s8) */ + || (inst & 0xFF9F07FF) == 0x00800021 /* move reg,$a0-$a3 */ + || high_word == 0x3c1c /* lui $gp,n */ + || high_word == 0x279c /* addiu $gp,$gp,n */ + || inst == 0x0399e021 /* addu $gp,$gp,$t9 */ + || inst == 0x033ce021 /* addu $gp,$t9,$gp */ + ) + { + /* These instructions are part of the prologue, but we don't + need to do anything special to handle them. */ + } + /* The instructions below load $at or $t0 with an immediate + value in preparation for a stack adjustment via + subu $sp,$sp,[$at,$t0]. These instructions could also + initialize a local variable, so we accept them only before + a stack adjustment instruction was seen. */ + else if (!seen_sp_adjust + && (high_word == 0x3c01 /* lui $at,n */ + || high_word == 0x3c08 /* lui $t0,n */ + || high_word == 0x3421 /* ori $at,$at,n */ + || high_word == 0x3508 /* ori $t0,$t0,n */ + || high_word == 0x3401 /* ori $at,$zero,n */ + || high_word == 0x3408 /* ori $t0,$zero,n */ + )) + { + load_immediate_bytes += MIPS_INSTLEN; /* FIXME!! */ + } + else + { + /* This instruction is not an instruction typically found + in a prologue, so we must have reached the end of the + prologue. */ + /* FIXME: brobecker/2004-10-10: Can't we just break out of this + loop now? Why would we need to continue scanning the function + instructions? */ + if (end_prologue_addr == 0) + end_prologue_addr = cur_pc; + } } if (this_cache != NULL) @@ -2541,6 +2585,23 @@ restart: this_cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc] = this_cache->saved_regs[NUM_REGS + RA_REGNUM]; } + + /* If we didn't reach the end of the prologue when scanning the function + instructions, then set end_prologue_addr to the address of the + instruction immediately after the last one we scanned. */ + /* brobecker/2004-10-10: I don't think this would ever happen, but + we may as well be careful and do our best if we have a null + end_prologue_addr. */ + if (end_prologue_addr == 0) + end_prologue_addr = cur_pc; + + /* In a frameless function, we might have incorrectly + skipped some load immediate instructions. Undo the skipping + if the load immediate was not followed by a stack adjustment. */ + if (load_immediate_bytes && !seen_sp_adjust) + end_prologue_addr -= load_immediate_bytes; + + return end_prologue_addr; } static mips_extra_func_info_t @@ -4860,107 +4921,12 @@ mips_step_skips_delay (CORE_ADDR pc) extract_unsigned_integer (buf, MIPS_INSTLEN)); } -/* Skip the PC past function prologue instructions (32-bit version). - This is a helper function for mips_skip_prologue. */ - -static CORE_ADDR -mips32_skip_prologue (CORE_ADDR pc) -{ - t_inst inst; - CORE_ADDR end_pc; - int seen_sp_adjust = 0; - int load_immediate_bytes = 0; - - /* Find an upper bound on the prologue. */ - end_pc = skip_prologue_using_sal (pc); - if (end_pc == 0) - end_pc = pc + 100; /* Magic. */ - - /* Skip the typical prologue instructions. These are the stack adjustment - instruction and the instructions that save registers on the stack - or in the gcc frame. */ - for (; pc < end_pc; pc += MIPS_INSTLEN) - { - unsigned long high_word; - - inst = mips_fetch_instruction (pc); - high_word = (inst >> 16) & 0xffff; - - if (high_word == 0x27bd /* addiu $sp,$sp,offset */ - || high_word == 0x67bd) /* daddiu $sp,$sp,offset */ - seen_sp_adjust = 1; - else if (inst == 0x03a1e823 || /* subu $sp,$sp,$at */ - inst == 0x03a8e823) /* subu $sp,$sp,$t0 */ - seen_sp_adjust = 1; - else if (((inst & 0xFFE00000) == 0xAFA00000 /* sw reg,n($sp) */ - || (inst & 0xFFE00000) == 0xFFA00000) /* sd reg,n($sp) */ - && (inst & 0x001F0000)) /* reg != $zero */ - continue; - - else if ((inst & 0xFFE00000) == 0xE7A00000) /* swc1 freg,n($sp) */ - continue; - else if ((inst & 0xF3E00000) == 0xA3C00000 && (inst & 0x001F0000)) - /* sx reg,n($s8) */ - continue; /* reg != $zero */ - - /* move $s8,$sp. With different versions of gas this will be either - `addu $s8,$sp,$zero' or `or $s8,$sp,$zero' or `daddu s8,sp,$0'. - Accept any one of these. */ - else if (inst == 0x03A0F021 || inst == 0x03a0f025 || inst == 0x03a0f02d) - continue; - - else if ((inst & 0xFF9F07FF) == 0x00800021) /* move reg,$a0-$a3 */ - continue; - else if (high_word == 0x3c1c) /* lui $gp,n */ - continue; - else if (high_word == 0x279c) /* addiu $gp,$gp,n */ - continue; - else if (inst == 0x0399e021 /* addu $gp,$gp,$t9 */ - || inst == 0x033ce021) /* addu $gp,$t9,$gp */ - continue; - /* The following instructions load $at or $t0 with an immediate - value in preparation for a stack adjustment via - subu $sp,$sp,[$at,$t0]. These instructions could also initialize - a local variable, so we accept them only before a stack adjustment - instruction was seen. */ - else if (!seen_sp_adjust) - { - if (high_word == 0x3c01 || /* lui $at,n */ - high_word == 0x3c08) /* lui $t0,n */ - { - load_immediate_bytes += MIPS_INSTLEN; /* FIXME!! */ - continue; - } - else if (high_word == 0x3421 || /* ori $at,$at,n */ - high_word == 0x3508 || /* ori $t0,$t0,n */ - high_word == 0x3401 || /* ori $at,$zero,n */ - high_word == 0x3408) /* ori $t0,$zero,n */ - { - load_immediate_bytes += MIPS_INSTLEN; /* FIXME!! */ - continue; - } - else - break; - } - else - break; - } - - /* In a frameless function, we might have incorrectly - skipped some load immediate instructions. Undo the skipping - if the load immediate was not followed by a stack adjustment. */ - if (load_immediate_bytes && !seen_sp_adjust) - pc -= load_immediate_bytes; - return pc; -} - /* Skip the PC past function prologue instructions (16-bit version). This is a helper function for mips_skip_prologue. */ static CORE_ADDR -mips16_skip_prologue (CORE_ADDR pc) +mips16_skip_prologue (CORE_ADDR pc, CORE_ADDR end_pc) { - CORE_ADDR end_pc; int extend_bytes = 0; int prev_extend_bytes; @@ -5009,11 +4975,6 @@ mips16_skip_prologue (CORE_ADDR pc) 0, 0} /* end of table marker */ }; - /* Find an upper bound on the prologue. */ - end_pc = skip_prologue_using_sal (pc); - if (end_pc == 0) - end_pc = pc + 100; /* Magic. */ - /* Skip the typical prologue instructions. These are the stack adjustment instruction and the instructions that save registers on the stack or in the gcc frame. */ @@ -5070,6 +5031,7 @@ mips_skip_prologue (CORE_ADDR pc) is greater. */ CORE_ADDR post_prologue_pc = after_prologue (pc); + CORE_ADDR limit_pc; if (post_prologue_pc != 0) return max (pc, post_prologue_pc); @@ -5077,10 +5039,17 @@ mips_skip_prologue (CORE_ADDR pc) /* Can't determine prologue from the symbol table, need to examine instructions. */ + /* Find an upper limit on the function prologue using the debug + information. If the debug information could not be used to provide + that bound, then use an arbitrary large number as the upper bound. */ + limit_pc = skip_prologue_using_sal (pc); + if (limit_pc == 0) + limit_pc = pc + 100; /* Magic. */ + if (pc_is_mips16 (pc)) - return mips16_skip_prologue (pc); + return mips16_skip_prologue (pc, limit_pc); else - return mips32_skip_prologue (pc); + return mips32_scan_prologue (pc, limit_pc, 0, NULL, NULL); } /* Root of all "set mips "/"show mips " commands. This will eventually be |