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