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