xref: /haiku/src/kits/debugger/debug_info/DwarfStackFrameDebugInfo.cpp (revision 9a6a20d4689307142a7ed26a1437ba47e244e73f)
1 /*
2  * Copyright 2012, 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 
8 #include "DwarfStackFrameDebugInfo.h"
9 
10 #include <new>
11 
12 #include "Architecture.h"
13 #include "CompilationUnit.h"
14 #include "CpuState.h"
15 #include "DebugInfoEntries.h"
16 #include "Dwarf.h"
17 #include "DwarfFile.h"
18 #include "DwarfTargetInterface.h"
19 #include "DwarfTypeFactory.h"
20 #include "DwarfUtils.h"
21 #include "DwarfTypes.h"
22 #include "FunctionID.h"
23 #include "FunctionParameterID.h"
24 #include "GlobalTypeLookup.h"
25 #include "LocalVariableID.h"
26 #include "Register.h"
27 #include "RegisterMap.h"
28 #include "ReturnValueID.h"
29 #include "Tracing.h"
30 #include "ValueLocation.h"
31 #include "Variable.h"
32 
33 
34 // #pragma mark - DwarfFunctionParameterID
35 
36 
37 struct DwarfStackFrameDebugInfo::DwarfFunctionParameterID
38 	: public FunctionParameterID {
39 
40 	DwarfFunctionParameterID(FunctionID* functionID, const BString& name)
41 		:
42 		fFunctionID(functionID),
43 		fName(name)
44 	{
45 		fFunctionID->AcquireReference();
46 	}
47 
48 	virtual ~DwarfFunctionParameterID()
49 	{
50 		fFunctionID->ReleaseReference();
51 	}
52 
53 	virtual bool operator==(const ObjectID& other) const
54 	{
55 		const DwarfFunctionParameterID* parameterID
56 			= dynamic_cast<const DwarfFunctionParameterID*>(&other);
57 		return parameterID != NULL && *fFunctionID == *parameterID->fFunctionID
58 			&& fName == parameterID->fName;
59 	}
60 
61 protected:
62 	virtual uint32 ComputeHashValue() const
63 	{
64 		uint32 hash = fFunctionID->HashValue();
65 		return hash * 19 + fName.HashValue();
66 	}
67 
68 private:
69 	FunctionID*		fFunctionID;
70 	const BString	fName;
71 };
72 
73 
74 // #pragma mark - DwarfLocalVariableID
75 
76 
77 struct DwarfStackFrameDebugInfo::DwarfLocalVariableID : public LocalVariableID {
78 
79 	DwarfLocalVariableID(FunctionID* functionID, const BString& name,
80 		int32 line, int32 column)
81 		:
82 		fFunctionID(functionID),
83 		fName(name),
84 		fLine(line),
85 		fColumn(column)
86 	{
87 		fFunctionID->AcquireReference();
88 	}
89 
90 	virtual ~DwarfLocalVariableID()
91 	{
92 		fFunctionID->ReleaseReference();
93 	}
94 
95 	virtual bool operator==(const ObjectID& other) const
96 	{
97 		const DwarfLocalVariableID* otherID
98 			= dynamic_cast<const DwarfLocalVariableID*>(&other);
99 		return otherID != NULL && *fFunctionID == *otherID->fFunctionID
100 			&& fName == otherID->fName && fLine == otherID->fLine
101 			&& fColumn == otherID->fColumn;
102 	}
103 
104 protected:
105 	virtual uint32 ComputeHashValue() const
106 	{
107 		uint32 hash = fFunctionID->HashValue();
108 		hash = hash * 19 + fName.HashValue();
109 		hash = hash * 19 + fLine;
110 		hash = hash * 19 + fColumn;
111 		return hash;
112 	}
113 
114 private:
115 	FunctionID*		fFunctionID;
116 	const BString	fName;
117 	int32			fLine;
118 	int32			fColumn;
119 };
120 
121 
122 // #pragma mark - DwarfReturnValueID
123 
124 
125 struct DwarfStackFrameDebugInfo::DwarfReturnValueID
126 	: public ReturnValueID {
127 
128 	DwarfReturnValueID(FunctionID* functionID)
129 		:
130 		fFunctionID(functionID),
131 		fName("(returned)")
132 	{
133 		fFunctionID->AcquireReference();
134 	}
135 
136 	virtual ~DwarfReturnValueID()
137 	{
138 		fFunctionID->ReleaseReference();
139 	}
140 
141 	virtual bool operator==(const ObjectID& other) const
142 	{
143 		const DwarfReturnValueID* returnValueID
144 			= dynamic_cast<const DwarfReturnValueID*>(&other);
145 		return returnValueID != NULL
146 			&& *fFunctionID == *returnValueID->fFunctionID
147 			&& fName == returnValueID->fName;
148 	}
149 
150 protected:
151 	virtual uint32 ComputeHashValue() const
152 	{
153 		uint32 hash = fFunctionID->HashValue();
154 		return hash * 25 + fName.HashValue();
155 	}
156 
157 private:
158 	FunctionID*		fFunctionID;
159 	const BString	fName;
160 };
161 
162 
163 // #pragma mark - DwarfStackFrameDebugInfo
164 
165 
166 DwarfStackFrameDebugInfo::DwarfStackFrameDebugInfo(Architecture* architecture,
167 	image_id imageID, DwarfFile* file, CompilationUnit* compilationUnit,
168 	DIESubprogram* subprogramEntry, GlobalTypeLookup* typeLookup,
169 	GlobalTypeCache* typeCache, target_addr_t instructionPointer,
170 	target_addr_t framePointer, target_addr_t relocationDelta,
171 	DwarfTargetInterface* targetInterface, RegisterMap* fromDwarfRegisterMap)
172 	:
173 	StackFrameDebugInfo(),
174 	fTypeContext(new(std::nothrow) DwarfTypeContext(architecture, imageID, file,
175 		compilationUnit, subprogramEntry, instructionPointer, framePointer,
176 		relocationDelta, targetInterface, fromDwarfRegisterMap)),
177 	fTypeLookup(typeLookup),
178 	fTypeCache(typeCache)
179 {
180 	fTypeCache->AcquireReference();
181 }
182 
183 
184 DwarfStackFrameDebugInfo::~DwarfStackFrameDebugInfo()
185 {
186 	fTypeCache->ReleaseReference();
187 
188 	if (fTypeContext != NULL)
189 		fTypeContext->ReleaseReference();
190 
191 	delete fTypeFactory;
192 }
193 
194 
195 status_t
196 DwarfStackFrameDebugInfo::Init()
197 {
198 	if (fTypeContext == NULL)
199 		return B_NO_MEMORY;
200 
201 	// create a type context without dependency to the stack frame
202 	DwarfTypeContext* typeContext = new(std::nothrow) DwarfTypeContext(
203 		fTypeContext->GetArchitecture(), fTypeContext->ImageID(),
204 		fTypeContext->File(), fTypeContext->GetCompilationUnit(), NULL, 0, 0,
205 		fTypeContext->RelocationDelta(), fTypeContext->TargetInterface(),
206 		fTypeContext->FromDwarfRegisterMap());
207 	if (typeContext == NULL)
208 		return B_NO_MEMORY;
209 	BReference<DwarfTypeContext> typeContextReference(typeContext, true);
210 
211 	// create the type factory
212 	fTypeFactory = new(std::nothrow) DwarfTypeFactory(typeContext, fTypeLookup,
213 		fTypeCache);
214 	if (fTypeFactory == NULL)
215 		return B_NO_MEMORY;
216 
217 	return B_OK;
218 }
219 
220 
221 status_t
222 DwarfStackFrameDebugInfo::CreateParameter(FunctionID* functionID,
223 	DIEFormalParameter* parameterEntry, Variable*& _parameter)
224 {
225 	// get the name
226 	BString name;
227 	DwarfUtils::GetDIEName(parameterEntry, name);
228 
229 	TRACE_LOCALS("DwarfStackFrameDebugInfo::CreateParameter(DIE: %p): name: "
230 		"\"%s\"\n", parameterEntry, name.String());
231 
232 	// create the ID
233 	DwarfFunctionParameterID* id = new(std::nothrow) DwarfFunctionParameterID(
234 		functionID, name);
235 	if (id == NULL)
236 		return B_NO_MEMORY;
237 	BReference<DwarfFunctionParameterID> idReference(id, true);
238 
239 	// create the variable
240 	return _CreateVariable(id, name, _GetDIEType(parameterEntry),
241 		parameterEntry->GetLocationDescription(), _parameter);
242 }
243 
244 
245 status_t
246 DwarfStackFrameDebugInfo::CreateLocalVariable(FunctionID* functionID,
247 	DIEVariable* variableEntry, Variable*& _variable)
248 {
249 	// get the name
250 	BString name;
251 	DwarfUtils::GetDIEName(variableEntry, name);
252 
253 	TRACE_LOCALS("DwarfStackFrameDebugInfo::CreateLocalVariable(DIE: %p): "
254 		"name: \"%s\"\n", variableEntry, name.String());
255 
256 	// get the declaration location
257 	int32 line = -1;
258 	int32 column = -1;
259 	const char* file;
260 	const char* directory;
261 	DwarfUtils::GetDeclarationLocation(fTypeContext->File(), variableEntry,
262 		directory, file, line, column);
263 		// TODO: If the declaration location is unavailable, we should probably
264 		// add a component to the ID to make it unique nonetheless (the name
265 		// might not suffice).
266 
267 	// create the ID
268 	DwarfLocalVariableID* id = new(std::nothrow) DwarfLocalVariableID(
269 		functionID, name, line, column);
270 	if (id == NULL)
271 		return B_NO_MEMORY;
272 	BReference<DwarfLocalVariableID> idReference(id, true);
273 
274 	// create the variable
275 	return _CreateVariable(id, name, _GetDIEType(variableEntry),
276 		variableEntry->GetLocationDescription(), _variable);
277 }
278 
279 
280 status_t
281 DwarfStackFrameDebugInfo::CreateReturnValue(FunctionID* functionID,
282 	DIEType* returnType, ValueLocation* location, CpuState* state,
283 	Variable*& _variable)
284 {
285 	if (returnType == NULL)
286 		return B_BAD_VALUE;
287 
288 	// create the type
289 	DwarfType* type;
290 	status_t error = fTypeFactory->CreateType(returnType, type);
291 	if (error != B_OK)
292 		return error;
293 	BReference<DwarfType> typeReference(type, true);
294 
295 	DwarfReturnValueID* id = new(std::nothrow) DwarfReturnValueID(
296 		functionID);
297 	if (id == NULL)
298 		return B_NO_MEMORY;
299 
300 	BString name;
301 	name.SetToFormat("%s returned", functionID->FunctionName().String());
302 
303 	Variable* variable = new(std::nothrow) Variable(id, name,
304 		type, location, state);
305 	if (variable == NULL)
306 		return B_NO_MEMORY;
307 
308 	_variable = variable;
309 
310 	return B_OK;
311 }
312 
313 
314 status_t
315 DwarfStackFrameDebugInfo::_CreateVariable(ObjectID* id, const BString& name,
316 	DIEType* typeEntry, LocationDescription* locationDescription,
317 	Variable*& _variable)
318 {
319 	if (typeEntry == NULL)
320 		return B_BAD_VALUE;
321 
322 	// create the type
323 	DwarfType* type;
324 	status_t error = fTypeFactory->CreateType(typeEntry, type);
325 	if (error != B_OK)
326 		return error;
327 	BReference<DwarfType> typeReference(type, true);
328 
329 	// get the location, if possible
330 	ValueLocation* location = new(std::nothrow) ValueLocation(
331 		fTypeContext->GetArchitecture()->IsBigEndian());
332 	if (location == NULL)
333 		return B_NO_MEMORY;
334 	BReference<ValueLocation> locationReference(location, true);
335 
336 	if (locationDescription->IsValid()) {
337 		status_t error = type->ResolveLocation(fTypeContext,
338 			locationDescription, 0, false, *location);
339 		if (error != B_OK)
340 			return error;
341 
342 		TRACE_LOCALS_ONLY(location->Dump());
343 	}
344 
345 	// create the variable
346 	Variable* variable = new(std::nothrow) Variable(id, name, type, location);
347 	if (variable == NULL)
348 		return B_NO_MEMORY;
349 
350 	_variable = variable;
351 	return B_OK;
352 }
353 
354 
355 template<typename EntryType>
356 /*static*/ DIEType*
357 DwarfStackFrameDebugInfo::_GetDIEType(EntryType* entry)
358 {
359 	if (DIEType* typeEntry = entry->GetType())
360 		return typeEntry;
361 
362 	if (EntryType* abstractOrigin = dynamic_cast<EntryType*>(
363 			entry->AbstractOrigin())) {
364 		entry = abstractOrigin;
365 		if (DIEType* typeEntry = entry->GetType())
366 			return typeEntry;
367 	}
368 
369 	if (EntryType* specification = dynamic_cast<EntryType*>(
370 			entry->Specification())) {
371 		entry = specification;
372 		if (DIEType* typeEntry = entry->GetType())
373 			return typeEntry;
374 	}
375 
376 	return NULL;
377 }
378