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