[Haiku-commits] r31126 - in haiku/trunk/src/apps/debugger: . arch arch/x86 gui/team_window

bonefish at BerliOS bonefish at mail.berlios.de
Sat Jun 20 00:13:33 CEST 2009


Author: bonefish
Date: 2009-06-20 00:13:32 +0200 (Sat, 20 Jun 2009)
New Revision: 31126
ViewCVS: http://svn.berlios.de/viewcvs/haiku?rev=31126&view=rev

Added:
   haiku/trunk/src/apps/debugger/arch/x86/StackFrameX86.cpp
   haiku/trunk/src/apps/debugger/arch/x86/StackFrameX86.h
   haiku/trunk/src/apps/debugger/gui/team_window/StackTraceView.cpp
   haiku/trunk/src/apps/debugger/gui/team_window/StackTraceView.h
Modified:
   haiku/trunk/src/apps/debugger/Debugger.cpp
   haiku/trunk/src/apps/debugger/Jamfile
   haiku/trunk/src/apps/debugger/Jobs.cpp
   haiku/trunk/src/apps/debugger/Jobs.h
   haiku/trunk/src/apps/debugger/TeamDebugger.cpp
   haiku/trunk/src/apps/debugger/TeamDebugger.h
   haiku/trunk/src/apps/debugger/arch/Architecture.h
   haiku/trunk/src/apps/debugger/arch/Register.h
   haiku/trunk/src/apps/debugger/arch/StackFrame.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/gui/team_window/TeamWindow.cpp
   haiku/trunk/src/apps/debugger/gui/team_window/TeamWindow.h
Log:
Some work towards getting stack traces:
* Added a virtual Architecture::CreateStackTrace() and added a basic
  implementation in ArchitectureX86. Fleshed out StackTrace/StackFrame a bit
  and added StackFrameX86. This needs to be organized differently, though, so
  that we can get the maximum available information for each stack frame,
  depending on what info is available for the respective function.
* Added job to get the stack trace for a thread.
* Added stack trace related handling in TeamDebugger. Reorganized the thread
  state/CPU state/stack trace change handling a bit -- we're using a
  Team::Listener now, and do things asynchronously.
* Added a StackTraceView to display the stack trace of the current thread. No
  function name available yet, otherwise working fine.


Modified: haiku/trunk/src/apps/debugger/Debugger.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/Debugger.cpp	2009-06-19 21:58:48 UTC (rev 31125)
+++ haiku/trunk/src/apps/debugger/Debugger.cpp	2009-06-19 22:13:32 UTC (rev 31126)
@@ -13,6 +13,8 @@
 #include <Application.h>
 #include <Message.h>
 
+#include <ObjectList.h>
+
 #include "debug_utils.h"
 
 #include "TeamDebugger.h"
@@ -216,7 +218,7 @@
 			stopInMain = true;
 		}
 
-		// If we've got 
+		// If we've got
 		if (team < 0) {
 printf("no team yet, getting thread info...\n");
 			thread_info threadInfo;
@@ -245,12 +247,10 @@
 			fprintf(stderr, "Error: Out of memory!\n");
 		}
 
-		if (debugger->Init(team, thread, stopInMain) == B_OK)
-{
+		if (debugger->Init(team, thread, stopInMain) == B_OK
+			&& fTeamDebuggers.AddItem(debugger)) {
 printf("debugger for team %ld created and initialized successfully!\n", team);
-			fTeamDebuggers.Add(debugger);
-}
-		else
+		} else
 			delete debugger;
 	}
 
@@ -261,13 +261,13 @@
 	}
 
 private:
