xref: /haiku/src/kits/debugger/dwarf/DwarfUtils.cpp (revision 410ed2fbba58819ac21e27d3676739728416761d)
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
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
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
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
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
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