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