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());
		}
	)
Example #3
0
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());
		}
	)