Exemple #1
0
status_t
Architecture::InitRegisterRules(CfaContext& context) const
{
    // Init the initial register rules. The DWARF 3 specs on the
    // matter: "The default rule for all columns before
    // interpretation of the initial instructions is the undefined
    // rule. However, an ABI authoring body or a compilation system
    // authoring body may specify an alternate default value for any
    // or all columns."
    // GCC's assumes the "same value" rule for all callee preserved
    // registers. We set them respectively.
    // the stack pointer is initialized to
    // CFA offset 0 by default.
    const Register* registers = Registers();
    RegisterMap* toDwarf = NULL;
    status_t result = GetDwarfRegisterMaps(&toDwarf, NULL);
    if (result != B_OK)
        return result;

    BReference<RegisterMap> toDwarfMapReference(toDwarf, true);
    for (int32 i = 0; i < CountRegisters(); i++) {
        int32 dwarfReg = toDwarf->MapRegisterIndex(i);
        if (dwarfReg < 0 || dwarfReg > CountRegisters() - 1)
            continue;

        // TODO: on CPUs that have a return address register
        // a default rule should be set up to use that to
        // extract the instruction pointer
        switch (registers[i].Type()) {
        case REGISTER_TYPE_STACK_POINTER:
        {
            context.RegisterRule(dwarfReg)->SetToValueOffset(0);
            break;
        }
        default:
        {
            context.RegisterRule(dwarfReg)->SetToSameValue();
            break;
        }
        }
    }

    return result;
}
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());
		}
	)
Exemple #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());
		}
	)