* Added DebuggerInterface::GetSymbolInfos() to get the symbols for an image.

* Added the beginnings of the debug info abstraction. Currently we can only load
  the symbols via the debugger.
* Added a job to retrieve debug info for an image. Extended the GetStackTraceJob
  to support waiting for image debug info to be loaded.
* Extended ImageInfo by text/data address and size.
* Removed StackFrameX86 and made StackFrame a simple non-polymorphic class
  featuring all the needed data. The really architecture-dependent is in the
  referenced CpuState already. Added Image* and FunctionDebugInfo* attributes,
  referring to the image respectively debug info for the function hit by the
  instruction pointer.
* Switched StrackTrace's StackFrame management from DoublyLinkedList to
  BObjectList. This makes it more comfortable to use.
* Changed the code for creating stack traces:
  - The creation of the StackTrace object and the main loop to collect the
    frames are now located in the no longer virtual
    Architecture::CreateStackTrace().
  - The decision how to create a StackFrame is based on the instruction pointer.
    If it hit a function for which debug info is available, the respective
    DebugInfo::CreateStackFrame() is used, otherwise we fall back to the new
    virtual Architecture::CreateStackFrame().
* Adjusted the stack trace view to also show function names (mangled ATM).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31142 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-06-20 17:20:49 +00:00
parent 8b5ee1118a
commit 0b60fa86e9
40 changed files with 1170 additions and 232 deletions
+32 -1
View File
@@ -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());
}
+11 -4
View File
@@ -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;
};
+25 -5
View File
@@ -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;
}
+21 -2
View File
@@ -8,25 +8,44 @@
#include <image.h>
#include <String.h>
#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;
};
+10 -1
View File
@@ -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
+110 -1
View File
@@ -5,11 +5,15 @@
#include "Jobs.h"
#include <new>
#include <AutoLocker.h>
#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<Team> teamLocker(fThread->GetTeam());
while (image->GetImageDebugInfo() == NULL) {
// The info has not yet been loaded -- check whether a job has already
// been scheduled.
AutoLocker<Worker> 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<Team> 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;
}
+29 -4
View File
@@ -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
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* 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()
{
}
+33
View File
@@ -0,0 +1,33 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef SYMBOL_INFO_H
#define SYMBOL_INFO_H
#include <String.h>
#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
+13
View File
@@ -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
{
+1
View File
@@ -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);
+89
View File
@@ -5,6 +5,20 @@
#include "Architecture.h"
#include <new>
#include <AutoDeleter.h>
#include <AutoLocker.h>
#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<CpuState> cpuStateReference(cpuState);
// create the object
StackTrace* stackTrace = new(std::nothrow) StackTrace;
if (stackTrace == NULL)
return B_NO_MEMORY;
ObjectDeleter<StackTrace> 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<Team> teamLocker(team);
Image* image = team->ImageByAddress(instructionPointer);
Reference<Image> imageReference(image);
teamLocker.Unlock();
// get the image debug info
ImageDebugInfo* imageDebugInfo = NULL;
if (image != NULL)
imageInfoProvider->GetImageDebugInfo(image, imageDebugInfo);
Reference<ImageDebugInfo> imageDebugInfoReference(imageDebugInfo, true);
// get the function
FunctionDebugInfo* function = NULL;
if (imageDebugInfo != NULL)
function = imageDebugInfo->FindFunction(instructionPointer);
Reference<FunctionDebugInfo> 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;
}
+17 -2
View File
@@ -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:
@@ -7,6 +7,7 @@
typedef uint64 target_addr_t;
typedef uint64 target_size_t;
+3
View File
@@ -10,6 +10,8 @@
#include <Referenceable.h>
#include <Variant.h>
#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;
};
+61
View File
@@ -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();
}
+26 -13
View File
@@ -8,7 +8,6 @@
#include <OS.h>
#include <Referenceable.h>
#include <util/DoublyLinkedList.h>
#include "ArchitectureTypes.h"
@@ -22,25 +21,39 @@ enum stack_frame_type {
class CpuState;
class Image;
class FunctionDebugInfo;
class StackFrame : public Referenceable,
public DoublyLinkedListLinkImpl<StackFrame> {
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<StackFrame> StackFrameList;
#endif // STACK_FRAME_H
+21 -3
View File
@@ -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);
}
+8 -7
View File
@@ -5,6 +5,8 @@
#ifndef STACK_TRACE_H
#define STACK_TRACE_H
#include <ObjectList.h>
#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<StackFrame> StackFrameList;
private:
StackFrameList fStackFrames;
+20 -42
View File
@@ -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<CpuStateX86*>(_cpuState);
// create the object
StackTrace* stackTrace = new(std::nothrow) StackTrace;
if (stackTrace == NULL)
return B_NO_MEMORY;
ObjectDeleter<StackTrace> 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<StackFrame> 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<CpuState> 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;
}
+5 -2
View File
@@ -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,
@@ -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)
{
+1
View File
@@ -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);
@@ -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;
}
@@ -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
@@ -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();
}
@@ -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 <String.h>
#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
@@ -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()
{
}
+39
View File
@@ -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 <Referenceable.h>
#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
@@ -0,0 +1,111 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "DebuggerDebugInfo.h"
#include <new>
#include "BasicFunctionDebugInfo.h"
#include "DebuggerInterface.h"
#include "SymbolInfo.h"
struct DebuggerDebugInfo::FindByAddressPredicate : UnaryPredicate<SymbolInfo> {
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;
}
@@ -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 <String.h>
#include <ObjectList.h>
#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<SymbolInfo> 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
@@ -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()
{
}
@@ -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 <Referenceable.h>
#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
@@ -0,0 +1,67 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "ImageDebugInfo.h"
#include <new>
#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;
}
@@ -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 <String.h>
#include <ObjectList.h>
#include <Referenceable.h>
#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<DebugInfo> DebugInfoList;
private:
ImageInfo fImageInfo;
DebuggerInterface* fDebuggerInterface;
Architecture* fArchitecture;
DebugInfoList fDebugInfos;
};
#endif // IMAGE_DEBUG_INFO_H
@@ -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()
{
}
@@ -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 <SupportDefs.h>
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
@@ -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<ImageInfo>& 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<ImageInfo>& infos)
}
status_t
DebuggerInterface::GetSymbolInfos(team_id team, image_id image,
BObjectList<SymbolInfo>& 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:
@@ -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<ThreadInfo>& infos);
virtual status_t GetImageInfos(BObjectList<ImageInfo>& infos);
virtual status_t GetSymbolInfos(team_id team, image_id image,
BObjectList<SymbolInfo>& infos);
virtual status_t GetThreadInfo(thread_id thread,
ThreadInfo& info);
@@ -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<StackFrame> fFrames;
};