status_t DwarfImageDebugInfo::GetType(GlobalTypeCache* cache, const BString& name, const TypeLookupConstraints& constraints, Type*& _type) { int32 registerCount = fArchitecture->CountRegisters(); const Register* registers = fArchitecture->Registers(); // get the DWARF -> architecture register map RegisterMap* fromDwarfMap; status_t error = fArchitecture->GetDwarfRegisterMaps(NULL, &fromDwarfMap); if (error != B_OK) return error; BReference<RegisterMap> fromDwarfMapReference(fromDwarfMap, true); // create the target interface BasicTargetInterface *inputInterface = new(std::nothrow) BasicTargetInterface(registers, registerCount, fromDwarfMap, fArchitecture, fDebuggerInterface); if (inputInterface == NULL) return B_NO_MEMORY; BReference<BasicTargetInterface> inputInterfaceReference(inputInterface, true); // iterate through all compilation units for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i); i++) { DwarfTypeContext* typeContext = NULL; BReference<DwarfTypeContext> typeContextReference; // iterate through all types of the compilation unit for (DebugInfoEntryList::ConstIterator it = unit->UnitEntry()->Types().GetIterator(); DIEType* typeEntry = dynamic_cast<DIEType*>(it.Next());) { if (typeEntry->IsDeclaration()) continue; if (constraints.HasTypeKind()) { if (dwarf_tag_to_type_kind(typeEntry->Tag()) != constraints.TypeKind()) continue; if (!_EvaluateBaseTypeConstraints(typeEntry, constraints)) continue; } if (constraints.HasSubtypeKind() && dwarf_tag_to_subtype_kind(typeEntry->Tag()) != constraints.SubtypeKind()) continue; BString typeEntryName; DwarfUtils::GetFullyQualifiedDIEName(typeEntry, typeEntryName); if (typeEntryName != name) continue; // The name matches and the entry is not just a declaration -- // create the type. First create the type context lazily. if (typeContext == NULL) { typeContext = new(std::nothrow) DwarfTypeContext(fArchitecture, fImageInfo.ImageID(), fFile, unit, NULL, 0, 0, fRelocationDelta, inputInterface, fromDwarfMap); if (typeContext == NULL) return B_NO_MEMORY; typeContextReference.SetTo(typeContext, true); } // create the type DwarfType* type; DwarfTypeFactory typeFactory(typeContext, fTypeLookup, cache); error = typeFactory.CreateType(typeEntry, type); if (error != B_OK) continue; _type = type; return B_OK; } } return B_ENTRY_NOT_FOUND; }
status_t DwarfImageDebugInfo::CreateFrame(Image* image, FunctionInstance* functionInstance, CpuState* cpuState, bool getFullFrameInfo, ReturnValueInfoList* returnValueInfos, StackFrame*& _frame, CpuState*& _previousCpuState) { DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>( functionInstance->GetFunctionDebugInfo()); FunctionID* functionID = functionInstance->GetFunctionID(); BReference<FunctionID> functionIDReference; if (functionID != NULL) functionIDReference.SetTo(functionID, true); DIESubprogram* entry = function != NULL ? function->SubprogramEntry() : NULL; TRACE_CFI("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p, " "function: %s\n", entry, functionID->FunctionName().String()); int32 registerCount = fArchitecture->CountRegisters(); const Register* registers = fArchitecture->Registers(); // get the DWARF <-> architecture register maps RegisterMap* toDwarfMap; RegisterMap* fromDwarfMap; status_t error = fArchitecture->GetDwarfRegisterMaps(&toDwarfMap, &fromDwarfMap); if (error != B_OK) return error; BReference<RegisterMap> toDwarfMapReference(toDwarfMap, true); BReference<RegisterMap> fromDwarfMapReference(fromDwarfMap, true); // create a clean CPU state for the previous frame CpuState* previousCpuState; error = fArchitecture->CreateCpuState(previousCpuState); if (error != B_OK) return error; BReference<CpuState> previousCpuStateReference(previousCpuState, true); // create the target interfaces UnwindTargetInterface* inputInterface = new(std::nothrow) UnwindTargetInterface(registers, registerCount, fromDwarfMap, toDwarfMap, cpuState, fArchitecture, fDebuggerInterface); if (inputInterface == NULL) return B_NO_MEMORY; BReference<UnwindTargetInterface> inputInterfaceReference(inputInterface, true); UnwindTargetInterface* outputInterface = new(std::nothrow) UnwindTargetInterface(registers, registerCount, fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture, fDebuggerInterface); if (outputInterface == NULL) return B_NO_MEMORY; BReference<UnwindTargetInterface> outputInterfaceReference(outputInterface, true); // do the unwinding target_addr_t instructionPointer = cpuState->InstructionPointer() - fRelocationDelta; target_addr_t framePointer; CompilationUnit* unit = function != NULL ? function->GetCompilationUnit() : NULL; error = fFile->UnwindCallFrame(unit, fArchitecture->AddressSize(), entry, instructionPointer, inputInterface, outputInterface, framePointer); if (error != B_OK) { TRACE_CFI("Failed to unwind call frame: %s\n", strerror(error)); return B_UNSUPPORTED; } TRACE_CFI_ONLY( TRACE_CFI("unwound registers:\n"); for (int32 i = 0; i < registerCount; i++) { const Register* reg = registers + i; BVariant value; if (previousCpuState->GetRegisterValue(reg, value)) { TRACE_CFI(" %3s: %#" B_PRIx64 "\n", reg->Name(), value.ToUInt64()); } else TRACE_CFI(" %3s: undefined\n", reg->Name()); } )
status_t DwarfImageDebugInfo::CreateFrame(Image* image, FunctionInstance* functionInstance, CpuState* cpuState, StackFrame*& _previousFrame, CpuState*& _previousCpuState) { DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>( functionInstance->GetFunctionDebugInfo()); if (function == NULL) return B_BAD_VALUE; TRACE_CFI("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p\n", function->SubprogramEntry()); int32 registerCount = fArchitecture->CountRegisters(); const Register* registers = fArchitecture->Registers(); // get the DWARF <-> architecture register maps RegisterMap* toDwarfMap; RegisterMap* fromDwarfMap; status_t error = fArchitecture->GetDwarfRegisterMaps(&toDwarfMap, &fromDwarfMap); if (error != B_OK) return error; Reference<RegisterMap> toDwarfMapReference(toDwarfMap, true); Reference<RegisterMap> fromDwarfMapReference(fromDwarfMap, true); // create a clean CPU state for the previous frame CpuState* previousCpuState; error = fArchitecture->CreateCpuState(previousCpuState); if (error != B_OK) return error; Reference<CpuState> previousCpuStateReference(previousCpuState, true); // create the target interfaces UnwindTargetInterface* inputInterface = new(std::nothrow) UnwindTargetInterface(registers, registerCount, fromDwarfMap, toDwarfMap, cpuState, fArchitecture, fTeamMemory); if (inputInterface == NULL) return B_NO_MEMORY; Reference<UnwindTargetInterface> inputInterfaceReference(inputInterface, true); UnwindTargetInterface* outputInterface = new(std::nothrow) UnwindTargetInterface(registers, registerCount, fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture, fTeamMemory); if (outputInterface == NULL) return B_NO_MEMORY; Reference<UnwindTargetInterface> outputInterfaceReference(outputInterface, true); // do the unwinding target_addr_t instructionPointer = cpuState->InstructionPointer() - fRelocationDelta; target_addr_t framePointer; CompilationUnit* unit = function->GetCompilationUnit(); error = fFile->UnwindCallFrame(unit, function->SubprogramEntry(), instructionPointer, inputInterface, outputInterface, framePointer); if (error != B_OK) { TRACE_CFI("Failed to unwind call frame: %s\n", strerror(error)); return B_UNSUPPORTED; } TRACE_CFI_ONLY( TRACE_CFI("unwound registers:\n"); for (int32 i = 0; i < registerCount; i++) { const Register* reg = registers + i; BVariant value; if (previousCpuState->GetRegisterValue(reg, value)) TRACE_CFI(" %3s: %#lx\n", reg->Name(), value.ToUInt32()); else TRACE_CFI(" %3s: undefined\n", reg->Name()); } )