1 /* 2 * Copyright 2012, Rene Gollent, rene@gollent.com. 3 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "DwarfStackFrameDebugInfo.h" 9 10 #include <new> 11 12 #include "Architecture.h" 13 #include "CompilationUnit.h" 14 #include "CpuState.h" 15 #include "DebugInfoEntries.h" 16 #include "Dwarf.h" 17 #include "DwarfFile.h" 18 #include "DwarfTargetInterface.h" 19 #include "DwarfTypeFactory.h" 20 #include "DwarfUtils.h" 21 #include "DwarfTypes.h" 22 #include "FunctionID.h" 23 #include "FunctionParameterID.h" 24 #include "GlobalTypeLookup.h" 25 #include "LocalVariableID.h" 26 #include "Register.h" 27 #include "RegisterMap.h" 28 #include "ReturnValueID.h" 29 #include "Tracing.h" 30 #include "ValueLocation.h" 31 #include "Variable.h" 32 33 34 // #pragma mark - DwarfFunctionParameterID 35 36 37 struct DwarfStackFrameDebugInfo::DwarfFunctionParameterID 38 : public FunctionParameterID { 39 40 DwarfFunctionParameterID(FunctionID* functionID, const BString& name) 41 : 42 fFunctionID(functionID), 43 fName(name) 44 { 45 fFunctionID->AcquireReference(); 46 } 47 48 virtual ~DwarfFunctionParameterID() 49 { 50 fFunctionID->ReleaseReference(); 51 } 52 53 virtual bool operator==(const ObjectID& other) const 54 { 55 const DwarfFunctionParameterID* parameterID 56 = dynamic_cast<const DwarfFunctionParameterID*>(&other); 57 return parameterID != NULL && *fFunctionID == *parameterID->fFunctionID 58 && fName == parameterID->fName; 59 } 60 61 protected: 62 virtual uint32 ComputeHashValue() const 63 { 64 uint32 hash = fFunctionID->HashValue(); 65 return hash * 19 + fName.HashValue(); 66 } 67 68 private: 69 FunctionID* fFunctionID; 70 const BString fName; 71 }; 72 73 74 // #pragma mark - DwarfLocalVariableID 75 76 77 struct DwarfStackFrameDebugInfo::DwarfLocalVariableID : public LocalVariableID { 78 79 DwarfLocalVariableID(FunctionID* functionID, const BString& name, 80 int32 line, int32 column) 81 : 82 fFunctionID(functionID), 83 fName(name), 84 fLine(line), 85 fColumn(column) 86 { 87 fFunctionID->AcquireReference(); 88 } 89 90 virtual ~DwarfLocalVariableID() 91 { 92 fFunctionID->ReleaseReference(); 93 } 94 95 virtual bool operator==(const ObjectID& other) const 96 { 97 const DwarfLocalVariableID* otherID 98 = dynamic_cast<const DwarfLocalVariableID*>(&other); 99 return otherID != NULL && *fFunctionID == *otherID->fFunctionID 100 && fName == otherID->fName && fLine == otherID->fLine 101 && fColumn == otherID->fColumn; 102 } 103 104 protected: 105 virtual uint32 ComputeHashValue() const 106 { 107 uint32 hash = fFunctionID->HashValue(); 108 hash = hash * 19 + fName.HashValue(); 109 hash = hash * 19 + fLine; 110 hash = hash * 19 + fColumn; 111 return hash; 112 } 113 114 private: 115 FunctionID* fFunctionID; 116 const BString fName; 117 int32 fLine; 118 int32 fColumn; 119 }; 120 121 122 // #pragma mark - DwarfReturnValueID 123 124 125 struct DwarfStackFrameDebugInfo::DwarfReturnValueID 126 : public ReturnValueID { 127 128 DwarfReturnValueID(FunctionID* functionID) 129 : 130 fFunctionID(functionID), 131 fName("(returned)") 132 { 133 fFunctionID->AcquireReference(); 134 } 135 136 virtual ~DwarfReturnValueID() 137 { 138 fFunctionID->ReleaseReference(); 139 } 140 141 virtual bool operator==(const ObjectID& other) const 142 { 143 const DwarfReturnValueID* returnValueID 144 = dynamic_cast<const DwarfReturnValueID*>(&other); 145 return returnValueID != NULL 146 && *fFunctionID == *returnValueID->fFunctionID 147 && fName == returnValueID->fName; 148 } 149 150 protected: 151 virtual uint32 ComputeHashValue() const 152 { 153 uint32 hash = fFunctionID->HashValue(); 154 return hash * 25 + fName.HashValue(); 155 } 156 157 private: 158 FunctionID* fFunctionID; 159 const BString fName; 160 }; 161 162 163 // #pragma mark - DwarfStackFrameDebugInfo 164 165 166 DwarfStackFrameDebugInfo::DwarfStackFrameDebugInfo(Architecture* architecture, 167 image_id imageID, DwarfFile* file, CompilationUnit* compilationUnit, 168 DIESubprogram* subprogramEntry, GlobalTypeLookup* typeLookup, 169 GlobalTypeCache* typeCache, target_addr_t instructionPointer, 170 target_addr_t framePointer, target_addr_t relocationDelta, 171 DwarfTargetInterface* targetInterface, RegisterMap* fromDwarfRegisterMap) 172 : 173 StackFrameDebugInfo(), 174 fTypeContext(new(std::nothrow) DwarfTypeContext(architecture, imageID, file, 175 compilationUnit, subprogramEntry, instructionPointer, framePointer, 176 relocationDelta, targetInterface, fromDwarfRegisterMap)), 177 fTypeLookup(typeLookup), 178 fTypeCache(typeCache) 179 { 180 fTypeCache->AcquireReference(); 181 } 182 183 184 DwarfStackFrameDebugInfo::~DwarfStackFrameDebugInfo() 185 { 186 fTypeCache->ReleaseReference(); 187 188 if (fTypeContext != NULL) 189 fTypeContext->ReleaseReference(); 190 191 delete fTypeFactory; 192 } 193 194 195 status_t 196 DwarfStackFrameDebugInfo::Init() 197 { 198 if (fTypeContext == NULL) 199 return B_NO_MEMORY; 200 201 // create a type context without dependency to the stack frame 202 DwarfTypeContext* typeContext = new(std::nothrow) DwarfTypeContext( 203 fTypeContext->GetArchitecture(), fTypeContext->ImageID(), 204 fTypeContext->File(), fTypeContext->GetCompilationUnit(), NULL, 0, 0, 205 fTypeContext->RelocationDelta(), fTypeContext->TargetInterface(), 206 fTypeContext->FromDwarfRegisterMap()); 207 if (typeContext == NULL) 208 return B_NO_MEMORY; 209 BReference<DwarfTypeContext> typeContextReference(typeContext, true); 210 211 // create the type factory 212 fTypeFactory = new(std::nothrow) DwarfTypeFactory(typeContext, fTypeLookup, 213 fTypeCache); 214 if (fTypeFactory == NULL) 215 return B_NO_MEMORY; 216 217 return B_OK; 218 } 219 220 221 status_t 222 DwarfStackFrameDebugInfo::CreateParameter(FunctionID* functionID, 223 DIEFormalParameter* parameterEntry, Variable*& _parameter) 224 { 225 // get the name 226 BString name; 227 DwarfUtils::GetDIEName(parameterEntry, name); 228 229 TRACE_LOCALS("DwarfStackFrameDebugInfo::CreateParameter(DIE: %p): name: " 230 "\"%s\"\n", parameterEntry, name.String()); 231 232 // create the ID 233 DwarfFunctionParameterID* id = new(std::nothrow) DwarfFunctionParameterID( 234 functionID, name); 235 if (id == NULL) 236 return B_NO_MEMORY; 237 BReference<DwarfFunctionParameterID> idReference(id, true); 238 239 // create the variable 240 return _CreateVariable(id, name, _GetDIEType(parameterEntry), 241 parameterEntry->GetLocationDescription(), _parameter); 242 } 243 244 245 status_t 246 DwarfStackFrameDebugInfo::CreateLocalVariable(FunctionID* functionID, 247 DIEVariable* variableEntry, Variable*& _variable) 248 { 249 // get the name 250 BString name; 251 DwarfUtils::GetDIEName(variableEntry, name); 252 253 TRACE_LOCALS("DwarfStackFrameDebugInfo::CreateLocalVariable(DIE: %p): " 254 "name: \"%s\"\n", variableEntry, name.String()); 255 256 // get the declaration location 257 int32 line = -1; 258 int32 column = -1; 259 const char* file; 260 const char* directory; 261 DwarfUtils::GetDeclarationLocation(fTypeContext->File(), variableEntry, 262 directory, file, line, column); 263 // TODO: If the declaration location is unavailable, we should probably 264 // add a component to the ID to make it unique nonetheless (the name 265 // might not suffice). 266 267 // create the ID 268 DwarfLocalVariableID* id = new(std::nothrow) DwarfLocalVariableID( 269 functionID, name, line, column); 270 if (id == NULL) 271 return B_NO_MEMORY; 272 BReference<DwarfLocalVariableID> idReference(id, true); 273 274 // create the variable 275 return _CreateVariable(id, name, _GetDIEType(variableEntry), 276 variableEntry->GetLocationDescription(), _variable); 277 } 278 279 280 status_t 281 DwarfStackFrameDebugInfo::CreateReturnValue(FunctionID* functionID, 282 DIEType* returnType, ValueLocation* location, CpuState* state, 283 Variable*& _variable) 284 { 285 if (returnType == NULL) 286 return B_BAD_VALUE; 287 288 // create the type 289 DwarfType* type; 290 status_t error = fTypeFactory->CreateType(returnType, type); 291 if (error != B_OK) 292 return error; 293 BReference<DwarfType> typeReference(type, true); 294 295 DwarfReturnValueID* id = new(std::nothrow) DwarfReturnValueID( 296 functionID); 297 if (id == NULL) 298 return B_NO_MEMORY; 299 300 BString name; 301 name.SetToFormat("%s returned", functionID->FunctionName().String()); 302 303 Variable* variable = new(std::nothrow) Variable(id, name, 304 type, location, state); 305 if (variable == NULL) 306 return B_NO_MEMORY; 307 308 _variable = variable; 309 310 return B_OK; 311 } 312 313 314 status_t 315 DwarfStackFrameDebugInfo::_CreateVariable(ObjectID* id, const BString& name, 316 DIEType* typeEntry, LocationDescription* locationDescription, 317 Variable*& _variable) 318 { 319 if (typeEntry == NULL) 320 return B_BAD_VALUE; 321 322 // create the type 323 DwarfType* type; 324 status_t error = fTypeFactory->CreateType(typeEntry, type); 325 if (error != B_OK) 326 return error; 327 BReference<DwarfType> typeReference(type, true); 328 329 // get the location, if possible 330 ValueLocation* location = new(std::nothrow) ValueLocation( 331 fTypeContext->GetArchitecture()->IsBigEndian()); 332 if (location == NULL) 333 return B_NO_MEMORY; 334 BReference<ValueLocation> locationReference(location, true); 335 336 if (locationDescription->IsValid()) { 337 status_t error = type->ResolveLocation(fTypeContext, 338 locationDescription, 0, false, *location); 339 if (error != B_OK) 340 return error; 341 342 TRACE_LOCALS_ONLY(location->Dump()); 343 } 344 345 // create the variable 346 Variable* variable = new(std::nothrow) Variable(id, name, type, location); 347 if (variable == NULL) 348 return B_NO_MEMORY; 349 350 _variable = variable; 351 return B_OK; 352 } 353 354 355 template<typename EntryType> 356 /*static*/ DIEType* 357 DwarfStackFrameDebugInfo::_GetDIEType(EntryType* entry) 358 { 359 if (DIEType* typeEntry = entry->GetType()) 360 return typeEntry; 361 362 if (EntryType* abstractOrigin = dynamic_cast<EntryType*>( 363 entry->AbstractOrigin())) { 364 entry = abstractOrigin; 365 if (DIEType* typeEntry = entry->GetType()) 366 return typeEntry; 367 } 368 369 if (EntryType* specification = dynamic_cast<EntryType*>( 370 entry->Specification())) { 371 entry = specification; 372 if (DIEType* typeEntry = entry->GetType()) 373 return typeEntry; 374 } 375 376 return NULL; 377 } 378