* 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).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31228 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-06-24 16:37:11 +00:00
parent 224fb9cf6e
commit 840c76534f
8 changed files with 86 additions and 9 deletions
+1 -1
View File
@@ -91,7 +91,7 @@ Architecture::CreateStackTrace(Team* team,
// If we have no frame yet, let the architecture create it. // If we have no frame yet, let the architecture create it.
if (previousFrame == NULL) { if (previousFrame == NULL) {
status_t error = CreateStackFrame(image, function, cpuState, status_t error = CreateStackFrame(image, function, cpuState,
previousFrame, previousCpuState); frame == NULL, previousFrame, previousCpuState);
if (error != B_OK) if (error != B_OK)
break; break;
} }
+1 -1
View File
@@ -37,7 +37,7 @@ public:
size_t size, CpuState*& _state) = 0; size_t size, CpuState*& _state) = 0;
virtual status_t CreateStackFrame(Image* image, virtual status_t CreateStackFrame(Image* image,
FunctionDebugInfo* function, FunctionDebugInfo* function,
CpuState* cpuState, CpuState* cpuState, bool isTopFrame,
StackFrame*& _previousFrame, StackFrame*& _previousFrame,
CpuState*& _previousCpuState) = 0; CpuState*& _previousCpuState) = 0;
// returns reference to previous frame // returns reference to previous frame
+47 -4
View File
@@ -111,16 +111,54 @@ ArchitectureX86::CreateCpuState(const void* cpuStateData, size_t size,
status_t status_t
ArchitectureX86::CreateStackFrame(Image* image, FunctionDebugInfo* function, ArchitectureX86::CreateStackFrame(Image* image, FunctionDebugInfo* function,
CpuState* _cpuState, StackFrame*& _previousFrame, CpuState* _cpuState, bool isTopFrame, StackFrame*& _previousFrame,
CpuState*& _previousCpuState) CpuState*& _previousCpuState)
{ {
CpuStateX86* cpuState = dynamic_cast<CpuStateX86*>(_cpuState); CpuStateX86* cpuState = dynamic_cast<CpuStateX86*>(_cpuState);
uint32 framePointer = cpuState->IntRegisterValue(X86_REGISTER_EBP); 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 // create the stack frame
StackFrame* frame = new(std::nothrow) StackFrame( StackFrame* frame = new(std::nothrow) StackFrame(frameType, cpuState,
STACK_FRAME_TYPE_STANDARD, cpuState, framePointer); framePointer, eip);
if (frame == NULL) if (frame == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
Reference<StackFrame> frameReference(frame, true); Reference<StackFrame> frameReference(frame, true);
@@ -135,9 +173,14 @@ ArchitectureX86::CreateStackFrame(Image* image, FunctionDebugInfo* function,
if (previousCpuState == NULL) if (previousCpuState == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
frame->SetReturnAddress(frameData[1]);
previousCpuState->SetIntRegister(X86_REGISTER_EBP, frameData[0]); previousCpuState->SetIntRegister(X86_REGISTER_EBP, frameData[0]);
previousCpuState->SetIntRegister(X86_REGISTER_EIP, frameData[1]); 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(); _previousFrame = frameReference.Detach();
+1 -1
View File
@@ -25,7 +25,7 @@ public:
size_t size, CpuState*& _state); size_t size, CpuState*& _state);
virtual status_t CreateStackFrame(Image* image, virtual status_t CreateStackFrame(Image* image,
FunctionDebugInfo* function, FunctionDebugInfo* function,
CpuState* cpuState, CpuState* cpuState, bool isTopFrame,
StackFrame*& _previousFrame, StackFrame*& _previousFrame,
CpuState*& _previousCpuState); CpuState*& _previousCpuState);
virtual status_t DisassembleCode(FunctionDebugInfo* function, virtual status_t DisassembleCode(FunctionDebugInfo* function,
+6 -2
View File
@@ -10,14 +10,16 @@
CpuStateX86::CpuStateX86() CpuStateX86::CpuStateX86()
: :
fSetRegisters() fSetRegisters(),
fInterruptVector(0)
{ {
} }
CpuStateX86::CpuStateX86(const debug_cpu_state_x86& state) CpuStateX86::CpuStateX86(const debug_cpu_state_x86& state)
: :
fSetRegisters() fSetRegisters(),
fInterruptVector(0)
{ {
SetIntRegister(X86_REGISTER_EIP, state.eip); SetIntRegister(X86_REGISTER_EIP, state.eip);
SetIntRegister(X86_REGISTER_ESP, state.user_esp); SetIntRegister(X86_REGISTER_ESP, state.user_esp);
@@ -34,6 +36,8 @@ CpuStateX86::CpuStateX86(const debug_cpu_state_x86& state)
SetIntRegister(X86_REGISTER_FS, state.fs); SetIntRegister(X86_REGISTER_FS, state.fs);
SetIntRegister(X86_REGISTER_GS, state.gs); SetIntRegister(X86_REGISTER_GS, state.gs);
SetIntRegister(X86_REGISTER_SS, state.user_ss); SetIntRegister(X86_REGISTER_SS, state.user_ss);
fInterruptVector = state.vector;
} }
+4
View File
@@ -50,6 +50,9 @@ public:
virtual bool GetRegisterValue(const Register* reg, virtual bool GetRegisterValue(const Register* reg,
BVariant& _value); BVariant& _value);
uint32 InterruptVector() const
{ return fInterruptVector; }
bool IsRegisterSet(int32 index) const; bool IsRegisterSet(int32 index) const;
uint32 IntRegisterValue(int32 index) const; uint32 IntRegisterValue(int32 index) const;
void SetIntRegister(int32 index, uint32 value); void SetIntRegister(int32 index, uint32 value);
@@ -61,6 +64,7 @@ private:
private: private:
uint32 fIntRegisters[X86_REGISTER_COUNT]; uint32 fIntRegisters[X86_REGISTER_COUNT];
RegisterBitSet fSetRegisters; RegisterBitSet fSetRegisters;
uint32 fInterruptVector;
}; };
@@ -86,3 +86,25 @@ DisassemblerX86::GetNextInstruction(BString& line, target_addr_t& _address,
return B_OK; 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;
}
}
}
@@ -22,6 +22,10 @@ public:
target_addr_t& _address, target_addr_t& _address,
target_size_t& _size, target_size_t& _size,
bool& _breakpointAllowed); bool& _breakpointAllowed);
virtual status_t GetPreviousInstruction(
target_addr_t nextAddress,
target_addr_t& _address,
target_size_t& _size);
private: private:
struct UdisData; struct UdisData;