* Since disassembled code is actually function instance specific,

FunctionInstance does now also have a (DisassembledCode) source code
  attribute. Function keeps its attribute, but it explicitly is a
  FileSourceCode now.
* SourceCode:
  - Removed GetStatementAtLocation(). Instead DisassembledCode has a
    StatementAtLocation() now. As well as a StatementAtAddress() and
    StatementAddressRange(). Rather cast to the subclass (in two instances)
    instead of having those methods in the base class. In most cases we already
    have the subclasses now, anyway.
  - Added Lock()/Unlock(), which are implemented in FileSourceCode. The
    statement ranges are no longer immutable, so we have to lock.
* TeamDebugModel:
  - Revived GetBreakpointsInAddressRange().
  - GetBreakpointsForSourceCode(): Optimized for DisassembledCode and fixed
    in the FileSourceCode case. We need to compare with the functions' source
    file instead of their source code, since they might not have the source
    code set yet. Fixed two instances of the same problem in SourceView. Setting
    breakpoints in functions that have no associated source code yet, works now.
* Team:
  - GetStatementAtAddress(): Optimized by using the DisassembledCode, if
    available.
  - GetStatementAtSourceLocation(): If the supplied source code is
    DisassembledCode, we have to get the statement from it directly, since
    we can't get that information from the image debug info.
* TeamDebugInfo: Added LoadSourceCode() and DisassembleFunction(), the new way
  to get FileSourceCode respectively DisassembledCode. SpecificTeamDebugInfo
  has lost LoadSourceCode() and gained service methods AddSourceCodeInfo() and
  ReadCode(). This avoids unnecessary code duplication in the subclasses.
  Moreover it allows for joining source location info source files from
  different images (and compilation units) -- interesting for inline functions
  in headers.
* Adjusted LoadSourceCodeJob and TeamDebugger::FunctionSourceCodeRequested()
  accordingly.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31514 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-07-11 00:05:26 +00:00
