Skip to content

Commit

Permalink
Fix #9247.
Browse files Browse the repository at this point in the history
- If a program crashed due to an invalid function pointer, the stack
  was being incorrectly unwound such that the top frame would actually
  be skipped, preventing one from seeing the actual line of code that
  invoked said pointer. On x86, we now check if the IP of the top frame
  of the stack lies at a readable location in order to catch this case.
  • Loading branch information
anevilyak committed Dec 1, 2012
1 parent e66ebce commit 1e11702
Showing 1 changed file with 27 additions and 15 deletions.
42 changes: 27 additions & 15 deletions src/apps/debugger/arch/x86/ArchitectureX86.cpp
Expand Up @@ -309,25 +309,37 @@ ArchitectureX86::CreateStackFrame(Image* image, FunctionDebugInfo* function,
// If the function is not frameless and we're at the top frame we need
// to check whether the prologue has not been executed (completely) or
// we're already after the epilogue.
if (hasPrologue && isTopFrame) {
if (isTopFrame) {
uint32 stack = 0;
if (eip < function->Address() + 3) {
// The prologue has not been executed yet, i.e. there's no
// stack frame yet. Get the return address from the stack.
stack = cpuState->IntRegisterValue(X86_REGISTER_ESP);
if (eip > function->Address()) {
// The "push %ebp" has already been executed.
stack += 4;
if (hasPrologue) {
if (eip < function->Address() + 3) {
// The prologue has not been executed yet, i.e. there's no
// stack frame yet. Get the return address from the stack.
stack = cpuState->IntRegisterValue(X86_REGISTER_ESP);
if (eip > function->Address()) {
// The "push %ebp" has already been executed.
stack += 4;
}
} else {
// Not in the function prologue, but maybe after the
// epilogue. The epilogue is a single "pop %ebp", so we
// check whether the current instruction is already a
// "ret".
uint8 code[1];
if (fTeamMemory->ReadMemory(eip, &code, 1) == 1
&& code[0] == 0xc3) {
stack = cpuState->IntRegisterValue(X86_REGISTER_ESP);
}
}
} else {
// Not in the function prologue, but maybe after the epilogue.
// The epilogue is a single "pop %ebp", so we check whether the
// current instruction is already a "ret".
uint8 code[1];
if (fTeamMemory->ReadMemory(eip, &code, 1) == 1
&& code[0] == 0xc3) {
// Check if the instruction pointer is at a readable location.
// If it isn't, then chances are we got here via a bogus
// function pointer, and the prologue hasn't actually been
// executed. In such a case, what we need is right at the top
// of the stack.
uint8 data[1];
if (fTeamMemory->ReadMemory(eip, &data, 1) != 1)
stack = cpuState->IntRegisterValue(X86_REGISTER_ESP);
}
}

if (stack != 0) {
Expand Down

0 comments on commit 1e11702

Please sign in to comment.