xref: /haiku/src/kits/debugger/jobs/LoadSourceCodeJob.cpp (revision 67e0301477b06c7be20198f96580e13a024a81d4)
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 "DebuggerInterface.h"
13 #include "DisassembledCode.h"
14 #include "Function.h"
15 #include "FunctionInstance.h"
16 #include "FileSourceCode.h"
17 #include "Team.h"
18 #include "TeamDebugInfo.h"
19 
20 
LoadSourceCodeJob(DebuggerInterface * debuggerInterface,Architecture * architecture,Team * team,FunctionInstance * functionInstance,bool loadForFunction)21 LoadSourceCodeJob::LoadSourceCodeJob(
22 	DebuggerInterface* debuggerInterface, Architecture* architecture,
23 	Team* team, FunctionInstance* functionInstance, bool loadForFunction)
24 	:
25 	fKey(functionInstance, JOB_TYPE_LOAD_SOURCE_CODE),
26 	fDebuggerInterface(debuggerInterface),
27 	fArchitecture(architecture),
28 	fTeam(team),
29 	fFunctionInstance(functionInstance),
30 	fLoadForFunction(loadForFunction)
31 {
32 	fFunctionInstance->AcquireReference();
33 
34 	SetDescription("Loading source code for function %s",
35 		fFunctionInstance->PrettyName().String());
36 }
37 
38 
~LoadSourceCodeJob()39 LoadSourceCodeJob::~LoadSourceCodeJob()
40 {
41 	fFunctionInstance->ReleaseReference();
42 }
43 
44 
45 const JobKey&
Key() const46 LoadSourceCodeJob::Key() const
47 {
48 	return fKey;
49 }
50 
51 
52 status_t
Do()53 LoadSourceCodeJob::Do()
54 {
55 	// if requested, try loading the source code for the function
56 	Function* function = fFunctionInstance->GetFunction();
57 	if (fLoadForFunction) {
58 		FileSourceCode* sourceCode;
59 		status_t error = fTeam->DebugInfo()->LoadSourceCode(
60 			function->SourceFile(), sourceCode);
61 
62 		AutoLocker<Team> locker(fTeam);
63 
64 		if (error == B_OK) {
65 			function->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED);
66 			sourceCode->ReleaseReference();
67 			return B_OK;
68 		}
69 
70 		function->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
71 	}
72 
73 	// Only try to load the function instance code, if it's not overridden yet.
74 	AutoLocker<Team> locker(fTeam);
75 	if (fFunctionInstance->SourceCodeState() != FUNCTION_SOURCE_LOADING)
76 		return B_OK;
77 	locker.Unlock();
78 
79 	// disassemble the function
80 	DisassembledCode* sourceCode = NULL;
81 	status_t error = fTeam->DebugInfo()->DisassembleFunction(fFunctionInstance,
82 		sourceCode);
83 
84 	// set the result
85 	locker.Lock();
86 	if (error == B_OK) {
87 		if (fFunctionInstance->SourceCodeState() == FUNCTION_SOURCE_LOADING) {
88 			// various parts of the debugger expect functions to have only
89 			// one of source or disassembly available. As such, if the current
90 			// function had source code previously active, unset it when
91 			// explicitly asked for disassembly. This needs to be done first
92 			// since Function will clear the disassembled code states of all
93 			// its child instances.
94 			function_source_state state
95 				= fLoadForFunction ? FUNCTION_SOURCE_LOADED
96 					: FUNCTION_SOURCE_SUPPRESSED;
97 			if (function->SourceCodeState() == FUNCTION_SOURCE_LOADED) {
98 				FileSourceCode* functionSourceCode = function->GetSourceCode();
99 				function->SetSourceCode(functionSourceCode, state);
100 			}
101 
102 			fFunctionInstance->SetSourceCode(sourceCode, state);
103 			sourceCode->ReleaseReference();
104 		}
105 	} else
106 		fFunctionInstance->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
107 
108 	return error;
109 }
110