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.
8 #include "DwarfStackFrameDebugInfo.h"
12 #include "Architecture.h"
13 #include "CompilationUnit.h"
15 #include "DebugInfoEntries.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"
27 #include "RegisterMap.h"
28 #include "ReturnValueID.h"
29 #include "StringUtils.h"
31 #include "ValueLocation.h"
35 // #pragma mark - DwarfFunctionParameterID
38 struct DwarfStackFrameDebugInfo::DwarfFunctionParameterID
39 : public FunctionParameterID
{
41 DwarfFunctionParameterID(FunctionID
* functionID
, const BString
& name
)
43 fFunctionID(functionID
),
46 fFunctionID
->AcquireReference();
49 virtual ~DwarfFunctionParameterID()
51 fFunctionID
->ReleaseReference();
54 virtual bool operator==(const ObjectID
& other
) const
56 const DwarfFunctionParameterID
* parameterID
57 = dynamic_cast<const DwarfFunctionParameterID
*>(&other
);
58 return parameterID
!= NULL
&& *fFunctionID
== *parameterID
->fFunctionID
59 && fName
== parameterID
->fName
;
63 virtual uint32
ComputeHashValue() const
65 uint32 hash
= fFunctionID
->HashValue();
66 return hash
* 19 + StringUtils::HashValue(fName
);
70 FunctionID
* fFunctionID
;
75 // #pragma mark - DwarfLocalVariableID
78 struct DwarfStackFrameDebugInfo::DwarfLocalVariableID
: public LocalVariableID
{
80 DwarfLocalVariableID(FunctionID
* functionID
, const BString
& name
,
81 int32 line
, int32 column
)
83 fFunctionID(functionID
),
88 fFunctionID
->AcquireReference();
91 virtual ~DwarfLocalVariableID()
93 fFunctionID
->ReleaseReference();
96 virtual bool operator==(const ObjectID
& other
) const
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
;
106 virtual uint32
ComputeHashValue() const
108 uint32 hash
= fFunctionID
->HashValue();
109 hash
= hash
* 19 + StringUtils::HashValue(fName
);
110 hash
= hash
* 19 + fLine
;
111 hash
= hash
* 19 + fColumn
;
116 FunctionID
* fFunctionID
;
123 // #pragma mark - DwarfReturnValueID
126 struct DwarfStackFrameDebugInfo::DwarfReturnValueID
127 : public ReturnValueID
{
129 DwarfReturnValueID(FunctionID
* functionID
)
131 fFunctionID(functionID
),
134 fFunctionID
->AcquireReference();
137 virtual ~DwarfReturnValueID()
139 fFunctionID
->ReleaseReference();
142 virtual bool operator==(const ObjectID
& other
) const
144 const DwarfReturnValueID
* returnValueID
145 = dynamic_cast<const DwarfReturnValueID
*>(&other
);
146 return returnValueID
!= NULL
147 && *fFunctionID
== *returnValueID
->fFunctionID
148 && fName
== returnValueID
->fName
;
152 virtual uint32
ComputeHashValue() const
154 uint32 hash
= fFunctionID
->HashValue();
155 return hash
* 25 + StringUtils::HashValue(fName
);
159 FunctionID
* fFunctionID
;
164 // #pragma mark - DwarfStackFrameDebugInfo
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
)
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
)
181 fTypeCache
->AcquireReference();
185 DwarfStackFrameDebugInfo::~DwarfStackFrameDebugInfo()
187 fTypeCache
->ReleaseReference();
189 if (fTypeContext
!= NULL
)
190 fTypeContext
->ReleaseReference();
197 DwarfStackFrameDebugInfo::Init()
199 if (fTypeContext
== NULL
)
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
)
210 BReference
<DwarfTypeContext
> typeContextReference(typeContext
, true);
212 // create the type factory
213 fTypeFactory
= new(std::nothrow
) DwarfTypeFactory(typeContext
, fTypeLookup
,
215 if (fTypeFactory
== NULL
)
223 DwarfStackFrameDebugInfo::CreateParameter(FunctionID
* functionID
,
224 DIEFormalParameter
* parameterEntry
, Variable
*& _parameter
)
228 DwarfUtils::GetDIEName(parameterEntry
, name
);
230 TRACE_LOCALS("DwarfStackFrameDebugInfo::CreateParameter(DIE: %p): name: "
231 "\"%s\"\n", parameterEntry
, name
.String());
234 DwarfFunctionParameterID
* id
= new(std::nothrow
) DwarfFunctionParameterID(
238 BReference
<DwarfFunctionParameterID
> idReference(id
, true);
240 // create the variable
241 return _CreateVariable(id
, name
, _GetDIEType(parameterEntry
),
242 parameterEntry
->GetLocationDescription(), _parameter
);
247 DwarfStackFrameDebugInfo::CreateLocalVariable(FunctionID
* functionID
,
248 DIEVariable
* variableEntry
, Variable
*& _variable
)
252 DwarfUtils::GetDIEName(variableEntry
, name
);
254 TRACE_LOCALS("DwarfStackFrameDebugInfo::CreateLocalVariable(DIE: %p): "
255 "name: \"%s\"\n", variableEntry
, name
.String());
257 // get the declaration location
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).
269 DwarfLocalVariableID
* id
= new(std::nothrow
) DwarfLocalVariableID(
270 functionID
, name
, line
, column
);
273 BReference
<DwarfLocalVariableID
> idReference(id
, true);
275 // create the variable
276 return _CreateVariable(id
, name
, _GetDIEType(variableEntry
),
277 variableEntry
->GetLocationDescription(), _variable
);
282 DwarfStackFrameDebugInfo::CreateReturnValue(FunctionID
* functionID
,
283 DIEType
* returnType
, ValueLocation
* location
, CpuState
* state
,
284 Variable
*& _variable
)
286 if (returnType
== NULL
)
291 status_t error
= fTypeFactory
->CreateType(returnType
, type
);
294 BReference
<DwarfType
> typeReference(type
, true);
296 DwarfReturnValueID
* id
= new(std::nothrow
) DwarfReturnValueID(
302 name
.SetToFormat("%s returned", functionID
->FunctionName().String());
304 Variable
* variable
= new(std::nothrow
) Variable(id
, name
,
305 type
, location
, state
);
306 if (variable
== NULL
)
309 _variable
= variable
;
316 DwarfStackFrameDebugInfo::_CreateVariable(ObjectID
* id
, const BString
& name
,
317 DIEType
* typeEntry
, LocationDescription
* locationDescription
,
318 Variable
*& _variable
)
320 if (typeEntry
== NULL
)
325 status_t error
= fTypeFactory
->CreateType(typeEntry
, type
);
328 BReference
<DwarfType
> typeReference(type
, true);
330 // get the location, if possible
331 ValueLocation
* location
= new(std::nothrow
) ValueLocation(
332 fTypeContext
->GetArchitecture()->IsBigEndian());
333 if (location
== NULL
)
335 BReference
<ValueLocation
> locationReference(location
, true);
337 if (locationDescription
->IsValid()) {
338 status_t error
= type
->ResolveLocation(fTypeContext
,
339 locationDescription
, 0, false, *location
);
343 TRACE_LOCALS_ONLY(location
->Dump());
346 // create the variable
347 Variable
* variable
= new(std::nothrow
) Variable(id
, name
, type
, location
);
348 if (variable
== NULL
)
351 _variable
= variable
;
356 template<typename EntryType
>
358 DwarfStackFrameDebugInfo::_GetDIEType(EntryType
* entry
)
360 if (DIEType
* typeEntry
= entry
->GetType())
363 if (EntryType
* abstractOrigin
= dynamic_cast<EntryType
*>(
364 entry
->AbstractOrigin())) {
365 entry
= abstractOrigin
;
366 if (DIEType
* typeEntry
= entry
->GetType())
370 if (EntryType
* specification
= dynamic_cast<EntryType
*>(
371 entry
->Specification())) {
372 entry
= specification
;
373 if (DIEType
* typeEntry
= entry
->GetType())