-	typedef DoublyLinkedList<TeamDebugger>	TeamDebuggerList;
+	typedef BObjectList<TeamDebugger>	TeamDebuggerList;
 
 private:
 	TeamDebugger* _TeamDebuggerForTeam(team_id teamID) const
 	{
-		for (TeamDebuggerList::ConstIterator it = fTeamDebuggers.GetIterator();
-				TeamDebugger* debugger = it.Next();) {
+		for (int32 i = 0; TeamDebugger* debugger = fTeamDebuggers.ItemAt(i);
+				i++) {
 			if (debugger->TeamID() == teamID)
 				return debugger;
 		}

Modified: haiku/trunk/src/apps/debugger/Jamfile
===================================================================
--- haiku/trunk/src/apps/debugger/Jamfile	2009-06-19 21:58:48 UTC (rev 31125)
+++ haiku/trunk/src/apps/debugger/Jamfile	2009-06-19 22:13:32 UTC (rev 31126)
@@ -41,6 +41,7 @@
 	# arch/x86
 	ArchitectureX86.cpp
 	CpuStateX86.cpp
+	StackFrameX86.cpp
 
 	# debugger_interface
 	DebugEvent.cpp
@@ -48,6 +49,8 @@
 
 	# gui/team_window
 	ImageListView.cpp
+	RegisterView.cpp
+	StackTraceView.cpp
 	TeamWindow.cpp
 	ThreadListView.cpp
 

Modified: haiku/trunk/src/apps/debugger/Jobs.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/Jobs.cpp	2009-06-19 21:58:48 UTC (rev 31125)
+++ haiku/trunk/src/apps/debugger/Jobs.cpp	2009-06-19 22:13:32 UTC (rev 31126)
@@ -7,12 +7,17 @@
 
 #include <AutoLocker.h>
 
+#include "Architecture.h"
 #include "CpuState.h"
 #include "DebuggerInterface.h"
+#include "StackTrace.h"
 #include "Team.h"
 #include "Thread.h"
 
 
+// #pragma mark - GetCpuStateJob
+
+
 GetCpuStateJob::GetCpuStateJob(DebuggerInterface* debuggerInterface,
 	Thread* thread)
 	:
@@ -52,3 +57,61 @@
 
 	return B_OK;
 }
+
+
+// #pragma mark - GetStackTraceJob
+
+
+GetStackTraceJob::GetStackTraceJob(DebuggerInterface* debuggerInterface,
+	Architecture* architecture, Thread* thread)
+	:
+	fDebuggerInterface(debuggerInterface),
+	fArchitecture(architecture),
+	fThread(thread)
+{
+	fThread->AddReference();
+
+	fCpuState = fThread->GetCpuState();
+	if (fCpuState != NULL)
+		fCpuState->AddReference();
+}
+
+
+GetStackTraceJob::~GetStackTraceJob()
+{
+	if (fCpuState != NULL)
+		fCpuState->RemoveReference();
+
+	fThread->RemoveReference();
+}
+
+
+JobKey
+GetStackTraceJob::Key() const
+{
+	return JobKey(fThread, JOB_TYPE_GET_CPU_STATE);
+}
+
+
+status_t
+GetStackTraceJob::Do()
+{
+	if (fCpuState == NULL)
+		return B_BAD_VALUE;
+
+	// get the stack trace
+	StackTrace* stackTrace;
+	status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(),
+		fCpuState, stackTrace);
+	if (error != B_OK)
+		return error;
+	Reference<StackTrace> stackTraceReference(stackTrace, true);
+
+	// set the stack trace, unless something has changed
+	AutoLocker<Team> locker(fThread->GetTeam());
+
+	if (fThread->GetCpuState() == fCpuState)
+		fThread->SetStackTrace(stackTrace);
+
+	return B_OK;
+}

Modified: haiku/trunk/src/apps/debugger/Jobs.h
===================================================================
--- haiku/trunk/src/apps/debugger/Jobs.h	2009-06-19 21:58:48 UTC (rev 31125)
+++ haiku/trunk/src/apps/debugger/Jobs.h	2009-06-19 22:13:32 UTC (rev 31126)
@@ -8,13 +8,16 @@
 #include "Worker.h"
 
 
+class Architecture;
+class CpuState;
 class DebuggerInterface;
 class Thread;
 
 
 // job types
 enum {
-	JOB_TYPE_GET_CPU_STATE
+	JOB_TYPE_GET_CPU_STATE,
+	JOB_TYPE_GET_STACK_TRACE
 };
 
 
@@ -34,4 +37,23 @@
 };
 
 
+class GetStackTraceJob : public Job {
+public:
+								GetStackTraceJob(
+									DebuggerInterface* debuggerInterface,
+									Architecture* architecture,
+									Thread* thread);
+	virtual						~GetStackTraceJob();
+
+	virtual	JobKey				Key() const;
+	virtual	status_t			Do();
+
+private:
+			DebuggerInterface*	fDebuggerInterface;
+			Architecture*		fArchitecture;
+			Thread*				fThread;
+			CpuState*			fCpuState;
+};
+
+
 #endif	// JOBS_H

