1*fce4895dSRene Gollent /*
2*fce4895dSRene Gollent * Copyright 2012-2016, Rene Gollent, rene@gollent.com.
3*fce4895dSRene Gollent * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
4*fce4895dSRene Gollent * Distributed under the terms of the MIT License.
5*fce4895dSRene Gollent */
6*fce4895dSRene Gollent
7*fce4895dSRene Gollent #include "Jobs.h"
8*fce4895dSRene Gollent
9*fce4895dSRene Gollent #include <AutoLocker.h>
10*fce4895dSRene Gollent
11*fce4895dSRene Gollent #include "Architecture.h"
12*fce4895dSRene Gollent #include "CpuState.h"
13*fce4895dSRene Gollent #include "DebuggerInterface.h"
14*fce4895dSRene Gollent #include "ImageDebugInfo.h"
15*fce4895dSRene Gollent #include "StackTrace.h"
16*fce4895dSRene Gollent #include "Thread.h"
17*fce4895dSRene Gollent #include "Team.h"
18*fce4895dSRene Gollent
19*fce4895dSRene Gollent
GetStackTraceJob(DebuggerInterface * debuggerInterface,JobListener * listener,Architecture * architecture,::Thread * thread)20*fce4895dSRene Gollent GetStackTraceJob::GetStackTraceJob(DebuggerInterface* debuggerInterface,
21*fce4895dSRene Gollent JobListener* listener, Architecture* architecture, ::Thread* thread)
22*fce4895dSRene Gollent :
23*fce4895dSRene Gollent fKey(thread, JOB_TYPE_GET_STACK_TRACE),
24*fce4895dSRene Gollent fDebuggerInterface(debuggerInterface),
25*fce4895dSRene Gollent fJobListener(listener),
26*fce4895dSRene Gollent fArchitecture(architecture),
27*fce4895dSRene Gollent fThread(thread)
28*fce4895dSRene Gollent {
29*fce4895dSRene Gollent fThread->AcquireReference();
30*fce4895dSRene Gollent
31*fce4895dSRene Gollent fCpuState = fThread->GetCpuState();
32*fce4895dSRene Gollent if (fCpuState != NULL)
33*fce4895dSRene Gollent fCpuState->AcquireReference();
34*fce4895dSRene Gollent
35*fce4895dSRene Gollent
36*fce4895dSRene Gollent SetDescription("Retrieving stack trace for thread %" B_PRId32, fThread->ID());
37*fce4895dSRene Gollent }
38*fce4895dSRene Gollent
39*fce4895dSRene Gollent
~GetStackTraceJob()40*fce4895dSRene Gollent GetStackTraceJob::~GetStackTraceJob()
41*fce4895dSRene Gollent {
42*fce4895dSRene Gollent if (fCpuState != NULL)
43*fce4895dSRene Gollent fCpuState->ReleaseReference();
44*fce4895dSRene Gollent
45*fce4895dSRene Gollent fThread->ReleaseReference();
46*fce4895dSRene Gollent }
47*fce4895dSRene Gollent
48*fce4895dSRene Gollent
49*fce4895dSRene Gollent const JobKey&
Key() const50*fce4895dSRene Gollent GetStackTraceJob::Key() const
51*fce4895dSRene Gollent {
52*fce4895dSRene Gollent return fKey;
53*fce4895dSRene Gollent }
54*fce4895dSRene Gollent
55*fce4895dSRene Gollent
56*fce4895dSRene Gollent status_t
Do()57*fce4895dSRene Gollent GetStackTraceJob::Do()
58*fce4895dSRene Gollent {
59*fce4895dSRene Gollent if (fCpuState == NULL)
60*fce4895dSRene Gollent return B_BAD_VALUE;
61*fce4895dSRene Gollent
62*fce4895dSRene Gollent // get the stack trace
63*fce4895dSRene Gollent StackTrace* stackTrace;
64*fce4895dSRene Gollent status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), this,
65*fce4895dSRene Gollent fCpuState, stackTrace, fThread->ReturnValueInfos());
66*fce4895dSRene Gollent if (error != B_OK)
67*fce4895dSRene Gollent return error;
68*fce4895dSRene Gollent BReference<StackTrace> stackTraceReference(stackTrace, true);
69*fce4895dSRene Gollent
70*fce4895dSRene Gollent // set the stack trace, unless something has changed
71*fce4895dSRene Gollent AutoLocker<Team> locker(fThread->GetTeam());
72*fce4895dSRene Gollent
73*fce4895dSRene Gollent if (fThread->GetCpuState() == fCpuState)
74*fce4895dSRene Gollent fThread->SetStackTrace(stackTrace);
75*fce4895dSRene Gollent
76*fce4895dSRene Gollent return B_OK;
77*fce4895dSRene Gollent }
78*fce4895dSRene Gollent
79*fce4895dSRene Gollent
80*fce4895dSRene Gollent status_t
GetImageDebugInfo(Image * image,ImageDebugInfo * & _info)81*fce4895dSRene Gollent GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info)
82*fce4895dSRene Gollent {
83*fce4895dSRene Gollent AutoLocker<Team> teamLocker(fThread->GetTeam());
84*fce4895dSRene Gollent
85*fce4895dSRene Gollent while (image->GetImageDebugInfo() == NULL) {
86*fce4895dSRene Gollent // schedule a job, if not loaded
87*fce4895dSRene Gollent ImageDebugInfo* info;
88*fce4895dSRene Gollent status_t error = LoadImageDebugInfoJob::ScheduleIfNecessary(GetWorker(),
89*fce4895dSRene Gollent image, fJobListener, &info);
90*fce4895dSRene Gollent if (error != B_OK)
91*fce4895dSRene Gollent return error;
92*fce4895dSRene Gollent
93*fce4895dSRene Gollent if (info != NULL) {
94*fce4895dSRene Gollent _info = info;
95*fce4895dSRene Gollent return B_OK;
96*fce4895dSRene Gollent }
97*fce4895dSRene Gollent
98*fce4895dSRene Gollent teamLocker.Unlock();
99*fce4895dSRene Gollent
100*fce4895dSRene Gollent // wait for the job to finish
101*fce4895dSRene Gollent switch (WaitFor(SimpleJobKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO))) {
102*fce4895dSRene Gollent case JOB_DEPENDENCY_SUCCEEDED:
103*fce4895dSRene Gollent case JOB_DEPENDENCY_NOT_FOUND:
104*fce4895dSRene Gollent // "Not found" can happen due to a race condition between
105*fce4895dSRene Gollent // unlocking the worker and starting to wait.
106*fce4895dSRene Gollent break;
107*fce4895dSRene Gollent case JOB_DEPENDENCY_FAILED:
108*fce4895dSRene Gollent case JOB_DEPENDENCY_ABORTED:
109*fce4895dSRene Gollent default:
110*fce4895dSRene Gollent return B_ERROR;
111*fce4895dSRene Gollent }
112*fce4895dSRene Gollent
113*fce4895dSRene Gollent teamLocker.Lock();
114*fce4895dSRene Gollent }
115*fce4895dSRene Gollent
116*fce4895dSRene Gollent _info = image->GetImageDebugInfo();
117*fce4895dSRene Gollent _info->AcquireReference();
118*fce4895dSRene Gollent
119*fce4895dSRene Gollent return B_OK;
120*fce4895dSRene Gollent }
121