[Haiku-commits] r31228 - in haiku/trunk/src/apps/debugger/arch: . x86 x86/disasm
bonefish at BerliOS
bonefish at mail.berlios.de
Wed Jun 24 18:37:16 CEST 2009
Author: bonefish
Date: 2009-06-24 18:37:11 +0200 (Wed, 24 Jun 2009)
New Revision: 31228
ViewCVS: http://svn.berlios.de/viewcvs/haiku?rev=31228&view=rev
Modified:
haiku/trunk/src/apps/debugger/arch/Architecture.cpp
haiku/trunk/src/apps/debugger/arch/Architecture.h
haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.cpp
haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.h
haiku/trunk/src/apps/debugger/arch/x86/CpuStateX86.cpp
haiku/trunk/src/apps/debugger/arch/x86/CpuStateX86.h
haiku/trunk/src/apps/debugger/arch/x86/disasm/DisassemblerX86.cpp
haiku/trunk/src/apps/debugger/arch/x86/disasm/DisassemblerX86.h
Log:
* Added StackFrame classification as syscall frame and added correct
identification for x86.
* For non-top stack frames adjust the instruction pointer so that it points to
the calling function instead of the return address.
* SourceView: Consider a syscall frame a non-top frame (the arrow is drawn
differently).
Modified: haiku/trunk/src/apps/debugger/arch/Architecture.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/arch/Architecture.cpp 2009-06-24 14:59:12 UTC (rev 31227)
+++ haiku/trunk/src/apps/debugger/arch/Architecture.cpp 2009-06-24 16:37:11 UTC (rev 31228)
@@ -91,7 +91,7 @@
// If we have no frame yet, let the architecture create it.
if (previousFrame == NULL) {
status_t error = CreateStackFrame(image, function, cpuState,
- previousFrame, previousCpuState);
+ frame == NULL, previousFrame, previousCpuState);
if (error != B_OK)
break;
}
Modified: haiku/trunk/src/apps/debugger/arch/Architecture.h
===================================================================
--- haiku/trunk/src/apps/debugger/arch/Architecture.h 2009-06-24 14:59:12 UTC (rev 31227)
+++ haiku/trunk/src/apps/debugger/arch/Architecture.h 2009-06-24 16:37:11 UTC (rev 31228)
@@ -37,7 +37,7 @@
size_t size, CpuState*& _state) = 0;
virtual status_t CreateStackFrame(Image* image,
FunctionDebugInfo* function,
- CpuState* cpuState,
+ CpuState* cpuState, bool isTopFrame,
StackFrame*& _previousFrame,
CpuState*& _previousCpuState) = 0;
// returns reference to previous frame
Modified: haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.cpp 2009-06-24 14:59:12 UTC (rev 31227)
+++ haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.cpp 2009-06-24 16:37:11 UTC (rev 31228)
@@ -111,16 +111,54 @@
status_t
ArchitectureX86::CreateStackFrame(Image* image, FunctionDebugInfo* function,
- CpuState* _cpuState, StackFrame*& _previousFrame,
+ CpuState* _cpuState, bool isTopFrame, StackFrame*& _previousFrame,
CpuState*& _previousCpuState)
{
CpuStateX86* cpuState = dynamic_cast<CpuStateX86*>(_cpuState);
uint32 framePointer = cpuState->IntRegisterValue(X86_REGISTER_EBP);
+ uint32 eip = cpuState->IntRegisterValue(X86_REGISTER_EIP);
+ // check for syscall frames
+ stack_frame_type frameType;
+ 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;
+
+ // If this is not a top-frame, we offset eip to the previous (calling)
+ // instruction.
+ if (!isTopFrame && function != NULL && eip > function->Address()) {
+ size_t bufferSize = eip - function->Address();
+ void* buffer = malloc(bufferSize);
+ if (buffer != NULL) {
+ ssize_t bytesRead = fDebuggerInterface->ReadMemory(
+ function->Address(), buffer, bufferSize);
+ if (bytesRead == (ssize_t)bufferSize) {
+ DisassemblerX86 disassembler;
+ target_addr_t instructionAddress;
+ target_size_t instructionSize;
+ if (disassembler.Init(function->Address(),
+ buffer, bufferSize) == B_OK
+ && disassembler.GetPreviousInstruction(eip,
+ instructionAddress, instructionSize) == B_OK) {
+ eip -= instructionSize;
+ cpuState->SetIntRegister(X86_REGISTER_EIP, eip);
+ }
+ }
+
+ free(buffer);
+ }
+ }
+ }
+
// create the stack frame
- StackFrame* frame = new(std::nothrow) StackFrame(
- STACK_FRAME_TYPE_STANDARD, cpuState, framePointer);
+ StackFrame* frame = new(std::nothrow) StackFrame(frameType, cpuState,
+ framePointer, eip);
if (frame == NULL)
return B_NO_MEMORY;
Reference<StackFrame> frameReference(frame, true);
@@ -135,9 +173,14 @@
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]);
- // TODO: Actually it's the instruction before!
+ // TODO: Actually it's the instruction before! We're currently
+ // offsetting it at the beginning of this method, but that's not
+ // correct, since for the previous stack frame there could be more
+ // debug info. Problem is that we don't have the function for the
+ // previous stack frame available at this point.
}
_previousFrame = frameReference.Detach();
Modified: haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.h
===================================================================
--- haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.h 2009-06-24 14:59:12 UTC (rev 31227)
+++ haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.h 2009-06-24 16:37:11 UTC (rev 31228)
@@ -25,7 +25,7 @@
size_t size, CpuState*& _state);
virtual status_t CreateStackFrame(Image* image,
FunctionDebugInfo* function,
- CpuState* cpuState,
+ CpuState* cpuState, bool isTopFrame,
StackFrame*& _previousFrame,
CpuState*& _previousCpuState);
virtual status_t DisassembleCode(FunctionDebugInfo* function,
Modified: haiku/trunk/src/apps/debugger/arch/x86/CpuStateX86.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/arch/x86/CpuStateX86.cpp 2009-06-24 14:59:12 UTC (rev 31227)
+++ haiku/trunk/src/apps/debugger/arch/x86/CpuStateX86.cpp 2009-06-24 16:37:11 UTC (rev 31228)
@@ -10,14 +10,16 @@
CpuStateX86::CpuStateX86()
:
- fSetRegisters()
+ fSetRegisters(),
+ fInterruptVector(0)
{
}
CpuStateX86::CpuStateX86(const debug_cpu_state_x86& state)
:
- fSetRegisters()
+ fSetRegisters(),
+ fInterruptVector(0)
{
SetIntRegister(X86_REGISTER_EIP, state.eip);
SetIntRegister(X86_REGISTER_ESP, state.user_esp);
@@ -34,6 +36,8 @@
SetIntRegister(X86_REGISTER_FS, state.fs);
SetIntRegister(X86_REGISTER_GS, state.gs);
SetIntRegister(X86_REGISTER_SS, state.user_ss);
+
+ fInterruptVector = state.vector;
}
Modified: haiku/trunk/src/apps/debugger/arch/x86/CpuStateX86.h
===================================================================
--- haiku/trunk/src/apps/debugger/arch/x86/CpuStateX86.h 2009-06-24 14:59:12 UTC (rev 31227)
+++ haiku/trunk/src/apps/debugger/arch/x86/CpuStateX86.h 2009-06-24 16:37:11 UTC (rev 31228)
@@ -50,6 +50,9 @@
virtual bool GetRegisterValue(const Register* reg,
BVariant& _value);
+ uint32 InterruptVector() const
+ { return fInterruptVector; }
+
bool IsRegisterSet(int32 index) const;
uint32 IntRegisterValue(int32 index) const;
void SetIntRegister(int32 index, uint32 value);
@@ -61,6 +64,7 @@
private:
uint32 fIntRegisters[X86_REGISTER_COUNT];
RegisterBitSet fSetRegisters;
+ uint32 fInterruptVector;
};
Modified: haiku/trunk/src/apps/debugger/arch/x86/disasm/DisassemblerX86.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/arch/x86/disasm/DisassemblerX86.cpp 2009-06-24 14:59:12 UTC (rev 31227)
+++ haiku/trunk/src/apps/debugger/arch/x86/disasm/DisassemblerX86.cpp 2009-06-24 16:37:11 UTC (rev 31228)
@@ -86,3 +86,25 @@
return B_OK;
}
+
+status_t
+DisassemblerX86::GetPreviousInstruction(target_addr_t nextAddress,
+ target_addr_t& _address, target_size_t& _size)
+{
+ if (nextAddress < fAddress || nextAddress > fAddress + fCodeSize)
+ return B_BAD_VALUE;
+
+ // loop until hitting the last instruction
+ while (true) {
+ unsigned int size = ud_disassemble(fUdisData);
+ if (size < 1)
+ return B_ENTRY_NOT_FOUND;
+
+ uint32 address = (uint32)ud_insn_off(fUdisData);
+ if (address + size == nextAddress) {
+ _address = address;
+ _size = size;
+ return B_OK;
+ }
+ }
+}
Modified: haiku/trunk/src/apps/debugger/arch/x86/disasm/DisassemblerX86.h
===================================================================
--- haiku/trunk/src/apps/debugger/arch/x86/disasm/DisassemblerX86.h 2009-06-24 14:59:12 UTC (rev 31227)
+++ haiku/trunk/src/apps/debugger/arch/x86/disasm/DisassemblerX86.h 2009-06-24 16:37:11 UTC (rev 31228)
@@ -22,6 +22,10 @@
target_addr_t& _address,
target_size_t& _size,
bool& _breakpointAllowed);
+ virtual status_t GetPreviousInstruction(
+ target_addr_t nextAddress,
+ target_addr_t& _address,
+ target_size_t& _size);
private:
struct UdisData;
More information about the Haiku-commits
mailing list