/* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ #include "Architecture.h" #include #include #include #include "CpuState.h" #include "FunctionInstance.h" #include "Image.h" #include "ImageDebugInfo.h" #include "ImageDebugInfoProvider.h" #include "SpecificImageDebugInfo.h" #include "StackTrace.h" #include "Team.h" Architecture::Architecture(TeamMemory* teamMemory, uint8 addressSize, bool bigEndian) : fTeamMemory(teamMemory), fAddressSize(addressSize), fBigEndian(bigEndian) { } Architecture::~Architecture() { } status_t Architecture::Init() { return B_OK; } status_t Architecture::CreateStackTrace(Team* team, ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState, StackTrace*& _stackTrace) { Reference cpuStateReference(cpuState); // create the object StackTrace* stackTrace = new(std::nothrow) StackTrace; if (stackTrace == NULL) return B_NO_MEMORY; ObjectDeleter stackTraceDeleter(stackTrace); StackFrame* frame = NULL; while (cpuState != NULL) { // get the instruction pointer target_addr_t instructionPointer = cpuState->InstructionPointer(); if (instructionPointer == 0) break; // get the image for the instruction pointer AutoLocker teamLocker(team); Image* image = team->ImageByAddress(instructionPointer); Reference imageReference(image); teamLocker.Unlock(); // get the image debug info ImageDebugInfo* imageDebugInfo = NULL; if (image != NULL) imageInfoProvider->GetImageDebugInfo(image, imageDebugInfo); Reference imageDebugInfoReference(imageDebugInfo, true); // get the function teamLocker.Lock(); FunctionInstance* function = NULL; FunctionDebugInfo* functionDebugInfo = NULL; if (imageDebugInfo != NULL) { function = imageDebugInfo->FunctionAtAddress(instructionPointer); if (function != NULL) functionDebugInfo = function->GetFunctionDebugInfo(); } Reference functionReference(function); teamLocker.Unlock(); // If the CPU state's instruction pointer is actually the return address // of the next frame, we let the architecture fix that. if (frame != NULL && frame->ReturnAddress() == cpuState->InstructionPointer()) { UpdateStackFrameCpuState(frame, image, functionDebugInfo, cpuState); } // create the frame using the debug info StackFrame* previousFrame = NULL; CpuState* previousCpuState = NULL; if (function != NULL) { status_t error = functionDebugInfo->GetSpecificImageDebugInfo() ->CreateFrame(image, function, cpuState, previousFrame, previousCpuState); if (error != B_OK && error != B_UNSUPPORTED) break; } // If we have no frame yet, let the architecture create it. if (previousFrame == NULL) { status_t error = CreateStackFrame(image, functionDebugInfo, cpuState, frame == NULL, previousFrame, previousCpuState); if (error != B_OK) break; } cpuStateReference.SetTo(previousCpuState, true); previousFrame->SetImage(image); previousFrame->SetFunction(function); if (!stackTrace->AddFrame(previousFrame)) return B_NO_MEMORY; frame = previousFrame; cpuState = previousCpuState; } stackTraceDeleter.Detach(); _stackTrace = stackTrace; return B_OK; }