parent 1dc94c6b69
commit 18ca318a3d
30 changed files with 564 additions and 348 deletions
+39 -25
View File
@@ -12,6 +12,8 @@
#include "Architecture.h"
#include "CpuState.h"
#include "DebuggerInterface.h"
#include "DisassembledCode.h"
#include "FileSourceCode.h"
#include "Function.h"
#include "Image.h"
#include "ImageDebugInfo.h"
@@ -319,61 +321,73 @@ LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image,
LoadSourceCodeJob::LoadSourceCodeJob(
DebuggerInterface* debuggerInterface, Architecture* architecture,
Team* team, Function* function)
Team* team, FunctionInstance* functionInstance, bool loadForFunction)
:
fDebuggerInterface(debuggerInterface),
fArchitecture(architecture),
fTeam(team),
fFunction(function)
fFunctionInstance(functionInstance),
fLoadForFunction(loadForFunction)
{
fFunction->AddReference();
fFunctionInstance->AddReference();
}
LoadSourceCodeJob::~LoadSourceCodeJob()
{
fFunction->RemoveReference();
fFunctionInstance->RemoveReference();
}
JobKey
LoadSourceCodeJob::Key() const
{
return JobKey(fFunction, JOB_TYPE_LOAD_SOURCE_CODE);
return JobKey(fFunctionInstance, JOB_TYPE_LOAD_SOURCE_CODE);
}
status_t
LoadSourceCodeJob::Do()
{
// Get the function debug info for an instance which we can use to load the
// source code.
// if requested, try loading the source code for the function
Function* function = fFunctionInstance->GetFunction();
if (fLoadForFunction) {
FileSourceCode* sourceCode;
status_t error = fTeam->DebugInfo()->LoadSourceCode(
function->SourceFile(), sourceCode);
AutoLocker<Team> locker(fTeam);
if (error == B_OK) {
function->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED);
sourceCode->RemoveReference();
return B_OK;
}
function->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
}
// Only try to load the function instance code, if it's not overridden yet.
AutoLocker<Team> locker(fTeam);
status_t error = B_OK;
FunctionDebugInfo* functionDebugInfo = NULL;
if (FunctionInstance* instance = fFunction->FirstInstance()) {
functionDebugInfo = instance->GetFunctionDebugInfo();
} else
error = B_ENTRY_NOT_FOUND;
Reference<FunctionDebugInfo> functionDebugInfoReference(functionDebugInfo);
if (fFunctionInstance->SourceCodeState() != FUNCTION_SOURCE_LOADING)
return B_OK;
locker.Unlock();
// load the source code, if we can
SourceCode* sourceCode = NULL;
if (error == B_OK) {
error = functionDebugInfo->GetSpecificImageDebugInfo()->LoadSourceCode(
functionDebugInfo, sourceCode);
}
// disassemble the function
DisassembledCode* sourceCode = NULL;
status_t error = fTeam->DebugInfo()->DisassembleFunction(fFunctionInstance,
sourceCode);
// set the result
locker.Lock();
if (error == B_OK) {
fFunction->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED);
sourceCode->RemoveReference();
if (fFunctionInstance->SourceCodeState() == FUNCTION_SOURCE_LOADING) {
fFunctionInstance->SetSourceCode(sourceCode,
FUNCTION_SOURCE_LOADED);
sourceCode->RemoveReference();
}
} else
fFunction->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
fFunctionInstance->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
return error;
}
+5 -2
View File
@@ -13,6 +13,7 @@ class Architecture;
class CpuState;
class DebuggerInterface;
class Function;
class FunctionInstance;
class Image;
class StackFrame;
class Team;
@@ -113,7 +114,8 @@ public:
LoadSourceCodeJob(
DebuggerInterface* debuggerInterface,
Architecture* architecture, Team* team,
Function* function);
FunctionInstance* functionInstance,
bool loadForFunction);
virtual ~LoadSourceCodeJob();
virtual JobKey Key() const;
@@ -123,7 +125,8 @@ private:
DebuggerInterface* fDebuggerInterface;
Architecture* fArchitecture;
Team* fTeam;
Function* fFunction;
FunctionInstance* fFunctionInstance;
bool fLoadForFunction;
};
+15 -3
View File
@@ -489,15 +489,27 @@ TeamDebugger::FunctionSourceCodeRequested(TeamWindow* window,
// mark loading
AutoLocker< ::Team> locker(fTeam);
if (function->SourceCodeState() != FUNCTION_SOURCE_NOT_LOADED)
if (functionInstance->SourceCodeState() != FUNCTION_SOURCE_NOT_LOADED)
return;
function->SetSourceCode(NULL, FUNCTION_SOURCE_LOADING);
if (function->SourceCodeState() == FUNCTION_SOURCE_LOADED)
return;
functionInstance->SetSourceCode(NULL, FUNCTION_SOURCE_LOADING);
bool loadForFunction = false;
if (function->SourceCodeState() == FUNCTION_SOURCE_NOT_LOADED) {
loadForFunction = true;
function->SetSourceCode(NULL, FUNCTION_SOURCE_LOADING);
}
locker.Unlock();
// schedule the job
if (fWorker->ScheduleJob(
new(std::nothrow) LoadSourceCodeJob(fDebuggerInterface,
fDebuggerInterface->GetArchitecture(), fTeam, function),
fDebuggerInterface->GetArchitecture(), fTeam, functionInstance,
loadForFunction),
this) != B_OK) {
// scheduling failed -- mark unavailable
locker.Lock();
+2 -2
View File
@@ -13,12 +13,12 @@
class CpuState;
class DisassembledCode;
class FunctionDebugInfo;
class Image;
class ImageDebugInfoProvider;
class InstructionInfo;
class Register;
class SourceCode;
class StackFrame;
class StackTrace;
class Statement;
@@ -57,7 +57,7 @@ public:
virtual status_t DisassembleCode(FunctionDebugInfo* function,
const void* buffer, size_t bufferSize,
SourceCode*& _sourceCode) = 0;
DisassembledCode*& _sourceCode) = 0;
virtual status_t GetStatement(FunctionDebugInfo* function,
target_addr_t address,
Statement*& _statement) = 0;
@@ -271,7 +271,7 @@ ArchitectureX86::UpdateStackFrameCpuState(const StackFrame* frame,
status_t
ArchitectureX86::DisassembleCode(FunctionDebugInfo* function,
const void* buffer, size_t bufferSize, SourceCode*& _sourceCode)
const void* buffer, size_t bufferSize, DisassembledCode*& _sourceCode)
{
DisassembledCode* source = new(std::nothrow) DisassembledCode;
if (source == NULL)
+1 -1
View File
@@ -35,7 +35,7 @@ public:
virtual status_t DisassembleCode(FunctionDebugInfo* function,
const void* buffer, size_t bufferSize,
SourceCode*& _sourceCode);
DisassembledCode*& _sourceCode);
virtual status_t GetStatement(FunctionDebugInfo* function,
target_addr_t address,
Statement*& _statement);
@@ -87,29 +87,6 @@ DebuggerImageDebugInfo::CreateFrame(Image* image, FunctionDebugInfo* function,
}
status_t
DebuggerImageDebugInfo::LoadSourceCode(FunctionDebugInfo* function,
SourceCode*& _sourceCode)
{
// allocate a buffer for the function code
static const target_size_t kMaxBufferSize = 64 * 1024;
target_size_t bufferSize = std::min(function->Size(), kMaxBufferSize);
void* buffer = malloc(bufferSize);
if (buffer == NULL)
return B_NO_MEMORY;
MemoryDeleter bufferDeleter(buffer);
// read the function code
ssize_t bytesRead = fDebuggerInterface->ReadMemory(function->Address(),
buffer, bufferSize);
if (bytesRead < 0)
return bytesRead;
return fArchitecture->DisassembleCode(function, buffer, bytesRead,
_sourceCode);
}
status_t
DebuggerImageDebugInfo::GetStatement(FunctionDebugInfo* function,
target_addr_t address, Statement*& _statement)
@@ -127,6 +104,22 @@ DebuggerImageDebugInfo::GetStatementAtSourceLocation(
}
ssize_t
DebuggerImageDebugInfo::ReadCode(target_addr_t address, void* buffer,
size_t size)
{
return fDebuggerInterface->ReadMemory(address, buffer, size);
}
status_t
DebuggerImageDebugInfo::AddSourceCodeInfo(LocatableFile* file,
FileSourceCode* sourceCode)
{
return B_UNSUPPORTED;
}
/*static*/ int
DebuggerImageDebugInfo::_CompareSymbols(const SymbolInfo* a,
const SymbolInfo* b)
@@ -31,8 +31,6 @@ public:
CpuState* cpuState,
StackFrame*& _previousFrame,
CpuState*& _previousCpuState);
virtual status_t LoadSourceCode(FunctionDebugInfo* function,
SourceCode*& _sourceCode);
virtual status_t GetStatement(FunctionDebugInfo* function,
target_addr_t address,
Statement*& _statement);
@@ -41,6 +39,12 @@ public:
const SourceLocation& sourceLocation,
Statement*& _statement);
virtual ssize_t ReadCode(target_addr_t address, void* buffer,
size_t size);
virtual status_t AddSourceCodeInfo(LocatableFile* file,
FileSourceCode* sourceCode);
private:
static int _CompareSymbols(const SymbolInfo* a,
const SymbolInfo* b);
@@ -3,8 +3,10 @@
* Distributed under the terms of the MIT License.
*/
#include "DwarfImageDebugInfo.h"
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
@@ -30,84 +32,6 @@
#include "StringUtils.h"
// #pragma mark - SourceCodeEntry
struct DwarfImageDebugInfo::SourceCodeKey {
CompilationUnit* unit;
LocatableFile* file;
SourceCodeKey(CompilationUnit* unit, LocatableFile* file)
:
unit(unit),
file(file)
{
file->AcquireReference();
}
~SourceCodeKey()
{
file->ReleaseReference();
}
uint32 HashValue() const
{
return (uint32)((addr_t)unit ^ (addr_t)file);
}
bool operator==(const SourceCodeKey& other) const
{
return unit == other.unit && file == other.file;
}
};
struct DwarfImageDebugInfo::SourceCodeEntry : SourceCodeKey,
HashTableLink<SourceCodeEntry> {
FileSourceCode* sourceCode;
SourceCodeEntry(CompilationUnit* unit, LocatableFile* file,
FileSourceCode* sourceCode)
:
SourceCodeKey(unit, file),
sourceCode(sourceCode)
{
}
};
// #pragma mark - SourceCodeHashDefinition
struct DwarfImageDebugInfo::SourceCodeHashDefinition {
typedef SourceCodeKey KeyType;
typedef SourceCodeEntry ValueType;
size_t HashKey(const SourceCodeKey& key) const
{
return key.HashValue();
}
size_t Hash(const SourceCodeEntry* value) const
{
return value->HashValue();
}
bool Compare(const SourceCodeKey& key, const SourceCodeEntry* value) const
{
return key == *value;
}
HashTableLink<SourceCodeEntry>* GetLink(SourceCodeEntry* value) const
{
return value;
}
};
// #pragma mark - DwarfImageDebugInfo
DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo,
Architecture* architecture, FileManager* fileManager, DwarfFile* file)
:
@@ -117,22 +41,13 @@ DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo,
fFileManager(fileManager),
fFile(file),
fTextSegment(NULL),
fRelocationDelta(0),
fSourceCodes(NULL)
fRelocationDelta(0)
{
}
DwarfImageDebugInfo::~DwarfImageDebugInfo()
{
SourceCodeEntry* entry = fSourceCodes->Clear(true);
while (entry != NULL) {
SourceCodeEntry* next = entry->fNext;
entry->sourceCode->ReleaseReference();
entry = next;
}
delete fSourceCodes;
}
@@ -143,14 +58,6 @@ DwarfImageDebugInfo::Init()
if (error != B_OK)
return error;
fSourceCodes = new (std::nothrow) SourceCodeTable;
if (fSourceCodes == NULL)
return B_NO_MEMORY;
error = fSourceCodes->Init();
if (error != B_OK)
return error;
fTextSegment = fFile->GetElfFile()->TextSegment();
if (fTextSegment == NULL)
return B_ENTRY_NOT_FOUND;
@@ -286,38 +193,6 @@ DwarfImageDebugInfo::CreateFrame(Image* image, FunctionDebugInfo* function,
}
status_t
DwarfImageDebugInfo::LoadSourceCode(FunctionDebugInfo* function,
SourceCode*& _sourceCode)
{
AutoLocker<BLocker> locker(fLock);
status_t error = _LoadSourceCode(function, _sourceCode);
if (error == B_OK)
return B_OK;
// fall back to disassembling
static const target_size_t kMaxBufferSize = 64 * 1024;
target_size_t bufferSize = std::min(function->Size(), kMaxBufferSize);
void* buffer = malloc(bufferSize);
if (buffer == NULL)
return B_NO_MEMORY;
MemoryDeleter bufferDeleter(buffer);
// read the function code
target_addr_t functionOffset = function->Address() - fRelocationDelta
- fTextSegment->LoadAddress() + fTextSegment->FileOffset();
ssize_t bytesRead = pread(fFile->GetElfFile()->FD(), buffer, bufferSize,
functionOffset);
if (bytesRead < 0)
return bytesRead;
return fArchitecture->DisassembleCode(function, buffer, bytesRead,
_sourceCode);
}
status_t
DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function,
target_addr_t address, Statement*& _statement)
@@ -489,55 +364,41 @@ printf(" -> found statement!\n");
}
status_t
DwarfImageDebugInfo::_LoadSourceCode(FunctionDebugInfo* _function,
SourceCode*& _sourceCode)
ssize_t
DwarfImageDebugInfo::ReadCode(target_addr_t address, void* buffer, size_t size)
{
DwarfFunctionDebugInfo* function
= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
if (function == NULL)
return B_BAD_VALUE;
// get the source file
LocatableFile* file = function->SourceFile();
if (file == NULL)
return B_ENTRY_NOT_FOUND;
// maybe it's already loaded
CompilationUnit* unit = function->GetCompilationUnit();
FileSourceCode* sourceCode = _LookupSourceCode(unit, file);
if (sourceCode) {
sourceCode->AcquireReference();
_sourceCode = sourceCode;
return B_OK;
}
// get the index of the source file in the compilation unit for cheaper
// comparison below
int32 fileIndex = _GetSourceFileIndex(unit, function->SourceFile());
printf("DwarfImageDebugInfo::_LoadSourceCode(), file: %ld, function at: %#llx\n", fileIndex, function->Address());
for (int32 i = 0; const char* fileName = unit->FileAt(i, NULL); i++) {
printf(" file %ld: %s\n", i, fileName);
target_addr_t offset = address - fRelocationDelta
- fTextSegment->LoadAddress() + fTextSegment->FileOffset();
ssize_t bytesRead = pread(fFile->GetElfFile()->FD(), buffer, size, offset);
return bytesRead >= 0 ? bytesRead : errno;
}
// not loaded yet -- get the source file
SourceFile* sourceFile;
status_t error = fFileManager->LoadSourceFile(file, sourceFile);
if (error != B_OK)
return error;
// create the source code
sourceCode = new(std::nothrow) FileSourceCode(file, sourceFile);
sourceFile->ReleaseReference();
if (sourceCode == NULL)
return B_NO_MEMORY;
status_t
DwarfImageDebugInfo::AddSourceCodeInfo(LocatableFile* file,
FileSourceCode* sourceCode)
{
bool addedAny = false;
for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i);
i++) {
int32 fileIndex = _GetSourceFileIndex(unit, file);
if (fileIndex < 0)
continue;
error = sourceCode->Init();
if (error != B_OK)
return error;
ObjectDeleter<FileSourceCode> sourceCodeDeleter(sourceCode);
status_t error = _AddSourceCodeInfo(unit, sourceCode, fileIndex);
if (error == B_NO_MEMORY)
return error;
addedAny |= error == B_OK;
}
return addedAny ? B_OK : B_ENTRY_NOT_FOUND;
}
status_t
DwarfImageDebugInfo::_AddSourceCodeInfo(CompilationUnit* unit,
FileSourceCode* sourceCode, int32 fileIndex)
{
// Get the statements by executing the line number program for the
// compilation unit and filtering the rows for our source file.
LineNumberProgram& program = unit->GetLineNumberProgram();
@@ -559,7 +420,7 @@ printf(" %#lx (%ld, %ld, %ld) %d\n", state.address, state.file, state.line, s
target_addr_t endAddress = state.address;
if (endAddress > statementAddress) {
// add the statement
error = sourceCode->AddSourceLocation(
status_t error = sourceCode->AddSourceLocation(
SourceLocation(statementLine, statementColumn));
if (error != B_OK)
return error;
@@ -580,28 +441,10 @@ printf(" -> statement: %#llx - %#llx, source location: (%ld, %ld)\n", statement
}
}
SourceCodeEntry* entry = new(std::nothrow) SourceCodeEntry(unit, file,
sourceCode);
if (entry == NULL)
return B_NO_MEMORY;
fSourceCodes->Insert(entry);
_sourceCode = sourceCodeDeleter.Detach();
_sourceCode->AcquireReference();
return B_OK;
}
FileSourceCode*
DwarfImageDebugInfo::_LookupSourceCode(CompilationUnit* unit,
LocatableFile* file)
{
SourceCodeEntry* entry = fSourceCodes->Lookup(SourceCodeKey(unit, file));
return entry != NULL ? entry->sourceCode : NULL;
}
int32
DwarfImageDebugInfo::_GetSourceFileIndex(CompilationUnit* unit,
LocatableFile* sourceFile) const
@@ -5,6 +5,7 @@
#ifndef DWARF_IMAGE_DEBUG_INFO_H
#define DWARF_IMAGE_DEBUG_INFO_H
#include <Locker.h>
#include <util/OpenHashTable.h>
@@ -42,8 +43,6 @@ public:
CpuState* cpuState,
StackFrame*& _previousFrame,
CpuState*& _previousCpuState);
virtual status_t LoadSourceCode(FunctionDebugInfo* function,
SourceCode*& _sourceCode);
virtual status_t GetStatement(FunctionDebugInfo* function,
target_addr_t address,
Statement*& _statement);
@@ -52,18 +51,16 @@ public:
const SourceLocation& sourceLocation,
Statement*& _statement);
private:
struct SourceCodeKey;
struct SourceCodeEntry;
struct SourceCodeHashDefinition;
virtual ssize_t ReadCode(target_addr_t address, void* buffer,
size_t size);
typedef OpenHashTable<SourceCodeHashDefinition> SourceCodeTable;
virtual status_t AddSourceCodeInfo(LocatableFile* file,
FileSourceCode* sourceCode);
private:
status_t _LoadSourceCode(FunctionDebugInfo* function,
SourceCode*& _sourceCode);
FileSourceCode* _LookupSourceCode(CompilationUnit* unit,
LocatableFile* file);
status_t _AddSourceCodeInfo(CompilationUnit* unit,
FileSourceCode* sourceCode,
int32 fileIndex);
int32 _GetSourceFileIndex(CompilationUnit* unit,
LocatableFile* sourceFile) const;
@@ -75,7 +72,6 @@ private:
DwarfFile* fFile;
ElfSegment* fTextSegment;
target_addr_t fRelocationDelta;
SourceCodeTable* fSourceCodes;
};
+28 -11
View File
@@ -5,13 +5,14 @@
#include "Function.h"
#include "SourceCode.h"
#include "FileSourceCode.h"
Function::Function()
:
fSourceCode(NULL),
fSourceCodeState(FUNCTION_SOURCE_NOT_LOADED)
fSourceCodeState(FUNCTION_SOURCE_NOT_LOADED),
fNotificationsDisabled(0)
{
}
@@ -23,7 +24,7 @@ Function::~Function()
void
Function::SetSourceCode(SourceCode* source, function_source_state state)
Function::SetSourceCode(FileSourceCode* source, function_source_state state)
{
if (source == fSourceCode && state == fSourceCodeState)
return;
@@ -34,14 +35,20 @@ Function::SetSourceCode(SourceCode* source, function_source_state state)
fSourceCode = source;
fSourceCodeState = state;
if (fSourceCode != NULL)
if (fSourceCode != NULL) {
fSourceCode->AddReference();
// notify listeners
for (ListenerList::Iterator it = fListeners.GetIterator();
Listener* listener = it.Next();) {
listener->FunctionSourceCodeChanged(this);
// unset all instances' source codes
fNotificationsDisabled++;
for (FunctionInstanceList::Iterator it = fInstances.GetIterator();
FunctionInstance* instance = it.Next();) {
instance->SetSourceCode(NULL, FUNCTION_SOURCE_NOT_LOADED);
}
fNotificationsDisabled--;
}
// notify listeners
NotifySourceCodeChanged();
}
@@ -59,11 +66,9 @@ Function::RemoveListener(Listener* listener)
}
#include <stdio.h>
void
Function::AddInstance(FunctionInstance* instance)
{
printf(" %p: added %p\n", this, instance);
fInstances.Add(instance);
}
@@ -71,11 +76,23 @@ printf(" %p: added %p\n", this, instance);
void
Function::RemoveInstance(FunctionInstance* instance)
{
printf(" %p: removed %p\n", this, instance);
fInstances.Remove(instance);
}
void
Function::NotifySourceCodeChanged()
{
if (fNotificationsDisabled > 0)
return;
for (ListenerList::Iterator it = fListeners.GetIterator();
Listener* listener = it.Next();) {
listener->FunctionSourceCodeChanged(this);
}
}
// #pragma mark - Listener
+7 -12
View File
@@ -11,15 +11,7 @@
#include "FunctionInstance.h"
enum function_source_state {
FUNCTION_SOURCE_NOT_LOADED,
FUNCTION_SOURCE_LOADING,
FUNCTION_SOURCE_LOADED,
FUNCTION_SOURCE_UNAVAILABLE
};
class SourceCode;
class FileSourceCode;
class Function : public Referenceable, public HashTableLink<Function> {
@@ -49,10 +41,10 @@ public:
->GetSourceLocation(); }
// mutable attributes follow (locking required)
SourceCode* GetSourceCode() const { return fSourceCode; }
FileSourceCode* GetSourceCode() const { return fSourceCode; }
function_source_state SourceCodeState() const
{ return fSourceCodeState; }
void SetSourceCode(SourceCode* source,
void SetSourceCode(FileSourceCode* source,
function_source_state state);
void AddListener(Listener* listener);
@@ -62,14 +54,17 @@ public:
void AddInstance(FunctionInstance* instance);
void RemoveInstance(FunctionInstance* instance);
void NotifySourceCodeChanged();
private:
typedef DoublyLinkedList<Listener> ListenerList;
private:
FunctionInstanceList fInstances;
SourceCode* fSourceCode;
FileSourceCode* fSourceCode;
function_source_state fSourceCodeState;
ListenerList fListeners;
int32 fNotificationsDisabled;
};
@@ -5,6 +5,7 @@
#include "FunctionInstance.h"
#include "DisassembledCode.h"
#include "Function.h"
@@ -13,7 +14,9 @@ FunctionInstance::FunctionInstance(ImageDebugInfo* imageDebugInfo,
:
fImageDebugInfo(imageDebugInfo),
fFunction(NULL),
fFunctionDebugInfo(functionDebugInfo)
fFunctionDebugInfo(functionDebugInfo),
fSourceCode(NULL),
fSourceCodeState(FUNCTION_SOURCE_NOT_LOADED)
{
fFunctionDebugInfo->AcquireReference();
// TODO: What about fImageDebugInfo? We must be careful regarding cyclic
@@ -39,3 +42,24 @@ FunctionInstance::SetFunction(Function* function)
if (fFunction != NULL)
fFunction->AcquireReference();
}
void
FunctionInstance::SetSourceCode(DisassembledCode* source,
function_source_state state)
{
if (source == fSourceCode && state == fSourceCodeState)
return;
if (fSourceCode != NULL)
fSourceCode->RemoveReference();
fSourceCode = source;
fSourceCodeState = state;
if (fSourceCode != NULL)
fSourceCode->AddReference();
if (fFunction != NULL)
fFunction->NotifySourceCodeChanged();
}
@@ -10,6 +10,15 @@
#include "FunctionDebugInfo.h"
enum function_source_state {
FUNCTION_SOURCE_NOT_LOADED,
FUNCTION_SOURCE_LOADING,
FUNCTION_SOURCE_LOADED,
FUNCTION_SOURCE_UNAVAILABLE
};
class DisassembledCode;
class Function;
class FunctionDebugInfo;
class ImageDebugInfo;
@@ -45,10 +54,21 @@ public:
void SetFunction(Function* function);
// package private
// mutable attributes follow (locking required)
DisassembledCode* GetSourceCode() const
{ return fSourceCode; }
function_source_state SourceCodeState() const
{ return fSourceCodeState; }
void SetSourceCode(DisassembledCode* source,
function_source_state state);
private:
ImageDebugInfo* fImageDebugInfo;
Function* fFunction;
FunctionDebugInfo* fFunctionDebugInfo;
DisassembledCode* fSourceCode;
function_source_state fSourceCodeState;
};
@@ -96,6 +96,23 @@ ImageDebugInfo::FunctionAtAddress(target_addr_t address) const
}
status_t
ImageDebugInfo::AddSourceCodeInfo(LocatableFile* file,
FileSourceCode* sourceCode) const
{
bool addedAny = false;
for (int32 i = 0; SpecificImageDebugInfo* specificInfo
= fSpecificInfos.ItemAt(i); i++) {
status_t error = specificInfo->AddSourceCodeInfo(file, sourceCode);
if (error == B_NO_MEMORY)
return error;
addedAny |= error == B_OK;
}
return addedAny ? B_OK : B_ENTRY_NOT_FOUND;
}
/*static*/ int
ImageDebugInfo::_CompareFunctions(const FunctionInstance* a,
const FunctionInstance* b)
@@ -16,8 +16,10 @@
class Architecture;
class DebuggerInterface;
class FileSourceCode;
class FunctionDebugInfo;
class FunctionInstance;
class LocatableFile;
class SpecificImageDebugInfo;
@@ -33,6 +35,9 @@ public:
FunctionInstance* FunctionAt(int32 index) const;
FunctionInstance* FunctionAtAddress(target_addr_t address) const;
status_t AddSourceCodeInfo(LocatableFile* file,
FileSourceCode* sourceCode) const;
private:
typedef BObjectList<SpecificImageDebugInfo> SpecificInfoList;
typedef BObjectList<FunctionInstance> FunctionList;
@@ -14,9 +14,10 @@
class Architecture;
class CpuState;
class DebuggerInterface;
class FileSourceCode;
class FunctionDebugInfo;
class Image;
class SourceCode;
class LocatableFile;
class SourceLocation;
class StackFrame;
class Statement;
@@ -39,9 +40,6 @@ public:
// returns reference to previous frame
// and CPU state; returned CPU state
// can be NULL; can return B_UNSUPPORTED
virtual status_t LoadSourceCode(FunctionDebugInfo* function,
SourceCode*& _sourceCode) = 0;
// returns reference
virtual status_t GetStatement(FunctionDebugInfo* function,
target_addr_t address,
Statement*& _statement) = 0;
@@ -51,6 +49,12 @@ public:
const SourceLocation& sourceLocation,
Statement*& _statement) = 0;
// returns reference
virtual ssize_t ReadCode(target_addr_t address, void* buffer,
size_t size) = 0;
virtual status_t AddSourceCodeInfo(LocatableFile* file,
FileSourceCode* sourceCode) = 0;
};
+157 -3
View File
@@ -11,12 +11,18 @@
#include <new>
#include <AutoDeleter.h>
#include <AutoLocker.h>
#include "Architecture.h"
#include "DebuggerTeamDebugInfo.h"
#include "DisassembledCode.h"
#include "DwarfTeamDebugInfo.h"
#include "FileManager.h"
#include "FileSourceCode.h"
#include "Function.h"
#include "ImageDebugInfo.h"
#include "LocatableFile.h"
#include "SourceFile.h"
#include "SpecificImageDebugInfo.h"
#include "StringUtils.h"
@@ -76,13 +82,15 @@ struct TeamDebugInfo::FunctionHashDefinition {
struct TeamDebugInfo::SourceFileEntry : public HashTableLink<SourceFileEntry> {
SourceFileEntry(LocatableFile* sourceFile)
:
fSourceFile(sourceFile)
fSourceFile(sourceFile),
fSourceCode(NULL)
{
fSourceFile->AcquireReference();
}
~SourceFileEntry()
{
SetSourceCode(NULL);
fSourceFile->ReleaseReference();
}
@@ -96,6 +104,26 @@ struct TeamDebugInfo::SourceFileEntry : public HashTableLink<SourceFileEntry> {
return fSourceFile;
}
FileSourceCode* GetSourceCode() const
{
return fSourceCode;
}
void SetSourceCode(FileSourceCode* sourceCode)
{
if (sourceCode == fSourceCode)
return;
if (fSourceCode != NULL)
fSourceCode->ReleaseReference();
fSourceCode = sourceCode;
if (fSourceCode != NULL)
fSourceCode->AcquireReference();
}
bool IsUnused() const
{
return fFunctions.IsEmpty();
@@ -162,6 +190,7 @@ private:
private:
LocatableFile* fSourceFile;
FileSourceCode* fSourceCode;
FunctionList fFunctions;
};
@@ -201,6 +230,7 @@ struct TeamDebugInfo::SourceFileHashDefinition {
TeamDebugInfo::TeamDebugInfo(DebuggerInterface* debuggerInterface,
Architecture* architecture, FileManager* fileManager)
:
fLock("team debug info"),
fDebuggerInterface(debuggerInterface),
fArchitecture(architecture),
fFileManager(fileManager),
@@ -240,12 +270,17 @@ TeamDebugInfo::~TeamDebugInfo()
status_t
TeamDebugInfo::Init()
{
// check the lock
status_t error = fLock.InitCheck();
if (error != B_OK)
return error;
// create function hash table
fFunctions = new(std::nothrow) FunctionTable;
if (fFunctions == NULL)
return B_NO_MEMORY;
status_t error = fFunctions->Init();
error = fFunctions->Init();
if (error != B_OK)
return error;
@@ -324,12 +359,103 @@ TeamDebugInfo::LoadImageDebugInfo(const ImageInfo& imageInfo,
}
#include <stdio.h>
status_t
TeamDebugInfo::LoadSourceCode(LocatableFile* file, FileSourceCode*& _sourceCode)
{
AutoLocker<BLocker> locker(fLock);
// If we don't know the source file, there's nothing we can do.
SourceFileEntry* entry = fSourceFiles->Lookup(file);
if (entry == NULL)
return B_ENTRY_NOT_FOUND;
// the source might already be loaded
FileSourceCode* sourceCode = entry->GetSourceCode();
if (sourceCode != NULL) {
sourceCode->AcquireReference();
_sourceCode = sourceCode;
return B_OK;
}
// no source code yet
// locker.Unlock();
// TODO: It would be nice to unlock here, but we need to iterate through
// the images below. We could clone the list, acquire references, and
// unlock. Then we have to compare the list with the then current list when
// we're done loading.
// load the source file
SourceFile* sourceFile;
status_t error = fFileManager->LoadSourceFile(file, sourceFile);
if (error != B_OK)
return error;
// create the source code
sourceCode = new(std::nothrow) FileSourceCode(file, sourceFile);
sourceFile->ReleaseReference();
if (sourceCode == NULL)
return B_NO_MEMORY;
Reference<FileSourceCode> sourceCodeReference(sourceCode, true);
error = sourceCode->Init();
if (error != B_OK)
return error;
// Iterate through all images that know the source file and ask them to add
// information.
bool anyInfo = false;
for (int32 i = 0; ImageDebugInfo* imageDebugInfo = fImages.ItemAt(i); i++)
anyInfo |= imageDebugInfo->AddSourceCodeInfo(file, sourceCode) == B_OK;
if (!anyInfo)
return B_ENTRY_NOT_FOUND;
entry->SetSourceCode(sourceCode);
_sourceCode = sourceCodeReference.Detach();
return B_OK;
}
status_t
TeamDebugInfo::DisassembleFunction(FunctionInstance* functionInstance,
DisassembledCode*& _sourceCode)
{
// allocate a buffer for the function code
static const target_size_t kMaxBufferSize = 64 * 1024;
target_size_t bufferSize = std::min(functionInstance->Size(),
kMaxBufferSize);
void* buffer = malloc(bufferSize);
if (buffer == NULL)
return B_NO_MEMORY;
MemoryDeleter bufferDeleter(buffer);
// read the function code
FunctionDebugInfo* functionDebugInfo
= functionInstance->GetFunctionDebugInfo();
ssize_t bytesRead = functionDebugInfo->GetSpecificImageDebugInfo()
->ReadCode(functionInstance->Address(), buffer, bufferSize);
if (bytesRead < 0)
return bytesRead;
return fArchitecture->DisassembleCode(functionDebugInfo, buffer, bytesRead,
_sourceCode);
}
status_t
TeamDebugInfo::AddImageDebugInfo(ImageDebugInfo* imageDebugInfo)
{
printf("TeamDebugInfo::AddImageDebugInfo(%p)\n", imageDebugInfo);
AutoLocker<BLocker> locker(fLock);
// We have both locks now, so that for read-only access either lock
// suffices.
if (!fImages.AddItem(imageDebugInfo))
return B_NO_MEMORY;
// Match all of the image debug info's functions instances with functions.
BObjectList<SourceFileEntry> sourceFileEntries;
for (int32 i = 0;
FunctionInstance* instance = imageDebugInfo->FunctionAt(i); i++) {
// lookup the function or create it, if it doesn't exist yet
@@ -339,6 +465,15 @@ printf("TeamDebugInfo::AddImageDebugInfo(%p)\n", imageDebugInfo);
printf(" adding instance %p to existing function %p\n", instance, function);
function->AddInstance(instance);
instance->SetFunction(function);
// The new image debug info might have additional information about
// the source file of the function, so remember the source file
// entry.
if (LocatableFile* sourceFile = function->SourceFile()) {
SourceFileEntry* entry = fSourceFiles->Lookup(sourceFile);
if (entry != NULL && entry->GetSourceCode() != NULL)
sourceFileEntries.AddItem(entry);
}
} else {
function = new(std::nothrow) Function;
if (function == NULL) {
@@ -361,6 +496,19 @@ printf(" adding instance %p to new function %p\n", instance, function);
}
}
// update the source files the image debug info knows about
for (int32 i = 0; SourceFileEntry* entry = sourceFileEntries.ItemAt(i);
i++) {
FileSourceCode* sourceCode = entry->GetSourceCode();
sourceCode->Lock();
if (imageDebugInfo->AddSourceCodeInfo(entry->SourceFile(),
sourceCode) == B_OK) {
// TODO: Notify interesting parties! Iterate through all functions
// for this source file?
}
sourceCode->Unlock();
}
return B_OK;
}
@@ -368,6 +516,10 @@ printf(" adding instance %p to new function %p\n", instance, function);
void
TeamDebugInfo::RemoveImageDebugInfo(ImageDebugInfo* imageDebugInfo)
{
AutoLocker<BLocker> locker(fLock);
// We have both locks now, so that for read-only access either lock
// suffices.
// Remove the functions from all of the image debug info's functions
// instances.
for (int32 i = 0;
@@ -390,6 +542,8 @@ TeamDebugInfo::RemoveImageDebugInfo(ImageDebugInfo* imageDebugInfo)
// reference to the function.
}
}
fImages.RemoveItem(imageDebugInfo);
}
@@ -6,6 +6,8 @@
#define TEAM_DEBUG_INFO_H
#include <Locker.h>
#include <ObjectList.h>
#include <Referenceable.h>
#include <util/OpenHashTable.h>
@@ -15,12 +17,15 @@
class Architecture;
class DebuggerInterface;
class DisassembledCode;
class FileManager;
class FileSourceCode;
class Function;
class FunctionInstance;
class ImageDebugInfo;
class ImageInfo;
class LocatableFile;
class SourceCode;
class SourceLocation;
class SpecificTeamDebugInfo;
@@ -39,6 +44,15 @@ public:
LocatableFile* imageFile,
ImageDebugInfo*& _imageDebugInfo);
status_t LoadSourceCode(LocatableFile* file,
FileSourceCode*& _sourceCode);
// returns reference
status_t DisassembleFunction(
FunctionInstance* functionInstance,
DisassembledCode*& _sourceCode);
// returns reference
// team is locked
status_t AddImageDebugInfo(
ImageDebugInfo* imageDebugInfo);
@@ -54,6 +68,7 @@ private:
struct SourceFileHashDefinition;
typedef BObjectList<SpecificTeamDebugInfo> SpecificInfoList;
typedef BObjectList<ImageDebugInfo> ImageList;
typedef OpenHashTable<FunctionHashDefinition> FunctionTable;
typedef OpenHashTable<SourceFileHashDefinition> SourceFileTable;
@@ -62,10 +77,12 @@ private:
void _RemoveFunction(Function* function);
private:
BLocker fLock;
DebuggerInterface* fDebuggerInterface;
Architecture* fArchitecture;
FileManager* fFileManager;
SpecificInfoList fSpecificInfos;
ImageList fImages;
FunctionTable* fFunctions;
SourceFileTable* fSourceFiles;
};
@@ -20,8 +20,9 @@
#include <ObjectList.h>
#include "Breakpoint.h"
#include "DisassembledCode.h"
#include "Function.h"
#include "SourceCode.h"
#include "FileSourceCode.h"
#include "StackTrace.h"
#include "Statement.h"
#include "TeamDebugModel.h"
@@ -503,6 +504,8 @@ SourceView::MarkerView::Draw(BRect updateRect)
float width = Bounds().Width();
AutoLocker<SourceCode> sourceLocker(fSourceCode);
int32 markerIndex = 0;
for (int32 line = minLine; line <= maxLine; line++) {
bool drawBreakpointOptionMarker = true;
@@ -518,7 +521,6 @@ SourceView::MarkerView::Draw(BRect updateRect)
if (!drawBreakpointOptionMarker)
continue;
SourceLocation statementStart, statementEnd;
if (!fSourceCode->GetStatementLocationRange(SourceLocation(line),
statementStart, statementEnd)
@@ -600,6 +602,8 @@ SourceView::MarkerView::_UpdateIPMarkers()
fIPMarkers.MakeEmpty();
if (fSourceCode != NULL && fStackTrace != NULL) {
LocatableFile* sourceFile = fSourceCode->GetSourceFile();
AutoLocker<TeamDebugModel> locker(fDebugModel);
for (int32 i = 0; StackFrame* frame = fStackTrace->FrameAt(i);
@@ -614,7 +618,9 @@ SourceView::MarkerView::_UpdateIPMarkers()
Reference<Statement> statementReference(statement, true);
uint32 line = statement->StartSourceLocation().Line();
if (functionInstance->GetFunction()->GetSourceCode() != fSourceCode
if ((functionInstance->GetSourceCode() != fSourceCode
&& functionInstance->GetFunction()->SourceFile()
!= sourceFile)
|| line < 0 || line >= (uint32)LineCount()) {
continue;
}
@@ -649,6 +655,8 @@ SourceView::MarkerView::_UpdateBreakpointMarkers()
fBreakpointMarkers.MakeEmpty();
if (fSourceCode != NULL) {
LocatableFile* sourceFile = fSourceCode->GetSourceFile();
AutoLocker<TeamDebugModel> locker(fDebugModel);
// get the breakpoints in our source code range
@@ -669,7 +677,9 @@ SourceView::MarkerView::_UpdateBreakpointMarkers()
Reference<Statement> statementReference(statement, true);
uint32 line = statement->StartSourceLocation().Line();
if (functionInstance->GetFunction()->GetSourceCode() != fSourceCode
if ((functionInstance->GetSourceCode() != fSourceCode
&& functionInstance->GetFunction()->SourceFile()
!= sourceFile)
|| line < 0 || line >= (uint32)LineCount()) {
continue;
}
@@ -18,11 +18,12 @@
#include <AutoLocker.h>
#include "CpuState.h"
#include "DisassembledCode.h"
#include "FileSourceCode.h"
#include "Image.h"
#include "ImageDebugInfo.h"
#include "MessageCodes.h"
#include "RegisterView.h"
#include "SourceCode.h"
#include "StackTrace.h"
#include "StackTraceView.h"
@@ -505,6 +506,8 @@ TeamWindow::_SetActiveFunction(FunctionInstance* functionInstance)
Function* function = fActiveFunction->GetFunction();
sourceCode = function->GetSourceCode();
if (sourceCode == NULL)
sourceCode = fActiveFunction->GetSourceCode();
sourceCodeReference.SetTo(sourceCode);
// If the source code is not loaded yet, request it.
@@ -703,6 +706,8 @@ TeamWindow::_HandleSourceCodeChanged()
AutoLocker<TeamDebugModel> locker(fDebugModel);
SourceCode* sourceCode = fActiveFunction->GetFunction()->GetSourceCode();
if (sourceCode == NULL)
sourceCode = fActiveFunction->GetSourceCode();
Reference<SourceCode> sourceCodeReference(sourceCode);
locker.Unlock();
+2
View File
@@ -36,6 +36,8 @@ public:
{ return fUserBreakpoints.Head(); }
UserBreakpointInstance* LastUserBreakpoint() const
{ return fUserBreakpoints.Tail(); }
const UserBreakpointInstanceList& UserBreakpoints() const
{ return fUserBreakpoints; }
void AddUserBreakpoint(
UserBreakpointInstance* instance);
+37 -8
View File
@@ -43,6 +43,20 @@ DisassembledCode::~DisassembledCode()
}
bool
DisassembledCode::Lock()
{
// We're immutable, so no locking required.
return true;
}
void
DisassembledCode::Unlock()
{
}
int32
DisassembledCode::CountLines() const
{
@@ -80,17 +94,32 @@ DisassembledCode::GetSourceFile() const
}
status_t
DisassembledCode::GetStatementAtLocation(const SourceLocation& location,
Statement*& _statement)
Statement*
DisassembledCode::StatementAtLocation(const SourceLocation& location) const
{
Line* line = fLines.ItemAt(location.Line());
if (line == NULL || line->statement == NULL)
return B_ENTRY_NOT_FOUND;
return line != NULL ? line->statement : NULL;
}
_statement = line->statement;
_statement->AcquireReference();
return B_OK;
Statement*
DisassembledCode::StatementAtAddress(target_addr_t address) const
{
return fStatements.BinarySearchByKey(address, &_CompareAddressStatement);
}
TargetAddressRange
DisassembledCode::StatementAddressRange() const
{
if (fStatements.IsEmpty())
return TargetAddressRange();
ContiguousStatement* first = fStatements.ItemAt(0);
ContiguousStatement* last
= fStatements.ItemAt(fStatements.CountItems() - 1);
return TargetAddressRange(first->AddressRange().Start(),
last->AddressRange().End());
}
+7 -3
View File
@@ -20,6 +20,9 @@ public:
DisassembledCode();
~DisassembledCode();
virtual bool Lock();
virtual void Unlock();
virtual int32 CountLines() const;
virtual const char* LineAt(int32 index) const;
@@ -30,9 +33,10 @@ public:
virtual LocatableFile* GetSourceFile() const;
virtual status_t GetStatementAtLocation(
const SourceLocation& location,
Statement*& _statement);
Statement* StatementAtAddress(target_addr_t address) const;
Statement* StatementAtLocation(
const SourceLocation& location) const;
TargetAddressRange StatementAddressRange() const;
public:
bool AddCommentLine(const BString& line);
+16 -9
View File
@@ -15,6 +15,7 @@
FileSourceCode::FileSourceCode(LocatableFile* file, SourceFile* sourceFile)
:
fLock("source code"),
fFile(file),
fSourceFile(sourceFile)
{
@@ -33,7 +34,7 @@ FileSourceCode::~FileSourceCode()
status_t
FileSourceCode::Init()
{
return B_OK;
return fLock.InitCheck();
}
@@ -50,6 +51,20 @@ FileSourceCode::AddSourceLocation(const SourceLocation& location)
}
bool
FileSourceCode::Lock()
{
return fLock.Lock();
}
void
FileSourceCode::Unlock()
{
fLock.Unlock();
}
int32
FileSourceCode::CountLines() const
{
@@ -95,14 +110,6 @@ FileSourceCode::GetSourceFile() const
}
status_t
FileSourceCode::GetStatementAtLocation(const SourceLocation& location,
Statement*& _statement)
{
return B_UNSUPPORTED;
}
int32
FileSourceCode::_FindSourceLocationIndex(const SourceLocation& location,
bool& _foundMatch) const
+7 -4
View File
@@ -6,6 +6,9 @@
#define FILE_SOURCE_CODE_H
#include <Locker.h>
#include "Array.h"
#include "SourceCode.h"
@@ -24,6 +27,9 @@ public:
status_t AddSourceLocation(
const SourceLocation& location);
virtual bool Lock();
virtual void Unlock();
virtual int32 CountLines() const;
virtual const char* LineAt(int32 index) const;
@@ -34,16 +40,13 @@ public:
virtual LocatableFile* GetSourceFile() const;
virtual status_t GetStatementAtLocation(
const SourceLocation& location,
Statement*& _statement);
private:
int32 _FindSourceLocationIndex(
const SourceLocation& location,
bool& _foundMatch) const;
private:
BLocker fLock;
LocatableFile* fFile;
SourceFile* fSourceFile;
Array<SourceLocation> fSourceLocations;
+5 -7
View File
@@ -20,6 +20,11 @@ class SourceCode : public Referenceable {
public:
virtual ~SourceCode();
// Locking needed for GetStatementLocationRange(), since that might use
// mutable data.
virtual bool Lock() = 0;
virtual void Unlock() = 0;
virtual int32 CountLines() const = 0;
virtual const char* LineAt(int32 index) const = 0;
@@ -29,13 +34,6 @@ public:
SourceLocation& _end) const = 0;
virtual LocatableFile* GetSourceFile() const = 0;
virtual status_t GetStatementAtLocation(
const SourceLocation& location,
Statement*& _statement) = 0;
// returns a reference,
// may return B_UNSUPPORTED, when
// SourceFile() returns non-NULL
};
+23 -4
View File
@@ -11,10 +11,12 @@
#include <AutoLocker.h>
#include "DisassembledCode.h"
#include "Function.h"
#include "ImageDebugInfo.h"
#include "SourceCode.h"
#include "SpecificImageDebugInfo.h"
#include "Statement.h"
#include "TeamDebugInfo.h"
@@ -236,12 +238,23 @@ printf(" -> no function instance\n");
return B_ENTRY_NOT_FOUND;
}
// If the function instance has disassembled code attached, we can get the
// statement directly.
if (DisassembledCode* code = functionInstance->GetSourceCode()) {
Statement* statement = code->StatementAtAddress(address);
if (statement != NULL) {
statement->AcquireReference();
_statement = statement;
_function = functionInstance;
return B_OK;
}
}
// get the statement from the image debug info
FunctionDebugInfo* functionDebugInfo
= functionInstance->GetFunctionDebugInfo();
status_t error = functionDebugInfo->GetSpecificImageDebugInfo()
->GetStatement(functionDebugInfo, address, _statement);
// TODO: Provide the corresponding SourceCode, if available!
if (error != B_OK)
{
printf(" -> no statement from the specific image debug info\n");
@@ -259,9 +272,15 @@ Team::GetStatementAtSourceLocation(SourceCode* sourceCode,
{
printf("Team::GetStatementAtSourceLocation(%p, (%ld, %ld))\n", sourceCode, location.Line(), location.Column());
// If we're lucky the source code can provide us with a statement.
status_t error = sourceCode->GetStatementAtLocation(location, _statement);
if (error == B_OK)
return error;
if (DisassembledCode* code = dynamic_cast<DisassembledCode*>(sourceCode)) {
Statement* statement = code->StatementAtLocation(location);
if (statement == NULL)
return B_ENTRY_NOT_FOUND;
statement->AcquireReference();
_statement = statement;
return B_OK;
}
// Go the long and stony way over the source file and the team debug info.
// get the source file for the source code
+33 -13
View File
@@ -10,6 +10,8 @@
#include <AutoLocker.h>
#include "Breakpoint.h"
#include "DisassembledCode.h"
#include "FileSourceCode.h"
#include "Function.h"
#include "UserBreakpoint.h"
@@ -109,24 +111,42 @@ TeamDebugModel::BreakpointAtAddress(target_addr_t address) const
}
//void
//TeamDebugModel::GetBreakpointsInAddressRange(TargetAddressRange range,
// BObjectList<Breakpoint>& breakpoints) const
//{
// int32 index = fBreakpoints.FindBinaryInsertionIndex(
// BreakpointByAddressPredicate(range.Start()));
// for (; Breakpoint* breakpoint = fBreakpoints.ItemAt(index); index++) {
// if (breakpoint->Address() > range.End())
// break;
// breakpoints.AddItem(breakpoint);
// }
//}
void
TeamDebugModel::GetBreakpointsInAddressRange(TargetAddressRange range,
BObjectList<UserBreakpoint>& breakpoints) const
{
int32 index = fBreakpoints.FindBinaryInsertionIndex(
BreakpointByAddressPredicate(range.Start()));
for (; Breakpoint* breakpoint = fBreakpoints.ItemAt(index); index++) {
if (breakpoint->Address() > range.End())
break;
for (UserBreakpointInstanceList::ConstIterator it
= breakpoint->UserBreakpoints().GetIterator();
UserBreakpointInstance* instance = it.Next();) {
breakpoints.AddItem(instance->GetUserBreakpoint());
}
}
// TODO: Avoid duplicates!
}
void
TeamDebugModel::GetBreakpointsForSourceCode(SourceCode* sourceCode,
BObjectList<UserBreakpoint>& breakpoints) const
{
if (DisassembledCode* disassembledCode
= dynamic_cast<DisassembledCode*>(sourceCode)) {
GetBreakpointsInAddressRange(disassembledCode->StatementAddressRange(),
breakpoints);
return;
}
LocatableFile* sourceFile = sourceCode->GetSourceFile();
if (sourceFile == NULL)
return;
// TODO: This can probably be optimized. Maybe by registering the user
// breakpoints with the team debug model and sorting them by source code.
for (int32 i = 0; Breakpoint* breakpoint = fBreakpoints.ItemAt(i); i++) {
@@ -137,7 +157,7 @@ TeamDebugModel::GetBreakpointsForSourceCode(SourceCode* sourceCode,
UserBreakpoint* userBreakpoint
= userBreakpointInstance->GetUserBreakpoint();
if (userBreakpoint->GetFunction()->GetSourceCode() == sourceCode)
if (userBreakpoint->GetFunction()->SourceFile() == sourceFile)
breakpoints.AddItem(userBreakpoint);
}
}
+4 -3
View File
@@ -58,9 +58,10 @@ public:
Breakpoint* BreakpointAt(int32 index) const;
Breakpoint* BreakpointAtAddress(
target_addr_t address) const;
// void GetBreakpointsInAddressRange(
// TargetAddressRange range,
// BObjectList<Breakpoint>& breakpoints) const;
void GetBreakpointsInAddressRange(
TargetAddressRange range,
BObjectList<UserBreakpoint>& breakpoints)
const;
void GetBreakpointsForSourceCode(
SourceCode* sourceCode,
BObjectList<UserBreakpoint>& breakpoints)