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
21LoadSourceCodeJob::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
39LoadSourceCodeJob::~LoadSourceCodeJob()
40{
41	fFunctionInstance->ReleaseReference();
42}
43
44
45const JobKey&
46LoadSourceCodeJob::Key() const
47{
48	return fKey;
49}
50
51
52status_t
53LoadSourceCodeJob::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