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