Index: i386-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/i386-tdep.c,v retrieving revision 1.213 diff -u -p -w -r1.213 i386-tdep.c --- i386-tdep.c 28 May 2005 16:44:28 -0000 1.213 +++ i386-tdep.c 8 Jun 2005 05:24:14 -0000 @@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include #include "defs.h" #include "arch-utils.h" #include "command.h" @@ -287,9 +288,10 @@ i386_breakpoint_from_pc (CORE_ADDR *pc, struct i386_frame_cache { - /* Base address. */ + /* Base address, usually the contents of the EBP. */ CORE_ADDR base; CORE_ADDR sp_offset; + /* The function's start address for this frame. */ CORE_ADDR pc; /* Saved registers. */ @@ -473,7 +475,7 @@ i386_skip_probe (CORE_ADDR pc) } /* Maximum instruction length we need to handle. */ -#define I386_MAX_INSN_LEN 6 +#define I386_MAX_INSN_LEN 7 /* Instruction description. */ struct i386_insn @@ -495,25 +497,46 @@ i386_match_insn (CORE_ADDR pc, struct i3 op = read_memory_unsigned_integer (pc, 1); + /* `push %ebp'? Let the caller look into it. */ + if (op == 0x55) + return NULL; + for (insn = skip_insns; insn->len > 0; insn++) { if ((op & insn->mask[0]) == insn->insn[0]) { unsigned char buf[I386_MAX_INSN_LEN - 1]; - size_t i; + int i, insn_matched; + + if (insn->len == 1) + return insn; gdb_assert (insn->len > 1); gdb_assert (insn->len <= I386_MAX_INSN_LEN); read_memory (pc + 1, buf, insn->len - 1); + + /* `mov %esp, %ebp'? `xor $ebp, $ebp'? `push $0x0'? + Let the caller check it out. */ + if (insn->len == 2 + && ((op == 0x89 && buf[0] == 0xe5) /* mov %esp, %ebp */ + || (op == 0x8b && buf[0] == 0xec) /* mov %esp, %ebp */ + || (op == 0x31 && buf[0] == 0xed) /* xor %ebp, %ebp */ + || (op == 0x6a && buf[0] == 0x00))) /* push $0x0 */ + return NULL; + + insn_matched = 1; for (i = 1; i < insn->len; i++) { if ((buf[i - 1] & insn->mask[i]) != insn->insn[i]) + { + insn_matched = 0; break; - - return insn; } } + if (insn_matched) + return insn; + } } return NULL; @@ -554,6 +577,91 @@ struct i386_insn i386_frame_setup_skip_i /* `movl m32, %edx' */ { 6, { 0x89, 0x15 }, {0xff, 0xff } }, + /* "01 /r ADD r/m32, r32" */ + { 2, { 0x01, 0xd0 }, { 0xff, 0xd0 } }, + /* "0F B6 /r MOVZX r32, r/m8" (aka `movzbl %al, %eax') */ + { 3, { 0x0f, 0xb6, 0xc0 }, { 0xff, 0xff, 0xc0 } }, + /* "0F B7 /r MOVZX r32, r/m16" (aka `movzwl r16, r32') */ + { 3, { 0x0f, 0xb7, 0xc0 }, { 0xff, 0xff, 0xc0 } }, + /* "25 id AND EAX, imm32" */ + { 5, { 0x25 }, { 0xff } }, + /* "31 /r XOR r/m32, r32" */ + { 2, { 0x31, 0xc0 }, { 0xff, 0xc0 } }, + /* "40+ rd INC r32" */ + { 1, { 0x40 }, { 0xf8 } }, + /* "48+rw DEC r32" */ + { 1, { 0x48 }, { 0xf8 } }, + /* "50+rd PUSH r32" */ + { 1, { 0x50 }, { 0xf8 } }, + /* "58+ rd POP r32" */ + { 1, { 0x58 }, { 0xf8 } }, + /* "B8+ rw MOV r16, imm16" */ + { 4, { 0x66, 0xb8 }, { 0xff, 0xf8 } }, + /* "74 cb JE rel8" */ + { 2, { 0x74 }, { 0xff } }, + /* "80 /7 ib CMP r/m8, imm8" (aka `cmpb imm8,(r32)') */ + { 3, { 0x80, 0x38 }, { 0xff, 0xf8 } }, + /* "81 /4 id AND r/m32, imm32" */ + { 6, { 0x81, 0xe0 }, { 0xff, 0xf8 } }, + /* "81 /0 id ADD r/m32, imm32" */ + { 6, { 0x81, 0xc0 }, { 0xff, 0xf8 } }, + /* "83 /7 ib CMP r/m32, imm8" */ + { 7, { 0x83, 0x3d }, { 0xff, 0xff } }, + /* "83 /0 ib ADD r/m32, imm8" */ + { 3, { 0x83, 0xc0 }, { 0xff, 0xf8 } }, + /* "83 /1 ib OR r/m32, imm8" */ + { 3, { 0x83, 0xc8 }, { 0xff, 0xf8 } }, + /* "83 /4 ib AND r/m32, imm8" */ + { 3, { 0x83, 0xe0 }, { 0xff, 0xf8 } }, + /* "83 /5 ib SUB r/m32, imm8" */ + { 3, { 0x83, 0xe8 }, { 0xff, 0xf8 } }, + /* "83 /7 ib CMP r/m32, imm8" */ + { 3, { 0x83, 0xf8 }, { 0xff, 0xf8 } }, + /* "85 /r TEST r/m32, r32" */ + { 2, { 0x85, 0xc0 }, { 0xff, 0xc0 } }, + /* "89 /r MOV r/m32, r32" (aka `mov r32, (r32)') */ + { 2, { 0x89, 0x00 }, { 0xff, 0xf8 } }, + /* "89 /r MOV r/m32, r32" (aka `mov r32, (r32)') */ + { 2, { 0x89, 0x10 }, { 0xff, 0xf8 } }, + /* "89 /r MOV r/m32, r32" */ + { 2, { 0x89, 0xc0 }, { 0xff, 0xc0 } }, + /* "8B /r MOV r32, r/m32" (aka `mov imm8(r32), r32') */ + { 3, { 0x8b, 0x40 }, { 0xff, 0xf8 } }, + /* "8B /r MOV r32, r/m32" */ + { 6, { 0x8b, 0x80 }, { 0xff, 0xf8 } }, + /* "8B /r MOV r32, r/m32" (aka `mov imm32(r32), r32') */ + { 6, { 0x8b, 0x90 }, { 0xff, 0xf8 } }, + /* "8D /r LEA r32, m" (aka `lea imm8(r32), r32') */ + { 3, { 0x8d, 0x48 }, { 0xff, 0xf8 } }, + /* "8D /r LEA r32, m" (aka `lea imm32(r32), r32') */ + { 6, { 0x8d, 0x90 }, { 0xff, 0xf8 } }, + /* "90 NOP" */ + { 1, { 0x90 }, { 0xff } }, + /* "A9 id TEST EAX, imm32" */ + { 5, { 0xa9 }, { 0xff } }, + /* "C1 /4 ib SAL r/m32, imm8" (aka `shl imm8, r32') */ + { 3, { 0xc1, 0xe0 }, { 0xff, 0xf8 } }, + /* "C1 /7 ib SAR r/m32, imm8" */ + { 3, { 0xc1, 0xf8 }, { 0xff, 0xf8 } }, + /* "C6 /0 MOV r/m8, imm8" (aka `mov imm8, (r32)') */ + { 3, { 0xc6, 0x00 }, { 0xff, 0xf8 } }, + /* "C7 /o MOV r/m32, imm32 (aka `mov imm32, (r32)') */ + { 6, { 0xc7, 0x00 }, { 0xff, 0xf8 } }, + /* "D9 EE FLDZ" */ + { 2, { 0xd9, 0xee }, { 0xff, 0xff } }, + /* "E8 cd CALL rel32" */ + { 5, { 0xe8 }, { 0xff } }, + /* "EB cb JMP rel8" */ + { 2, { 0xeb }, { 0xff } }, + /* "F7 /6 DIV r/m32" */ + { 2, { 0xf7, 0xf0 }, { 0xff, 0xf8 } }, + /* "FC CLD" */ + { 1, { 0xfc }, { 0xff } }, + /* "FF /6 PUSH r/m32" */ + { 6, { 0xff, 0xb0 }, { 0xff, 0xf8 } }, + /* "FF /4 JMP r/m32" */ + { 2, { 0xff, 0xe0 }, { 0xff, 0xf8 } }, + /* Check for `xorl r32, r32' and the equivalent `subl r32, r32'. Because of the symmetry, there are actually two ways to encode these instructions; opcode bytes 0x29 and 0x2b for `subl' and @@ -587,21 +695,71 @@ i386_analyze_frame_setup (CORE_ADDR pc, gdb_byte op; int skip = 0; + /* This function returns a CORE_ADDR which is the instruction + following the last frame-setup instruction we saw such that "frame-setup + instruction" is one of push %ebp, push $0x0, mov %esp, %ebp, + sub $, $esp, or enter. + Specifically, we may scan past some of these instructions but we don't + want to return the last address we scanned to -- we must return the + address of the instruction after one of those frame setup insns so that + i386_analyze_register_saves () can look for register saves that may exist + after them. + (and you can have register saves without any frame setup, e.g. in a + frameless function.) + I pedantically changed all returns to return end_of_frame_setup so it + is completely clear what is going on. jmolenda/2005-05-03 */ + + CORE_ADDR end_of_frame_setup = pc; + if (limit <= pc) return limit; + + /* Skip over non-prologue instructions until we hit one of + push %ebp [ 0x55 ] + push $0x0 [ 0x6a 0x00 ] + xor %ebp, %ebp [ 0x31 0xed ] + the latter instructions being the first frame setup insns in + MacOS X and Linux _start()s. */ + op = read_memory_unsigned_integer (pc, 1); + while (op != 0x55 + && (op != 0x6a || + read_memory_unsigned_integer (pc + skip + 1, 1) != 0x00) + && (op != 0x31 || + read_memory_unsigned_integer (pc + skip + 1, 1) != 0xed) + && pc + skip <= limit) + { + insn = i386_match_insn (pc + skip, i386_frame_setup_skip_insns); + if (insn) + { + skip += insn->len; + op = read_memory_unsigned_integer (pc + skip, 1); + } + else + break; + } + + if (limit <= pc + skip) + return end_of_frame_setup; - if (op == 0x55) /* pushl %ebp */ + /* Do we have our initial frame setup instruction? */ + if (op == 0x55 || op == 0x6a || op == 0x31) { /* Take into account that we've executed the `pushl %ebp' that starts this instruction sequence. */ cache->saved_regs[I386_EBP_REGNUM] = 0; cache->sp_offset += 4; - pc++; + + /* Skip over the second byte of `push $0x0' and `xor %ebp, %ebp' */ + if (op == 0x6a || op == 0x31) + skip += 2; + else + skip++; + end_of_frame_setup = pc + skip; /* If that's all, return now. */ - if (limit <= pc) + if (limit <= pc + skip) return limit; /* Check for some special instructions that might be migrated by @@ -623,7 +781,7 @@ i386_analyze_frame_setup (CORE_ADDR pc, /* If that's all, return now. */ if (limit <= pc + skip) - return limit; + return end_of_frame_setup; op = read_memory_unsigned_integer (pc + skip, 1); @@ -632,14 +790,14 @@ i386_analyze_frame_setup (CORE_ADDR pc, { case 0x8b: if (read_memory_unsigned_integer (pc + skip + 1, 1) != 0xec) - return pc; + return end_of_frame_setup; break; case 0x89: if (read_memory_unsigned_integer (pc + skip + 1, 1) != 0xe5) - return pc; + return end_of_frame_setup; break; default: - return pc; + return end_of_frame_setup; } /* OK, we actually have a frame. We just don't know how large @@ -648,6 +806,7 @@ i386_analyze_frame_setup (CORE_ADDR pc, instructions mentioned before. */ cache->locals = 0; pc += (skip + 2); + end_of_frame_setup = pc; /* If that's all, return now. */ if (limit <= pc) @@ -695,7 +854,7 @@ i386_analyze_frame_setup (CORE_ADDR pc, return pc + 4; } - return pc; + return end_of_frame_setup; } /* Check whether PC points at code that saves registers on the stack. @@ -771,6 +930,11 @@ i386_analyze_prologue (CORE_ADDR pc, COR static CORE_ADDR i386_skip_prologue (CORE_ADDR start_pc) { + /* FIXME: this code assumes the "call L1; L1: pop $ebx" type of pic base + setup, but that's less optimal on x86 than a call to + __i686.get_pc_thunk.bx and friends, so you're unlikely to see this + sequence these days. jmolenda/2005-06-06. */ + static gdb_byte pic_pat[6] = { 0xe8, 0, 0, 0, 0, /* call 0x0 */ @@ -844,6 +1008,95 @@ i386_skip_prologue (CORE_ADDR start_pc) return pc; } +/* Find adjustments of the ESP so we can locate the + caller's saved EIP and backtrace out of a frameless function. PC is + the start of the function. CURRENT_PC is the current instruction, + or the last instruction of the function to limit this search. + + Returns a signed offset of how much the ESP has moved since the + start of the function. The return value should be a negative number + or 0. */ + +static int +i386_find_esp_adjustments (CORE_ADDR pc, CORE_ADDR current_pc) +{ + gdb_byte op, next_op; + int esp_change = 0; + struct i386_insn *insn; + + if (pc == current_pc) + return esp_change; + + /* We're looking for PUSH r32, POP r32, SUB $x,ESP, ADD $x ESP. */ + + while (pc < current_pc) + { + op = read_memory_unsigned_integer (pc, 1); + next_op = read_memory_unsigned_integer (pc + 1, 1); + + /* `push %ebp'? We shouldn't see that in here; give up. */ + if (op == 0x55) + return esp_change; + /* `ret'? We're at the end of the func; stop parsing. */ + if (op == 0xc3) + return esp_change; + + /* 50+rd PUSH r32 */ + if ((op & 0xf8) == 0x50) + { + esp_change -= 4; + pc += 1; + continue; + } + /* 58+ rd POP r32 */ + if ((op & 0xf8) == 0x58) + { + esp_change += 4; + pc += 1; + continue; + } + /* 83 /5 ib SUB r/m32, imm8 */ + if (op == 0x83 && next_op == 0xec) + { + uint8_t imm8 = read_memory_integer (pc + 2, 1); + esp_change -= imm8; + pc += 3; + continue; + } + /* 81 /5 id SUB r/m32, imm32 */ + if (op == 0x81 && next_op == 0xec) + { + uint32_t imm32 = read_memory_integer (pc + 2, 4); + esp_change -= imm32; + pc += 6; + continue; + } + /* 83 /0 ib ADD r/m32, imm8 */ + if (op == 0x83 && next_op == 0xc4) + { + uint8_t imm8 = read_memory_integer (pc + 2, 1); + esp_change += imm8; + pc += 3; + continue; + } + /* 81 /0 id ADD r/m32, imm8 */ + if (op == 0x81 && next_op == 0xc4) + { + uint32_t imm32 = read_memory_integer (pc + 2, 4); + esp_change += imm32; + pc += 6; + continue; + } + + insn = i386_match_insn (pc, i386_frame_setup_skip_insns); + if (insn) + pc += insn->len; + else + return esp_change; /* Hit an instruction we don't know; stop here. */ + } + return esp_change; +} + /* This function is 64-bit safe. */ static CORE_ADDR @@ -856,7 +1109,30 @@ i386_unwind_pc (struct gdbarch *gdbarch, } -/* Normal frames. */ +/* Normal frames. + This function must handle the following possible function types: + + 0. We're in a function we cannot know anything about - we have no + symbol for it; we can't find the start address. + + 1. The function is frameless. + a. The ESP hasn't reached its Final Resting Place for the body of + the function yet. + b. We've finished the prologue (wherein we move the ESP, i.e. SUBs to + make space for local storage, PUSHes to preserve saved regs.) + + 2. The function sets up a frame and + a. We haven't executed any prologue instructions. + b. We've executed the initial push %ebp (this one is critical). + c. We've executed the mov %esp, %ebp + d. We've completed the entire prologue. + e. We're in the middle of a function which has a prologue, + but we can't parse it (we hit an unknown instruction mid-prologue). + + When reading i386_frame_cache, keep these three function types in mind + and the different stages for #1 and #2 - the behavior of this function + differs greatly depending on where you are. */ + static struct i386_frame_cache * i386_frame_cache (struct frame_info *next_frame, void **this_cache) @@ -864,6 +1140,32 @@ i386_frame_cache (struct frame_info *nex struct i386_frame_cache *cache; gdb_byte buf[4]; int i; + int potentially_frameless; + CORE_ADDR prologue_parsed_to = 0; + CORE_ADDR current_pc; + + /* If the frame we're examining is frame #0, we could + be frameless. If NEXT_FRAME is _sigtramp(), then we could be + frameless. + + Explanation: If a frameless function is executing when a + signal is caught, the frameless function will have _sigtramp() + as its next_frame, followed by whatever signal handler is defined. + This is not as rare as you'd think, at least in a testsuite: + On MacOS X, sleep() calls nanosleep() which calls mach_wait_until() + which is frameless. If an alarm(1) is done before that sequence, + you'll get a frameless function in the middle of the stack. + + If potentially_frameless == 0, there's no way the function we're + examining is frameless; it has a stack frame set up with + the saved-EBP/saved-EIP at the standard locations. + (not entirely true -- if gcc's -fomit-frame-pointer is used you can + have a function that doesn't ever set up the EBP, but calls other + functions. Handling that situation correctly is not easy with + i386-tdep.c's frame code as it stands today.) */ + + potentially_frameless = frame_relative_level (next_frame) == -1 + || get_frame_type (next_frame) == SIGTRAMP_FRAME; if (*this_cache) return *this_cache; @@ -871,41 +1173,86 @@ i386_frame_cache (struct frame_info *nex cache = i386_alloc_frame_cache (); *this_cache = cache; - /* In principle, for normal frames, %ebp holds the frame pointer, - which holds the base address for the current stack frame. - However, for functions that don't need it, the frame pointer is - optional. For these "frameless" functions the frame pointer is - actually the frame pointer of the calling frame. Signal - trampolines are just a special case of a "frameless" function. - They (usually) share their frame pointer with the frame that was - in progress when the signal occurred. */ + /* Set up reasonable defaults that we'll override later on as necessary. */ + + /* For normal frames, saved-%eip is stored at 4(%ebp). */ + cache->saved_regs[I386_EIP_REGNUM] = 4; + + /* For normal frames, saved-%ebp is stored at 0(%ebp). */ + cache->saved_regs[I386_EBP_REGNUM] = 0; frame_unwind_register (next_frame, I386_EBP_REGNUM, buf); cache->base = extract_unsigned_integer (buf, 4); if (cache->base == 0) return cache; - /* For normal frames, %eip is stored at 4(%ebp). */ - cache->saved_regs[I386_EIP_REGNUM] = 4; - cache->pc = frame_func_unwind (next_frame); + current_pc = frame_pc_unwind (next_frame); + + /* Only do i386_analyze_prologue () if we found a debug symbol pointing to + the actual start of the function. */ if (cache->pc != 0) - i386_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); + i386_analyze_prologue (cache->pc, current_pc, cache); + + /* Let's see if the prologue parser didn't find any prologue instructions. + And our current function has the potential to be frameless. + If so, let's go frameless. Assume EBP is unused, or not yet used. + + We'll put ESP in the cache->base instead of EBP; for genuinely + frameless (e.g. -momit-leaf-frame-pointer) functions, the + the debug info for function args will be relative to ESP once its + setup/adjustements in the prologue are complete, so cache->base has + to hold the stack pointer if we're to find them. */ + + /* We found a function-start address, + or $pc is at 0x0 (someone jmp'ed thru NULL ptr). */ + if ((cache->pc != 0 || current_pc == 0) + /* The prologue parser didn't find any prologue instructions. */ + && prologue_parsed_to == cache->pc + /* We have the potential to be frameless. */ + && potentially_frameless) + { + int esp_offset; + CORE_ADDR actual_frame_base; + esp_offset = i386_find_esp_adjustments (cache->pc, current_pc); + frame_unwind_register (next_frame, I386_ESP_REGNUM, buf); + actual_frame_base = extract_unsigned_integer (buf, 4) - esp_offset; + cache->base = extract_unsigned_integer (buf, 4); + cache->saved_sp = actual_frame_base + 4; + cache->saved_regs[I386_EBP_REGNUM] = -1; + cache->saved_regs[I386_EIP_REGNUM] = 0; + /* NB: There's a good chance we didn't record register saves a la + i386_analyze_register_saves. It'd be nice to fix this. + For now we'll say "Debugging optimized code is an adventure!" + jmolenda/2005-04-27 */ - if (cache->locals < 0) + for (i = 0; i < I386_NUM_SAVED_REGS; i++) + if (cache->saved_regs[i] != -1) + cache->saved_regs[i] += actual_frame_base; + return cache; + } + + if (cache->locals < 0 && potentially_frameless) { - /* We didn't find a valid frame, which means that CACHE->base - currently holds the frame pointer for our calling frame. If - we're at the start of a function, or somewhere half-way its - prologue, the function's frame probably hasn't been fully - setup yet. Try to reconstruct the base address for the stack - frame by looking at the stack pointer. For truly "frameless" - functions this might work too. */ + /* We've seen PART of a frame setup, but not the whole deal. + We've probably executed just the `push %ebp'. + Right now, ESP has our real frame base address in it. */ frame_unwind_register (next_frame, I386_ESP_REGNUM, buf); cache->base = extract_unsigned_integer (buf, 4) + cache->sp_offset; } + /* If we have no idea where this function began (so we can't analyze + the prologue in any way), what should we assume? Frameless or + not? It's a tough call. On Linux systems, a call to a system + library involves a couple of trampoline jumps that have no symbols, + so to work correctly on Linux we MUST assume frameless. */ + if (potentially_frameless && cache->pc == 0) + { + cache->saved_regs[I386_EIP_REGNUM] = 4; + cache->saved_regs[I386_EBP_REGNUM] = -1; + } + /* Now that we have the base address for the stack frame we can calculate the value of %esp in the calling frame. */ cache->saved_sp = cache->base + 8;