* 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 "Architecture.h"
#include "CpuState.h" #include "CpuState.h"
#include "DebuggerInterface.h" #include "DebuggerInterface.h"
#include "DisassembledCode.h"
#include "FileSourceCode.h"
#include "Function.h" #include "Function.h"
#include "Image.h" #include "Image.h"
#include "ImageDebugInfo.h" #include "ImageDebugInfo.h"
@@ -319,61 +321,73 @@ LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image,
LoadSourceCodeJob::LoadSourceCodeJob( LoadSourceCodeJob::LoadSourceCodeJob(
DebuggerInterface* debuggerInterface, Architecture* architecture, DebuggerInterface* debuggerInterface, Architecture* architecture,
Team* team, Function* function) Team* team, FunctionInstance* functionInstance, bool loadForFunction)
: :
fDebuggerInterface(debuggerInterface), fDebuggerInterface(debuggerInterface),
fArchitecture(architecture), fArchitecture(architecture),
fTeam(team), fTeam(team),
fFunction(function) fFunctionInstance(functionInstance),
fLoadForFunction(loadForFunction)
{ {
fFunction->AddReference(); fFunctionInstance->AddReference();
} }
LoadSourceCodeJob::~LoadSourceCodeJob() LoadSourceCodeJob::~LoadSourceCodeJob()
{ {
fFunction->RemoveReference(); fFunctionInstance->RemoveReference();
} }
JobKey JobKey
LoadSourceCodeJob::Key() const LoadSourceCodeJob::Key() const
{ {
return JobKey(fFunction, JOB_TYPE_LOAD_SOURCE_CODE); return JobKey(fFunctionInstance, JOB_TYPE_LOAD_SOURCE_CODE);
} }
status_t status_t
LoadSourceCodeJob::Do() LoadSourceCodeJob::Do()
{ {
// Get the function debug info for an instance which we can use to load the // if requested, try loading the source code for the function
// source code. 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); AutoLocker<Team> locker(fTeam);
if (fFunctionInstance->SourceCodeState() != FUNCTION_SOURCE_LOADING)
status_t error = B_OK; return B_OK;
FunctionDebugInfo* functionDebugInfo = NULL;
if (FunctionInstance* instance = fFunction->FirstInstance()) {
functionDebugInfo = instance->GetFunctionDebugInfo();
} else
error = B_ENTRY_NOT_FOUND;
Reference<FunctionDebugInfo> functionDebugInfoReference(functionDebugInfo);
locker.Unlock(); locker.Unlock();
// load the source code, if we can // disassemble the function
SourceCode* sourceCode = NULL; DisassembledCode* sourceCode = NULL;
if (error == B_OK) { status_t error = fTeam->DebugInfo()->DisassembleFunction(fFunctionInstance,
error = functionDebugInfo->GetSpecificImageDebugInfo()->LoadSourceCode( sourceCode);
functionDebugInfo, sourceCode);
}
// set the result // set the result
locker.Lock(); locker.Lock();
if (error == B_OK) { if (error == B_OK) {
fFunction->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED); if (fFunctionInstance->SourceCodeState() == FUNCTION_SOURCE_LOADING) {
sourceCode->RemoveReference(); fFunctionInstance->SetSourceCode(sourceCode,
FUNCTION_SOURCE_LOADED);
sourceCode->RemoveReference();
}
} else } else
fFunction->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE); fFunctionInstance->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
return error; return error;
} }
+5 -2
View File
@@ -13,6 +13,7 @@ class Architecture;
class CpuState; class CpuState;
class DebuggerInterface; class DebuggerInterface;
class Function; class Function;
class FunctionInstance;
class Image; class Image;
class StackFrame; class StackFrame;
class Team; class Team;
@@ -113,7 +114,8 @@ public:
LoadSourceCodeJob( LoadSourceCodeJob(
DebuggerInterface* debuggerInterface, DebuggerInterface* debuggerInterface,
Architecture* architecture, Team* team, Architecture* architecture, Team* team,
Function* function); FunctionInstance* functionInstance,
bool loadForFunction);
virtual ~LoadSourceCodeJob(); virtual ~LoadSourceCodeJob();
virtual JobKey Key() const; virtual JobKey Key() const;
@@ -123,7 +125,8 @@ private:
DebuggerInterface* fDebuggerInterface; DebuggerInterface* fDebuggerInterface;
Architecture* fArchitecture; Architecture* fArchitecture;
Team* fTeam; Team* fTeam;
Function* fFunction; FunctionInstance* fFunctionInstance;
bool fLoadForFunction;
}; };
+15 -3
View File
@@ -489,15 +489,27 @@ TeamDebugger::FunctionSourceCodeRequested(TeamWindow* window,
// mark loading // mark loading
AutoLocker< ::Team> locker(fTeam); AutoLocker< ::Team> locker(fTeam);
if (function->SourceCodeState() != FUNCTION_SOURCE_NOT_LOADED)
if (functionInstance->SourceCodeState() != FUNCTION_SOURCE_NOT_LOADED)
return; 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(); locker.Unlock();
// schedule the job // schedule the job
if (fWorker->ScheduleJob( if (fWorker->ScheduleJob(
new(std::nothrow) LoadSourceCodeJob(fDebuggerInterface, new(std::nothrow) LoadSourceCodeJob(fDebuggerInterface,
fDebuggerInterface->GetArchitecture(), fTeam, function), fDebuggerInterface->GetArchitecture(), fTeam, functionInstance,
loadForFunction),
this) != B_OK) { this) != B_OK) {
// scheduling failed -- mark unavailable // scheduling failed -- mark unavailable
locker.Lock(); locker.Lock();
+2 -2
View File
@@ -13,12 +13,12 @@
class CpuState; class CpuState;
class DisassembledCode;
class FunctionDebugInfo; class FunctionDebugInfo;
class Image; class Image;
class ImageDebugInfoProvider; class ImageDebugInfoProvider;
class InstructionInfo; class InstructionInfo;
class Register; class Register;
class SourceCode;
class StackFrame; class StackFrame;
class StackTrace; class StackTrace;
class Statement; class Statement;
@@ -57,7 +57,7 @@ public:
virtual status_t DisassembleCode(FunctionDebugInfo* function, virtual status_t DisassembleCode(FunctionDebugInfo* function,
const void* buffer, size_t bufferSize, const void* buffer, size_t bufferSize,
SourceCode*& _sourceCode) = 0; DisassembledCode*& _sourceCode) = 0;
virtual status_t GetStatement(FunctionDebugInfo* function, virtual status_t GetStatement(FunctionDebugInfo* function,
target_addr_t address, target_addr_t address,
Statement*& _statement) = 0; Statement*& _statement) = 0;
@@ -271,7 +271,7 @@ ArchitectureX86::UpdateStackFrameCpuState(const StackFrame* frame,
status_t status_t
ArchitectureX86::DisassembleCode(FunctionDebugInfo* function, 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; DisassembledCode* source = new(std::nothrow) DisassembledCode;
if (source == NULL) if (source == NULL)
+1 -1
View File
@@ -35,7 +35,7 @@ public:
virtual status_t DisassembleCode(FunctionDebugInfo* function, virtual status_t DisassembleCode(FunctionDebugInfo* function,
const void* buffer, size_t bufferSize, const void* buffer, size_t bufferSize,
SourceCode*& _sourceCode); DisassembledCode*& _sourceCode);
virtual status_t GetStatement(FunctionDebugInfo* function, virtual status_t GetStatement(FunctionDebugInfo* function,
target_addr_t address, target_addr_t address,
Statement*& _statement); 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 status_t
DebuggerImageDebugInfo::GetStatement(FunctionDebugInfo* function, DebuggerImageDebugInfo::GetStatement(FunctionDebugInfo* function,
target_addr_t address, Statement*& _statement) 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 /*static*/ int
DebuggerImageDebugInfo::_CompareSymbols(const SymbolInfo* a, DebuggerImageDebugInfo::_CompareSymbols(const SymbolInfo* a,
const SymbolInfo* b) const SymbolInfo* b)
@@ -31,8 +31,6 @@ public:
CpuState* cpuState, CpuState* cpuState,
StackFrame*& _previousFrame, StackFrame*& _previousFrame,
CpuState*& _previousCpuState); CpuState*& _previousCpuState);
virtual status_t LoadSourceCode(FunctionDebugInfo* function,
SourceCode*& _sourceCode);
virtual status_t GetStatement(FunctionDebugInfo* function, virtual status_t GetStatement(FunctionDebugInfo* function,
target_addr_t address, target_addr_t address,
Statement*& _statement); Statement*& _statement);
@@ -41,6 +39,12 @@ public:
const SourceLocation& sourceLocation, const SourceLocation& sourceLocation,
Statement*& _statement); Statement*& _statement);
virtual ssize_t ReadCode(target_addr_t address, void* buffer,
size_t size);
virtual status_t AddSourceCodeInfo(LocatableFile* file,
FileSourceCode* sourceCode);
private: private:
static int _CompareSymbols(const SymbolInfo* a, static int _CompareSymbols(const SymbolInfo* a,
const SymbolInfo* b); const SymbolInfo* b);
@@ -3,8 +3,10 @@
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include "DwarfImageDebugInfo.h" #include "DwarfImageDebugInfo.h"
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
@@ -30,84 +32,6 @@
#include "StringUtils.h" #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, DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo,
Architecture* architecture, FileManager* fileManager, DwarfFile* file) Architecture* architecture, FileManager* fileManager, DwarfFile* file)
: :
@@ -117,22 +41,13 @@ DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo,
fFileManager(fileManager), fFileManager(fileManager),
fFile(file), fFile(file),
fTextSegment(NULL), fTextSegment(NULL),
fRelocationDelta(0), fRelocationDelta(0)
fSourceCodes(NULL)
{ {
} }
DwarfImageDebugInfo::~DwarfImageDebugInfo() 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) if (error != B_OK)
return error; 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(); fTextSegment = fFile->GetElfFile()->TextSegment();
if (fTextSegment == NULL) if (fTextSegment == NULL)
return B_ENTRY_NOT_FOUND; 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 status_t
DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function, DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function,
target_addr_t address, Statement*& _statement) target_addr_t address, Statement*& _statement)
@@ -489,55 +364,41 @@ printf(" -> found statement!\n");
} }
status_t ssize_t
DwarfImageDebugInfo::_LoadSourceCode(FunctionDebugInfo* _function, DwarfImageDebugInfo::ReadCode(target_addr_t address, void* buffer, size_t size)
SourceCode*& _sourceCode)
{ {
DwarfFunctionDebugInfo* function target_addr_t offset = address - fRelocationDelta
= dynamic_cast<DwarfFunctionDebugInfo*>(_function); - fTextSegment->LoadAddress() + fTextSegment->FileOffset();
if (function == NULL) ssize_t bytesRead = pread(fFile->GetElfFile()->FD(), buffer, size, offset);
return B_BAD_VALUE; return bytesRead >= 0 ? bytesRead : errno;
// 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);
} }
// 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 status_t
sourceCode = new(std::nothrow) FileSourceCode(file, sourceFile); DwarfImageDebugInfo::AddSourceCodeInfo(LocatableFile* file,
sourceFile->ReleaseReference(); FileSourceCode* sourceCode)
if (sourceCode == NULL) {
return B_NO_MEMORY; 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(); status_t error = _AddSourceCodeInfo(unit, sourceCode, fileIndex);
if (error != B_OK) if (error == B_NO_MEMORY)
return error; return error;
ObjectDeleter<FileSourceCode> sourceCodeDeleter(sourceCode); 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 // Get the statements by executing the line number program for the
// compilation unit and filtering the rows for our source file. // compilation unit and filtering the rows for our source file.
LineNumberProgram& program = unit->GetLineNumberProgram(); 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; target_addr_t endAddress = state.address;
if (endAddress > statementAddress) { if (endAddress > statementAddress) {
// add the statement // add the statement
error = sourceCode->AddSourceLocation( status_t error = sourceCode->AddSourceLocation(
SourceLocation(statementLine, statementColumn)); SourceLocation(statementLine, statementColumn));
if (error != B_OK) if (error != B_OK)
return error; 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; return B_OK;
} }
FileSourceCode*
DwarfImageDebugInfo::_LookupSourceCode(CompilationUnit* unit,
LocatableFile* file)
{
SourceCodeEntry* entry = fSourceCodes->Lookup(SourceCodeKey(unit, file));
return entry != NULL ? entry->sourceCode : NULL;
}
int32 int32
DwarfImageDebugInfo::_GetSourceFileIndex(CompilationUnit* unit, DwarfImageDebugInfo::_GetSourceFileIndex(CompilationUnit* unit,
LocatableFile* sourceFile) const LocatableFile* sourceFile) const
@@ -5,6 +5,7 @@
#ifndef DWARF_IMAGE_DEBUG_INFO_H #ifndef DWARF_IMAGE_DEBUG_INFO_H
#define DWARF_IMAGE_DEBUG_INFO_H #define DWARF_IMAGE_DEBUG_INFO_H
#include <Locker.h> #include <Locker.h>
#include <util/OpenHashTable.h> #include <util/OpenHashTable.h>
@@ -42,8 +43,6 @@ public:
CpuState* cpuState, CpuState* cpuState,
StackFrame*& _previousFrame, StackFrame*& _previousFrame,
CpuState*& _previousCpuState); CpuState*& _previousCpuState);
virtual status_t LoadSourceCode(FunctionDebugInfo* function,
SourceCode*& _sourceCode);
virtual status_t GetStatement(FunctionDebugInfo* function, virtual status_t GetStatement(FunctionDebugInfo* function,
target_addr_t address, target_addr_t address,
Statement*& _statement); Statement*& _statement);
@@ -52,18 +51,16 @@ public:
const SourceLocation& sourceLocation, const SourceLocation& sourceLocation,
Statement*& _statement); Statement*& _statement);
private: virtual ssize_t ReadCode(target_addr_t address, void* buffer,
struct SourceCodeKey; size_t size);
struct SourceCodeEntry;
struct SourceCodeHashDefinition;
typedef OpenHashTable<SourceCodeHashDefinition> SourceCodeTable; virtual status_t AddSourceCodeInfo(LocatableFile* file,
FileSourceCode* sourceCode);
private: private:
status_t _LoadSourceCode(FunctionDebugInfo* function, status_t _AddSourceCodeInfo(CompilationUnit* unit,
SourceCode*& _sourceCode); FileSourceCode* sourceCode,
FileSourceCode* _LookupSourceCode(CompilationUnit* unit, int32 fileIndex);
LocatableFile* file);
int32 _GetSourceFileIndex(CompilationUnit* unit, int32 _GetSourceFileIndex(CompilationUnit* unit,
LocatableFile* sourceFile) const; LocatableFile* sourceFile) const;
@@ -75,7 +72,6 @@ private:
DwarfFile* fFile; DwarfFile* fFile;
ElfSegment* fTextSegment; ElfSegment* fTextSegment;
target_addr_t fRelocationDelta; target_addr_t fRelocationDelta;
SourceCodeTable* fSourceCodes;
}; };
+28 -11
View File
@@ -5,13 +5,14 @@
#include "Function.h" #include "Function.h"
#include "SourceCode.h" #include "FileSourceCode.h"
Function::Function() Function::Function()
: :
fSourceCode(NULL), fSourceCode(NULL),
fSourceCodeState(FUNCTION_SOURCE_NOT_LOADED) fSourceCodeState(FUNCTION_SOURCE_NOT_LOADED),
fNotificationsDisabled(0)
{ {
} }
@@ -23,7 +24,7 @@ Function::~Function()
void void
Function::SetSourceCode(SourceCode* source, function_source_state state) Function::SetSourceCode(FileSourceCode* source, function_source_state state)
{ {
if (source == fSourceCode && state == fSourceCodeState) if (source == fSourceCode && state == fSourceCodeState)
return; return;
@@ -34,14 +35,20 @@ Function::SetSourceCode(SourceCode* source, function_source_state state)
fSourceCode = source; fSourceCode = source;
fSourceCodeState = state; fSourceCodeState = state;
if (fSourceCode != NULL) if (fSourceCode != NULL) {
fSourceCode->AddReference(); fSourceCode->AddReference();
// notify listeners // unset all instances' source codes
for (ListenerList::Iterator it = fListeners.GetIterator(); fNotificationsDisabled++;
Listener* listener = it.Next();) { for (FunctionInstanceList::Iterator it = fInstances.GetIterator();
listener->FunctionSourceCodeChanged(this); 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 void
Function::AddInstance(FunctionInstance* instance) Function::AddInstance(FunctionInstance* instance)
{ {
printf(" %p: added %p\n", this, instance);
fInstances.Add(instance); fInstances.Add(instance);
} }
@@ -71,11 +76,23 @@ printf(" %p: added %p\n", this, instance);
void void
Function::RemoveInstance(FunctionInstance* instance) Function::RemoveInstance(FunctionInstance* instance)
{ {
printf(" %p: removed %p\n", this, instance);
fInstances.Remove(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 // #pragma mark - Listener
+7 -12
View File
@@ -11,15 +11,7 @@
#include "FunctionInstance.h" #include "FunctionInstance.h"
enum function_source_state { class FileSourceCode;
FUNCTION_SOURCE_NOT_LOADED,
FUNCTION_SOURCE_LOADING,
FUNCTION_SOURCE_LOADED,
FUNCTION_SOURCE_UNAVAILABLE
};
class SourceCode;
class Function : public Referenceable, public HashTableLink<Function> { class Function : public Referenceable, public HashTableLink<Function> {
@@ -49,10 +41,10 @@ public:
->GetSourceLocation(); } ->GetSourceLocation(); }
// mutable attributes follow (locking required) // mutable attributes follow (locking required)
SourceCode* GetSourceCode() const { return fSourceCode; } FileSourceCode* GetSourceCode() const { return fSourceCode; }
function_source_state SourceCodeState() const function_source_state SourceCodeState() const
{ return fSourceCodeState; } { return fSourceCodeState; }
void SetSourceCode(SourceCode* source, void SetSourceCode(FileSourceCode* source,
function_source_state state); function_source_state state);
void AddListener(Listener* listener); void AddListener(Listener* listener);
@@ -62,14 +54,17 @@ public:
void AddInstance(FunctionInstance* instance); void AddInstance(FunctionInstance* instance);
void RemoveInstance(FunctionInstance* instance); void RemoveInstance(FunctionInstance* instance);
void NotifySourceCodeChanged();
private: private:
typedef DoublyLinkedList<Listener> ListenerList; typedef DoublyLinkedList<Listener> ListenerList;
private: private:
FunctionInstanceList fInstances; FunctionInstanceList fInstances;
SourceCode* fSourceCode; FileSourceCode* fSourceCode;
function_source_state fSourceCodeState; function_source_state fSourceCodeState;
ListenerList fListeners; ListenerList fListeners;
int32 fNotificationsDisabled;
}; };
@@ -5,6 +5,7 @@
#include "FunctionInstance.h" #include "FunctionInstance.h"
#include "DisassembledCode.h"
#include "Function.h" #include "Function.h"
@@ -13,7 +14,9 @@ FunctionInstance::FunctionInstance(ImageDebugInfo* imageDebugInfo,
: :
fImageDebugInfo(imageDebugInfo), fImageDebugInfo(imageDebugInfo),
fFunction(NULL), fFunction(NULL),
fFunctionDebugInfo(functionDebugInfo) fFunctionDebugInfo(functionDebugInfo),
fSourceCode(NULL),
fSourceCodeState(FUNCTION_SOURCE_NOT_LOADED)
{ {
fFunctionDebugInfo->AcquireReference(); fFunctionDebugInfo->AcquireReference();
// TODO: What about fImageDebugInfo? We must be careful regarding cyclic // TODO: What about fImageDebugInfo? We must be careful regarding cyclic
@@ -39,3 +42,24 @@ FunctionInstance::SetFunction(Function* function)
if (fFunction != NULL) if (fFunction != NULL)
fFunction->AcquireReference(); 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" #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 Function;
class FunctionDebugInfo; class FunctionDebugInfo;
class ImageDebugInfo; class ImageDebugInfo;
@@ -45,10 +54,21 @@ public:
void SetFunction(Function* function); void SetFunction(Function* function);
// package private // 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: private:
ImageDebugInfo* fImageDebugInfo; ImageDebugInfo* fImageDebugInfo;
Function* fFunction; Function* fFunction;
FunctionDebugInfo* fFunctionDebugInfo; 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 /*static*/ int
ImageDebugInfo::_CompareFunctions(const FunctionInstance* a, ImageDebugInfo::_CompareFunctions(const FunctionInstance* a,
const FunctionInstance* b) const FunctionInstance* b)
@@ -16,8 +16,10 @@
class Architecture; class Architecture;
class DebuggerInterface; class DebuggerInterface;
class FileSourceCode;
class FunctionDebugInfo; class FunctionDebugInfo;
class FunctionInstance; class FunctionInstance;
class LocatableFile;
class SpecificImageDebugInfo; class SpecificImageDebugInfo;
@@ -33,6 +35,9 @@ public:
FunctionInstance* FunctionAt(int32 index) const; FunctionInstance* FunctionAt(int32 index) const;
FunctionInstance* FunctionAtAddress(target_addr_t address) const; FunctionInstance* FunctionAtAddress(target_addr_t address) const;
status_t AddSourceCodeInfo(LocatableFile* file,
FileSourceCode* sourceCode) const;
private: private:
typedef BObjectList<SpecificImageDebugInfo> SpecificInfoList; typedef BObjectList<SpecificImageDebugInfo> SpecificInfoList;
typedef BObjectList<FunctionInstance> FunctionList; typedef BObjectList<FunctionInstance> FunctionList;
@@ -14,9 +14,10 @@
class Architecture; class Architecture;
class CpuState; class CpuState;
class DebuggerInterface; class DebuggerInterface;
class FileSourceCode;
class FunctionDebugInfo; class FunctionDebugInfo;
class Image; class Image;
class SourceCode; class LocatableFile;
class SourceLocation; class SourceLocation;
class StackFrame; class StackFrame;
class Statement; class Statement;
@@ -39,9 +40,6 @@ public:
// returns reference to previous frame // returns reference to previous frame
// and CPU state; returned CPU state // and CPU state; returned CPU state
// can be NULL; can return B_UNSUPPORTED // can be NULL; can return B_UNSUPPORTED
virtual status_t LoadSourceCode(FunctionDebugInfo* function,
SourceCode*& _sourceCode) = 0;
// returns reference
virtual status_t GetStatement(FunctionDebugInfo* function, virtual status_t GetStatement(FunctionDebugInfo* function,
target_addr_t address, target_addr_t address,
Statement*& _statement) = 0; Statement*& _statement) = 0;
@@ -51,6 +49,12 @@ public:
const SourceLocation& sourceLocation, const SourceLocation& sourceLocation,
Statement*& _statement) = 0; Statement*& _statement) = 0;
// returns reference // 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 <new>
#include <AutoDeleter.h> #include <AutoDeleter.h>
#include <AutoLocker.h>
#include "Architecture.h"
#include "DebuggerTeamDebugInfo.h" #include "DebuggerTeamDebugInfo.h"
#include "DisassembledCode.h"
#include "DwarfTeamDebugInfo.h" #include "DwarfTeamDebugInfo.h"
#include "FileManager.h"
#include "FileSourceCode.h"
#include "Function.h" #include "Function.h"
#include "ImageDebugInfo.h" #include "ImageDebugInfo.h"
#include "LocatableFile.h" #include "LocatableFile.h"
#include "SourceFile.h"
#include "SpecificImageDebugInfo.h" #include "SpecificImageDebugInfo.h"
#include "StringUtils.h" #include "StringUtils.h"
@@ -76,13 +82,15 @@ struct TeamDebugInfo::FunctionHashDefinition {
struct TeamDebugInfo::SourceFileEntry : public HashTableLink<SourceFileEntry> { struct TeamDebugInfo::SourceFileEntry : public HashTableLink<SourceFileEntry> {
SourceFileEntry(LocatableFile* sourceFile) SourceFileEntry(LocatableFile* sourceFile)
: :
fSourceFile(sourceFile) fSourceFile(sourceFile),
fSourceCode(NULL)
{ {
fSourceFile->AcquireReference(); fSourceFile->AcquireReference();
} }
~SourceFileEntry() ~SourceFileEntry()
{ {
SetSourceCode(NULL);
fSourceFile->ReleaseReference(); fSourceFile->ReleaseReference();
} }
@@ -96,6 +104,26 @@ struct TeamDebugInfo::SourceFileEntry : public HashTableLink<SourceFileEntry> {
return fSourceFile; 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 bool IsUnused() const
{ {
return fFunctions.IsEmpty(); return fFunctions.IsEmpty();
@@ -162,6 +190,7 @@ private:
private: private:
LocatableFile* fSourceFile; LocatableFile* fSourceFile;
FileSourceCode* fSourceCode;
FunctionList fFunctions; FunctionList fFunctions;
}; };
@@ -201,6 +230,7 @@ struct TeamDebugInfo::SourceFileHashDefinition {
TeamDebugInfo::TeamDebugInfo(DebuggerInterface* debuggerInterface, TeamDebugInfo::TeamDebugInfo(DebuggerInterface* debuggerInterface,
Architecture* architecture, FileManager* fileManager) Architecture* architecture, FileManager* fileManager)
: :
fLock("team debug info"),
fDebuggerInterface(debuggerInterface), fDebuggerInterface(debuggerInterface),
fArchitecture(architecture), fArchitecture(architecture),
fFileManager(fileManager), fFileManager(fileManager),
@@ -240,12 +270,17 @@ TeamDebugInfo::~TeamDebugInfo()
status_t status_t
TeamDebugInfo::Init() TeamDebugInfo::Init()
{ {
// check the lock
status_t error = fLock.InitCheck();
if (error != B_OK)
return error;
// create function hash table // create function hash table
fFunctions = new(std::nothrow) FunctionTable; fFunctions = new(std::nothrow) FunctionTable;
if (fFunctions == NULL) if (fFunctions == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
status_t error = fFunctions->Init(); error = fFunctions->Init();
if (error != B_OK) if (error != B_OK)
return error; 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 status_t
TeamDebugInfo::AddImageDebugInfo(ImageDebugInfo* imageDebugInfo) TeamDebugInfo::AddImageDebugInfo(ImageDebugInfo* imageDebugInfo)
{ {
printf("TeamDebugInfo::AddImageDebugInfo(%p)\n", 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. // Match all of the image debug info's functions instances with functions.
BObjectList<SourceFileEntry> sourceFileEntries;
for (int32 i = 0; for (int32 i = 0;
FunctionInstance* instance = imageDebugInfo->FunctionAt(i); i++) { FunctionInstance* instance = imageDebugInfo->FunctionAt(i); i++) {
// lookup the function or create it, if it doesn't exist yet // 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); printf(" adding instance %p to existing function %p\n", instance, function);
function->AddInstance(instance); function->AddInstance(instance);
instance->SetFunction(function); 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 { } else {
function = new(std::nothrow) Function; function = new(std::nothrow) Function;
if (function == NULL) { 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; return B_OK;
} }
@@ -368,6 +516,10 @@ printf(" adding instance %p to new function %p\n", instance, function);
void void
TeamDebugInfo::RemoveImageDebugInfo(ImageDebugInfo* imageDebugInfo) 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 // Remove the functions from all of the image debug info's functions
// instances. // instances.
for (int32 i = 0; for (int32 i = 0;
@@ -390,6 +542,8 @@ TeamDebugInfo::RemoveImageDebugInfo(ImageDebugInfo* imageDebugInfo)
// reference to the function. // reference to the function.
} }
} }
fImages.RemoveItem(imageDebugInfo);
} }
@@ -6,6 +6,8 @@
#define TEAM_DEBUG_INFO_H #define TEAM_DEBUG_INFO_H
#include <Locker.h>
#include <ObjectList.h> #include <ObjectList.h>
#include <Referenceable.h> #include <Referenceable.h>
#include <util/OpenHashTable.h> #include <util/OpenHashTable.h>
@@ -15,12 +17,15 @@
class Architecture; class Architecture;
class DebuggerInterface; class DebuggerInterface;
class DisassembledCode;
class FileManager; class FileManager;
class FileSourceCode;
class Function; class Function;
class FunctionInstance; class FunctionInstance;
class ImageDebugInfo; class ImageDebugInfo;
class ImageInfo; class ImageInfo;
class LocatableFile; class LocatableFile;
class SourceCode;
class SourceLocation; class SourceLocation;
class SpecificTeamDebugInfo; class SpecificTeamDebugInfo;
@@ -39,6 +44,15 @@ public:
LocatableFile* imageFile, LocatableFile* imageFile,
ImageDebugInfo*& _imageDebugInfo); ImageDebugInfo*& _imageDebugInfo);
status_t LoadSourceCode(LocatableFile* file,
FileSourceCode*& _sourceCode);
// returns reference
status_t DisassembleFunction(
FunctionInstance* functionInstance,
DisassembledCode*& _sourceCode);
// returns reference
// team is locked // team is locked
status_t AddImageDebugInfo( status_t AddImageDebugInfo(
ImageDebugInfo* imageDebugInfo); ImageDebugInfo* imageDebugInfo);
@@ -54,6 +68,7 @@ private:
struct SourceFileHashDefinition; struct SourceFileHashDefinition;
typedef BObjectList<SpecificTeamDebugInfo> SpecificInfoList; typedef BObjectList<SpecificTeamDebugInfo> SpecificInfoList;
typedef BObjectList<ImageDebugInfo> ImageList;
typedef OpenHashTable<FunctionHashDefinition> FunctionTable; typedef OpenHashTable<FunctionHashDefinition> FunctionTable;
typedef OpenHashTable<SourceFileHashDefinition> SourceFileTable; typedef OpenHashTable<SourceFileHashDefinition> SourceFileTable;
@@ -62,10 +77,12 @@ private:
void _RemoveFunction(Function* function); void _RemoveFunction(Function* function);
private: private:
BLocker fLock;
DebuggerInterface* fDebuggerInterface; DebuggerInterface* fDebuggerInterface;
Architecture* fArchitecture; Architecture* fArchitecture;
FileManager* fFileManager; FileManager* fFileManager;
SpecificInfoList fSpecificInfos; SpecificInfoList fSpecificInfos;
ImageList fImages;
FunctionTable* fFunctions; FunctionTable* fFunctions;
SourceFileTable* fSourceFiles; SourceFileTable* fSourceFiles;
}; };
@@ -20,8 +20,9 @@
#include <ObjectList.h> #include <ObjectList.h>
#include "Breakpoint.h" #include "Breakpoint.h"
#include "DisassembledCode.h"
#include "Function.h" #include "Function.h"
#include "SourceCode.h" #include "FileSourceCode.h"
#include "StackTrace.h" #include "StackTrace.h"
#include "Statement.h" #include "Statement.h"
#include "TeamDebugModel.h" #include "TeamDebugModel.h"
@@ -503,6 +504,8 @@ SourceView::MarkerView::Draw(BRect updateRect)
float width = Bounds().Width(); float width = Bounds().Width();
AutoLocker<SourceCode> sourceLocker(fSourceCode);
int32 markerIndex = 0; int32 markerIndex = 0;
for (int32 line = minLine; line <= maxLine; line++) { for (int32 line = minLine; line <= maxLine; line++) {
bool drawBreakpointOptionMarker = true; bool drawBreakpointOptionMarker = true;
@@ -518,7 +521,6 @@ SourceView::MarkerView::Draw(BRect updateRect)
if (!drawBreakpointOptionMarker) if (!drawBreakpointOptionMarker)
continue; continue;
SourceLocation statementStart, statementEnd; SourceLocation statementStart, statementEnd;
if (!fSourceCode->GetStatementLocationRange(SourceLocation(line), if (!fSourceCode->GetStatementLocationRange(SourceLocation(line),
statementStart, statementEnd) statementStart, statementEnd)
@@ -600,6 +602,8 @@ SourceView::MarkerView::_UpdateIPMarkers()
fIPMarkers.MakeEmpty(); fIPMarkers.MakeEmpty();
if (fSourceCode != NULL && fStackTrace != NULL) { if (fSourceCode != NULL && fStackTrace != NULL) {
LocatableFile* sourceFile = fSourceCode->GetSourceFile();
AutoLocker<TeamDebugModel> locker(fDebugModel); AutoLocker<TeamDebugModel> locker(fDebugModel);
for (int32 i = 0; StackFrame* frame = fStackTrace->FrameAt(i); for (int32 i = 0; StackFrame* frame = fStackTrace->FrameAt(i);
@@ -614,7 +618,9 @@ SourceView::MarkerView::_UpdateIPMarkers()
Reference<Statement> statementReference(statement, true); Reference<Statement> statementReference(statement, true);
uint32 line = statement->StartSourceLocation().Line(); uint32 line = statement->StartSourceLocation().Line();
if (functionInstance->GetFunction()->GetSourceCode() != fSourceCode if ((functionInstance->GetSourceCode() != fSourceCode
&& functionInstance->GetFunction()->SourceFile()
!= sourceFile)
|| line < 0 || line >= (uint32)LineCount()) { || line < 0 || line >= (uint32)LineCount()) {
continue; continue;
} }
@@ -649,6 +655,8 @@ SourceView::MarkerView::_UpdateBreakpointMarkers()
fBreakpointMarkers.MakeEmpty(); fBreakpointMarkers.MakeEmpty();
if (fSourceCode != NULL) { if (fSourceCode != NULL) {
LocatableFile* sourceFile = fSourceCode->GetSourceFile();
AutoLocker<TeamDebugModel> locker(fDebugModel); AutoLocker<TeamDebugModel> locker(fDebugModel);
// get the breakpoints in our source code range // get the breakpoints in our source code range
@@ -669,7 +677,9 @@ SourceView::MarkerView::_UpdateBreakpointMarkers()
Reference<Statement> statementReference(statement, true); Reference<Statement> statementReference(statement, true);
uint32 line = statement->StartSourceLocation().Line(); uint32 line = statement->StartSourceLocation().Line();
if (functionInstance->GetFunction()->GetSourceCode() != fSourceCode if ((functionInstance->GetSourceCode() != fSourceCode
&& functionInstance->GetFunction()->SourceFile()
!= sourceFile)
|| line < 0 || line >= (uint32)LineCount()) { || line < 0 || line >= (uint32)LineCount()) {
continue; continue;
} }
@@ -18,11 +18,12 @@
#include <AutoLocker.h> #include <AutoLocker.h>
#include "CpuState.h" #include "CpuState.h"
#include "DisassembledCode.h"
#include "FileSourceCode.h"
#include "Image.h" #include "Image.h"
#include "ImageDebugInfo.h" #include "ImageDebugInfo.h"
#include "MessageCodes.h" #include "MessageCodes.h"
#include "RegisterView.h" #include "RegisterView.h"
#include "SourceCode.h"
#include "StackTrace.h" #include "StackTrace.h"
#include "StackTraceView.h" #include "StackTraceView.h"
@@ -505,6 +506,8 @@ TeamWindow::_SetActiveFunction(FunctionInstance* functionInstance)
Function* function = fActiveFunction->GetFunction(); Function* function = fActiveFunction->GetFunction();
sourceCode = function->GetSourceCode(); sourceCode = function->GetSourceCode();
if (sourceCode == NULL)
sourceCode = fActiveFunction->GetSourceCode();
sourceCodeReference.SetTo(sourceCode); sourceCodeReference.SetTo(sourceCode);
// If the source code is not loaded yet, request it. // If the source code is not loaded yet, request it.
@@ -703,6 +706,8 @@ TeamWindow::_HandleSourceCodeChanged()
AutoLocker<TeamDebugModel> locker(fDebugModel); AutoLocker<TeamDebugModel> locker(fDebugModel);
SourceCode* sourceCode = fActiveFunction->GetFunction()->GetSourceCode(); SourceCode* sourceCode = fActiveFunction->GetFunction()->GetSourceCode();
if (sourceCode == NULL)
sourceCode = fActiveFunction->GetSourceCode();
Reference<SourceCode> sourceCodeReference(sourceCode); Reference<SourceCode> sourceCodeReference(sourceCode);
locker.Unlock(); locker.Unlock();
+2
View File
@@ -36,6 +36,8 @@ public:
{ return fUserBreakpoints.Head(); } { return fUserBreakpoints.Head(); }
UserBreakpointInstance* LastUserBreakpoint() const UserBreakpointInstance* LastUserBreakpoint() const
{ return fUserBreakpoints.Tail(); } { return fUserBreakpoints.Tail(); }
const UserBreakpointInstanceList& UserBreakpoints() const
{ return fUserBreakpoints; }
void AddUserBreakpoint( void AddUserBreakpoint(
UserBreakpointInstance* instance); 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 int32
DisassembledCode::CountLines() const DisassembledCode::CountLines() const
{ {
@@ -80,17 +94,32 @@ DisassembledCode::GetSourceFile() const
} }
status_t Statement*
DisassembledCode::GetStatementAtLocation(const SourceLocation& location, DisassembledCode::StatementAtLocation(const SourceLocation& location) const
Statement*& _statement)
{ {
Line* line = fLines.ItemAt(location.Line()); Line* line = fLines.ItemAt(location.Line());
if (line == NULL || line->statement == NULL) return line != NULL ? line->statement : NULL;
return B_ENTRY_NOT_FOUND; }
_statement = line->statement;
_statement->AcquireReference(); Statement*
return B_OK; 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();
~DisassembledCode(); ~DisassembledCode();
virtual bool Lock();
virtual void Unlock();
virtual int32 CountLines() const; virtual int32 CountLines() const;
virtual const char* LineAt(int32 index) const; virtual const char* LineAt(int32 index) const;
@@ -30,9 +33,10 @@ public:
virtual LocatableFile* GetSourceFile() const; virtual LocatableFile* GetSourceFile() const;
virtual status_t GetStatementAtLocation( Statement* StatementAtAddress(target_addr_t address) const;
const SourceLocation& location, Statement* StatementAtLocation(
Statement*& _statement); const SourceLocation& location) const;
TargetAddressRange StatementAddressRange() const;
public: public:
bool AddCommentLine(const BString& line); bool AddCommentLine(const BString& line);
+16 -9
View File
@@ -15,6 +15,7 @@
FileSourceCode::FileSourceCode(LocatableFile* file, SourceFile* sourceFile) FileSourceCode::FileSourceCode(LocatableFile* file, SourceFile* sourceFile)
: :
fLock("source code"),
fFile(file), fFile(file),
fSourceFile(sourceFile) fSourceFile(sourceFile)
{ {
@@ -33,7 +34,7 @@ FileSourceCode::~FileSourceCode()
status_t status_t
FileSourceCode::Init() 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 int32
FileSourceCode::CountLines() const FileSourceCode::CountLines() const
{ {
@@ -95,14 +110,6 @@ FileSourceCode::GetSourceFile() const
} }
status_t
FileSourceCode::GetStatementAtLocation(const SourceLocation& location,
Statement*& _statement)
{
return B_UNSUPPORTED;
}
int32 int32
FileSourceCode::_FindSourceLocationIndex(const SourceLocation& location, FileSourceCode::_FindSourceLocationIndex(const SourceLocation& location,
bool& _foundMatch) const bool& _foundMatch) const
+7 -4
View File
@@ -6,6 +6,9 @@
#define FILE_SOURCE_CODE_H #define FILE_SOURCE_CODE_H
#include <Locker.h>
#include "Array.h" #include "Array.h"
#include "SourceCode.h" #include "SourceCode.h"
@@ -24,6 +27,9 @@ public:
status_t AddSourceLocation( status_t AddSourceLocation(
const SourceLocation& location); const SourceLocation& location);
virtual bool Lock();
virtual void Unlock();
virtual int32 CountLines() const; virtual int32 CountLines() const;
virtual const char* LineAt(int32 index) const; virtual const char* LineAt(int32 index) const;
@@ -34,16 +40,13 @@ public:
virtual LocatableFile* GetSourceFile() const; virtual LocatableFile* GetSourceFile() const;
virtual status_t GetStatementAtLocation(
const SourceLocation& location,
Statement*& _statement);
private: private:
int32 _FindSourceLocationIndex( int32 _FindSourceLocationIndex(
const SourceLocation& location, const SourceLocation& location,
bool& _foundMatch) const; bool& _foundMatch) const;
private: private:
BLocker fLock;
LocatableFile* fFile; LocatableFile* fFile;
SourceFile* fSourceFile; SourceFile* fSourceFile;
Array<SourceLocation> fSourceLocations; Array<SourceLocation> fSourceLocations;
+5 -7
View File
@@ -20,6 +20,11 @@ class SourceCode : public Referenceable {
public: public:
virtual ~SourceCode(); 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 int32 CountLines() const = 0;
virtual const char* LineAt(int32 index) const = 0; virtual const char* LineAt(int32 index) const = 0;
@@ -29,13 +34,6 @@ public:
SourceLocation& _end) const = 0; SourceLocation& _end) const = 0;
virtual LocatableFile* GetSourceFile() 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 <AutoLocker.h>
#include "DisassembledCode.h"
#include "Function.h" #include "Function.h"
#include "ImageDebugInfo.h" #include "ImageDebugInfo.h"
#include "SourceCode.h" #include "SourceCode.h"
#include "SpecificImageDebugInfo.h" #include "SpecificImageDebugInfo.h"
#include "Statement.h"
#include "TeamDebugInfo.h" #include "TeamDebugInfo.h"
@@ -236,12 +238,23 @@ printf(" -> no function instance\n");
return B_ENTRY_NOT_FOUND; 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 // get the statement from the image debug info
FunctionDebugInfo* functionDebugInfo FunctionDebugInfo* functionDebugInfo
= functionInstance->GetFunctionDebugInfo(); = functionInstance->GetFunctionDebugInfo();
status_t error = functionDebugInfo->GetSpecificImageDebugInfo() status_t error = functionDebugInfo->GetSpecificImageDebugInfo()
->GetStatement(functionDebugInfo, address, _statement); ->GetStatement(functionDebugInfo, address, _statement);
// TODO: Provide the corresponding SourceCode, if available!
if (error != B_OK) if (error != B_OK)
{ {
printf(" -> no statement from the specific image debug info\n"); 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()); 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. // If we're lucky the source code can provide us with a statement.
status_t error = sourceCode->GetStatementAtLocation(location, _statement); if (DisassembledCode* code = dynamic_cast<DisassembledCode*>(sourceCode)) {
if (error == B_OK) Statement* statement = code->StatementAtLocation(location);
return error; 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. // Go the long and stony way over the source file and the team debug info.
// get the source file for the source code // get the source file for the source code
+33 -13
View File
@@ -10,6 +10,8 @@
#include <AutoLocker.h> #include <AutoLocker.h>
#include "Breakpoint.h" #include "Breakpoint.h"
#include "DisassembledCode.h"
#include "FileSourceCode.h"
#include "Function.h" #include "Function.h"
#include "UserBreakpoint.h" #include "UserBreakpoint.h"
@@ -109,24 +111,42 @@ TeamDebugModel::BreakpointAtAddress(target_addr_t address) const
} }
//void void
//TeamDebugModel::GetBreakpointsInAddressRange(TargetAddressRange range, TeamDebugModel::GetBreakpointsInAddressRange(TargetAddressRange range,
// BObjectList<Breakpoint>& breakpoints) const BObjectList<UserBreakpoint>& breakpoints) const
//{ {
// int32 index = fBreakpoints.FindBinaryInsertionIndex( int32 index = fBreakpoints.FindBinaryInsertionIndex(
// BreakpointByAddressPredicate(range.Start())); BreakpointByAddressPredicate(range.Start()));
// for (; Breakpoint* breakpoint = fBreakpoints.ItemAt(index); index++) { for (; Breakpoint* breakpoint = fBreakpoints.ItemAt(index); index++) {
// if (breakpoint->Address() > range.End()) if (breakpoint->Address() > range.End())
// break; break;
// breakpoints.AddItem(breakpoint);
// } for (UserBreakpointInstanceList::ConstIterator it
//} = breakpoint->UserBreakpoints().GetIterator();
UserBreakpointInstance* instance = it.Next();) {
breakpoints.AddItem(instance->GetUserBreakpoint());
}
}
// TODO: Avoid duplicates!
}
void void
TeamDebugModel::GetBreakpointsForSourceCode(SourceCode* sourceCode, TeamDebugModel::GetBreakpointsForSourceCode(SourceCode* sourceCode,
BObjectList<UserBreakpoint>& breakpoints) const 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 // TODO: This can probably be optimized. Maybe by registering the user
// breakpoints with the team debug model and sorting them by source code. // breakpoints with the team debug model and sorting them by source code.
for (int32 i = 0; Breakpoint* breakpoint = fBreakpoints.ItemAt(i); i++) { for (int32 i = 0; Breakpoint* breakpoint = fBreakpoints.ItemAt(i); i++) {
@@ -137,7 +157,7 @@ TeamDebugModel::GetBreakpointsForSourceCode(SourceCode* sourceCode,
UserBreakpoint* userBreakpoint UserBreakpoint* userBreakpoint
= userBreakpointInstance->GetUserBreakpoint(); = userBreakpointInstance->GetUserBreakpoint();
if (userBreakpoint->GetFunction()->GetSourceCode() == sourceCode) if (userBreakpoint->GetFunction()->SourceFile() == sourceFile)
breakpoints.AddItem(userBreakpoint); breakpoints.AddItem(userBreakpoint);
} }
} }
+4 -3
View File
@@ -58,9 +58,10 @@ public:
Breakpoint* BreakpointAt(int32 index) const; Breakpoint* BreakpointAt(int32 index) const;
Breakpoint* BreakpointAtAddress( Breakpoint* BreakpointAtAddress(
target_addr_t address) const; target_addr_t address) const;
// void GetBreakpointsInAddressRange( void GetBreakpointsInAddressRange(
// TargetAddressRange range, TargetAddressRange range,
// BObjectList<Breakpoint>& breakpoints) const; BObjectList<UserBreakpoint>& breakpoints)
const;
void GetBreakpointsForSourceCode( void GetBreakpointsForSourceCode(
SourceCode* sourceCode, SourceCode* sourceCode,
BObjectList<UserBreakpoint>& breakpoints) BObjectList<UserBreakpoint>& breakpoints)