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 "DebugInfoEntries.h" 15#include "Dwarf.h" 16#include "DwarfFile.h" 17#include "DwarfTargetInterface.h" 18#include "DwarfTypeFactory.h" 19#include "DwarfUtils.h" 20#include "DwarfTypes.h" 21#include "FunctionID.h" 22#include "FunctionParameterID.h" 23#include "GlobalTypeLookup.h" 24#include "LocalVariableID.h" 25#include "Register.h" 26#include "RegisterMap.h" 27#include "ReturnValueID.h" 28#include "StringUtils.h" 29#include "Tracing.h" 30#include "ValueLocation.h" 31#include "Variable.h" 32 33 34// #pragma mark - DwarfFunctionParameterID 35 36 37struct 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 61protected: 62 virtual uint32 ComputeHashValue() const 63 { 64 uint32 hash = fFunctionID->HashValue(); 65 return hash * 19 + StringUtils::HashValue(fName); 66 } 67 68private: 69 FunctionID* fFunctionID; 70 const BString fName; 71}; 72 73 74// #pragma mark - DwarfLocalVariableID 75 76 77struct 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 104protected: 105 virtual uint32 ComputeHashValue() const 106 { 107 uint32 hash = fFunctionID->HashValue(); 108 hash = hash * 19 + StringUtils::HashValue(fName); 109 hash = hash * 19 + fLine; 110 hash = hash * 19 + fColumn; 111 return hash; 112 } 113 114private: 115 FunctionID* fFunctionID; 116 const BString fName; 117 int32 fLine; 118 int32 fColumn; 119}; 120 121 122// #pragma mark - DwarfReturnValueID 123 124 125struct 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 150protected: 151 virtual uint32 ComputeHashValue() const 152 { 153 uint32 hash = fFunctionID->HashValue(); 154 return hash * 25 + StringUtils::HashValue(fName); 155 } 156 157private: 158 FunctionID* fFunctionID; 159 const BString fName; 160}; 161 162 163// #pragma mark - DwarfStackFrameDebugInfo 164 165 166DwarfStackFrameDebugInfo::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 184DwarfStackFrameDebugInfo::~DwarfStackFrameDebugInfo() 185{ 186 fTypeCache->ReleaseReference(); 187 188 if (fTypeContext != NULL) 189 fTypeContext->ReleaseReference(); 190 191 delete fTypeFactory; 192} 193 194 195status_t 196DwarfStackFrameDebugInfo::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 221status_t 222DwarfStackFrameDebugInfo::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 245status_t 246DwarfStackFrameDebugInfo::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 280status_t 281DwarfStackFrameDebugInfo::CreateReturnValue(FunctionID* functionID, 282 DIEType* returnType, ValueLocation* location, Variable*& _variable) 283{ 284 if (returnType == NULL) 285 return B_BAD_VALUE; 286 287 // create the type 288 DwarfType* type; 289 status_t error = fTypeFactory->CreateType(returnType, type); 290 if (error != B_OK) 291 return error; 292 BReference<DwarfType> typeReference(type, true); 293 294 DwarfReturnValueID* id = new(std::nothrow) DwarfReturnValueID( 295 functionID); 296 if (id == NULL) 297 return B_NO_MEMORY; 298 299 BString name; 300 name.SetToFormat("%s returned", functionID->FunctionName().String()); 301 302 Variable* variable = new(std::nothrow) Variable(id, name, 303 type, location); 304 if (variable == NULL) 305 return B_NO_MEMORY; 306 307 _variable = variable; 308 309 return B_OK; 310} 311 312 313status_t 314DwarfStackFrameDebugInfo::_CreateVariable(ObjectID* id, const BString& name, 315 DIEType* typeEntry, LocationDescription* locationDescription, 316 Variable*& _variable) 317{ 318 if (typeEntry == NULL) 319 return B_BAD_VALUE; 320 321 // create the type 322 DwarfType* type; 323 status_t error = fTypeFactory->CreateType(typeEntry, type); 324 if (error != B_OK) 325 return error; 326 BReference<DwarfType> typeReference(type, true); 327 328 // get the location, if possible 329 ValueLocation* location = new(std::nothrow) ValueLocation( 330 fTypeContext->GetArchitecture()->IsBigEndian()); 331 if (location == NULL) 332 return B_NO_MEMORY; 333 BReference<ValueLocation> locationReference(location, true); 334 335 if (locationDescription->IsValid()) { 336 status_t error = type->ResolveLocation(fTypeContext, 337 locationDescription, 0, false, *location); 338 if (error != B_OK) 339 return error; 340 341 TRACE_LOCALS_ONLY(location->Dump()); 342 } 343 344 // create the variable 345 Variable* variable = new(std::nothrow) Variable(id, name, type, location); 346 if (variable == NULL) 347 return B_NO_MEMORY; 348 349 _variable = variable; 350 return B_OK; 351} 352 353 354template<typename EntryType> 355/*static*/ DIEType* 356DwarfStackFrameDebugInfo::_GetDIEType(EntryType* entry) 357{ 358 if (DIEType* typeEntry = entry->GetType()) 359 return typeEntry; 360 361 if (EntryType* abstractOrigin = dynamic_cast<EntryType*>( 362 entry->AbstractOrigin())) { 363 entry = abstractOrigin; 364 if (DIEType* typeEntry = entry->GetType()) 365 return typeEntry; 366 } 367 368 if (EntryType* specification = dynamic_cast<EntryType*>( 369 entry->Specification())) { 370 entry = specification; 371 if (DIEType* typeEntry = entry->GetType()) 372 return typeEntry; 373 } 374 375 return NULL; 376} 377