headers/bsd: Add sys/queue.h.
[haiku.git] / src / kits / debugger / dwarf / DwarfUtils.cpp
blob88fd0de2f9be2f764b76d7eda6f15301fe1cdd1d
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 */
7 #include "DwarfUtils.h"
9 #include <String.h>
11 #include "CompilationUnit.h"
12 #include "Dwarf.h"
13 #include "DwarfFile.h"
16 /*static*/ void
17 DwarfUtils::GetDIEName(const DebugInfoEntry* entry, BString& _name)
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();
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();
38 _name = name;
42 /*static*/ void
43 DwarfUtils::GetDIETypeName(const DebugInfoEntry* entry, BString& _name)
45 const DIEType* type = dynamic_cast<const DIEType*>(entry);
46 if (type == NULL)
47 return;
49 const DIEModifiedType* modifiedType = dynamic_cast<const DIEModifiedType*>(
50 type);
51 BString typeName;
52 BString modifier;
54 if (modifiedType != NULL) {
55 const DIEType* baseType = type;
56 while ((modifiedType = dynamic_cast<const DIEModifiedType*>(
57 baseType)) != NULL) {
58 switch (modifiedType->Tag()) {
59 case DW_TAG_pointer_type:
60 modifier.Prepend("*");
61 break;
62 case DW_TAG_reference_type:
63 modifier.Prepend("&");
64 break;
65 case DW_TAG_const_type:
66 modifier.Prepend(" const ");
67 break;
68 default:
69 break;
72 baseType = modifiedType->GetType();
74 type = baseType;
77 // if the parameter has no type associated,
78 // then it's the unspecified type.
79 if (type == NULL)
80 typeName = "void";
81 else
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);
96 typeName += modifier;
99 _name = typeName;
103 /*static*/ void
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
108 // origin's name.
109 const char* name = entry->Name();
110 if (name == NULL) {
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.
119 if (name == NULL) {
120 if (DebugInfoEntry* specification = entry->Specification()) {
121 entry = specification;
122 name = entry->Name();
126 if (name == NULL) {
127 if (dynamic_cast<const DIEModifiedType*>(entry) != NULL)
128 GetDIETypeName(entry, _name);
130 // we found no name for this entry whatsoever, abort.
131 return;
134 generatedName = name;
136 const DIESubprogram* subProgram = dynamic_cast<const DIESubprogram*>(
137 entry);
138 if (subProgram != NULL) {
139 generatedName += "(";
140 BString parameters;
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)
148 != NULL) {
149 parameters += ", ...";
150 continue;
153 const DIEFormalParameter* parameter
154 = dynamic_cast<DIEFormalParameter*>(parameterEntry);
155 if (parameter == NULL) {
156 // this shouldn't happen
157 return;
160 if (parameter->IsArtificial())
161 continue;
163 BString paramName;
164 BString modifier;
165 DIEType* type = parameter->GetType();
166 GetDIETypeName(type, paramName);
168 if (firstParameter)
169 firstParameter = false;
170 else
171 parameters += ", ";
173 parameters += paramName;
176 if (parameters.Length() > 0)
177 generatedName += parameters;
178 else
179 generatedName += "void";
180 generatedName += ")";
182 _name = generatedName;
186 /*static*/ void
187 DwarfUtils::GetFullyQualifiedDIEName(const DebugInfoEntry* entry,
188 BString& _name)
190 // If we don't seem to have a name but an abstract origin, return the
191 // origin's name.
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;
204 _name.Truncate(0);
205 BString generatedName;
207 // Get the namespace, if any.
208 DebugInfoEntry* parent = entry->Parent();
209 while (parent != NULL) {
210 if (parent->IsNamespace()) {
211 BString parentName;
212 GetFullyQualifiedDIEName(parent, parentName);
213 if (parentName.Length() > 0) {
214 parentName += "::";
215 generatedName.Prepend(parentName);
217 break;
220 parent = parent->Parent();
223 BString name;
224 GetFullDIEName(entry, name);
225 if (name.Length() == 0)
226 return;
228 generatedName += name;
230 _name = generatedName;
234 /*static*/ bool
235 DwarfUtils::GetDeclarationLocation(DwarfFile* dwarfFile,
236 const DebugInfoEntry* entry, const char*& _directory, const char*& _file,
237 int32& _line, int32& _column)
239 uint32 file = 0;
240 uint32 line = 0;
241 uint32 column = 0;
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;
250 if (!fileSet)
251 fileSet = entry->GetDeclarationFile(file);
252 if (!lineSet)
253 lineSet = entry->GetDeclarationLine(line);
254 if (!columnSet)
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;
263 if (!fileSet)
264 fileSet = entry->GetDeclarationFile(file);
265 if (!lineSet)
266 lineSet = entry->GetDeclarationLine(line);
267 if (!columnSet)
268 columnSet = entry->GetDeclarationColumn(column);
272 if (file == 0)
273 return false;
275 // get the compilation unit
276 CompilationUnit* unit = dwarfFile->CompilationUnitForDIE(entry);
277 if (unit == NULL)
278 return false;
280 const char* directoryName;
281 const char* fileName = unit->FileAt(file - 1, &directoryName);
282 if (fileName == NULL)
283 return false;
285 _directory = directoryName;
286 _file = fileName;
287 _line = (int32)line - 1;
288 _column = (int32)column - 1;
289 return true;