Modified: haiku/trunk/src/apps/debugger/TeamDebugger.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/TeamDebugger.cpp	2009-06-19 21:58:48 UTC (rev 31125)
+++ haiku/trunk/src/apps/debugger/TeamDebugger.cpp	2009-06-19 22:13:32 UTC (rev 31126)
@@ -19,7 +19,6 @@
 #include "DebuggerInterface.h"
 #include "Jobs.h"
 #include "MessageCodes.h"
-#include "Team.h"
 #include "TeamDebugModel.h"
 
 
@@ -81,6 +80,8 @@
 	fTeam->SetName(teamInfo.args);
 		// TODO: Set a better name!
 
+	fTeam->AddListener(this);
+
 	// create our worker
 	fWorker = new(std::nothrow) Worker;
 	if (fWorker == NULL)
@@ -196,6 +197,35 @@
 			_HandleThreadAction(threadID, message->what);
 			break;
 		}
+
+		case MSG_THREAD_STATE_CHANGED:
+		{
+			int32 threadID;
+			if (message->FindInt32("thread", &threadID) != B_OK)
+				break;
+
+			_HandleThreadStateChanged(threadID);
+			break;
+		}
+		case MSG_THREAD_CPU_STATE_CHANGED:
+		{
+			int32 threadID;
+			if (message->FindInt32("thread", &threadID) != B_OK)
+				break;
+
+			_HandleCpuStateChanged(threadID);
+			break;
+		}
+		case MSG_THREAD_STACK_TRACE_CHANGED:
+		{
+			int32 threadID;
+			if (message->FindInt32("thread", &threadID) != B_OK)
+				break;
+
+			_HandleStackTraceChanged(threadID);
+			break;
+		}
+
 		default:
 			BLooper::MessageReceived(message);
 			break;
@@ -242,6 +272,33 @@
 }
 
 
+void
+TeamDebugger::ThreadStateChanged(const ::Team::ThreadEvent& event)
+{
+	BMessage message(MSG_THREAD_STATE_CHANGED);
+	message.AddInt32("thread", event.GetThread()->ID());
+	PostMessage(&message);
+}
+
+
+void
+TeamDebugger::ThreadCpuStateChanged(const ::Team::ThreadEvent& event)
+{
+	BMessage message(MSG_THREAD_CPU_STATE_CHANGED);
+	message.AddInt32("thread", event.GetThread()->ID());
+	PostMessage(&message);
+}
+
+
+void
+TeamDebugger::ThreadStackTraceChanged(const ::Team::ThreadEvent& event)
+{
+	BMessage message(MSG_THREAD_STACK_TRACE_CHANGED);
+	message.AddInt32("thread", event.GetThread()->ID());
+	PostMessage(&message);
+}
+
+
 /*static*/ status_t
 TeamDebugger::_DebugEventListenerEntry(void* data)
 {
@@ -481,24 +538,8 @@
 TeamDebugger::_SetThreadState(::Thread* thread, uint32 state,
 	CpuState* cpuState)
 {
-	// update the thread state
-	uint32 oldState = thread->State();
 	thread->SetState(state);
-
-	// cancel jobs for this thread
-	if (oldState == THREAD_STATE_STOPPED)
-		fWorker->AbortJob(JobKey(thread, JOB_TYPE_GET_CPU_STATE));
-
-	if (state == THREAD_STATE_STOPPED) {
-		if (cpuState != NULL) {
-			thread->SetCpuState(cpuState);
-		} else {
-			// trigger updating the CPU state
-			fWorker->ScheduleJob(new(std::nothrow) GetCpuStateJob(
-					fDebuggerInterface, thread),
-				this);
-		}
-	}
+	thread->SetCpuState(cpuState);
 }
 
 
@@ -550,3 +591,55 @@
 // TODO: Handle stepping correctly!
 	}
 }
