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