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