+
+
+void
+TeamDebugger::_HandleThreadStateChanged(thread_id threadID)
+{
+	AutoLocker< ::Team> teamLocker(fTeam);
+
+	::Thread* thread = fTeam->ThreadByID(threadID);
+	if (thread == NULL)
+		return;
+
+	// cancel jobs for this thread
+	fWorker->AbortJob(JobKey(thread, JOB_TYPE_GET_CPU_STATE));
+	fWorker->AbortJob(JobKey(thread, JOB_TYPE_GET_STACK_TRACE));
+
+	// If the thread is stopped and has no CPU state yet, schedule a job.
+	if (thread->State() == THREAD_STATE_STOPPED
+			&& thread->GetCpuState() == NULL) {
+		fWorker->ScheduleJob(
+			new(std::nothrow) GetCpuStateJob(fDebuggerInterface, thread),
+			this);
+	}
+}
+
+
+void
+TeamDebugger::_HandleCpuStateChanged(thread_id threadID)
+{
+	AutoLocker< ::Team> teamLocker(fTeam);
+
+	::Thread* thread = fTeam->ThreadByID(threadID);
+	if (thread == NULL)
+		return;
+
+	// cancel stack trace job for this thread
+	fWorker->AbortJob(JobKey(thread, JOB_TYPE_GET_STACK_TRACE));
+
+	// If the thread has a CPU state, but no stack trace yet, schedule a job.
+	if (thread->GetCpuState() != NULL && thread->GetStackTrace() == NULL) {
+		fWorker->ScheduleJob(
+			new(std::nothrow) GetStackTraceJob(fDebuggerInterface,
+				fDebuggerInterface->GetArchitecture(), thread),
+			this);
+	}
+}
+
+
+void
+TeamDebugger::_HandleStackTraceChanged(thread_id threadID)
+{
+printf("TeamDebugger::_HandleStackTraceChanged()\n");
+}

Modified: haiku/trunk/src/apps/debugger/TeamDebugger.h
===================================================================
--- haiku/trunk/src/apps/debugger/TeamDebugger.h	2009-06-19 21:58:48 UTC (rev 31125)
+++ haiku/trunk/src/apps/debugger/TeamDebugger.h	2009-06-19 22:13:32 UTC (rev 31126)
@@ -9,20 +9,19 @@
 #include <Looper.h>
 
 #include <debug_support.h>
-#include <util/DoublyLinkedList.h>
 
 #include "DebugEvent.h"
+#include "Team.h"
 #include "TeamWindow.h"
 #include "Worker.h"
 
 
 class DebuggerInterface;
-class Team;
 class TeamDebugModel;
 
 
