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