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
DwarfFunctionParameterIDDwarfStackFrameDebugInfo::DwarfFunctionParameterID40 DwarfFunctionParameterID(FunctionID* functionID, const BString& name)
41 :
42 fFunctionID(functionID),
43 fName(name)
44 {
45 fFunctionID->AcquireReference();
46 }
47
~DwarfFunctionParameterIDDwarfStackFrameDebugInfo::DwarfFunctionParameterID48 virtual ~DwarfFunctionParameterID()
49 {
50 fFunctionID->ReleaseReference();
51 }
52
operator ==DwarfStackFrameDebugInfo::DwarfFunctionParameterID53 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:
ComputeHashValueDwarfStackFrameDebugInfo::DwarfFunctionParameterID62 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
DwarfLocalVariableIDDwarfStackFrameDebugInfo::DwarfLocalVariableID79 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
~DwarfLocalVariableIDDwarfStackFrameDebugInfo::DwarfLocalVariableID90 virtual ~DwarfLocalVariableID()
91 {
92 fFunctionID->ReleaseReference();
93 }
94
operator ==DwarfStackFrameDebugInfo::DwarfLocalVariableID95 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:
ComputeHashValueDwarfStackFrameDebugInfo::DwarfLocalVariableID105 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
DwarfReturnValueIDDwarfStackFrameDebugInfo::DwarfReturnValueID128 DwarfReturnValueID(FunctionID* functionID)
129 :
130 fFunctionID(functionID),
131 fName("(returned)")
132 {
133 fFunctionID->AcquireReference();
134 }
135
~DwarfReturnValueIDDwarfStackFrameDebugInfo::DwarfReturnValueID136 virtual ~DwarfReturnValueID()
137 {
138 fFunctionID->ReleaseReference();
139 }
140
operator ==DwarfStackFrameDebugInfo::DwarfReturnValueID141 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:
ComputeHashValueDwarfStackFrameDebugInfo::DwarfReturnValueID151 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
DwarfStackFrameDebugInfo(Architecture * architecture,image_id imageID,DwarfFile * file,CompilationUnit * compilationUnit,DIESubprogram * subprogramEntry,GlobalTypeLookup * typeLookup,GlobalTypeCache * typeCache,target_addr_t instructionPointer,target_addr_t framePointer,target_addr_t relocationDelta,DwarfTargetInterface * targetInterface,RegisterMap * fromDwarfRegisterMap)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
~DwarfStackFrameDebugInfo()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
Init()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
CreateParameter(FunctionID * functionID,DIEFormalParameter * parameterEntry,Variable * & _parameter)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
CreateLocalVariable(FunctionID * functionID,DIEVariable * variableEntry,Variable * & _variable)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
CreateReturnValue(FunctionID * functionID,DIEType * returnType,ValueLocation * location,CpuState * state,Variable * & _variable)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
_CreateVariable(ObjectID * id,const BString & name,DIEType * typeEntry,LocationDescription * locationDescription,Variable * & _variable)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*
_GetDIEType(EntryType * entry)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