diff --git a/src/apps/debugger/Image.cpp b/src/apps/debugger/Image.cpp index e8c4af4b4d..5987a992e5 100644 --- a/src/apps/debugger/Image.cpp +++ b/src/apps/debugger/Image.cpp @@ -5,17 +5,22 @@ #include "Image.h" +#include "ImageDebugInfo.h" + Image::Image(Team* team,const ImageInfo& imageInfo) : fTeam(team), - fInfo(imageInfo) + fInfo(imageInfo), + fDebugInfo(NULL) { } Image::~Image() { + if (fDebugInfo != NULL) + fDebugInfo->RemoveReference(); } @@ -24,3 +29,29 @@ Image::Init() { return B_OK; } + + +void +Image::SetImageDebugInfo(ImageDebugInfo* debugInfo) +{ + if (debugInfo == fDebugInfo) + return; + + if (fDebugInfo != NULL) + fDebugInfo->RemoveReference(); + + fDebugInfo = debugInfo; + + if (fDebugInfo != NULL) + fDebugInfo->AddReference(); +} + + +bool +Image::ContainsAddress(target_addr_t address) const +{ + return (address >= fInfo.TextBase() + && address < fInfo.TextBase() + fInfo.TextSize()) + || (address >= fInfo.DataBase() + && address < fInfo.DataBase() + fInfo.DataSize()); +} diff --git a/src/apps/debugger/Image.h b/src/apps/debugger/Image.h index 2e3581cd87..feeb96bc70 100644 --- a/src/apps/debugger/Image.h +++ b/src/apps/debugger/Image.h @@ -13,6 +13,7 @@ #include "ImageInfo.h" +class ImageDebugInfo; class Team; @@ -24,14 +25,20 @@ public: status_t Init(); - Team* GetTeam() const { return fTeam; } - image_id ID() const { return fInfo.ImageID(); } - const char* Name() const { return fInfo.Name(); } - const ImageInfo& Info() const { return fInfo; } + Team* GetTeam() const { return fTeam; } + image_id ID() const { return fInfo.ImageID(); } + const char* Name() const { return fInfo.Name(); } + const ImageInfo& Info() const { return fInfo; } + + ImageDebugInfo* GetImageDebugInfo() const { return fDebugInfo; } + void SetImageDebugInfo(ImageDebugInfo* debugInfo); + + bool ContainsAddress(target_addr_t address) const; private: Team* fTeam; ImageInfo fInfo; + ImageDebugInfo* fDebugInfo; }; diff --git a/src/apps/debugger/ImageInfo.cpp b/src/apps/debugger/ImageInfo.cpp index 3733124c19..72ee170500 100644 --- a/src/apps/debugger/ImageInfo.cpp +++ b/src/apps/debugger/ImageInfo.cpp @@ -10,7 +10,11 @@ ImageInfo::ImageInfo() : fTeam(-1), fImage(-1), - fName() + fName(), + fTextBase(0), + fTextSize(0), + fDataBase(0), + fDataSize(0) { } @@ -18,24 +22,40 @@ ImageInfo::ImageInfo(const ImageInfo& other) : fTeam(other.fTeam), fImage(other.fImage), - fName(other.fName) + fName(other.fName), + fTextBase(other.fTextBase), + fTextSize(other.fTextSize), + fDataBase(other.fDataBase), + fDataSize(other.fDataSize) { } -ImageInfo::ImageInfo(team_id team, image_id image, const BString& name) +ImageInfo::ImageInfo(team_id team, image_id image, const BString& name, + target_addr_t textBase, target_size_t textSize, target_addr_t dataBase, + target_size_t dataSize) : fTeam(team), fImage(image), - fName(name) + fName(name), + fTextBase(textBase), + fTextSize(textSize), + fDataBase(dataBase), + fDataSize(dataSize) { } void -ImageInfo::SetTo(team_id team, image_id image, const BString& name) +ImageInfo::SetTo(team_id team, image_id image, const BString& name, + target_addr_t textBase, target_size_t textSize, target_addr_t dataBase, + target_size_t dataSize) { fTeam = team; fImage = image; fName = name; + fTextBase = textBase; + fTextSize = textSize; + fDataBase = dataBase; + fDataSize = dataSize; } diff --git a/src/apps/debugger/ImageInfo.h b/src/apps/debugger/ImageInfo.h index c34fb6f14b..8af5cf3960 100644 --- a/src/apps/debugger/ImageInfo.h +++ b/src/apps/debugger/ImageInfo.h @@ -8,25 +8,44 @@ #include #include +#include "ArchitectureTypes.h" + class ImageInfo { public: ImageInfo(); ImageInfo(const ImageInfo& other); ImageInfo(team_id team, image_id image, - const BString& name); + const BString& name, + target_addr_t textBase, + target_size_t textSize, + target_addr_t dataBase, + target_size_t dataSize); void SetTo(team_id team, image_id image, - const BString& name); + const BString& name, + target_addr_t textBase, + target_size_t textSize, + target_addr_t dataBase, + target_size_t dataSize); team_id TeamID() const { return fTeam; } image_id ImageID() const { return fImage; } const char* Name() const { return fName.String(); } + target_addr_t TextBase() const { return fTextBase; } + target_size_t TextSize() const { return fTextSize; } + target_addr_t DataBase() const { return fDataBase; } + target_size_t DataSize() const { return fDataSize; } + private: thread_id fTeam; image_id fImage; BString fName; + target_addr_t fTextBase; + target_size_t fTextSize; + target_addr_t fDataBase; + target_size_t fDataSize; }; diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 0cd515093a..200eef15ff 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -8,6 +8,7 @@ UsePrivateSystemHeaders ; SEARCH_SOURCE += [ FDirName $(SUBDIR) arch ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) arch x86 ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) gui team_window ] ; @@ -23,6 +24,7 @@ Application Debugger : Image.cpp ImageInfo.cpp Jobs.cpp + SymbolInfo.cpp Team.cpp TeamDebugger.cpp TeamDebugModel.cpp @@ -40,7 +42,14 @@ Application Debugger : # arch/x86 ArchitectureX86.cpp CpuStateX86.cpp - StackFrameX86.cpp + + # debug_info + BasicFunctionDebugInfo.cpp + DebuggerDebugInfo.cpp + DebugInfo.cpp + FunctionDebugInfo.cpp + ImageDebugInfo.cpp + ImageDebugInfoProvider.cpp # debugger_interface DebugEvent.cpp diff --git a/src/apps/debugger/Jobs.cpp b/src/apps/debugger/Jobs.cpp index 2fe12efd2e..d1d9c8f79f 100644 --- a/src/apps/debugger/Jobs.cpp +++ b/src/apps/debugger/Jobs.cpp @@ -5,11 +5,15 @@ #include "Jobs.h" +#include + #include #include "Architecture.h" #include "CpuState.h" #include "DebuggerInterface.h" +#include "Image.h" +#include "ImageDebugInfo.h" #include "StackTrace.h" #include "Team.h" #include "Thread.h" @@ -101,7 +105,7 @@ GetStackTraceJob::Do() // get the stack trace StackTrace* stackTrace; - status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), + status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), this, fCpuState, stackTrace); if (error != B_OK) return error; @@ -115,3 +119,108 @@ GetStackTraceJob::Do() return B_OK; } + + +status_t +GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info) +{ + AutoLocker teamLocker(fThread->GetTeam()); + + while (image->GetImageDebugInfo() == NULL) { + // The info has not yet been loaded -- check whether a job has already + // been scheduled. + AutoLocker workerLocker(GetWorker()); + JobKey key(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO); + Job* loadImageDebugInfoJob = GetWorker()->GetJob(key); + if (loadImageDebugInfoJob == NULL) { + // no job yet -- schedule one + loadImageDebugInfoJob = new(std::nothrow) LoadImageDebugInfoJob( + fDebuggerInterface, fArchitecture, image); + if (loadImageDebugInfoJob == NULL) + return B_NO_MEMORY; + + status_t error = GetWorker()->ScheduleJob(loadImageDebugInfoJob); + if (error != B_OK) + return error; + } + + workerLocker.Unlock(); + teamLocker.Unlock(); + + // wait for the job to finish + switch (WaitFor(key)) { + case JOB_DEPENDENCY_SUCCEEDED: + case JOB_DEPENDENCY_NOT_FOUND: + // "Not found" can happen due to a race condition between + // unlocking the worker and starting to wait. + break; + case JOB_DEPENDENCY_FAILED: + case JOB_DEPENDENCY_ABORTED: + default: + return B_ERROR; + } + + teamLocker.Lock(); + } + + _info = image->GetImageDebugInfo(); + _info->AddReference(); + + return B_OK; +} + + +// #pragma mark - GetStackTraceJob + + +LoadImageDebugInfoJob::LoadImageDebugInfoJob( + DebuggerInterface* debuggerInterface, Architecture* architecture, + Image* image) + : + fDebuggerInterface(debuggerInterface), + fArchitecture(architecture), + fImage(image) +{ + fImage->AddReference(); +} + + +LoadImageDebugInfoJob::~LoadImageDebugInfoJob() +{ + fImage->RemoveReference(); +} + + +JobKey +LoadImageDebugInfoJob::Key() const +{ + return JobKey(fImage, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO); +} + + +status_t +LoadImageDebugInfoJob::Do() +{ + // get an image info for the image + AutoLocker locker(fImage->GetTeam()); + ImageInfo imageInfo(fImage->Info()); + locker.Unlock(); + + // create the debug info + ImageDebugInfo* debugInfo = new(std::nothrow) ImageDebugInfo(imageInfo, + fDebuggerInterface, fArchitecture); + if (debugInfo == NULL) + return B_NO_MEMORY; + + status_t error = debugInfo->Init(); + if (error != B_OK) { + delete debugInfo; + return error; + } + + // set the info + locker.Lock(); + fImage->SetImageDebugInfo(debugInfo); + + return B_OK; +} diff --git a/src/apps/debugger/Jobs.h b/src/apps/debugger/Jobs.h index 37ae58d8cb..b6d1772f7b 100644 --- a/src/apps/debugger/Jobs.h +++ b/src/apps/debugger/Jobs.h @@ -5,19 +5,22 @@ #ifndef JOBS_H #define JOBS_H +#include "ImageDebugInfoProvider.h" #include "Worker.h" class Architecture; class CpuState; class DebuggerInterface; +class Image; class Thread; // job types enum { JOB_TYPE_GET_CPU_STATE, - JOB_TYPE_GET_STACK_TRACE + JOB_TYPE_GET_STACK_TRACE, + JOB_TYPE_LOAD_IMAGE_DEBUG_INFO }; @@ -37,17 +40,21 @@ private: }; -class GetStackTraceJob : public Job { +class GetStackTraceJob : public Job, private ImageDebugInfoProvider { public: GetStackTraceJob( DebuggerInterface* debuggerInterface, - Architecture* architecture, - Thread* thread); + Architecture* architecture, Thread* thread); virtual ~GetStackTraceJob(); virtual JobKey Key() const; virtual status_t Do(); +private: + // ImageDebugInfoProvider + virtual status_t GetImageDebugInfo(Image* image, + ImageDebugInfo*& _info); + private: DebuggerInterface* fDebuggerInterface; Architecture* fArchitecture; @@ -56,4 +63,22 @@ private: }; +class LoadImageDebugInfoJob : public Job { +public: + LoadImageDebugInfoJob( + DebuggerInterface* debuggerInterface, + Architecture* architecture, + Image* image); + virtual ~LoadImageDebugInfoJob(); + + virtual JobKey Key() const; + virtual status_t Do(); + +private: + DebuggerInterface* fDebuggerInterface; + Architecture* fArchitecture; + Image* fImage; +}; + + #endif // JOBS_H diff --git a/src/apps/debugger/SymbolInfo.cpp b/src/apps/debugger/SymbolInfo.cpp new file mode 100644 index 0000000000..942ed66d09 --- /dev/null +++ b/src/apps/debugger/SymbolInfo.cpp @@ -0,0 +1,22 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "SymbolInfo.h" + + +SymbolInfo::SymbolInfo(target_addr_t address, target_size_t size, uint32 type, + const BString& name) + : + fAddress(address), + fSize(size), + fType(type), + fName(name) +{ +} + + +SymbolInfo::~SymbolInfo() +{ +} diff --git a/src/apps/debugger/SymbolInfo.h b/src/apps/debugger/SymbolInfo.h new file mode 100644 index 0000000000..3e091779c4 --- /dev/null +++ b/src/apps/debugger/SymbolInfo.h @@ -0,0 +1,33 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef SYMBOL_INFO_H +#define SYMBOL_INFO_H + +#include + +#include "ArchitectureTypes.h" + + +class SymbolInfo { +public: + SymbolInfo(target_addr_t address, + target_size_t size, uint32 type, + const BString& name); + ~SymbolInfo(); + + target_addr_t Address() const { return fAddress; } + target_size_t Size() const { return fSize; } + uint32 Type() const { return fType; } + const char* Name() const { return fName.String(); } + +private: + target_addr_t fAddress; + target_size_t fSize; + uint32 fType; + BString fName; +}; + + +#endif // SYMBOL_INFO_H diff --git a/src/apps/debugger/Team.cpp b/src/apps/debugger/Team.cpp index 196bb937e0..528584f7ad 100644 --- a/src/apps/debugger/Team.cpp +++ b/src/apps/debugger/Team.cpp @@ -181,6 +181,19 @@ Team::ImageByID(image_id imageID) const } +Image* +Team::ImageByAddress(target_addr_t address) const +{ + for (ImageList::ConstIterator it = fImages.GetIterator(); + Image* image = it.Next();) { + if (image->ContainsAddress(address)) + return image; + } + + return NULL; +} + + const ImageList& Team::Images() const { diff --git a/src/apps/debugger/Team.h b/src/apps/debugger/Team.h index c285c232e9..28f36a9d67 100644 --- a/src/apps/debugger/Team.h +++ b/src/apps/debugger/Team.h @@ -58,6 +58,7 @@ public: void RemoveImage(Image* image); bool RemoveImage(image_id imageID); Image* ImageByID(image_id imageID) const; + Image* ImageByAddress(target_addr_t address) const; const ImageList& Images() const; void AddListener(Listener* listener); diff --git a/src/apps/debugger/arch/Architecture.cpp b/src/apps/debugger/arch/Architecture.cpp index c7b285d060..c76e6d8b28 100644 --- a/src/apps/debugger/arch/Architecture.cpp +++ b/src/apps/debugger/arch/Architecture.cpp @@ -5,6 +5,20 @@ #include "Architecture.h" +#include + +#include +#include + +#include "CpuState.h" +#include "DebugInfo.h" +#include "FunctionDebugInfo.h" +#include "Image.h" +#include "ImageDebugInfo.h" +#include "ImageDebugInfoProvider.h" +#include "StackTrace.h" +#include "Team.h" + Architecture::Architecture(DebuggerInterface* debuggerInterface) : @@ -23,3 +37,78 @@ 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 + FunctionDebugInfo* function = NULL; + if (imageDebugInfo != NULL) + function = imageDebugInfo->FindFunction(instructionPointer); + Reference functionReference(function, true); + + // create the frame using the debug info + StackFrame* previousFrame = NULL; + CpuState* previousCpuState = NULL; + if (function != NULL) { + status_t error = function->GetDebugInfo()->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, function, cpuState, + 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; +} diff --git a/src/apps/debugger/arch/Architecture.h b/src/apps/debugger/arch/Architecture.h index 64adbb3a99..5d9d415acd 100644 --- a/src/apps/debugger/arch/Architecture.h +++ b/src/apps/debugger/arch/Architecture.h @@ -12,7 +12,11 @@ class CpuState; class DebuggerInterface; +class FunctionDebugInfo; +class Image; +class ImageDebugInfoProvider; class Register; +class StackFrame; class StackTrace; class Team; @@ -30,8 +34,19 @@ public: virtual status_t CreateCpuState(const void* cpuStateData, size_t size, CpuState*& _state) = 0; - virtual status_t CreateStackTrace(Team* team, CpuState* cpuState, - StackTrace*& _stackTrace) = 0; + virtual status_t CreateStackFrame(Image* image, + FunctionDebugInfo* function, + CpuState* cpuState, + StackFrame*& _previousFrame, + CpuState*& _previousCpuState) = 0; + // returns reference to previous frame + // and CPU state; returned CPU state + // can be NULL + + status_t CreateStackTrace(Team* team, + ImageDebugInfoProvider* imageInfoProvider, + CpuState* cpuState, + StackTrace*& _stackTrace); // team is not locked protected: diff --git a/src/apps/debugger/arch/ArchitectureTypes.h b/src/apps/debugger/arch/ArchitectureTypes.h index 7e1db1d7c2..15460d16da 100644 --- a/src/apps/debugger/arch/ArchitectureTypes.h +++ b/src/apps/debugger/arch/ArchitectureTypes.h @@ -7,6 +7,7 @@ typedef uint64 target_addr_t; +typedef uint64 target_size_t; diff --git a/src/apps/debugger/arch/CpuState.h b/src/apps/debugger/arch/CpuState.h index 79f2c8f135..6ebd1cdb9c 100644 --- a/src/apps/debugger/arch/CpuState.h +++ b/src/apps/debugger/arch/CpuState.h @@ -10,6 +10,8 @@ #include #include +#include "ArchitectureTypes.h" + class Register; @@ -18,6 +20,7 @@ class CpuState : public Referenceable { public: virtual ~CpuState(); + virtual target_addr_t InstructionPointer() const = 0; virtual bool GetRegisterValue(const Register* reg, BVariant& _value) = 0; }; diff --git a/src/apps/debugger/arch/StackFrame.cpp b/src/apps/debugger/arch/StackFrame.cpp index f84ec2a37d..6047c40aba 100644 --- a/src/apps/debugger/arch/StackFrame.cpp +++ b/src/apps/debugger/arch/StackFrame.cpp @@ -5,7 +5,68 @@ #include "StackFrame.h" +#include "CpuState.h" +#include "FunctionDebugInfo.h" +#include "Image.h" + + +StackFrame::StackFrame(stack_frame_type type, CpuState* cpuState, + target_addr_t frameAddress) + : + fType(type), + fCpuState(cpuState), + fFrameAddress(frameAddress), + fReturnAddress(0), + fImage(NULL), + fFunction(NULL) +{ + fCpuState->AddReference(); +} + StackFrame::~StackFrame() { + SetImage(NULL); + SetFunction(NULL); + fCpuState->RemoveReference(); +} + + +target_addr_t +StackFrame::InstructionPointer() const +{ + return fCpuState->InstructionPointer(); +} + + +void +StackFrame::SetReturnAddress(target_addr_t address) +{ + fReturnAddress = address; +} + + +void +StackFrame::SetImage(Image* image) +{ + if (fImage != NULL) + fImage->RemoveReference(); + + fImage = image; + + if (fImage != NULL) + fImage->AddReference(); +} + + +void +StackFrame::SetFunction(FunctionDebugInfo* function) +{ + if (fFunction != NULL) + fFunction->RemoveReference(); + + fFunction = function; + + if (fFunction != NULL) + fFunction->AddReference(); } diff --git a/src/apps/debugger/arch/StackFrame.h b/src/apps/debugger/arch/StackFrame.h index 4017b18808..4c99c36c27 100644 --- a/src/apps/debugger/arch/StackFrame.h +++ b/src/apps/debugger/arch/StackFrame.h @@ -8,7 +8,6 @@ #include #include -#include #include "ArchitectureTypes.h" @@ -22,25 +21,39 @@ enum stack_frame_type { class CpuState; +class Image; +class FunctionDebugInfo; -class StackFrame : public Referenceable, - public DoublyLinkedListLinkImpl { +class StackFrame : public Referenceable { public: - virtual ~StackFrame(); + StackFrame(stack_frame_type type, + CpuState* cpuState, + target_addr_t frameAddress); + ~StackFrame(); - virtual stack_frame_type Type() const = 0; + stack_frame_type Type() const { return fType; } + CpuState* GetCpuState() const { return fCpuState; } + target_addr_t InstructionPointer() const; + target_addr_t FrameAddress() const { return fFrameAddress; } - virtual CpuState* GetCpuState() const = 0; + target_addr_t ReturnAddress() const { return fReturnAddress; } + void SetReturnAddress(target_addr_t address); - virtual target_addr_t InstructionPointer() const = 0; - virtual target_addr_t FrameAddress() const = 0; - virtual target_addr_t ReturnAddress() const = 0; - virtual target_addr_t PreviousFrameAddress() const = 0; + Image* GetImage() const { return fImage; } + void SetImage(Image* image); + + FunctionDebugInfo* Function() const { return fFunction; } + void SetFunction(FunctionDebugInfo* function); + +private: + stack_frame_type fType; + CpuState* fCpuState; + target_addr_t fFrameAddress; + target_addr_t fReturnAddress; + Image* fImage; + FunctionDebugInfo* fFunction; }; -typedef DoublyLinkedList StackFrameList; - - #endif // STACK_FRAME_H diff --git a/src/apps/debugger/arch/StackTrace.cpp b/src/apps/debugger/arch/StackTrace.cpp index 34eb3ad8a2..e5460d6255 100644 --- a/src/apps/debugger/arch/StackTrace.cpp +++ b/src/apps/debugger/arch/StackTrace.cpp @@ -13,13 +13,31 @@ StackTrace::StackTrace() StackTrace::~StackTrace() { - while (StackFrame* frame = fStackFrames.RemoveHead()) + for (int32 i = 0; StackFrame* frame = FrameAt(i); i++) frame->RemoveReference(); } -void +bool StackTrace::AddFrame(StackFrame* frame) { - fStackFrames.Add(frame); + if (fStackFrames.AddItem(frame)) + return true; + + frame->RemoveReference(); + return false; +} + + +int32 +StackTrace::CountFrames() const +{ + return fStackFrames.CountItems(); +} + + +StackFrame* +StackTrace::FrameAt(int32 index) const +{ + return fStackFrames.ItemAt(index); } diff --git a/src/apps/debugger/arch/StackTrace.h b/src/apps/debugger/arch/StackTrace.h index 59516e7e9f..4e7e442ce8 100644 --- a/src/apps/debugger/arch/StackTrace.h +++ b/src/apps/debugger/arch/StackTrace.h @@ -5,6 +5,8 @@ #ifndef STACK_TRACE_H #define STACK_TRACE_H +#include + #include "StackFrame.h" @@ -13,15 +15,14 @@ public: StackTrace(); virtual ~StackTrace(); - void AddFrame(StackFrame* frame); - // takes over reference + bool AddFrame(StackFrame* frame); + // takes over reference (also on error) - const StackFrameList& Frames() const { return fStackFrames; } + int32 CountFrames() const; + StackFrame* FrameAt(int32 index) const; - StackFrame* TopFrame() const - { return fStackFrames.Head(); } - StackFrame* BottomFrame() const - { return fStackFrames.Tail(); } +private: + typedef BObjectList StackFrameList; private: StackFrameList fStackFrames; diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.cpp b/src/apps/debugger/arch/x86/ArchitectureX86.cpp index 289a7df385..6929756544 100644 --- a/src/apps/debugger/arch/x86/ArchitectureX86.cpp +++ b/src/apps/debugger/arch/x86/ArchitectureX86.cpp @@ -11,8 +11,7 @@ #include "CpuStateX86.h" #include "DebuggerInterface.h" -#include "StackFrameX86.h" -#include "StackTrace.h" +#include "StackFrame.h" ArchitectureX86::ArchitectureX86(DebuggerInterface* debuggerInterface) @@ -104,59 +103,38 @@ ArchitectureX86::CreateCpuState(const void* cpuStateData, size_t size, status_t -ArchitectureX86::CreateStackTrace(Team* team, CpuState* _cpuState, - StackTrace*& _stackTrace) +ArchitectureX86::CreateStackFrame(Image* image, FunctionDebugInfo* function, + CpuState* _cpuState, StackFrame*& _previousFrame, + CpuState*& _previousCpuState) { CpuStateX86* cpuState = dynamic_cast(_cpuState); - // create the object - StackTrace* stackTrace = new(std::nothrow) StackTrace; - if (stackTrace == NULL) - return B_NO_MEMORY; - ObjectDeleter stackTraceDeleter(stackTrace); + uint32 framePointer = cpuState->IntRegisterValue(X86_REGISTER_EBP); - // create the top frame - StackFrameX86* frame = new StackFrameX86(STACK_FRAME_TYPE_TOP, cpuState); + // create the stack frame + StackFrame* frame = new(std::nothrow) StackFrame( + STACK_FRAME_TYPE_STANDARD, cpuState, framePointer); if (frame == NULL) return B_NO_MEMORY; - stackTrace->AddFrame(frame); - - while (true) { - uint32 framePointer = (uint32)frame->FrameAddress(); - if (framePointer == 0) - break; - - // get previous frame and return address - uint32 frameData[2]; - ssize_t bytesRead = fDebuggerInterface->ReadMemory(framePointer, - frameData, 8); - if (bytesRead != 8) - break; - - frame->SetPreviousAddresses(frameData[0], frameData[1]); - - if (frameData[0] == 0 || frameData[1] == 0) - break; + Reference frameReference(frame, true); + // read the previous frame and return address and create the CPU state + CpuStateX86* previousCpuState = NULL; + uint32 frameData[2]; + if (framePointer != 0 + && fDebuggerInterface->ReadMemory(framePointer, frameData, 8) == 8) { // prepare the previous CPU state - cpuState = new(std::nothrow) CpuStateX86; - if (cpuState == NULL) + previousCpuState = new(std::nothrow) CpuStateX86; + if (previousCpuState == NULL) return B_NO_MEMORY; - Reference cpuStateReference(cpuState, true); - cpuState->SetIntRegister(X86_REGISTER_EBP, frameData[0]); - cpuState->SetIntRegister(X86_REGISTER_EIP, frameData[1]); + previousCpuState->SetIntRegister(X86_REGISTER_EBP, frameData[0]); + previousCpuState->SetIntRegister(X86_REGISTER_EIP, frameData[1]); // TODO: Actually it's the instruction before! - - // create the next frame - frame = new StackFrameX86(STACK_FRAME_TYPE_STANDARD, cpuState); - if (frame == NULL) - return B_NO_MEMORY; - stackTrace->AddFrame(frame); } - stackTraceDeleter.Detach(); - _stackTrace = stackTrace; + _previousFrame = frameReference.Detach(); + _previousCpuState = previousCpuState; return B_OK; } diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.h b/src/apps/debugger/arch/x86/ArchitectureX86.h index bb3657b408..cf7d65f543 100644 --- a/src/apps/debugger/arch/x86/ArchitectureX86.h +++ b/src/apps/debugger/arch/x86/ArchitectureX86.h @@ -23,8 +23,11 @@ public: virtual status_t CreateCpuState(const void* cpuStateData, size_t size, CpuState*& _state); - virtual status_t CreateStackTrace(Team* team, CpuState* cpuState, - StackTrace*& _stackTrace); + virtual status_t CreateStackFrame(Image* image, + FunctionDebugInfo* function, + CpuState* cpuState, + StackFrame*& _previousFrame, + CpuState*& _previousCpuState); private: void _AddRegister(int32 index, const char* name, diff --git a/src/apps/debugger/arch/x86/CpuStateX86.cpp b/src/apps/debugger/arch/x86/CpuStateX86.cpp index fe46a915bf..ec351a7d92 100644 --- a/src/apps/debugger/arch/x86/CpuStateX86.cpp +++ b/src/apps/debugger/arch/x86/CpuStateX86.cpp @@ -42,6 +42,14 @@ CpuStateX86::~CpuStateX86() } +target_addr_t +CpuStateX86::InstructionPointer() const +{ + return IsRegisterSet(X86_REGISTER_EIP) + ? IntRegisterValue(X86_REGISTER_EIP) : 0; +} + + bool CpuStateX86::GetRegisterValue(const Register* reg, BVariant& _value) { diff --git a/src/apps/debugger/arch/x86/CpuStateX86.h b/src/apps/debugger/arch/x86/CpuStateX86.h index c69670e515..6ac30a1a51 100644 --- a/src/apps/debugger/arch/x86/CpuStateX86.h +++ b/src/apps/debugger/arch/x86/CpuStateX86.h @@ -46,6 +46,7 @@ public: CpuStateX86(const debug_cpu_state_x86& state); virtual ~CpuStateX86(); + virtual target_addr_t InstructionPointer() const; virtual bool GetRegisterValue(const Register* reg, BVariant& _value); diff --git a/src/apps/debugger/arch/x86/StackFrameX86.cpp b/src/apps/debugger/arch/x86/StackFrameX86.cpp deleted file mode 100644 index c077df327c..0000000000 --- a/src/apps/debugger/arch/x86/StackFrameX86.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Distributed under the terms of the MIT License. - */ - -#include "StackFrameX86.h" - -#include "CpuStateX86.h" - - -StackFrameX86::StackFrameX86(stack_frame_type type, CpuStateX86* cpuState) - : - fType(type), - fCpuState(cpuState), - fPreviousFrameAddress(0), - fReturnAddress(0) -{ - fCpuState->AddReference(); -} - - -StackFrameX86::~StackFrameX86() -{ - fCpuState->RemoveReference(); -} - - -void -StackFrameX86::SetPreviousAddresses(target_addr_t previousFrameAddress, - target_addr_t returnAddress) -{ - fPreviousFrameAddress = previousFrameAddress; - fReturnAddress = returnAddress; -} - - -stack_frame_type -StackFrameX86::Type() const -{ - return fType; -} - - -CpuState* -StackFrameX86::GetCpuState() const -{ - return fCpuState; -} - - -target_addr_t -StackFrameX86::InstructionPointer() const -{ - return fCpuState->IntRegisterValue(X86_REGISTER_EIP); -} - - -target_addr_t -StackFrameX86::FrameAddress() const -{ - return fCpuState->IntRegisterValue(X86_REGISTER_EBP); -} - - -target_addr_t -StackFrameX86::ReturnAddress() const -{ - return fReturnAddress; -} - - -target_addr_t -StackFrameX86::PreviousFrameAddress() const -{ - return fPreviousFrameAddress; -} diff --git a/src/apps/debugger/arch/x86/StackFrameX86.h b/src/apps/debugger/arch/x86/StackFrameX86.h deleted file mode 100644 index 82fdda977c..0000000000 --- a/src/apps/debugger/arch/x86/StackFrameX86.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Distributed under the terms of the MIT License. - */ -#ifndef STACK_FRAME_X86_H -#define STACK_FRAME_X86_H - -#include "StackFrame.h" - - -class CpuStateX86; - - -class StackFrameX86 : public StackFrame { -public: - StackFrameX86(stack_frame_type type, - CpuStateX86* cpuState); - virtual ~StackFrameX86(); - - void SetPreviousAddresses( - target_addr_t previousFrameAddress, - target_addr_t returnAddress); - - virtual stack_frame_type Type() const; - - virtual CpuState* GetCpuState() const; - - virtual target_addr_t InstructionPointer() const; - virtual target_addr_t FrameAddress() const; - virtual target_addr_t ReturnAddress() const; - virtual target_addr_t PreviousFrameAddress() const; - -private: - stack_frame_type fType; - CpuStateX86* fCpuState; - target_addr_t fPreviousFrameAddress; - target_addr_t fReturnAddress; -}; - - -#endif // STACK_FRAME_X86_H diff --git a/src/apps/debugger/debug_info/BasicFunctionDebugInfo.cpp b/src/apps/debugger/debug_info/BasicFunctionDebugInfo.cpp new file mode 100644 index 0000000000..b444db2f40 --- /dev/null +++ b/src/apps/debugger/debug_info/BasicFunctionDebugInfo.cpp @@ -0,0 +1,63 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "BasicFunctionDebugInfo.h" + +#include "DebugInfo.h" + + +BasicFunctionDebugInfo::BasicFunctionDebugInfo(DebugInfo* debugInfo, + target_addr_t address, target_size_t size, const BString& name, + const BString& prettyName) + : + fDebugInfo(debugInfo), + fAddress(address), + fSize(size), + fName(name), + fPrettyName(prettyName) +{ + fDebugInfo->AddReference(); +} + + +BasicFunctionDebugInfo::~BasicFunctionDebugInfo() +{ + fDebugInfo->RemoveReference(); +} + + +DebugInfo* +BasicFunctionDebugInfo::GetDebugInfo() const +{ + return fDebugInfo; +} + + +target_addr_t +BasicFunctionDebugInfo::Address() const +{ + return fAddress; +} + + +target_size_t +BasicFunctionDebugInfo::Size() const +{ + return fSize; +} + + +const char* +BasicFunctionDebugInfo::Name() const +{ + return fName.String(); +} + + +const char* +BasicFunctionDebugInfo::PrettyName() const +{ + return fPrettyName.String(); +} diff --git a/src/apps/debugger/debug_info/BasicFunctionDebugInfo.h b/src/apps/debugger/debug_info/BasicFunctionDebugInfo.h new file mode 100644 index 0000000000..e6a570f563 --- /dev/null +++ b/src/apps/debugger/debug_info/BasicFunctionDebugInfo.h @@ -0,0 +1,38 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef BASIC_FUNCTION_DEBUG_INFO_H +#define BASIC_FUNCTION_DEBUG_INFO_H + +#include + +#include "FunctionDebugInfo.h" + + +class BasicFunctionDebugInfo : public FunctionDebugInfo { +public: + BasicFunctionDebugInfo( + DebugInfo* debugInfo, + target_addr_t address, + target_size_t size, + const BString& name, + const BString& prettyName); + virtual ~BasicFunctionDebugInfo(); + + virtual DebugInfo* GetDebugInfo() const; + virtual target_addr_t Address() const; + virtual target_size_t Size() const; + virtual const char* Name() const; + virtual const char* PrettyName() const; + +private: + DebugInfo* fDebugInfo; + target_addr_t fAddress; + target_size_t fSize; + const BString fName; + const BString fPrettyName; +}; + + +#endif // BASIC_FUNCTION_DEBUG_INFO_H diff --git a/src/apps/debugger/debug_info/DebugInfo.cpp b/src/apps/debugger/debug_info/DebugInfo.cpp new file mode 100644 index 0000000000..91cf5974da --- /dev/null +++ b/src/apps/debugger/debug_info/DebugInfo.cpp @@ -0,0 +1,11 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "DebugInfo.h" + + +DebugInfo::~DebugInfo() +{ +} diff --git a/src/apps/debugger/debug_info/DebugInfo.h b/src/apps/debugger/debug_info/DebugInfo.h new file mode 100644 index 0000000000..60655d8ae6 --- /dev/null +++ b/src/apps/debugger/debug_info/DebugInfo.h @@ -0,0 +1,39 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef DEBUG_INFO_H +#define DEBUG_INFO_H + +#include + +#include "ArchitectureTypes.h" + + +class Architecture; +class CpuState; +class DebuggerInterface; +class FunctionDebugInfo; +class Image; +class StackFrame; + + +class DebugInfo : public Referenceable { +public: + virtual ~DebugInfo(); + + virtual FunctionDebugInfo* FindFunction(target_addr_t address) = 0; + // returns a reference + + virtual status_t CreateFrame(Image* image, + FunctionDebugInfo* function, + CpuState* cpuState, + StackFrame*& _previousFrame, + CpuState*& _previousCpuState) = 0; + // returns reference to previous frame + // and CPU state; returned CPU state + // can be NULL; can return B_UNSUPPORTED +}; + + +#endif // DEBUG_INFO_H diff --git a/src/apps/debugger/debug_info/DebuggerDebugInfo.cpp b/src/apps/debugger/debug_info/DebuggerDebugInfo.cpp new file mode 100644 index 0000000000..bcd221134e --- /dev/null +++ b/src/apps/debugger/debug_info/DebuggerDebugInfo.cpp @@ -0,0 +1,111 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "DebuggerDebugInfo.h" + +#include + +#include "BasicFunctionDebugInfo.h" +#include "DebuggerInterface.h" +#include "SymbolInfo.h" + + +struct DebuggerDebugInfo::FindByAddressPredicate : UnaryPredicate { + FindByAddressPredicate(target_addr_t address) + : + fAddress(address) + { + } + + virtual int operator()(const SymbolInfo* info) const + { + if (fAddress < info->Address()) + return -1; + return fAddress < info->Address() + info->Size() ? 0 : 1; + } + +private: + target_addr_t fAddress; +}; + + +DebuggerDebugInfo::DebuggerDebugInfo(const ImageInfo& imageInfo, + DebuggerInterface* debuggerInterface, Architecture* architecture) + : + fImageInfo(imageInfo), + fDebuggerInterface(debuggerInterface), + fArchitecture(architecture), + fSymbols(20, true) +{ +} + + +DebuggerDebugInfo::~DebuggerDebugInfo() +{ +} + + +status_t +DebuggerDebugInfo::Init() +{ + // TODO: Extend DebuggerInterface to find a symbol on demand! + + status_t error = fDebuggerInterface->GetSymbolInfos(fImageInfo.TeamID(), + fImageInfo.ImageID(), fSymbols); + if (error != B_OK) + return error; + + // sort the symbols + fSymbols.SortItems(&_CompareSymbols); + + return B_OK; +} + + +FunctionDebugInfo* +DebuggerDebugInfo::FindFunction(target_addr_t address) +{ + SymbolInfo* symbolInfo = _FindSymbol(address); + if (symbolInfo == NULL || symbolInfo->Type() != B_SYMBOL_TYPE_TEXT) + return NULL; + + return new(std::nothrow) BasicFunctionDebugInfo(this, symbolInfo->Address(), + symbolInfo->Size(), symbolInfo->Name(), symbolInfo->Name()); + // TODO: Demangle! +} + + +status_t +DebuggerDebugInfo::CreateFrame(Image* image, FunctionDebugInfo* function, + CpuState* cpuState, StackFrame*& _previousFrame, + CpuState*& _previousCpuState) +{ + return B_UNSUPPORTED; +} + + +SymbolInfo* +DebuggerDebugInfo::_FindSymbol(target_addr_t address) +{ + return fSymbols.BinarySearchByKey(address, &_CompareAddressSymbol); +} + + +/*static*/ int +DebuggerDebugInfo::_CompareSymbols(const SymbolInfo* a, const SymbolInfo* b) +{ + return a->Address() < b->Address() + ? -1 : (a->Address() == b->Address() ? 0 : 1); +} + + +/*static*/ int +DebuggerDebugInfo::_CompareAddressSymbol(const target_addr_t* address, + const SymbolInfo* info) +{ + if (*address < info->Address()) + return -1; + return *address < info->Address() + info->Size() ? 0 : 1; +} diff --git a/src/apps/debugger/debug_info/DebuggerDebugInfo.h b/src/apps/debugger/debug_info/DebuggerDebugInfo.h new file mode 100644 index 0000000000..8d964ede45 --- /dev/null +++ b/src/apps/debugger/debug_info/DebuggerDebugInfo.h @@ -0,0 +1,59 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef DEBUGGER_DEBUG_INFO_H +#define DEBUGGER_DEBUG_INFO_H + +#include + +#include + +#include "DebugInfo.h" +#include "ImageInfo.h" + + +class Architecture; +class DebuggerInterface; +class FunctionDebugInfo; +class SymbolInfo; + + +class DebuggerDebugInfo : public DebugInfo { +public: + DebuggerDebugInfo(const ImageInfo& imageInfo, + DebuggerInterface* debuggerInterface, + Architecture* architecture); + virtual ~DebuggerDebugInfo(); + + status_t Init(); + + virtual FunctionDebugInfo* FindFunction(target_addr_t address); + virtual status_t CreateFrame(Image* image, + FunctionDebugInfo* function, + CpuState* cpuState, + StackFrame*& _previousFrame, + CpuState*& _previousCpuState); + +private: + typedef BObjectList SymbolList; + + struct FindByAddressPredicate; + +private: + SymbolInfo* _FindSymbol(target_addr_t address); + static int _CompareSymbols(const SymbolInfo* a, + const SymbolInfo* b); + static int _CompareAddressSymbol( + const target_addr_t* address, + const SymbolInfo* info); + +private: + ImageInfo fImageInfo; + DebuggerInterface* fDebuggerInterface; + Architecture* fArchitecture; + SymbolList fSymbols; +}; + + +#endif // DEBUGGER_DEBUG_INFO_H diff --git a/src/apps/debugger/debug_info/FunctionDebugInfo.cpp b/src/apps/debugger/debug_info/FunctionDebugInfo.cpp new file mode 100644 index 0000000000..2d8405dc6c --- /dev/null +++ b/src/apps/debugger/debug_info/FunctionDebugInfo.cpp @@ -0,0 +1,12 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "FunctionDebugInfo.h" + + +FunctionDebugInfo::~FunctionDebugInfo() +{ +} + diff --git a/src/apps/debugger/debug_info/FunctionDebugInfo.h b/src/apps/debugger/debug_info/FunctionDebugInfo.h new file mode 100644 index 0000000000..f19fc46004 --- /dev/null +++ b/src/apps/debugger/debug_info/FunctionDebugInfo.h @@ -0,0 +1,28 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef FUNCTION_DEBUG_INFO_H +#define FUNCTION_DEBUG_INFO_H + +#include + +#include "ArchitectureTypes.h" + + +class DebugInfo; + + +class FunctionDebugInfo : public Referenceable { +public: + virtual ~FunctionDebugInfo(); + + virtual DebugInfo* GetDebugInfo() const = 0; + virtual target_addr_t Address() const = 0; + virtual target_size_t Size() const = 0; + virtual const char* Name() const = 0; + virtual const char* PrettyName() const = 0; +}; + + +#endif // FUNCTION_DEBUG_INFO_H diff --git a/src/apps/debugger/debug_info/ImageDebugInfo.cpp b/src/apps/debugger/debug_info/ImageDebugInfo.cpp new file mode 100644 index 0000000000..bc7014c7ca --- /dev/null +++ b/src/apps/debugger/debug_info/ImageDebugInfo.cpp @@ -0,0 +1,67 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "ImageDebugInfo.h" + +#include + +#include "DebuggerDebugInfo.h" + + +ImageDebugInfo::ImageDebugInfo(const ImageInfo& imageInfo, + DebuggerInterface* debuggerInterface, Architecture* architecture) + : + fImageInfo(imageInfo), + fDebuggerInterface(debuggerInterface), + fArchitecture(architecture) +{ +} + + +ImageDebugInfo::~ImageDebugInfo() +{ +} + + +status_t +ImageDebugInfo::Init() +{ + // Create debug infos for every kind debug info available, sorted + // descendingly by expressiveness. + + // TODO: DWARF, etc. + + // debugger based info + DebuggerDebugInfo* debuggerDebugInfo = new(std::nothrow) DebuggerDebugInfo( + fImageInfo, fDebuggerInterface, fArchitecture); + if (debuggerDebugInfo == NULL) + return B_NO_MEMORY; + + status_t error = debuggerDebugInfo->Init(); + if (error == B_OK && !fDebugInfos.AddItem(debuggerDebugInfo)) + error = B_NO_MEMORY; + + if (error != B_OK) { + delete debuggerDebugInfo; + if (error == B_NO_MEMORY) + return error; + // only "no memory" is fatal + } + + return B_OK; +} + + +FunctionDebugInfo* +ImageDebugInfo::FindFunction(target_addr_t address) +{ + for (int32 i = 0; DebugInfo* debugInfo = fDebugInfos.ItemAt(i); i++) { + FunctionDebugInfo* functionInfo = debugInfo->FindFunction(address); + if (functionInfo) + return functionInfo; + } + + return NULL; +} diff --git a/src/apps/debugger/debug_info/ImageDebugInfo.h b/src/apps/debugger/debug_info/ImageDebugInfo.h new file mode 100644 index 0000000000..e38db02102 --- /dev/null +++ b/src/apps/debugger/debug_info/ImageDebugInfo.h @@ -0,0 +1,46 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef IMAGE_DEBUG_INFO_H +#define IMAGE_DEBUG_INFO_H + +#include + +#include +#include + +#include "ArchitectureTypes.h" +#include "ImageInfo.h" + + +class Architecture; +class DebuggerInterface; +class DebugInfo; +class FunctionDebugInfo; + + +class ImageDebugInfo : public Referenceable { +public: + ImageDebugInfo(const ImageInfo& imageInfo, + DebuggerInterface* debuggerInterface, + Architecture* architecture); + ~ImageDebugInfo(); + + status_t Init(); + + FunctionDebugInfo* FindFunction(target_addr_t address); + // returns a reference + +private: + typedef BObjectList DebugInfoList; + +private: + ImageInfo fImageInfo; + DebuggerInterface* fDebuggerInterface; + Architecture* fArchitecture; + DebugInfoList fDebugInfos; +}; + + +#endif // IMAGE_DEBUG_INFO_H diff --git a/src/apps/debugger/debug_info/ImageDebugInfoProvider.cpp b/src/apps/debugger/debug_info/ImageDebugInfoProvider.cpp new file mode 100644 index 0000000000..bd421df174 --- /dev/null +++ b/src/apps/debugger/debug_info/ImageDebugInfoProvider.cpp @@ -0,0 +1,11 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "ImageDebugInfoProvider.h" + + +ImageDebugInfoProvider::~ImageDebugInfoProvider() +{ +} diff --git a/src/apps/debugger/debug_info/ImageDebugInfoProvider.h b/src/apps/debugger/debug_info/ImageDebugInfoProvider.h new file mode 100644 index 0000000000..4763a1556e --- /dev/null +++ b/src/apps/debugger/debug_info/ImageDebugInfoProvider.h @@ -0,0 +1,25 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef IMAGE_DEBUG_INFO_PROVIDER_H +#define IMAGE_DEBUG_INFO_PROVIDER_H + +#include + + +class Image; +class ImageDebugInfo; + + +class ImageDebugInfoProvider { +public: + virtual ~ImageDebugInfoProvider(); + + virtual status_t GetImageDebugInfo(Image* image, + ImageDebugInfo*& _info) = 0; + // returns a reference +}; + + +#endif // IMAGE_DEBUG_INFO_PROVIDER_H diff --git a/src/apps/debugger/debugger_interface/DebuggerInterface.cpp b/src/apps/debugger/debugger_interface/DebuggerInterface.cpp index 8bba417a5c..0acef63861 100644 --- a/src/apps/debugger/debugger_interface/DebuggerInterface.cpp +++ b/src/apps/debugger/debugger_interface/DebuggerInterface.cpp @@ -20,6 +20,7 @@ #include "CpuState.h" #include "DebugEvent.h" #include "ImageInfo.h" +#include "SymbolInfo.h" #include "ThreadInfo.h" @@ -386,7 +387,8 @@ DebuggerInterface::GetImageInfos(BObjectList& infos) int32 cookie = 0; while (get_next_image_info(fTeamID, &cookie, &imageInfo) == B_OK) { ImageInfo* info = new(std::nothrow) ImageInfo(fTeamID, imageInfo.id, - imageInfo.name); + imageInfo.name, (addr_t)imageInfo.text, imageInfo.text_size, + (addr_t)imageInfo.data, imageInfo.data_size); if (info == NULL || !infos.AddItem(info)) { delete info; return B_NO_MEMORY; @@ -397,6 +399,51 @@ DebuggerInterface::GetImageInfos(BObjectList& infos) } +status_t +DebuggerInterface::GetSymbolInfos(team_id team, image_id image, + BObjectList& infos) +{ + // create a lookup context +// TODO: It's too expensive to create a lookup context for each image! + debug_symbol_lookup_context* lookupContext; + status_t error = debug_create_symbol_lookup_context(team, &lookupContext); + if (error != B_OK) + return error; + + // create a symbol iterator + debug_symbol_iterator* iterator; + error = debug_create_image_symbol_iterator( + lookupContext, image, &iterator); + if (error != B_OK) { + debug_delete_symbol_lookup_context(lookupContext); + return error; + } + + // get the symbols + char name[1024]; + int32 type; + void* address; + size_t size; + while (debug_next_image_symbol(iterator, name, sizeof(name), &type, + &address, &size) == B_OK) { + SymbolInfo* info = new(std::nothrow) SymbolInfo( + (target_addr_t)(addr_t)address, size, type, name); + if (info == NULL) + break; + if (!infos.AddItem(info)) { + delete info; + break; + } + } + + // delete the symbol iterator and lookup context + debug_delete_symbol_iterator(iterator); + debug_delete_symbol_lookup_context(lookupContext); + + return B_OK; +} + + status_t DebuggerInterface::GetThreadInfo(thread_id thread, ThreadInfo& info) { @@ -536,14 +583,18 @@ DebuggerInterface::_CreateDebugEvent(int32 messageCode, { const image_info& info = message.image_created.info; event = new(std::nothrow) ImageCreatedEvent(message.origin.team, - message.origin.thread, ImageInfo(fTeamID, info.id, info.name)); + message.origin.thread, + ImageInfo(fTeamID, info.id, info.name, (addr_t)info.text, + info.text_size, (addr_t)info.data, info.data_size)); break; } case B_DEBUGGER_MESSAGE_IMAGE_DELETED: { const image_info& info = message.image_deleted.info; event = new(std::nothrow) ImageDeletedEvent(message.origin.team, - message.origin.thread, ImageInfo(fTeamID, info.id, info.name)); + message.origin.thread, + ImageInfo(fTeamID, info.id, info.name, (addr_t)info.text, + info.text_size, (addr_t)info.data, info.data_size)); break; } default: diff --git a/src/apps/debugger/debugger_interface/DebuggerInterface.h b/src/apps/debugger/debugger_interface/DebuggerInterface.h index aab9315b9d..37fadec4ee 100644 --- a/src/apps/debugger/debugger_interface/DebuggerInterface.h +++ b/src/apps/debugger/debugger_interface/DebuggerInterface.h @@ -17,6 +17,7 @@ class Architecture; class CpuState; class DebugEvent; class ImageInfo; +class SymbolInfo; class ThreadInfo; @@ -41,6 +42,8 @@ public: virtual status_t GetThreadInfos(BObjectList& infos); virtual status_t GetImageInfos(BObjectList& infos); + virtual status_t GetSymbolInfos(team_id team, image_id image, + BObjectList& infos); virtual status_t GetThreadInfo(thread_id thread, ThreadInfo& info); diff --git a/src/apps/debugger/gui/team_window/StackTraceView.cpp b/src/apps/debugger/gui/team_window/StackTraceView.cpp index e40a028eef..64c036a3c2 100644 --- a/src/apps/debugger/gui/team_window/StackTraceView.cpp +++ b/src/apps/debugger/gui/team_window/StackTraceView.cpp @@ -11,6 +11,8 @@ #include "table/TableColumns.h" +#include "FunctionDebugInfo.h" +#include "Image.h" #include "StackTrace.h" @@ -66,30 +68,14 @@ public: void SetStackTrace(StackTrace* stackTrace) { // unset old frames - if (fFrames.CountItems() > 0) { - NotifyRowsRemoved(0, fFrames.CountItems()); - - for (int32 i = 0; StackFrame* frame = fFrames.ItemAt(i); i++) - frame->RemoveReference(); - - fFrames.MakeEmpty(); - } + if (fStackTrace != NULL && fStackTrace->CountFrames()) + NotifyRowsRemoved(0, fStackTrace->CountFrames()); fStackTrace = stackTrace; // set new frames - if (fStackTrace != NULL) { - for (StackFrameList::ConstIterator it - = fStackTrace->Frames().GetIterator(); - StackFrame* frame = it.Next();) { - if (!fFrames.AddItem(frame)) - return; - frame->AddReference(); - } - - if (fFrames.CountItems() > 0) - NotifyRowsAdded(0, fFrames.CountItems()); - } + if (fStackTrace != NULL && fStackTrace->CountFrames() > 0) + NotifyRowsAdded(0, fStackTrace->CountFrames()); } virtual int32 CountColumns() const @@ -99,12 +85,13 @@ public: virtual int32 CountRows() const { - return fFrames.CountItems(); + return fStackTrace != NULL ? fStackTrace->CountFrames() : 0; } virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, BVariant& value) { - StackFrame* frame = fFrames.ItemAt(rowIndex); + StackFrame* frame + = fStackTrace != NULL ? fStackTrace->FrameAt(rowIndex) : NULL; if (frame == NULL) return false; @@ -116,8 +103,33 @@ public: value.SetTo(frame->InstructionPointer()); return true; case 2: - // TODO: function name... - return false; + { + Image* image = frame->GetImage(); + FunctionDebugInfo* function = frame->Function(); + if (image == NULL && function == NULL) { + value.SetTo("?", B_VARIANT_DONT_COPY_DATA); + return true; + } + + BString name; + target_addr_t baseAddress; + if (function != NULL) { + name = function->PrettyName(); + baseAddress = function->Address(); + } else { + name = image->Name(); + baseAddress = image->Info().TextBase(); + } + + char offset[32]; + snprintf(offset, sizeof(offset), " + %#llx", + frame->InstructionPointer() - baseAddress); + + name << offset; + value.SetTo(name.String()); + + return true; + } default: return false; } @@ -125,7 +137,6 @@ public: private: StackTrace* fStackTrace; - BObjectList fFrames; };