[Haiku-commits] r31232 - haiku/trunk/src/apps/debugger/arch/x86
bonefish at BerliOS
bonefish at mail.berlios.de
Thu Jun 25 01:38:30 CEST 2009
Author: bonefish
Date: 2009-06-25 01:38:29 +0200 (Thu, 25 Jun 2009)
New Revision: 31232
ViewCVS: http://svn.berlios.de/viewcvs/haiku?rev=31232&view=rev
Modified:
haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.cpp
haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.h
Log:
Recognize non-frameless functions and deal with situations where the instruction
pointer is before/in the prologue or after the epilogue. No solution for
frameless functions yet.
Modified: haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.cpp 2009-06-24 23:14:10 UTC (rev 31231)
+++ haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.cpp 2009-06-24 23:38:29 UTC (rev 31232)
@@ -119,17 +119,76 @@
uint32 framePointer = cpuState->IntRegisterValue(X86_REGISTER_EBP);
uint32 eip = cpuState->IntRegisterValue(X86_REGISTER_EIP);
+ bool readStandardFrame = true;
+ uint32 previousFramePointer = 0;
+ uint32 returnAddress = 0;
+
// check for syscall frames
stack_frame_type frameType;
+ bool hasPrologue = false;
if (isTopFrame && cpuState->InterruptVector() == 99) {
// The thread is performing a syscall. So this frame is not really the
// top-most frame and we need to adjust the eip.
frameType = STACK_FRAME_TYPE_SYSCALL;
eip -= 2;
// int 99, sysenter, and syscall all are 2 byte instructions
- } else
- frameType = STACK_FRAME_TYPE_STANDARD;
+ // The syscall stubs are frameless, the return address is on top of the
+ // stack.
+ uint32 esp = cpuState->IntRegisterValue(X86_REGISTER_ESP);
+ uint32 address;
+ if (fDebuggerInterface->ReadMemory(esp, &address, 4) == 4) {
+ returnAddress = address;
+ previousFramePointer = framePointer;
+ framePointer = 0;
+ readStandardFrame = false;
+ }
+ } else {
+ hasPrologue = _HasFunctionPrologue(function);
+ if (hasPrologue)
+ frameType = STACK_FRAME_TYPE_STANDARD;
+ else
+ frameType = STACK_FRAME_TYPE_FRAMELESS;
+ // TODO: Handling for frameless functions. It's not trivial to find the
+ // return address on the stack, though.
+
+ // 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) {
+ 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;
+ }
+ } 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 (fDebuggerInterface->ReadMemory(eip, &code, 1) == 1
+ && code[0] == 0xc3) {
+ stack = cpuState->IntRegisterValue(X86_REGISTER_ESP);
+ }
+ }
+
+ if (stack != 0) {
+ uint32 address;
+ if (fDebuggerInterface->ReadMemory(stack, &address, 4) == 4) {
+ returnAddress = address;
+ previousFramePointer = framePointer;
+ framePointer = 0;
+ readStandardFrame = false;
+ frameType = STACK_FRAME_TYPE_FRAMELESS;
+ }
+ }
+ }
+ }
+
// create the stack frame
StackFrame* frame = new(std::nothrow) StackFrame(frameType, cpuState,
framePointer, eip);
@@ -137,21 +196,32 @@
return B_NO_MEMORY;
Reference<StackFrame> frameReference(frame, true);
- // read the previous frame and return address and create the CPU state
+ // read the previous frame and return address, if this is a standard frame
+ if (readStandardFrame) {
+ uint32 frameData[2];
+ if (framePointer != 0
+ && fDebuggerInterface->ReadMemory(framePointer, frameData, 8)
+ == 8) {
+ previousFramePointer = frameData[0];
+ returnAddress = frameData[1];
+ }
+ }
+
+ // create the CPU state, if we have any info
CpuStateX86* previousCpuState = NULL;
- uint32 frameData[2];
- if (framePointer != 0
- && fDebuggerInterface->ReadMemory(framePointer, frameData, 8) == 8) {
+ if (returnAddress != 0) {
// prepare the previous CPU state
previousCpuState = new(std::nothrow) CpuStateX86;
if (previousCpuState == NULL)
return B_NO_MEMORY;
- frame->SetReturnAddress(frameData[1]);
- previousCpuState->SetIntRegister(X86_REGISTER_EBP, frameData[0]);
- previousCpuState->SetIntRegister(X86_REGISTER_EIP, frameData[1]);
+ previousCpuState->SetIntRegister(X86_REGISTER_EBP,
+ previousFramePointer);
+ previousCpuState->SetIntRegister(X86_REGISTER_EIP, returnAddress);
}
+ frame->SetReturnAddress(returnAddress);
+
_previousFrame = frameReference.Detach();
_previousCpuState = previousCpuState;
return B_OK;
@@ -171,17 +241,17 @@
uint32 eip = cpuState->IntRegisterValue(X86_REGISTER_EIP);
if (previousFunction == NULL || eip <= previousFunction->Address())
return;
- target_addr_t functionAddresss = previousFunction->Address();
+ target_addr_t functionAddress = previousFunction->Address();
// allocate a buffer for the function code to disassemble
- size_t bufferSize = eip - functionAddresss;
+ size_t bufferSize = eip - functionAddress;
void* buffer = malloc(bufferSize);
if (buffer == NULL)
return;
MemoryDeleter bufferDeleter(buffer);
// read the code
- ssize_t bytesRead = fDebuggerInterface->ReadMemory(functionAddresss, buffer,
+ ssize_t bytesRead = fDebuggerInterface->ReadMemory(functionAddress, buffer,
bufferSize);
if (bytesRead != (ssize_t)bufferSize)
return;
@@ -190,7 +260,7 @@
DisassemblerX86 disassembler;
target_addr_t instructionAddress;
target_size_t instructionSize;
- if (disassembler.Init(functionAddresss, buffer, bufferSize) == B_OK
+ if (disassembler.Init(functionAddress, buffer, bufferSize) == B_OK
&& disassembler.GetPreviousInstruction(eip, instructionAddress,
instructionSize) == B_OK) {
eip -= instructionSize;
@@ -252,3 +322,21 @@
{
_AddRegister(index, name, REGISTER_FORMAT_INTEGER, bitSize, type);
}
+
+
+bool
+ArchitectureX86::_HasFunctionPrologue(FunctionDebugInfo* function) const
+{
+ if (function == NULL)
+ return false;
+
+ // check whether the function has the typical prologue
+ if (function->Size() < 3)
+ return false;
+
+ uint8 buffer[3];
+ if (fDebuggerInterface->ReadMemory(function->Address(), buffer, 3) != 3)
+ return false;
+
+ return buffer[0] == 0x55 && buffer[1] == 0x89 && buffer[2] == 0xe5;
+}
Modified: haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.h
===================================================================
--- haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.h 2009-06-24 23:14:10 UTC (rev 31231)
+++ haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.h 2009-06-24 23:38:29 UTC (rev 31232)
@@ -45,6 +45,9 @@
const char* name, uint32 bitSize,
register_type type);
+ bool _HasFunctionPrologue(
+ FunctionDebugInfo* function) const;
+
private:
Array<Register> fRegisters;
};
More information about the Haiku-commits
mailing list