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