[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