xref: /haiku/src/kits/debugger/jobs/LoadImageDebugInfoJob.cpp (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
1 /*
2  * Copyright 2012-2014, 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 "Image.h"
12 #include "ImageDebugInfo.h"
13 #include "TeamDebugInfo.h"
14 #include "Team.h"
15 
16 
17 // #pragma mark - LoadImageDebugInfoJob
18 
19 
20 LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image)
21 	:
22 	fKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO),
23 	fImage(image),
24 	fState()
25 {
26 	fImage->AcquireReference();
27 
28 	SetDescription("Loading debugging information for %s",
29 		fImage->Name().String());
30 }
31 
32 
33 LoadImageDebugInfoJob::~LoadImageDebugInfoJob()
34 {
35 	fImage->ReleaseReference();
36 }
37 
38 
39 const JobKey&
40 LoadImageDebugInfoJob::Key() const
41 {
42 	return fKey;
43 }
44 
45 
46 status_t
47 LoadImageDebugInfoJob::Do()
48 {
49 	// get an image info for the image
50 	AutoLocker<Team> locker(fImage->GetTeam());
51 	ImageInfo imageInfo(fImage->Info());
52 	locker.Unlock();
53 
54 	// create the debug info
55 	ImageDebugInfo* debugInfo;
56 	status_t error = fImage->GetTeam()->DebugInfo()->LoadImageDebugInfo(
57 		imageInfo, fImage->ImageFile(), fState, debugInfo);
58 
59 	// set the result
60 	locker.Lock();
61 
62 	if (fState.UserInputRequired()) {
63 		return WaitForUserInput();
64 	} else if (error == B_OK) {
65 		error = fImage->SetImageDebugInfo(debugInfo, IMAGE_DEBUG_INFO_LOADED);
66 		debugInfo->ReleaseReference();
67 	} else
68 		fImage->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE);
69 
70 	return error;
71 }
72 
73 
74 /*static*/ status_t
75 LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image,
76 	JobListener* listener, ImageDebugInfo** _imageDebugInfo)
77 {
78 	AutoLocker<Team> teamLocker(image->GetTeam());
79 
80 	// If already loaded, we're done.
81 	if (image->GetImageDebugInfo() != NULL) {
82 		if (_imageDebugInfo != NULL) {
83 			*_imageDebugInfo = image->GetImageDebugInfo();
84 			(*_imageDebugInfo)->AcquireReference();
85 		}
86 		return B_OK;
87 	}
88 
89 	// If already loading, the caller has to wait, if desired.
90 	if (image->ImageDebugInfoState() == IMAGE_DEBUG_INFO_LOADING) {
91 		if (_imageDebugInfo != NULL)
92 			*_imageDebugInfo = NULL;
93 		return B_OK;
94 	}
95 
96 	// If an earlier load attempt failed, bail out.
97 	if (image->ImageDebugInfoState() != IMAGE_DEBUG_INFO_NOT_LOADED)
98 		return B_ERROR;
99 
100 	// schedule a job
101 	LoadImageDebugInfoJob* job = new(std::nothrow) LoadImageDebugInfoJob(
102 		image);
103 	if (job == NULL)
104 		return B_NO_MEMORY;
105 
106 	status_t error = worker->ScheduleJob(job, listener);
107 	if (error != B_OK) {
108 		image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE);
109 		return error;
110 	}
111 
112 	image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_LOADING);
113 
114 	if (_imageDebugInfo != NULL)
115 		*_imageDebugInfo = NULL;
116 	return B_OK;
117 }
118