* 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:
@@ -5,17 +5,22 @@
|
|||||||
|
|
||||||
#include "Image.h"
|
#include "Image.h"
|
||||||
|
|
||||||
|
#include "ImageDebugInfo.h"
|
||||||
|
|
||||||
|
|
||||||
Image::Image(Team* team,const ImageInfo& imageInfo)
|
Image::Image(Team* team,const ImageInfo& imageInfo)
|
||||||
:
|
:
|
||||||
fTeam(team),
|
fTeam(team),
|
||||||
fInfo(imageInfo)
|
fInfo(imageInfo),
|
||||||
|
fDebugInfo(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Image::~Image()
|
Image::~Image()
|
||||||
{
|
{
|
||||||
|
if (fDebugInfo != NULL)
|
||||||
|
fDebugInfo->RemoveReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -24,3 +29,29 @@ Image::Init()
|
|||||||
{
|
{
|
||||||
return B_OK;
|
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());
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "ImageInfo.h"
|
#include "ImageInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
class ImageDebugInfo;
|
||||||
class Team;
|
class Team;
|
||||||
|
|
||||||
|
|
||||||
@@ -24,14 +25,20 @@ public:
|
|||||||
status_t Init();
|
status_t Init();
|
||||||
|
|
||||||
|
|
||||||
Team* GetTeam() const { return fTeam; }
|
Team* GetTeam() const { return fTeam; }
|
||||||
image_id ID() const { return fInfo.ImageID(); }
|
image_id ID() const { return fInfo.ImageID(); }
|
||||||
const char* Name() const { return fInfo.Name(); }
|
const char* Name() const { return fInfo.Name(); }
|
||||||
const ImageInfo& Info() const { return fInfo; }
|
const ImageInfo& Info() const { return fInfo; }
|
||||||
|
|
||||||
|
ImageDebugInfo* GetImageDebugInfo() const { return fDebugInfo; }
|
||||||
|
void SetImageDebugInfo(ImageDebugInfo* debugInfo);
|
||||||
|
|
||||||
|
bool ContainsAddress(target_addr_t address) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Team* fTeam;
|
Team* fTeam;
|
||||||
ImageInfo fInfo;
|
ImageInfo fInfo;
|
||||||
|
ImageDebugInfo* fDebugInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ ImageInfo::ImageInfo()
|
|||||||
:
|
:
|
||||||
fTeam(-1),
|
fTeam(-1),
|
||||||
fImage(-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),
|
fTeam(other.fTeam),
|
||||||
fImage(other.fImage),
|
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),
|
fTeam(team),
|
||||||
fImage(image),
|
fImage(image),
|
||||||
fName(name)
|
fName(name),
|
||||||
|
fTextBase(textBase),
|
||||||
|
fTextSize(textSize),
|
||||||
|
fDataBase(dataBase),
|
||||||
|
fDataSize(dataSize)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
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;
|
fTeam = team;
|
||||||
fImage = image;
|
fImage = image;
|
||||||
fName = name;
|
fName = name;
|
||||||
|
fTextBase = textBase;
|
||||||
|
fTextSize = textSize;
|
||||||
|
fDataBase = dataBase;
|
||||||
|
fDataSize = dataSize;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,25 +8,44 @@
|
|||||||
#include <image.h>
|
#include <image.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
|
#include "ArchitectureTypes.h"
|
||||||
|
|
||||||
|
|
||||||
class ImageInfo {
|
class ImageInfo {
|
||||||
public:
|
public:
|
||||||
ImageInfo();
|
ImageInfo();
|
||||||
ImageInfo(const ImageInfo& other);
|
ImageInfo(const ImageInfo& other);
|
||||||
ImageInfo(team_id team, image_id image,
|
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,
|
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; }
|
team_id TeamID() const { return fTeam; }
|
||||||
image_id ImageID() const { return fImage; }
|
image_id ImageID() const { return fImage; }
|
||||||
const char* Name() const { return fName.String(); }
|
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:
|
private:
|
||||||
thread_id fTeam;
|
thread_id fTeam;
|
||||||
image_id fImage;
|
image_id fImage;
|
||||||
BString fName;
|
BString fName;
|
||||||
|
target_addr_t fTextBase;
|
||||||
|
target_size_t fTextSize;
|
||||||
|
target_addr_t fDataBase;
|
||||||
|
target_size_t fDataSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ UsePrivateSystemHeaders ;
|
|||||||
|
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch x86 ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch x86 ] ;
|
||||||
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) gui team_window ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) gui team_window ] ;
|
||||||
|
|
||||||
@@ -23,6 +24,7 @@ Application Debugger :
|
|||||||
Image.cpp
|
Image.cpp
|
||||||
ImageInfo.cpp
|
ImageInfo.cpp
|
||||||
Jobs.cpp
|
Jobs.cpp
|
||||||
|
SymbolInfo.cpp
|
||||||
Team.cpp
|
Team.cpp
|
||||||
TeamDebugger.cpp
|
TeamDebugger.cpp
|
||||||
TeamDebugModel.cpp
|
TeamDebugModel.cpp
|
||||||
@@ -40,7 +42,14 @@ Application Debugger :
|
|||||||
# arch/x86
|
# arch/x86
|
||||||
ArchitectureX86.cpp
|
ArchitectureX86.cpp
|
||||||
CpuStateX86.cpp
|
CpuStateX86.cpp
|
||||||
StackFrameX86.cpp
|
|
||||||
|
# debug_info
|
||||||
|
BasicFunctionDebugInfo.cpp
|
||||||
|
DebuggerDebugInfo.cpp
|
||||||
|
DebugInfo.cpp
|
||||||
|
FunctionDebugInfo.cpp
|
||||||
|
ImageDebugInfo.cpp
|
||||||
|
ImageDebugInfoProvider.cpp
|
||||||
|
|
||||||
# debugger_interface
|
# debugger_interface
|
||||||
DebugEvent.cpp
|
DebugEvent.cpp
|
||||||
|
|||||||
+110
-1
@@ -5,11 +5,15 @@
|
|||||||
|
|
||||||
#include "Jobs.h"
|
#include "Jobs.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
#include <AutoLocker.h>
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
#include "Architecture.h"
|
#include "Architecture.h"
|
||||||
#include "CpuState.h"
|
#include "CpuState.h"
|
||||||
#include "DebuggerInterface.h"
|
#include "DebuggerInterface.h"
|
||||||
|
#include "Image.h"
|
||||||
|
#include "ImageDebugInfo.h"
|
||||||
#include "StackTrace.h"
|
#include "StackTrace.h"
|
||||||
#include "Team.h"
|
#include "Team.h"
|
||||||
#include "Thread.h"
|
#include "Thread.h"
|
||||||
@@ -101,7 +105,7 @@ GetStackTraceJob::Do()
|
|||||||
|
|
||||||
// get the stack trace
|
// get the stack trace
|
||||||
StackTrace* stackTrace;
|
StackTrace* stackTrace;
|
||||||
status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(),
|
status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), this,
|
||||||
fCpuState, stackTrace);
|
fCpuState, stackTrace);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
@@ -115,3 +119,108 @@ GetStackTraceJob::Do()
|
|||||||
|
|
||||||
return B_OK;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,19 +5,22 @@
|
|||||||
#ifndef JOBS_H
|
#ifndef JOBS_H
|
||||||
#define JOBS_H
|
#define JOBS_H
|
||||||
|
|
||||||
|
#include "ImageDebugInfoProvider.h"
|
||||||
#include "Worker.h"
|
#include "Worker.h"
|
||||||
|
|
||||||
|
|
||||||
class Architecture;
|
class Architecture;
|
||||||
class CpuState;
|
class CpuState;
|
||||||
class DebuggerInterface;
|
class DebuggerInterface;
|
||||||
|
class Image;
|
||||||
class Thread;
|
class Thread;
|
||||||
|
|
||||||
|
|
||||||
// job types
|
// job types
|
||||||
enum {
|
enum {
|
||||||
JOB_TYPE_GET_CPU_STATE,
|
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:
|
public:
|
||||||
GetStackTraceJob(
|
GetStackTraceJob(
|
||||||
DebuggerInterface* debuggerInterface,
|
DebuggerInterface* debuggerInterface,
|
||||||
Architecture* architecture,
|
Architecture* architecture, Thread* thread);
|
||||||
Thread* thread);
|
|
||||||
virtual ~GetStackTraceJob();
|
virtual ~GetStackTraceJob();
|
||||||
|
|
||||||
virtual JobKey Key() const;
|
virtual JobKey Key() const;
|
||||||
virtual status_t Do();
|
virtual status_t Do();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// ImageDebugInfoProvider
|
||||||
|
virtual status_t GetImageDebugInfo(Image* image,
|
||||||
|
ImageDebugInfo*& _info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DebuggerInterface* fDebuggerInterface;
|
DebuggerInterface* fDebuggerInterface;
|
||||||
Architecture* fArchitecture;
|
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
|
#endif // JOBS_H
|
||||||
|
|||||||
@@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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&
|
const ImageList&
|
||||||
Team::Images() const
|
Team::Images() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ public:
|
|||||||
void RemoveImage(Image* image);
|
void RemoveImage(Image* image);
|
||||||
bool RemoveImage(image_id imageID);
|
bool RemoveImage(image_id imageID);
|
||||||
Image* ImageByID(image_id imageID) const;
|
Image* ImageByID(image_id imageID) const;
|
||||||
|
Image* ImageByAddress(target_addr_t address) const;
|
||||||
const ImageList& Images() const;
|
const ImageList& Images() const;
|
||||||
|
|
||||||
void AddListener(Listener* listener);
|
void AddListener(Listener* listener);
|
||||||
|
|||||||
@@ -5,6 +5,20 @@
|
|||||||
|
|
||||||
#include "Architecture.h"
|
#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)
|
Architecture::Architecture(DebuggerInterface* debuggerInterface)
|
||||||
:
|
:
|
||||||
@@ -23,3 +37,78 @@ Architecture::Init()
|
|||||||
{
|
{
|
||||||
return B_OK;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,7 +12,11 @@
|
|||||||
|
|
||||||
class CpuState;
|
class CpuState;
|
||||||
class DebuggerInterface;
|
class DebuggerInterface;
|
||||||
|
class FunctionDebugInfo;
|
||||||
|
class Image;
|
||||||
|
class ImageDebugInfoProvider;
|
||||||
class Register;
|
class Register;
|
||||||
|
class StackFrame;
|
||||||
class StackTrace;
|
class StackTrace;
|
||||||
class Team;
|
class Team;
|
||||||
|
|
||||||
@@ -30,8 +34,19 @@ public:
|
|||||||
|
|
||||||
virtual status_t CreateCpuState(const void* cpuStateData,
|
virtual status_t CreateCpuState(const void* cpuStateData,
|
||||||
size_t size, CpuState*& _state) = 0;
|
size_t size, CpuState*& _state) = 0;
|
||||||
virtual status_t CreateStackTrace(Team* team, CpuState* cpuState,
|
virtual status_t CreateStackFrame(Image* image,
|
||||||
StackTrace*& _stackTrace) = 0;
|
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
|
// team is not locked
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
typedef uint64 target_addr_t;
|
typedef uint64 target_addr_t;
|
||||||
|
typedef uint64 target_size_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
#include <Variant.h>
|
#include <Variant.h>
|
||||||
|
|
||||||
|
#include "ArchitectureTypes.h"
|
||||||
|
|
||||||
|
|
||||||
class Register;
|
class Register;
|
||||||
|
|
||||||
@@ -18,6 +20,7 @@ class CpuState : public Referenceable {
|
|||||||
public:
|
public:
|
||||||
virtual ~CpuState();
|
virtual ~CpuState();
|
||||||
|
|
||||||
|
virtual target_addr_t InstructionPointer() const = 0;
|
||||||
virtual bool GetRegisterValue(const Register* reg,
|
virtual bool GetRegisterValue(const Register* reg,
|
||||||
BVariant& _value) = 0;
|
BVariant& _value) = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,68 @@
|
|||||||
|
|
||||||
#include "StackFrame.h"
|
#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()
|
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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
|
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
#include <util/DoublyLinkedList.h>
|
|
||||||
|
|
||||||
#include "ArchitectureTypes.h"
|
#include "ArchitectureTypes.h"
|
||||||
|
|
||||||
@@ -22,25 +21,39 @@ enum stack_frame_type {
|
|||||||
|
|
||||||
|
|
||||||
class CpuState;
|
class CpuState;
|
||||||
|
class Image;
|
||||||
|
class FunctionDebugInfo;
|
||||||
|
|
||||||
|
|
||||||
class StackFrame : public Referenceable,
|
class StackFrame : public Referenceable {
|
||||||
public DoublyLinkedListLinkImpl<StackFrame> {
|
|
||||||
public:
|
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;
|
Image* GetImage() const { return fImage; }
|
||||||
virtual target_addr_t FrameAddress() const = 0;
|
void SetImage(Image* image);
|
||||||
virtual target_addr_t ReturnAddress() const = 0;
|
|
||||||
virtual target_addr_t PreviousFrameAddress() const = 0;
|
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
|
#endif // STACK_FRAME_H
|
||||||
|
|||||||
@@ -13,13 +13,31 @@ StackTrace::StackTrace()
|
|||||||
|
|
||||||
StackTrace::~StackTrace()
|
StackTrace::~StackTrace()
|
||||||
{
|
{
|
||||||
while (StackFrame* frame = fStackFrames.RemoveHead())
|
for (int32 i = 0; StackFrame* frame = FrameAt(i); i++)
|
||||||
frame->RemoveReference();
|
frame->RemoveReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
bool
|
||||||
StackTrace::AddFrame(StackFrame* frame)
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#ifndef STACK_TRACE_H
|
#ifndef STACK_TRACE_H
|
||||||
#define STACK_TRACE_H
|
#define STACK_TRACE_H
|
||||||
|
|
||||||
|
#include <ObjectList.h>
|
||||||
|
|
||||||
#include "StackFrame.h"
|
#include "StackFrame.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -13,15 +15,14 @@ public:
|
|||||||
StackTrace();
|
StackTrace();
|
||||||
virtual ~StackTrace();
|
virtual ~StackTrace();
|
||||||
|
|
||||||
void AddFrame(StackFrame* frame);
|
bool AddFrame(StackFrame* frame);
|
||||||
// takes over reference
|
// takes over reference (also on error)
|
||||||
|
|
||||||
const StackFrameList& Frames() const { return fStackFrames; }
|
int32 CountFrames() const;
|
||||||
|
StackFrame* FrameAt(int32 index) const;
|
||||||
|
|
||||||
StackFrame* TopFrame() const
|
private:
|
||||||
{ return fStackFrames.Head(); }
|
typedef BObjectList<StackFrame> StackFrameList;
|
||||||
StackFrame* BottomFrame() const
|
|
||||||
{ return fStackFrames.Tail(); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StackFrameList fStackFrames;
|
StackFrameList fStackFrames;
|
||||||
|
|||||||
@@ -11,8 +11,7 @@
|
|||||||
|
|
||||||
#include "CpuStateX86.h"
|
#include "CpuStateX86.h"
|
||||||
#include "DebuggerInterface.h"
|
#include "DebuggerInterface.h"
|
||||||
#include "StackFrameX86.h"
|
#include "StackFrame.h"
|
||||||
#include "StackTrace.h"
|
|
||||||
|
|
||||||
|
|
||||||
ArchitectureX86::ArchitectureX86(DebuggerInterface* debuggerInterface)
|
ArchitectureX86::ArchitectureX86(DebuggerInterface* debuggerInterface)
|
||||||
@@ -104,59 +103,38 @@ ArchitectureX86::CreateCpuState(const void* cpuStateData, size_t size,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ArchitectureX86::CreateStackTrace(Team* team, CpuState* _cpuState,
|
ArchitectureX86::CreateStackFrame(Image* image, FunctionDebugInfo* function,
|
||||||
StackTrace*& _stackTrace)
|
CpuState* _cpuState, StackFrame*& _previousFrame,
|
||||||
|
CpuState*& _previousCpuState)
|
||||||
{
|
{
|
||||||
CpuStateX86* cpuState = dynamic_cast<CpuStateX86*>(_cpuState);
|
CpuStateX86* cpuState = dynamic_cast<CpuStateX86*>(_cpuState);
|
||||||
|
|
||||||
// create the object
|
uint32 framePointer = cpuState->IntRegisterValue(X86_REGISTER_EBP);
|
||||||
StackTrace* stackTrace = new(std::nothrow) StackTrace;
|
|
||||||
if (stackTrace == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
ObjectDeleter<StackTrace> stackTraceDeleter(stackTrace);
|
|
||||||
|
|
||||||
// create the top frame
|
// create the stack frame
|
||||||
StackFrameX86* frame = new StackFrameX86(STACK_FRAME_TYPE_TOP, cpuState);
|
StackFrame* frame = new(std::nothrow) StackFrame(
|
||||||
|
STACK_FRAME_TYPE_STANDARD, cpuState, framePointer);
|
||||||
if (frame == NULL)
|
if (frame == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
stackTrace->AddFrame(frame);
|
Reference<StackFrame> frameReference(frame, true);
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
// 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
|
// prepare the previous CPU state
|
||||||
cpuState = new(std::nothrow) CpuStateX86;
|
previousCpuState = new(std::nothrow) CpuStateX86;
|
||||||
if (cpuState == NULL)
|
if (previousCpuState == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
Reference<CpuState> cpuStateReference(cpuState, true);
|
|
||||||
|
|
||||||
cpuState->SetIntRegister(X86_REGISTER_EBP, frameData[0]);
|
previousCpuState->SetIntRegister(X86_REGISTER_EBP, frameData[0]);
|
||||||
cpuState->SetIntRegister(X86_REGISTER_EIP, frameData[1]);
|
previousCpuState->SetIntRegister(X86_REGISTER_EIP, frameData[1]);
|
||||||
// TODO: Actually it's the instruction before!
|
// 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();
|
_previousFrame = frameReference.Detach();
|
||||||
_stackTrace = stackTrace;
|
_previousCpuState = previousCpuState;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,11 @@ public:
|
|||||||
|
|
||||||
virtual status_t CreateCpuState(const void* cpuStateData,
|
virtual status_t CreateCpuState(const void* cpuStateData,
|
||||||
size_t size, CpuState*& _state);
|
size_t size, CpuState*& _state);
|
||||||
virtual status_t CreateStackTrace(Team* team, CpuState* cpuState,
|
virtual status_t CreateStackFrame(Image* image,
|
||||||
StackTrace*& _stackTrace);
|
FunctionDebugInfo* function,
|
||||||
|
CpuState* cpuState,
|
||||||
|
StackFrame*& _previousFrame,
|
||||||
|
CpuState*& _previousCpuState);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _AddRegister(int32 index, const char* name,
|
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
|
bool
|
||||||
CpuStateX86::GetRegisterValue(const Register* reg, BVariant& _value)
|
CpuStateX86::GetRegisterValue(const Register* reg, BVariant& _value)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ public:
|
|||||||
CpuStateX86(const debug_cpu_state_x86& state);
|
CpuStateX86(const debug_cpu_state_x86& state);
|
||||||
virtual ~CpuStateX86();
|
virtual ~CpuStateX86();
|
||||||
|
|
||||||
|
virtual target_addr_t InstructionPointer() const;
|
||||||
virtual bool GetRegisterValue(const Register* reg,
|
virtual bool GetRegisterValue(const Register* reg,
|
||||||
BVariant& _value);
|
BVariant& _value);
|
||||||
|
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
|
||||||
* 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, [email protected].
|
|
||||||
* 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, [email protected].
|
||||||
|
* 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, [email protected].
|
||||||
|
* 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()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -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 "CpuState.h"
|
||||||
#include "DebugEvent.h"
|
#include "DebugEvent.h"
|
||||||
#include "ImageInfo.h"
|
#include "ImageInfo.h"
|
||||||
|
#include "SymbolInfo.h"
|
||||||
#include "ThreadInfo.h"
|
#include "ThreadInfo.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -386,7 +387,8 @@ DebuggerInterface::GetImageInfos(BObjectList<ImageInfo>& infos)
|
|||||||
int32 cookie = 0;
|
int32 cookie = 0;
|
||||||
while (get_next_image_info(fTeamID, &cookie, &imageInfo) == B_OK) {
|
while (get_next_image_info(fTeamID, &cookie, &imageInfo) == B_OK) {
|
||||||
ImageInfo* info = new(std::nothrow) ImageInfo(fTeamID, imageInfo.id,
|
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)) {
|
if (info == NULL || !infos.AddItem(info)) {
|
||||||
delete info;
|
delete info;
|
||||||
return B_NO_MEMORY;
|
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
|
status_t
|
||||||
DebuggerInterface::GetThreadInfo(thread_id thread, ThreadInfo& info)
|
DebuggerInterface::GetThreadInfo(thread_id thread, ThreadInfo& info)
|
||||||
{
|
{
|
||||||
@@ -536,14 +583,18 @@ DebuggerInterface::_CreateDebugEvent(int32 messageCode,
|
|||||||
{
|
{
|
||||||
const image_info& info = message.image_created.info;
|
const image_info& info = message.image_created.info;
|
||||||
event = new(std::nothrow) ImageCreatedEvent(message.origin.team,
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case B_DEBUGGER_MESSAGE_IMAGE_DELETED:
|
case B_DEBUGGER_MESSAGE_IMAGE_DELETED:
|
||||||
{
|
{
|
||||||
const image_info& info = message.image_deleted.info;
|
const image_info& info = message.image_deleted.info;
|
||||||
event = new(std::nothrow) ImageDeletedEvent(message.origin.team,
|
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;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ class Architecture;
|
|||||||
class CpuState;
|
class CpuState;
|
||||||
class DebugEvent;
|
class DebugEvent;
|
||||||
class ImageInfo;
|
class ImageInfo;
|
||||||
|
class SymbolInfo;
|
||||||
class ThreadInfo;
|
class ThreadInfo;
|
||||||
|
|
||||||
|
|
||||||
@@ -41,6 +42,8 @@ public:
|
|||||||
|
|
||||||
virtual status_t GetThreadInfos(BObjectList<ThreadInfo>& infos);
|
virtual status_t GetThreadInfos(BObjectList<ThreadInfo>& infos);
|
||||||
virtual status_t GetImageInfos(BObjectList<ImageInfo>& 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,
|
virtual status_t GetThreadInfo(thread_id thread,
|
||||||
ThreadInfo& info);
|
ThreadInfo& info);
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include "table/TableColumns.h"
|
#include "table/TableColumns.h"
|
||||||
|
|
||||||
|
#include "FunctionDebugInfo.h"
|
||||||
|
#include "Image.h"
|
||||||
#include "StackTrace.h"
|
#include "StackTrace.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -66,30 +68,14 @@ public:
|
|||||||
void SetStackTrace(StackTrace* stackTrace)
|
void SetStackTrace(StackTrace* stackTrace)
|
||||||
{
|
{
|
||||||
// unset old frames
|
// unset old frames
|
||||||
if (fFrames.CountItems() > 0) {
|
if (fStackTrace != NULL && fStackTrace->CountFrames())
|
||||||
NotifyRowsRemoved(0, fFrames.CountItems());
|
NotifyRowsRemoved(0, fStackTrace->CountFrames());
|
||||||
|
|
||||||
for (int32 i = 0; StackFrame* frame = fFrames.ItemAt(i); i++)
|
|
||||||
frame->RemoveReference();
|
|
||||||
|
|
||||||
fFrames.MakeEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
fStackTrace = stackTrace;
|
fStackTrace = stackTrace;
|
||||||
|
|
||||||
// set new frames
|
// set new frames
|
||||||
if (fStackTrace != NULL) {
|
if (fStackTrace != NULL && fStackTrace->CountFrames() > 0)
|
||||||
for (StackFrameList::ConstIterator it
|
NotifyRowsAdded(0, fStackTrace->CountFrames());
|
||||||
= fStackTrace->Frames().GetIterator();
|
|
||||||
StackFrame* frame = it.Next();) {
|
|
||||||
if (!fFrames.AddItem(frame))
|
|
||||||
return;
|
|
||||||
frame->AddReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fFrames.CountItems() > 0)
|
|
||||||
NotifyRowsAdded(0, fFrames.CountItems());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int32 CountColumns() const
|
virtual int32 CountColumns() const
|
||||||
@@ -99,12 +85,13 @@ public:
|
|||||||
|
|
||||||
virtual int32 CountRows() const
|
virtual int32 CountRows() const
|
||||||
{
|
{
|
||||||
return fFrames.CountItems();
|
return fStackTrace != NULL ? fStackTrace->CountFrames() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, BVariant& value)
|
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)
|
if (frame == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -116,8 +103,33 @@ public:
|
|||||||
value.SetTo(frame->InstructionPointer());
|
value.SetTo(frame->InstructionPointer());
|
||||||
return true;
|
return true;
|
||||||
case 2:
|
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:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -125,7 +137,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
StackTrace* fStackTrace;
|
StackTrace* fStackTrace;
|
||||||
BObjectList<StackFrame> fFrames;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user