2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2011-2013, Rene Gollent, rene@gollent.com.
4 * Distributed under the terms of the MIT License.
7 #include "DwarfUtils.h"
11 #include "CompilationUnit.h"
13 #include "DwarfFile.h"
17 DwarfUtils::GetDIEName(const DebugInfoEntry
* entry
, BString
& _name
)
19 // If we don't seem to have a name but an abstract origin, return the
21 const char* name
= entry
->Name();
23 if (DebugInfoEntry
* abstractOrigin
= entry
->AbstractOrigin()) {
24 entry
= abstractOrigin
;
29 // If we still don't have a name but a specification, return the
30 // specification's name.
32 if (DebugInfoEntry
* specification
= entry
->Specification()) {
33 entry
= specification
;
43 DwarfUtils::GetDIETypeName(const DebugInfoEntry
* entry
, BString
& _name
)
45 const DIEType
* type
= dynamic_cast<const DIEType
*>(entry
);
49 const DIEModifiedType
* modifiedType
= dynamic_cast<const DIEModifiedType
*>(
54 if (modifiedType
!= NULL
) {
55 const DIEType
* baseType
= type
;
56 while ((modifiedType
= dynamic_cast<const DIEModifiedType
*>(
58 switch (modifiedType
->Tag()) {
59 case DW_TAG_pointer_type
:
60 modifier
.Prepend("*");
62 case DW_TAG_reference_type
:
63 modifier
.Prepend("&");
65 case DW_TAG_const_type
:
66 modifier
.Prepend(" const ");
72 baseType
= modifiedType
->GetType();
77 // if the parameter has no type associated,
78 // then it's the unspecified type.
82 GetFullyQualifiedDIEName(type
, typeName
);
84 if (modifier
.Length() > 0) {
85 if (modifier
[modifier
.Length() - 1] == ' ')
86 modifier
.Truncate(modifier
.Length() - 1);
88 // if the modifier has a leading const, treat it
89 // as the degenerate case and prepend it to the
90 // type name since that's the more typically used
91 // representation in source
92 if (modifier
[0] == ' ') {
93 typeName
.Prepend("const ");
94 modifier
.Remove(0, 7);
104 DwarfUtils::GetFullDIEName(const DebugInfoEntry
* entry
, BString
& _name
)
106 BString generatedName
;
107 // If we don't seem to have a name but an abstract origin, return the
109 const char* name
= entry
->Name();
111 if (DebugInfoEntry
* abstractOrigin
= entry
->AbstractOrigin()) {
112 entry
= abstractOrigin
;
113 name
= entry
->Name();
117 // If we still don't have a name but a specification, return the
118 // specification's name.
120 if (DebugInfoEntry
* specification
= entry
->Specification()) {
121 entry
= specification
;
122 name
= entry
->Name();
127 if (dynamic_cast<const DIEModifiedType
*>(entry
) != NULL
)
128 GetDIETypeName(entry
, _name
);
130 // we found no name for this entry whatsoever, abort.
134 generatedName
= name
;
136 const DIESubprogram
* subProgram
= dynamic_cast<const DIESubprogram
*>(
138 if (subProgram
!= NULL
) {
139 generatedName
+= "(";
141 DebugInfoEntryList::ConstIterator iterator
142 = subProgram
->Parameters().GetIterator();
144 bool firstParameter
= true;
145 while (iterator
.HasNext()) {
146 DebugInfoEntry
* parameterEntry
= iterator
.Next();
147 if (dynamic_cast<DIEUnspecifiedParameters
*>(parameterEntry
)
149 parameters
+= ", ...";
153 const DIEFormalParameter
* parameter
154 = dynamic_cast<DIEFormalParameter
*>(parameterEntry
);
155 if (parameter
== NULL
) {
156 // this shouldn't happen
160 if (parameter
->IsArtificial())
165 DIEType
* type
= parameter
->GetType();
166 GetDIETypeName(type
, paramName
);
169 firstParameter
= false;
173 parameters
+= paramName
;
176 if (parameters
.Length() > 0)
177 generatedName
+= parameters
;
179 generatedName
+= "void";
180 generatedName
+= ")";
182 _name
= generatedName
;
187 DwarfUtils::GetFullyQualifiedDIEName(const DebugInfoEntry
* entry
,
190 // If we don't seem to have a name but an abstract origin, return the
192 if (entry
->Name() == NULL
) {
193 if (DebugInfoEntry
* abstractOrigin
= entry
->AbstractOrigin())
194 entry
= abstractOrigin
;
197 // If we don't still don't have a name but a specification, get the
198 // specification's name.
199 if (entry
->Name() == NULL
) {
200 if (DebugInfoEntry
* specification
= entry
->Specification())
201 entry
= specification
;
205 BString generatedName
;
207 // Get the namespace, if any.
208 DebugInfoEntry
* parent
= entry
->Parent();
209 while (parent
!= NULL
) {
210 if (parent
->IsNamespace()) {
212 GetFullyQualifiedDIEName(parent
, parentName
);
213 if (parentName
.Length() > 0) {
215 generatedName
.Prepend(parentName
);
220 parent
= parent
->Parent();
224 GetFullDIEName(entry
, name
);
225 if (name
.Length() == 0)
228 generatedName
+= name
;
230 _name
= generatedName
;
235 DwarfUtils::GetDeclarationLocation(DwarfFile
* dwarfFile
,
236 const DebugInfoEntry
* entry
, const char*& _directory
, const char*& _file
,
237 int32
& _line
, int32
& _column
)
242 bool fileSet
= entry
->GetDeclarationFile(file
);
243 bool lineSet
= entry
->GetDeclarationLine(line
);
244 bool columnSet
= entry
->GetDeclarationColumn(column
);
246 // if something is not set yet, try the abstract origin (if any)
247 if (!fileSet
|| !lineSet
|| !columnSet
) {
248 if (DebugInfoEntry
* abstractOrigin
= entry
->AbstractOrigin()) {
249 entry
= abstractOrigin
;
251 fileSet
= entry
->GetDeclarationFile(file
);
253 lineSet
= entry
->GetDeclarationLine(line
);
255 columnSet
= entry
->GetDeclarationColumn(column
);
259 // something is not set yet, try the specification (if any)
260 if (!fileSet
|| !lineSet
|| !columnSet
) {
261 if (DebugInfoEntry
* specification
= entry
->Specification()) {
262 entry
= specification
;
264 fileSet
= entry
->GetDeclarationFile(file
);
266 lineSet
= entry
->GetDeclarationLine(line
);
268 columnSet
= entry
->GetDeclarationColumn(column
);
275 // get the compilation unit
276 CompilationUnit
* unit
= dwarfFile
->CompilationUnitForDIE(entry
);
280 const char* directoryName
;
281 const char* fileName
= unit
->FileAt(file
- 1, &directoryName
);
282 if (fileName
== NULL
)
285 _directory
= directoryName
;
287 _line
= (int32
)line
- 1;
288 _column
= (int32
)column
- 1;