-class TeamDebugger :  public DoublyLinkedListLinkImpl<TeamDebugger>,
-	private BLooper, private TeamWindow::Listener, private JobListener {
+class TeamDebugger : private BLooper, private TeamWindow::Listener,
+	private JobListener, private Team::Listener {
 public:
 								TeamDebugger();
 								~TeamDebugger();
@@ -45,6 +44,14 @@
 	virtual	void				JobFailed(Job* job);
 	virtual	void				JobAborted(Job* job);
 
+	// Team::Listener
+	virtual	void				ThreadStateChanged(
+									const ::Team::ThreadEvent& event);
+	virtual	void				ThreadCpuStateChanged(
+									const ::Team::ThreadEvent& event);
+	virtual	void				ThreadStackTraceChanged(
+									const ::Team::ThreadEvent& event);
+
 private:
 	static	status_t			_DebugEventListenerEntry(void* data);
 			status_t			_DebugEventListener();
@@ -82,6 +89,10 @@
 			void				_HandleThreadAction(thread_id threadID,
 									uint32 action);
 
+			void				_HandleThreadStateChanged(thread_id threadID);
+			void				_HandleCpuStateChanged(thread_id threadID);
+			void				_HandleStackTraceChanged(thread_id threadID);
+
 private:
 			::Team*				fTeam;
 			TeamDebugModel*		fDebugModel;

Modified: haiku/trunk/src/apps/debugger/arch/Architecture.h
===================================================================
--- haiku/trunk/src/apps/debugger/arch/Architecture.h	2009-06-19 21:58:48 UTC (rev 31125)
+++ haiku/trunk/src/apps/debugger/arch/Architecture.h	2009-06-19 22:13:32 UTC (rev 31126)
@@ -13,6 +13,8 @@
 class CpuState;
 class DebuggerInterface;
 class Register;
+class StackTrace;
+class Team;
 
 
 class Architecture : public Referenceable {
@@ -28,6 +30,9 @@
 
 	virtual	status_t			CreateCpuState(const void* cpuStateData,
 									size_t size, CpuState*& _state) = 0;
+	virtual	status_t			CreateStackTrace(Team* team, CpuState* cpuState,
+									StackTrace*& _stackTrace) = 0;
+										// team is not locked
 
 protected:
 			DebuggerInterface*	fDebuggerInterface;

Modified: haiku/trunk/src/apps/debugger/arch/Register.h
===================================================================
--- haiku/trunk/src/apps/debugger/arch/Register.h	2009-06-19 21:58:48 UTC (rev 31125)
+++ haiku/trunk/src/apps/debugger/arch/Register.h	2009-06-19 22:13:32 UTC (rev 31126)
@@ -14,7 +14,7 @@
 };
 
 enum register_type {
-	REGISTER_TYPE_PROGRAM_COUNTER,
+	REGISTER_TYPE_INSTRUCTION_POINTER,
 	REGISTER_TYPE_STACK_POINTER,
 	REGISTER_TYPE_GENERAL_PURPOSE,
 	REGISTER_TYPE_SPECIAL_PURPOSE,

Modified: haiku/trunk/src/apps/debugger/arch/StackFrame.h
===================================================================
--- haiku/trunk/src/apps/debugger/arch/StackFrame.h	2009-06-19 21:58:48 UTC (rev 31125)
+++ haiku/trunk/src/apps/debugger/arch/StackFrame.h	2009-06-19 22:13:32 UTC (rev 31126)
@@ -13,6 +13,14 @@
 #include "ArchitectureTypes.h"
 
 
+enum stack_frame_type {
+	STACK_FRAME_TYPE_TOP,			// top-most frame
+	STACK_FRAME_TYPE_STANDARD,		// non-top-most standard frame
+	STACK_FRAME_TYPE_SIGNAL,		// signal handler frame
+	STACK_FRAME_TYPE_FRAMELESS		// dummy frame for a frameless function
+};
+
+
 class CpuState;
 
 
@@ -21,8 +29,11 @@
 public:
 	virtual						~StackFrame();
 
+	virtual	stack_frame_type	Type() const = 0;
+
 	virtual	CpuState*			GetCpuState() const = 0;
 
+	virtual	target_addr_t		InstructionPointer() const = 0;
 	virtual	target_addr_t		FrameAddress() const = 0;
 	virtual	target_addr_t		ReturnAddress() const = 0;
 	virtual	target_addr_t		PreviousFrameAddress() const = 0;

Modified: haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.cpp	2009-06-19 21:58:48 UTC (rev 31125)
+++ haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.cpp	2009-06-19 22:13:32 UTC (rev 31126)
@@ -7,7 +7,12 @@
 
 #include <new>
 
+#include <AutoDeleter.h>
+
 #include "CpuStateX86.h"
+#include "DebuggerInterface.h"
+#include "StackFrameX86.h"
+#include "StackTrace.h"
 
 
 ArchitectureX86::ArchitectureX86(DebuggerInterface* debuggerInterface)
@@ -27,7 +32,7 @@
 {
 	try {
 		_AddIntegerRegister(X86_REGISTER_EIP, "eip", 32,
-			REGISTER_TYPE_PROGRAM_COUNTER);
+			REGISTER_TYPE_INSTRUCTION_POINTER);
 		_AddIntegerRegister(X86_REGISTER_ESP, "esp", 32,
 			REGISTER_TYPE_STACK_POINTER);
 		_AddIntegerRegister(X86_REGISTER_EBP, "ebp", 32,
@@ -98,6 +103,64 @@
 }
 
 
+status_t
+ArchitectureX86::CreateStackTrace(Team* team, CpuState* _cpuState,
+	StackTrace*& _stackTrace)
+{
+	CpuStateX86* cpuState = dynamic_cast<CpuStateX86*>(_cpuState);
+
+	// create the object
+	StackTrace* stackTrace = new(std::nothrow) StackTrace;
+	if (stackTrace == NULL)
+		return B_NO_MEMORY;
+	ObjectDeleter<StackTrace> stackTraceDeleter(stackTrace);
+
+	// create the top frame
+	StackFrameX86* frame = new StackFrameX86(STACK_FRAME_TYPE_TOP, cpuState);
+	if (frame == NULL)
+		return B_NO_MEMORY;
+	stackTrace->AddFrame(frame);
+
+	while (true) {
+		uint32 framePointer = (uint32)frame->FrameAddress();
+		if (framePointer == 0)
+			break;
+
+		// get previous frame and return address
+		uint32 frameData[2];
+		ssize_t bytesRead = fDebuggerInterface->ReadMemory(framePointer,
+			frameData, 8);
+		if (bytesRead != 8)
+			break;
+
+		frame->SetPreviousAddresses(frameData[0], frameData[1]);
+
+		if (frameData[0] == 0 || frameData[1] == 0)
+			break;
+
+		// prepare the previous CPU state
+		cpuState = new(std::nothrow) CpuStateX86;
+		if (cpuState == NULL)
+			return B_NO_MEMORY;
+		Reference<CpuState> cpuStateReference(cpuState, true);
+
+		cpuState->SetIntRegister(X86_REGISTER_EBP, frameData[0]);
+		cpuState->SetIntRegister(X86_REGISTER_EIP, frameData[1]);
+			// TODO: Actually it's the instruction before!
+
+		// create the next frame
+		frame = new StackFrameX86(STACK_FRAME_TYPE_STANDARD, cpuState);
+		if (frame == NULL)
+			return B_NO_MEMORY;
+		stackTrace->AddFrame(frame);
+	}
+
+	stackTraceDeleter.Detach();
+	_stackTrace = stackTrace;
+	return B_OK;
+}
+
+
 void
 ArchitectureX86::_AddRegister(int32 index, const char* name,
 	register_format format, uint32 bitSize, register_type type)

Modified: haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.h
===================================================================
--- haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.h	2009-06-19 21:58:48 UTC (rev 31125)
+++ haiku/trunk/src/apps/debugger/arch/x86/ArchitectureX86.h	2009-06-19 22:13:32 UTC (rev 31126)
@@ -23,6 +23,8 @@
 
 	virtual	status_t			CreateCpuState(const void* cpuStateData,
 									size_t size, CpuState*& _state);
+	virtual	status_t			CreateStackTrace(Team* team, CpuState* cpuState,
+									StackTrace*& _stackTrace);
 
 private:
 			void				_AddRegister(int32 index, const char* name,

Modified: haiku/trunk/src/apps/debugger/arch/x86/CpuStateX86.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/arch/x86/CpuStateX86.cpp	2009-06-19 21:58:48 UTC (rev 31125)
+++ haiku/trunk/src/apps/debugger/arch/x86/CpuStateX86.cpp	2009-06-19 22:13:32 UTC (rev 31126)
@@ -8,6 +8,13 @@
 #include "Register.h"
 
 
+CpuStateX86::CpuStateX86()
+	:
+	fSetRegisters()
+{
+}
+
+
 CpuStateX86::CpuStateX86(const debug_cpu_state_x86& state)
 	:
 	fSetRegisters()

Modified: haiku/trunk/src/apps/debugger/arch/x86/CpuStateX86.h
===================================================================
--- haiku/trunk/src/apps/debugger/arch/x86/CpuStateX86.h	2009-06-19 21:58:48 UTC (rev 31125)
+++ haiku/trunk/src/apps/debugger/arch/x86/CpuStateX86.h	2009-06-19 22:13:32 UTC (rev 31126)
@@ -42,6 +42,7 @@
 
 class CpuStateX86 : public CpuState {
 public:
+								CpuStateX86();
 								CpuStateX86(const debug_cpu_state_x86& state);
 	virtual						~CpuStateX86();
 

Added: haiku/trunk/src/apps/debugger/arch/x86/StackFrameX86.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/arch/x86/StackFrameX86.cpp	2009-06-19 21:58:48 UTC (rev 31125)
+++ haiku/trunk/src/apps/debugger/arch/x86/StackFrameX86.cpp	2009-06-19 22:13:32 UTC (rev 31126)
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2009, Ingo Weinhold, ingo_weinhold at gmx.de.
+ * Distributed under the terms of the MIT License.
+ */
+
+#include "StackFrameX86.h"
+
+#include "CpuStateX86.h"
+
+
+StackFrameX86::StackFrameX86(stack_frame_type type, CpuStateX86* cpuState)
+	:
+	fType(type),
+	fCpuState(cpuState),
+	fPreviousFrameAddress(0),
+	fReturnAddress(0)
+{
+	fCpuState->AddReference();
+}
+
+
+StackFrameX86::~StackFrameX86()
+{
+	fCpuState->RemoveReference();
+}
+
+
+void
+StackFrameX86::SetPreviousAddresses(target_addr_t previousFrameAddress,
+	target_addr_t returnAddress)
+{
+	fPreviousFrameAddress = previousFrameAddress;
+	fReturnAddress = returnAddress;
+}
+
+
+stack_frame_type
+StackFrameX86::Type() const
+{
+	return fType;
+}
+
+
+CpuState*
+StackFrameX86::GetCpuState() const
+{
+	return fCpuState;
+}
+
+
+target_addr_t
+StackFrameX86::InstructionPointer() const
+{
+	return fCpuState->IntRegisterValue(X86_REGISTER_EIP);
+}
+
+
+target_addr_t
+StackFrameX86::FrameAddress() const
+{
+	return fCpuState->IntRegisterValue(X86_REGISTER_EBP);
+}
+
+
+target_addr_t
+StackFrameX86::ReturnAddress() const
+{
+	return fReturnAddress;
+}
+
+
+target_addr_t
+StackFrameX86::PreviousFrameAddress() const
+{
+	return fPreviousFrameAddress;
+}

Added: haiku/trunk/src/apps/debugger/arch/x86/StackFrameX86.h
===================================================================
--- haiku/trunk/src/apps/debugger/arch/x86/StackFrameX86.h	2009-06-19 21:58:48 UTC (rev 31125)
+++ haiku/trunk/src/apps/debugger/arch/x86/StackFrameX86.h	2009-06-19 22:13:32 UTC (rev 31126)
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2009, Ingo Weinhold, ingo_weinhold at gmx.de.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef STACK_FRAME_X86_H
+#define STACK_FRAME_X86_H
+
+#include "StackFrame.h"
+
+
+class CpuStateX86;
+
+
+class StackFrameX86 : public StackFrame {
+public:
+								StackFrameX86(stack_frame_type type,
+									CpuStateX86* cpuState);
+	virtual						~StackFrameX86();
+
+			void				SetPreviousAddresses(
+									target_addr_t previousFrameAddress,
+									target_addr_t returnAddress);
+
+	virtual	stack_frame_type	Type() const;
+
+	virtual	CpuState*			GetCpuState() const;
+
+	virtual	target_addr_t		InstructionPointer() const;
+	virtual	target_addr_t		FrameAddress() const;
+	virtual	target_addr_t		ReturnAddress() const;
+	virtual	target_addr_t		PreviousFrameAddress() const;
+
+private:
+			stack_frame_type	fType;
+			CpuStateX86*		fCpuState;
+			target_addr_t		fPreviousFrameAddress;
+			target_addr_t		fReturnAddress;
+};
+
+
+#endif	// STACK_FRAME_X86_H

Added: haiku/trunk/src/apps/debugger/gui/team_window/StackTraceView.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/gui/team_window/StackTraceView.cpp	2009-06-19 21:58:48 UTC (rev 31125)
+++ haiku/trunk/src/apps/debugger/gui/team_window/StackTraceView.cpp	2009-06-19 22:13:32 UTC (rev 31126)
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2009, Ingo Weinhold, ingo_weinhold at gmx.de.
+ * Distributed under the terms of the MIT License.
+ */
+
+#include "StackTraceView.h"
+
+#include <stdio.h>
+
+#include <new>
+
+#include "table/TableColumns.h"
+
+#include "StackTrace.h"
+
+
+// #pragma mark - TargetAddressValueColumn
+
+
+class TargetAddressValueColumn : public StringTableColumn {
+public:
+	TargetAddressValueColumn(int32 modelIndex, const char* title, float width,
+		float minWidth, float maxWidth, uint32 truncate = B_TRUNCATE_MIDDLE,
+		alignment align = B_ALIGN_RIGHT)
+		:
+		StringTableColumn(modelIndex, title, width, minWidth, maxWidth,
+			truncate, align)
+	{
+	}
+
+protected:
+	virtual BField* PrepareField(const Variant& value) const
+	{
+		char buffer[64];
+		snprintf(buffer, sizeof(buffer), "%#llx", value.ToUInt64());
+
+		return StringTableColumn::PrepareField(
+			Variant(buffer, VARIANT_DONT_COPY_DATA));
+	}
+
+	virtual int CompareValues(const Variant& a, const Variant& b)
+	{
+		uint64 valueA = a.ToUInt64();
+		uint64 valueB = b.ToUInt64();
+		return valueA < valueB ? -1 : (valueA == valueB ? 0 : 1);
+	}
+};
+
+
+// #pragma mark - FramesTableModel
+
+
+class StackTraceView::FramesTableModel : public TableModel {
+public:
+	FramesTableModel()
+		:
+		fStackTrace(NULL)
+	{
+	}
+
+	~FramesTableModel()
+	{
+		SetStackTrace(NULL);
+	}
+
+	void SetStackTrace(StackTrace* stackTrace)
+	{
+		// unset old frames
+		if (fFrames.CountItems() > 0) {
+			NotifyRowsRemoved(0, fFrames.CountItems());
+
+			for (int32 i = 0; StackFrame* frame = fFrames.ItemAt(i); i++)
+				frame->RemoveReference();
+
+			fFrames.MakeEmpty();
+		}
+
+		fStackTrace = stackTrace;
+
+		// set new frames
+		if (fStackTrace != NULL) {
+			for (StackFrameList::ConstIterator it
+						= fStackTrace->Frames().GetIterator();
+					StackFrame* frame = it.Next();) {
+				if (!fFrames.AddItem(frame))
+					return;
+				frame->AddReference();
+			}
+
+			if (fFrames.CountItems() > 0)
+				NotifyRowsAdded(0, fFrames.CountItems());
+		}
+	}
+
+	virtual int32 CountColumns() const
+	{
+		return 3;
+	}
+
+	virtual int32 CountRows() const
+	{
+		return fFrames.CountItems();
+	}
+
+	virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, Variant& value)
+	{
+		StackFrame* frame = fFrames.ItemAt(rowIndex);
+		if (frame == NULL)
+			return false;
+
+		switch (columnIndex) {
+			case 0:
+				value.SetTo(frame->FrameAddress());
+				return true;
+			case 1:
+				value.SetTo(frame->InstructionPointer());
+				return true;
+			case 2:
+				// TODO: function name...
+				return false;
+			default:
+				return false;
+		}
+	}
+
+private:
+	StackTrace*				fStackTrace;
+	BObjectList<StackFrame>	fFrames;
+};
+
+
+// #pragma mark - StackTraceView
+
+
+StackTraceView::StackTraceView()
+	:
+	BGroupView(B_VERTICAL),
+	fFramesTable(NULL),
+	fFramesTableModel(NULL)
+{
+	SetName("Stack Trace");
+}
+
+
+StackTraceView::~StackTraceView()
+{
+	SetStackTrace(NULL);
+	fFramesTable->SetTableModel(NULL);
+	delete fFramesTableModel;
+}
+
+
+/*static*/ StackTraceView*
+StackTraceView::Create()
+{
+	StackTraceView* self = new StackTraceView();
+
+	try {
+		self->_Init();
+	} catch (...) {
+		delete self;
+		throw;
+	}
+
+	return self;
+}
+
+
+void
+StackTraceView::SetStackTrace(StackTrace* stackTrace)
+{
+	if (stackTrace == fStackTrace)
+		return;
+
+	if (fStackTrace != NULL)
+		fStackTrace->RemoveReference();
+
+	fStackTrace = stackTrace;
+
+	if (fStackTrace != NULL)
+		fStackTrace->AddReference();
+
+	fFramesTableModel->SetStackTrace(fStackTrace);
+}
+
+
+void
+StackTraceView::TableRowInvoked(Table* table, int32 rowIndex)
+{
+}
+
+
+void
+StackTraceView::_Init()
+{
+	fFramesTable = new Table("register list", 0);
+	AddChild(fFramesTable->ToView());
+	fFramesTable->SetSortingEnabled(false);
+
+	// columns
+	fFramesTable->AddColumn(new TargetAddressValueColumn(0, "Frame", 80, 40,
+		1000, B_TRUNCATE_END, B_ALIGN_RIGHT));
+	fFramesTable->AddColumn(new TargetAddressValueColumn(1, "IP", 80, 40, 1000,
+		B_TRUNCATE_END, B_ALIGN_RIGHT));
+	fFramesTable->AddColumn(new StringTableColumn(2, "Function", 80, 40, 1000,
+		B_TRUNCATE_END, B_ALIGN_LEFT));
+
+	fFramesTableModel = new FramesTableModel();
+	fFramesTable->SetTableModel(fFramesTableModel);
+
+	fFramesTable->AddTableListener(this);
+}

Added: haiku/trunk/src/apps/debugger/gui/team_window/StackTraceView.h
===================================================================
--- haiku/trunk/src/apps/debugger/gui/team_window/StackTraceView.h	2009-06-19 21:58:48 UTC (rev 31125)
+++ haiku/trunk/src/apps/debugger/gui/team_window/StackTraceView.h	2009-06-19 22:13:32 UTC (rev 31126)
@@ -0,0 +1,40 @@
+/*

[... truncated: 165 lines follow ...]



More information about the Haiku-commits mailing list