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.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31126 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-06-19 22:13:32 +00:00
parent 1ae2cffc83
commit 15f040e596
19 changed files with 727 additions and 37 deletions
+111 -18
View File
@@ -19,7 +19,6 @@
#include "DebuggerInterface.h"
#include "Jobs.h"
#include "MessageCodes.h"
#include "Team.h"
#include "TeamDebugModel.h"
@@ -81,6 +80,8 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
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 @@ TeamDebugger::MessageReceived(BMessage* message)
_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 @@ printf("TeamDebugger::JobAborted(%p)\n", job);
}
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 @@ void
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 @@ printf("MSG_THREAD_STEP_OUT\n");
// 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");
}