1 /*
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.
5 */
6
7 #include "DwarfUtils.h"
8
9 #include <String.h>
10
11 #include "CompilationUnit.h"
12 #include "Dwarf.h"
13 #include "DwarfFile.h"
14
15
16 /*static*/ void
GetDIEName(const DebugInfoEntry * entry,BString & _name)17 DwarfUtils::GetDIEName(const DebugInfoEntry* entry, BString& _name)
18 {
19 // If we don't seem to have a name but an abstract origin, return the
20 // origin's name.
21 const char* name = entry->Name();
22 if (name == NULL) {
23 if (DebugInfoEntry* abstractOrigin = entry->AbstractOrigin()) {
24 entry = abstractOrigin;
25 name = entry->Name();
26 }
27 }
28
29 // If we still don't have a name but a specification, return the
30 // specification's name.
31 if (name == NULL) {
32 if (DebugInfoEntry* specification = entry->Specification()) {
33 entry = specification;
34 name = entry->Name();
35 }
36 }
37
38 _name = name;
39 }
40
41
42 /*static*/ void
GetDIETypeName(const DebugInfoEntry * entry,BString & _name,const DebugInfoEntry * requestingEntry)43 DwarfUtils::GetDIETypeName(const DebugInfoEntry* entry, BString& _name,
44 const DebugInfoEntry* requestingEntry)
45 {
46 const DIEType* type = dynamic_cast<const DIEType*>(entry);
47 if (type == NULL)
48 return;
49
50 const DIEModifiedType* modifiedType = dynamic_cast<const DIEModifiedType*>(
51 type);
52 BString typeName;
53 BString modifier;
54
55 if (modifiedType != NULL) {
56 const DIEType* baseType = type;
57 while ((modifiedType = dynamic_cast<const DIEModifiedType*>(
58 baseType)) != NULL) {
59 switch (modifiedType->Tag()) {
60 case DW_TAG_pointer_type:
61 modifier.Prepend("*");
62 break;
63 case DW_TAG_reference_type:
64 modifier.Prepend("&");
65 break;
66 case DW_TAG_const_type:
67 modifier.Prepend(" const ");
68 break;
69 default:
70 break;
71 }
72
73 baseType = modifiedType->GetType();
74 }
75 type = baseType;
76 }
77
78 // if the parameter has no type associated,
79 // then it's the unspecified type.
80 if (type == NULL)
81 typeName = "void";
82 else
83 GetFullyQualifiedDIEName(type, typeName, requestingEntry);
84
85 if (modifier.Length() > 0) {
86 if (modifier[modifier.Length() - 1] == ' ')
87 modifier.Truncate(modifier.Length() - 1);
88
89 // if the modifier has a leading const, treat it
90 // as the degenerate case and prepend it to the
91 // type name since that's the more typically used
92 // representation in source
93 if (modifier[0] == ' ') {
94 typeName.Prepend("const ");
95 modifier.Remove(0, 7);
96 }
97 typeName += modifier;
98 }
99
100 _name = typeName;
101 }
102
103
104 /*static*/ void
GetFullDIEName(const DebugInfoEntry * entry,BString & _name)105 DwarfUtils::GetFullDIEName(const DebugInfoEntry* entry, BString& _name)
106 {
107 BString generatedName;
108 // If we don't seem to have a name but an abstract origin, return the
109 // origin's name.
110 const char* name = entry->Name();
111 if (name == NULL) {
112 if (DebugInfoEntry* abstractOrigin = entry->AbstractOrigin()) {
113 entry = abstractOrigin;
114 name = entry->Name();
115 }
116 }
117
118 // If we still don't have a name but a specification, return the
119 // specification's name.
120 if (name == NULL) {
121 if (DebugInfoEntry* specification = entry->Specification()) {
122 entry = specification;
123 name = entry->Name();
124 }
125 }
126
127 if (name == NULL) {
128 if (dynamic_cast<const DIEModifiedType*>(entry) != NULL)
129 GetDIETypeName(entry, _name);
130
131 // we found no name for this entry whatsoever, abort.
132 return;
133 }
134
135 generatedName = name;
136
137 const DIESubprogram* subProgram = dynamic_cast<const DIESubprogram*>(
138 entry);
139 if (subProgram != NULL) {
140 generatedName += "(";
141 BString parameters;
142 DebugInfoEntryList::ConstIterator iterator
143 = subProgram->Parameters().GetIterator();
144
145 bool firstParameter = true;
146 while (iterator.HasNext()) {
147 DebugInfoEntry* parameterEntry = iterator.Next();
148 if (dynamic_cast<DIEUnspecifiedParameters*>(parameterEntry)
149 != NULL) {
150 parameters += ", ...";
151 continue;
152 }
153
154 const DIEFormalParameter* parameter
155 = dynamic_cast<DIEFormalParameter*>(parameterEntry);
156 if (parameter == NULL) {
157 // this shouldn't happen
158 return;
159 }
160
161 if (parameter->IsArtificial())
162 continue;
163
164 BString paramName;
165 BString modifier;
166 DIEType* type = parameter->GetType();
167 GetDIETypeName(type, paramName, entry);
168
169 if (firstParameter)
170 firstParameter = false;
171 else
172 parameters += ", ";
173
174 parameters += paramName;
175 }
176
177 if (parameters.Length() > 0)
178 generatedName += parameters;
179 else
180 generatedName += "void";
181 generatedName += ")";
182 }
183 _name = generatedName;
184 }
185
186
187 /*static*/ void
GetFullyQualifiedDIEName(const DebugInfoEntry * entry,BString & _name,const DebugInfoEntry * requestingEntry)188 DwarfUtils::GetFullyQualifiedDIEName(const DebugInfoEntry* entry,
189 BString& _name, const DebugInfoEntry* requestingEntry)
190 {
191 // If we don't seem to have a name but an abstract origin, return the
192 // origin's name.
193 if (entry->Name() == NULL) {
194 if (DebugInfoEntry* abstractOrigin = entry->AbstractOrigin())
195 entry = abstractOrigin;
196 }
197
198 // If we don't still don't have a name but a specification, get the
199 // specification's name.
200 if (entry->Name() == NULL) {
201 if (DebugInfoEntry* specification = entry->Specification())
202 entry = specification;
203 }
204
205 _name.Truncate(0);
206 BString generatedName;
207
208 // Get the namespace, if any.
209 DebugInfoEntry* parent = entry->Parent();
210 while (parent != NULL) {
211 if (parent == requestingEntry)
212 break;
213 if (parent->IsNamespace()) {
214 BString parentName;
215 GetFullyQualifiedDIEName(parent, parentName);
216 if (parentName.Length() > 0) {
217 parentName += "::";
218 generatedName.Prepend(parentName);
219 }
220 break;
221 }
222
223 parent = parent->Parent();
224 }
225
226 BString name;
227 GetFullDIEName(entry, name);
228 if (name.Length() == 0)
229 return;
230
231 generatedName += name;
232
233 _name = generatedName;
234 }
235
236
237 /*static*/ bool
GetDeclarationLocation(DwarfFile * dwarfFile,const DebugInfoEntry * entry,const char * & _directory,const char * & _file,int32 & _line,int32 & _column)238 DwarfUtils::GetDeclarationLocation(DwarfFile* dwarfFile,
239 const DebugInfoEntry* entry, const char*& _directory, const char*& _file,
240 int32& _line, int32& _column)
241 {
242 uint32 file = 0;
243 uint32 line = 0;
244 uint32 column = 0;
245 bool fileSet = entry->GetDeclarationFile(file);
246 bool lineSet = entry->GetDeclarationLine(line);
247 bool columnSet = entry->GetDeclarationColumn(column);
248
249 // if something is not set yet, try the abstract origin (if any)
250 if (!fileSet || !lineSet || !columnSet) {
251 if (DebugInfoEntry* abstractOrigin = entry->AbstractOrigin()) {
252 entry = abstractOrigin;
253 if (!fileSet)
254 fileSet = entry->GetDeclarationFile(file);
255 if (!lineSet)
256 lineSet = entry->GetDeclarationLine(line);
257 if (!columnSet)
258 columnSet = entry->GetDeclarationColumn(column);
259 }
260 }
261
262 // something is not set yet, try the specification (if any)
263 if (!fileSet || !lineSet || !columnSet) {
264 if (DebugInfoEntry* specification = entry->Specification()) {
265 entry = specification;
266 if (!fileSet)
267 fileSet = entry->GetDeclarationFile(file);
268 if (!lineSet)
269 lineSet = entry->GetDeclarationLine(line);
270 if (!columnSet)
271 columnSet = entry->GetDeclarationColumn(column);
272 }
273 }
274
275 if (file == 0)
276 return false;
277
278 // get the compilation unit
279 CompilationUnit* unit = dwarfFile->CompilationUnitForDIE(entry);
280 if (unit == NULL)
281 return false;
282
283 const char* directoryName;
284 const char* fileName = unit->FileAt(file - 1, &directoryName);
285 if (fileName == NULL)
286 return false;
287
288 _directory = directoryName;
289 _file = fileName;
290 _line = (int32)line - 1;
291 _column = (int32)column - 1;
292 return true;
293 }
294