* Finished the transformation of the SourceCode interface:

- Replaced StatementAtLine() by GetStatementLocationRange(), which doesn't
    return a statement (i.e. also target addresses), but just a range in the
    source code. This can also be implemented by FileSourceCode, which can
    therefore be used for more than one instance of a function.
  - Added GetStatementAtLocation() which kind of is also a replacement for
    StatementAtLine(), but is optional and only provided by
    DisassembledSourceCode.
  - Added GetSourceFile(), which has to be provided when
    GetStatementAtLocation() is not implemented.
  - Kicked the statement stuff out of FileSourceCode. It only knows source
    ranges, now.
* Team: Added GetStatementAtSourceLocation(), which is the real replacement for
  SourceCode::StatementAtLine() in cases where a statement is actually
  needed. It uses SourceCode::GetStatementAtLocation(), if available and
  otherwise finds a function at the source location, and gets a statement for
  one of its instances.
* TeamDebugInfo: Does now manage a source file -> functions map allowing to
  look up functions at source file locations.
* DwarfImageDebugInfo:
  - Switched the path in the source code hash table key for a LocatableFile,
    which is cheaper to hash and to compare.
  - Fixed bugs where the relocation delta was ignored.
  - Replace a -1 in the SourceLocation column component by 0 to avoid
    mismatches.
* SourceLocation: Changed component types from uint32 to int32. Otherwise -1 is
  not representable.

Things mostly work as before starting the refactoring to support function
instances. All is not well yet, though. E.g. we don't merge the source code
information for common source files (like headers) provided by different
compilation units (or even images) yet. We need to do that, since the debug
info for a compilation unit only contains line number information for inline
functions (in headers) that are actually used.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31495 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-07-10 00:08:45 +00:00
parent 7d095b893a
commit a4b0c19209
18 changed files with 524 additions and 209 deletions
+2 -9
View File
@@ -879,14 +879,7 @@ printf(" function: %p\n", function);
= functionInstance->GetFunctionDebugInfo(); = functionInstance->GetFunctionDebugInfo();
SourceLocation sourceLocation; SourceLocation sourceLocation;
Statement* breakpointStatement = NULL; Statement* breakpointStatement = NULL;
// if (SourceCode* sourceCode = functionDebugInfo->GetSourceCode()) { if (functionDebugInfo->GetSpecificImageDebugInfo()->GetStatement(
// breakpointStatement = sourceCode->StatementAtAddress(address);
// if (breakpointStatement != NULL)
// sourceLocation = breakpointStatement->StartSourceLocation();
// }
if (breakpointStatement == NULL
&& functionDebugInfo->GetSpecificImageDebugInfo()->GetStatement(
functionDebugInfo, address, breakpointStatement) != B_OK) { functionDebugInfo, address, breakpointStatement) != B_OK) {
return; return;
} }
@@ -920,7 +913,7 @@ printf(" function instance %p: range: %#llx - %#llx\n", instance, instance->Add
Statement* statement = NULL; Statement* statement = NULL;
functionDebugInfo = instance->GetFunctionDebugInfo(); functionDebugInfo = instance->GetFunctionDebugInfo();
functionDebugInfo->GetSpecificImageDebugInfo() functionDebugInfo->GetSpecificImageDebugInfo()
->GetStatementForSourceLocation(functionDebugInfo, ->GetStatementAtSourceLocation(functionDebugInfo,
sourceLocation, statement); sourceLocation, statement);
if (statement != NULL) { if (statement != NULL) {
instanceAddress = statement->CoveringAddressRange().Start(); instanceAddress = statement->CoveringAddressRange().Start();
@@ -119,7 +119,7 @@ DebuggerImageDebugInfo::GetStatement(FunctionDebugInfo* function,
status_t status_t
DebuggerImageDebugInfo::GetStatementForSourceLocation( DebuggerImageDebugInfo::GetStatementAtSourceLocation(
FunctionDebugInfo* function, const SourceLocation& sourceLocation, FunctionDebugInfo* function, const SourceLocation& sourceLocation,
Statement*& _statement) Statement*& _statement)
{ {
@@ -36,7 +36,7 @@ public:
virtual status_t GetStatement(FunctionDebugInfo* function, virtual status_t GetStatement(FunctionDebugInfo* function,
target_addr_t address, target_addr_t address,
Statement*& _statement); Statement*& _statement);
virtual status_t GetStatementForSourceLocation( virtual status_t GetStatementAtSourceLocation(
FunctionDebugInfo* function, FunctionDebugInfo* function,
const SourceLocation& sourceLocation, const SourceLocation& sourceLocation,
Statement*& _statement); Statement*& _statement);
@@ -8,6 +8,7 @@
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <algorithm>
#include <new> #include <new>
#include <AutoDeleter.h> #include <AutoDeleter.h>
@@ -34,30 +35,29 @@
struct DwarfImageDebugInfo::SourceCodeKey { struct DwarfImageDebugInfo::SourceCodeKey {
CompilationUnit* unit; CompilationUnit* unit;
BString filePath; LocatableFile* file;
SourceCodeKey(CompilationUnit* unit, const BString& filePath)
:
unit(unit),
filePath(filePath)
{
}
SourceCodeKey(CompilationUnit* unit, LocatableFile* file) SourceCodeKey(CompilationUnit* unit, LocatableFile* file)
: :
unit(unit) unit(unit),
file(file)
{ {
file->GetLocatedPath(filePath); file->AcquireReference();
}
~SourceCodeKey()
{
file->ReleaseReference();
} }
uint32 HashValue() const uint32 HashValue() const
{ {
return (uint32)(addr_t)unit ^ StringUtils::HashValue(filePath); return (uint32)((addr_t)unit ^ (addr_t)file);
} }
bool operator==(const SourceCodeKey& other) const bool operator==(const SourceCodeKey& other) const
{ {
return unit == other.unit && filePath == other.filePath; return unit == other.unit && file == other.file;
} }
}; };
@@ -244,7 +244,7 @@ printf(" %ld compilation units\n", fFile->CountCompilationUnits());
DwarfFunctionDebugInfo* function DwarfFunctionDebugInfo* function
= new(std::nothrow) DwarfFunctionDebugInfo(this, unit, = new(std::nothrow) DwarfFunctionDebugInfo(this, unit,
subprogramEntry, rangeList, name, file, subprogramEntry, rangeList, name, file,
SourceLocation(line, column)); SourceLocation(line, std::max(column, 0L)));
if (function == NULL || !functions.AddItem(function)) { if (function == NULL || !functions.AddItem(function)) {
delete function; delete function;
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -292,7 +292,6 @@ DwarfImageDebugInfo::LoadSourceCode(FunctionDebugInfo* function,
{ {
AutoLocker<BLocker> locker(fLock); AutoLocker<BLocker> locker(fLock);
// TODO: Load the actual source code!
status_t error = _LoadSourceCode(function, _sourceCode); status_t error = _LoadSourceCode(function, _sourceCode);
if (error == B_OK) if (error == B_OK)
return B_OK; return B_OK;
@@ -323,30 +322,26 @@ status_t
DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function, DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function,
target_addr_t address, Statement*& _statement) target_addr_t address, Statement*& _statement)
{ {
printf("DwarfImageDebugInfo::GetStatement(function: %p, address: %#llx)\n",
_function, address);
DwarfFunctionDebugInfo* function DwarfFunctionDebugInfo* function
= dynamic_cast<DwarfFunctionDebugInfo*>(_function); = dynamic_cast<DwarfFunctionDebugInfo*>(_function);
if (function == NULL) if (function == NULL)
{
printf(" -> no dwarf function\n");
return B_BAD_VALUE; return B_BAD_VALUE;
}
AutoLocker<BLocker> locker(fLock); AutoLocker<BLocker> locker(fLock);
// get the source file // check whether we have the source code
LocatableFile* file = function->SourceFile();
if (file == NULL)
return B_ENTRY_NOT_FOUND;
// maybe the source code is already loaded -- this will simplify things
CompilationUnit* unit = function->GetCompilationUnit(); CompilationUnit* unit = function->GetCompilationUnit();
// FileSourceCode* sourceCode = _LookupSourceCode(unit, file); LocatableFile* file = function->SourceFile();
// if (sourceCode) { if (file == NULL) {
// Statement* statement = sourceCode->StatementAtAddress(address); printf(" -> no source file\n");
// if (statement == NULL) // no source code -- rather return the assembly statement
// return B_ENTRY_NOT_FOUND; return fArchitecture->GetStatement(function, address, _statement);
// }
// statement->AcquireReference();
// _statement = statement;
// return B_OK;
// }
// get the index of the source file in the compilation unit for cheaper // get the index of the source file in the compilation unit for cheaper
// comparison below // comparison below
@@ -356,7 +351,13 @@ DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function,
// compilation unit. // compilation unit.
LineNumberProgram& program = unit->GetLineNumberProgram(); LineNumberProgram& program = unit->GetLineNumberProgram();
if (!program.IsValid()) if (!program.IsValid())
{
printf(" -> no line number program\n");
return B_BAD_DATA; return B_BAD_DATA;
}
// adjust address
address -= fRelocationDelta;
LineNumberProgram::State state; LineNumberProgram::State state;
program.GetInitialState(state); program.GetInitialState(state);
@@ -393,26 +394,27 @@ DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function,
if (state.isStatement) { if (state.isStatement) {
statementAddress = state.address; statementAddress = state.address;
statementLine = state.line - 1; statementLine = state.line - 1;
statementColumn = state.column - 1; statementColumn = std::max(state.column - 1, 0L);
} }
} }
printf(" -> no line number program match\n");
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
} }
status_t status_t
DwarfImageDebugInfo::GetStatementForSourceLocation(FunctionDebugInfo* _function, DwarfImageDebugInfo::GetStatementAtSourceLocation(FunctionDebugInfo* _function,
const SourceLocation& sourceLocation, Statement*& _statement) const SourceLocation& sourceLocation, Statement*& _statement)
{ {
DwarfFunctionDebugInfo* function DwarfFunctionDebugInfo* function
= dynamic_cast<DwarfFunctionDebugInfo*>(_function); = dynamic_cast<DwarfFunctionDebugInfo*>(_function);
if (function == NULL) if (function == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
target_addr_t functionStartAddress = function->Address(); target_addr_t functionStartAddress = function->Address() - fRelocationDelta;
target_addr_t functionEndAddress = functionStartAddress + function->Size(); target_addr_t functionEndAddress = functionStartAddress + function->Size();
printf("DwarfImageDebugInfo::GetStatementForSourceLocation(%p): function range: %#llx - %#llx\n", printf("DwarfImageDebugInfo::GetStatementAtSourceLocation(%p, (%ld, %ld)): function range: %#llx - %#llx\n",
function, functionStartAddress, functionEndAddress); function, sourceLocation.Line(), sourceLocation.Column(), functionStartAddress, functionEndAddress);
AutoLocker<BLocker> locker(fLock); AutoLocker<BLocker> locker(fLock);
@@ -421,26 +423,13 @@ function, functionStartAddress, functionEndAddress);
if (file == NULL) if (file == NULL)
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
// maybe the source code is already loaded -- this will simplify things
CompilationUnit* unit = function->GetCompilationUnit(); CompilationUnit* unit = function->GetCompilationUnit();
FileSourceCode* sourceCode = _LookupSourceCode(unit, file);
if (sourceCode) {
// TODO: This is not precise enough -- columns are ignored!
Statement* statement = sourceCode->StatementAtLine(
sourceLocation.Line());
if (statement == NULL)
return B_ENTRY_NOT_FOUND;
statement->AcquireReference();
_statement = statement;
return B_OK;
}
// get the index of the source file in the compilation unit for cheaper // get the index of the source file in the compilation unit for cheaper
// comparison below // comparison below
int32 fileIndex = _GetSourceFileIndex(unit, file); int32 fileIndex = _GetSourceFileIndex(unit, file);
// target_addr_t functionStartAddress = function->Address(); // target_addr_t functionStartAddress = function->Address() - fRelocationDelta;
// target_addr_t functionEndAddress = functionStartAddress + function->Size(); // target_addr_t functionEndAddress = functionStartAddress + function->Size();
// Get the statement by executing the line number program for the // Get the statement by executing the line number program for the
@@ -461,11 +450,15 @@ function, functionStartAddress, functionEndAddress);
if (statementAddress != 0 if (statementAddress != 0
&& (!isOurFile || state.isStatement || state.isSequenceEnd)) { && (!isOurFile || state.isStatement || state.isSequenceEnd)) {
target_addr_t endAddress = state.address; target_addr_t endAddress = state.address;
if (statementAddress < endAddress) {
printf(" statement: %#llx - %#llx, location: (%ld, %ld)\n", statementAddress, endAddress, statementLine, statementColumn);
}
if (statementAddress < endAddress if (statementAddress < endAddress
&& statementAddress >= functionStartAddress && statementAddress >= functionStartAddress
&& statementAddress < functionEndAddress && statementAddress < functionEndAddress
&& statementLine == (int32)sourceLocation.Line() && statementLine == (int32)sourceLocation.Line()
&& statementColumn == (int32)sourceLocation.Column()) { && statementColumn == (int32)sourceLocation.Column()) {
printf(" -> found statement!\n");
ContiguousStatement* statement = new(std::nothrow) ContiguousStatement* statement = new(std::nothrow)
ContiguousStatement( ContiguousStatement(
SourceLocation(statementLine, statementColumn), SourceLocation(statementLine, statementColumn),
@@ -488,7 +481,7 @@ function, functionStartAddress, functionEndAddress);
if (state.isStatement) { if (state.isStatement) {
statementAddress = state.address; statementAddress = state.address;
statementLine = state.line - 1; statementLine = state.line - 1;
statementColumn = state.column - 1; statementColumn = std::max(state.column - 1, 0L);
} }
} }
@@ -535,7 +528,7 @@ printf(" file %ld: %s\n", i, fileName);
return error; return error;
// create the source code // create the source code
sourceCode = new(std::nothrow) FileSourceCode(sourceFile); sourceCode = new(std::nothrow) FileSourceCode(file, sourceFile);
sourceFile->ReleaseReference(); sourceFile->ReleaseReference();
if (sourceCode == NULL) if (sourceCode == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -564,23 +557,13 @@ printf(" %#lx (%ld, %ld, %ld) %d\n", state.address, state.file, state.line, s
if (statementAddress != 0 if (statementAddress != 0
&& (!isOurFile || state.isStatement || state.isSequenceEnd)) { && (!isOurFile || state.isStatement || state.isSequenceEnd)) {
target_addr_t endAddress = state.address; target_addr_t endAddress = state.address;
if (endAddress > statementAddress) { if (endAddress > statementAddress) {
// add the statement // add the statement
ContiguousStatement* statement = new(std::nothrow) error = sourceCode->AddSourceLocation(
ContiguousStatement( SourceLocation(statementLine, statementColumn));
SourceLocation(statementLine, statementColumn), if (error != B_OK)
TargetAddressRange(fRelocationDelta + statementAddress,
endAddress - statementAddress));
if (statement == NULL)
return B_NO_MEMORY;
error = sourceCode->AddStatement(statement);
if (error != B_OK) {
delete statement;
return error; return error;
} printf(" -> statement: %#llx - %#llx, source location: (%ld, %ld)\n", statementAddress, endAddress, statementLine, statementColumn);
printf(" -> statement: %#llx - %#llx, line: %ld\n", statement->AddressRange().Start(),
statement->AddressRange().End(), statementLine);
} }
statementAddress = 0; statementAddress = 0;
@@ -593,7 +576,7 @@ statement->AddressRange().End(), statementLine);
if (state.isStatement) { if (state.isStatement) {
statementAddress = state.address; statementAddress = state.address;
statementLine = state.line - 1; statementLine = state.line - 1;
statementColumn = state.column - 1; statementColumn = std::max(state.column - 1, 0L);
} }
} }
@@ -47,7 +47,7 @@ public:
virtual status_t GetStatement(FunctionDebugInfo* function, virtual status_t GetStatement(FunctionDebugInfo* function,
target_addr_t address, target_addr_t address,
Statement*& _statement); Statement*& _statement);
virtual status_t GetStatementForSourceLocation( virtual status_t GetStatementAtSourceLocation(
FunctionDebugInfo* function, FunctionDebugInfo* function,
const SourceLocation& sourceLocation, const SourceLocation& sourceLocation,
Statement*& _statement); Statement*& _statement);
@@ -46,7 +46,7 @@ public:
target_addr_t address, target_addr_t address,
Statement*& _statement) = 0; Statement*& _statement) = 0;
// returns reference // returns reference
virtual status_t GetStatementForSourceLocation( virtual status_t GetStatementAtSourceLocation(
FunctionDebugInfo* function, FunctionDebugInfo* function,
const SourceLocation& sourceLocation, const SourceLocation& sourceLocation,
Statement*& _statement) = 0; Statement*& _statement) = 0;
+222 -3
View File
@@ -3,8 +3,11 @@
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include "TeamDebugInfo.h" #include "TeamDebugInfo.h"
#include <stdio.h>
#include <new> #include <new>
#include <AutoDeleter.h> #include <AutoDeleter.h>
@@ -13,6 +16,7 @@
#include "DwarfTeamDebugInfo.h" #include "DwarfTeamDebugInfo.h"
#include "Function.h" #include "Function.h"
#include "ImageDebugInfo.h" #include "ImageDebugInfo.h"
#include "LocatableFile.h"
#include "SpecificImageDebugInfo.h" #include "SpecificImageDebugInfo.h"
#include "StringUtils.h" #include "StringUtils.h"
@@ -66,6 +70,131 @@ struct TeamDebugInfo::FunctionHashDefinition {
}; };
// #pragma mark - SourceFileEntry
struct TeamDebugInfo::SourceFileEntry : public HashTableLink<SourceFileEntry> {
SourceFileEntry(LocatableFile* sourceFile)
:
fSourceFile(sourceFile)
{
fSourceFile->AcquireReference();
}
~SourceFileEntry()
{
fSourceFile->ReleaseReference();
}
status_t Init()
{
return B_OK;
}
LocatableFile* SourceFile() const
{
return fSourceFile;
}
bool IsUnused() const
{
return fFunctions.IsEmpty();
}
status_t AddFunction(Function* function)
{
if (!fFunctions.BinaryInsert(function, &_CompareFunctions))
return B_NO_MEMORY;
return B_OK;
}
void RemoveFunction(Function* function)
{
int32 index = fFunctions.BinarySearchIndex(*function,
&_CompareFunctions);
if (index >= 0)
fFunctions.RemoveItemAt(index);
}
Function* FunctionAtLocation(const SourceLocation& location) const
{
int32 index = fFunctions.BinarySearchIndexByKey(location,
&_CompareLocationFunction);
if (index >= 0)
return fFunctions.ItemAt(index);
// No exact match, so we return the previous function which might still
// contain the location.
index = -index - 1;
if (index == 0)
return NULL;
return fFunctions.ItemAt(index - 1);
}
private:
typedef BObjectList<Function> FunctionList;
private:
static int _CompareFunctions(const Function* a, const Function* b)
{
SourceLocation locationA = a->GetSourceLocation();
SourceLocation locationB = b->GetSourceLocation();
if (locationA < locationB)
return -1;
return locationA == locationB ? 0 : 1;
}
static int _CompareLocationFunction(const SourceLocation* location,
const Function* function)
{
SourceLocation functionLocation = function->GetSourceLocation();
if (*location < functionLocation)
return -1;
return *location == functionLocation ? 0 : 1;
}
private:
LocatableFile* fSourceFile;
FunctionList fFunctions;
};
// #pragma mark - SourceFileHashDefinition
struct TeamDebugInfo::SourceFileHashDefinition {
typedef const LocatableFile* KeyType;
typedef SourceFileEntry ValueType;
size_t HashKey(const LocatableFile* key) const
{
return (size_t)(addr_t)key;
}
size_t Hash(const SourceFileEntry* value) const
{
return HashKey(value->SourceFile());
}
bool Compare(const LocatableFile* key, const SourceFileEntry* value) const
{
return key == value->SourceFile();
}
HashTableLink<SourceFileEntry>* GetLink(SourceFileEntry* value) const
{
return value;
}
};
// #pragma mark - TeamDebugInfo // #pragma mark - TeamDebugInfo
@@ -76,13 +205,25 @@ TeamDebugInfo::TeamDebugInfo(DebuggerInterface* debuggerInterface,
fArchitecture(architecture), fArchitecture(architecture),
fFileManager(fileManager), fFileManager(fileManager),
fSpecificInfos(10, true), fSpecificInfos(10, true),
fFunctions(NULL) fFunctions(NULL),
fSourceFiles(NULL)
{ {
} }
TeamDebugInfo::~TeamDebugInfo() TeamDebugInfo::~TeamDebugInfo()
{ {
if (fSourceFiles != NULL) {
SourceFileEntry* entry = fSourceFiles->Clear(true);
while (entry != NULL) {
SourceFileEntry* next = entry->fNext;
delete entry;
entry = next;
}
delete fSourceFiles;
}
if (fFunctions != NULL) { if (fFunctions != NULL) {
Function* function = fFunctions->Clear(true); Function* function = fFunctions->Clear(true);
while (function != NULL) { while (function != NULL) {
@@ -108,6 +249,15 @@ TeamDebugInfo::Init()
if (error != B_OK) if (error != B_OK)
return error; return error;
// create source file hash table
fSourceFiles = new(std::nothrow) SourceFileTable;
if (fSourceFiles == NULL)
return B_NO_MEMORY;
error = fSourceFiles->Init();
if (error != B_OK)
return error;
// Create specific infos for all types of debug info we support, in // Create specific infos for all types of debug info we support, in
// descending order of expressiveness. // descending order of expressiveness.
@@ -198,9 +348,16 @@ printf(" adding instance %p to existing function %p\n", instance, function);
printf(" adding instance %p to new function %p\n", instance, function); printf(" adding instance %p to new function %p\n", instance, function);
function->AddInstance(instance); function->AddInstance(instance);
instance->SetFunction(function); instance->SetFunction(function);
fFunctions->Insert(function);
status_t error = _AddFunction(function);
// Insert after adding the instance. Otherwise the function // Insert after adding the instance. Otherwise the function
// wouldn't be hashable/comparable. // wouldn't be hashable/comparable.
if (error != B_OK) {
function->RemoveInstance(instance);
instance->SetFunction(NULL);
RemoveImageDebugInfo(imageDebugInfo);
return error;
}
} }
} }
@@ -222,7 +379,7 @@ TeamDebugInfo::RemoveImageDebugInfo(ImageDebugInfo* imageDebugInfo)
// Note, that we have to remove it from the hash before removing // Note, that we have to remove it from the hash before removing
// the instance, since otherwise the function cannot be compared // the instance, since otherwise the function cannot be compared
// anymore. // anymore.
fFunctions->Remove(function); _RemoveFunction(function);
function->ReleaseReference(); function->ReleaseReference();
// The instance still has a reference. // The instance still has a reference.
} }
@@ -234,3 +391,65 @@ TeamDebugInfo::RemoveImageDebugInfo(ImageDebugInfo* imageDebugInfo)
} }
} }
} }
Function*
TeamDebugInfo::FunctionAtSourceLocation(LocatableFile* file,
const SourceLocation& location)
{
if (SourceFileEntry* entry = fSourceFiles->Lookup(file))
return entry->FunctionAtLocation(location);
return NULL;
}
status_t
TeamDebugInfo::_AddFunction(Function* function)
{
// If the function refers to a source file, add it to the respective entry.
if (LocatableFile* sourceFile = function->SourceFile()) {
SourceFileEntry* entry = fSourceFiles->Lookup(sourceFile);
if (entry == NULL) {
// no entry for the source file yet -- create on
entry = new(std::nothrow) SourceFileEntry(sourceFile);
if (entry == NULL)
return B_NO_MEMORY;
status_t error = entry->Init();
if (error != B_OK) {
delete entry;
return error;
}
fSourceFiles->Insert(entry);
}
// add the function
status_t error = entry->AddFunction(function);
if (error != B_OK) {
if (entry->IsUnused()) {
fSourceFiles->Remove(entry);
delete entry;
}
return error;
}
}
fFunctions->Insert(function);
return B_OK;
}
void
TeamDebugInfo::_RemoveFunction(Function* function)
{
fFunctions->Remove(function);
// If the function refers to a source file, remove it from the respective
// entry.
if (LocatableFile* sourceFile = function->SourceFile()) {
if (SourceFileEntry* entry = fSourceFiles->Lookup(sourceFile))
entry->RemoveFunction(function);
}
}
@@ -5,6 +5,7 @@
#ifndef TEAM_DEBUG_INFO_H #ifndef TEAM_DEBUG_INFO_H
#define TEAM_DEBUG_INFO_H #define TEAM_DEBUG_INFO_H
#include <ObjectList.h> #include <ObjectList.h>
#include <Referenceable.h> #include <Referenceable.h>
#include <util/OpenHashTable.h> #include <util/OpenHashTable.h>
@@ -20,6 +21,7 @@ class FunctionInstance;
class ImageDebugInfo; class ImageDebugInfo;
class ImageInfo; class ImageInfo;
class LocatableFile; class LocatableFile;
class SourceLocation;
class SpecificTeamDebugInfo; class SpecificTeamDebugInfo;
@@ -43,11 +45,21 @@ public:
void RemoveImageDebugInfo( void RemoveImageDebugInfo(
ImageDebugInfo* imageDebugInfo); ImageDebugInfo* imageDebugInfo);
Function* FunctionAtSourceLocation(LocatableFile* file,
const SourceLocation& location);
private: private:
struct FunctionHashDefinition; struct FunctionHashDefinition;
struct SourceFileEntry;
struct SourceFileHashDefinition;
typedef BObjectList<SpecificTeamDebugInfo> SpecificInfoList; typedef BObjectList<SpecificTeamDebugInfo> SpecificInfoList;
typedef OpenHashTable<FunctionHashDefinition> FunctionTable; typedef OpenHashTable<FunctionHashDefinition> FunctionTable;
typedef OpenHashTable<SourceFileHashDefinition> SourceFileTable;
private:
status_t _AddFunction(Function* function);
void _RemoveFunction(Function* function);
private: private:
DebuggerInterface* fDebuggerInterface; DebuggerInterface* fDebuggerInterface;
@@ -55,6 +67,7 @@ private:
FileManager* fFileManager; FileManager* fFileManager;
SpecificInfoList fSpecificInfos; SpecificInfoList fSpecificInfos;
FunctionTable* fFunctions; FunctionTable* fFunctions;
SourceFileTable* fSourceFiles;
}; };
@@ -518,9 +518,11 @@ SourceView::MarkerView::Draw(BRect updateRect)
if (!drawBreakpointOptionMarker) if (!drawBreakpointOptionMarker)
continue; continue;
Statement* statement = fSourceCode->StatementAtLine(line);
if (statement == NULL SourceLocation statementStart, statementEnd;
|| statement->StartSourceLocation().Line() != (uint32)line) { if (!fSourceCode->GetStatementLocationRange(SourceLocation(line),
statementStart, statementEnd)
|| statementStart.Line() != line) {
continue; continue;
} }
@@ -541,11 +543,15 @@ SourceView::MarkerView::MouseDown(BPoint where)
if (line < 0) if (line < 0)
return; return;
Statement* statement = fSourceCode->StatementAtLine(line); AutoLocker<TeamDebugModel> locker(fDebugModel);
if (statement == NULL Statement* statement;
|| statement->StartSourceLocation().Line() != (uint32)line) { if (fDebugModel->GetTeam()->GetStatementAtSourceLocation(fSourceCode,
SourceLocation(line), statement) != B_OK) {
return; return;
} }
Reference<Statement> statementReference(statement, true);
if (statement->StartSourceLocation().Line() != line)
return;
int32 modifiers; int32 modifiers;
if (Looper()->CurrentMessage()->FindInt32("modifiers", &modifiers) != B_OK) if (Looper()->CurrentMessage()->FindInt32("modifiers", &modifiers) != B_OK)
@@ -1005,6 +1011,7 @@ SourceView::UserBreakpointChanged(target_addr_t address)
bool bool
SourceView::ScrollToAddress(target_addr_t address) SourceView::ScrollToAddress(target_addr_t address)
{ {
printf("SourceView::ScrollToAddress(%#llx)\n", address);
if (fSourceCode == NULL) if (fSourceCode == NULL)
return false; return false;
@@ -1025,6 +1032,7 @@ SourceView::ScrollToAddress(target_addr_t address)
bool bool
SourceView::ScrollToLine(uint32 line) SourceView::ScrollToLine(uint32 line)
{ {
printf("SourceView::ScrollToLine(%lu)\n", line);
if (fSourceCode == NULL || line >= (uint32)fSourceCode->CountLines()) if (fSourceCode == NULL || line >= (uint32)fSourceCode->CountLines())
return false; return false;
+29 -21
View File
@@ -3,6 +3,7 @@
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include "DisassembledCode.h" #include "DisassembledCode.h"
#include <stdlib.h> #include <stdlib.h>
@@ -57,33 +58,40 @@ DisassembledCode::LineAt(int32 index) const
} }
Statement* bool
DisassembledCode::StatementAtLine(int32 index) const DisassembledCode::GetStatementLocationRange(const SourceLocation& location,
SourceLocation& _start, SourceLocation& _end) const
{ {
Line* line = fLines.ItemAt(index); Line* line = fLines.ItemAt(location.Line());
return line != NULL ? line->statement : NULL; if (line == NULL || line->statement == NULL)
return false;
_start = line->statement->StartSourceLocation();
_end = SourceLocation(_start.Line() + 1);
// TODO: Multi-line instructions!
return true;
} }
//Statement* LocatableFile*
//DisassembledCode::StatementAtAddress(target_addr_t address) const DisassembledCode::GetSourceFile() const
//{ {
// return fStatements.BinarySearchByKey(address, &_CompareAddressStatement); return NULL;
//} }
//TargetAddressRange status_t
//DisassembledCode::StatementAddressRange() const DisassembledCode::GetStatementAtLocation(const SourceLocation& location,
//{ Statement*& _statement)
// if (fStatements.IsEmpty()) {
// return TargetAddressRange(); Line* line = fLines.ItemAt(location.Line());
// if (line == NULL || line->statement == NULL)
// ContiguousStatement* first = fStatements.ItemAt(0); return B_ENTRY_NOT_FOUND;
// ContiguousStatement* last
// = fStatements.ItemAt(fStatements.CountItems() - 1); _statement = line->statement;
// return TargetAddressRange(first->AddressRange().Start(), _statement->AcquireReference();
// last->AddressRange().End()); return B_OK;
//} }
bool bool
+10 -3
View File
@@ -5,6 +5,7 @@
#ifndef DISASSEMBLED_CODE_H #ifndef DISASSEMBLED_CODE_H
#define DISASSEMBLED_CODE_H #define DISASSEMBLED_CODE_H
#include <ObjectList.h> #include <ObjectList.h>
#include "SourceCode.h" #include "SourceCode.h"
@@ -22,10 +23,16 @@ public:
virtual int32 CountLines() const; virtual int32 CountLines() const;
virtual const char* LineAt(int32 index) const; virtual const char* LineAt(int32 index) const;
virtual Statement* StatementAtLine(int32 index) const; virtual bool GetStatementLocationRange(
// Statement* StatementAtAddress(target_addr_t address) const; const SourceLocation& location,
SourceLocation& _start,
SourceLocation& _end) const;
// TargetAddressRange StatementAddressRange() const; virtual LocatableFile* GetSourceFile() const;
virtual status_t GetStatementAtLocation(
const SourceLocation& location,
Statement*& _statement);
public: public:
bool AddCommentLine(const BString& line); bool AddCommentLine(const BString& line);
+63 -70
View File
@@ -3,33 +3,29 @@
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include "FileSourceCode.h" #include "FileSourceCode.h"
#include <string.h> #include <string.h>
#include "LocatableFile.h"
#include "SourceFile.h" #include "SourceFile.h"
#include "Statement.h" #include "SourceLocation.h"
// TODO: Lot's of code duplication from DissassembledCode! FileSourceCode::FileSourceCode(LocatableFile* file, SourceFile* sourceFile)
FileSourceCode::FileSourceCode(SourceFile* file)
: :
fFile(file), fFile(file),
fLineStatements(NULL) fSourceFile(sourceFile)
{ {
fFile->AcquireReference(); fFile->AcquireReference();
fSourceFile->AcquireReference();
} }
FileSourceCode::~FileSourceCode() FileSourceCode::~FileSourceCode()
{ {
for (int32 i = 0; Statement* statement = fStatements.ItemAt(i); i++) fSourceFile->ReleaseReference();
statement->RemoveReference();
delete[] fLineStatements;
fFile->ReleaseReference(); fFile->ReleaseReference();
} }
@@ -37,94 +33,91 @@ FileSourceCode::~FileSourceCode()
status_t status_t
FileSourceCode::Init() FileSourceCode::Init()
{ {
fLineStatements = new(std::nothrow) Statement*[fFile->CountLines()];
if (fLineStatements == NULL)
return B_NO_MEMORY;
memset(fLineStatements, 0, fFile->CountLines() * sizeof(Statement*));
return B_OK; return B_OK;
} }
status_t status_t
FileSourceCode::AddStatement(ContiguousStatement* statement) FileSourceCode::AddSourceLocation(const SourceLocation& location)
{ {
if (!fStatements.BinaryInsert(statement, &_CompareStatements)) // Find the insertion index; don't insert twice.
return B_NO_MEMORY; bool foundMatch;
int32 index = _FindSourceLocationIndex(location, foundMatch);
if (foundMatch)
return B_OK;
int32 line = statement->StartSourceLocation().Line(); return fSourceLocations.Insert(location, index) ? B_OK : B_NO_MEMORY;
if (line >= 0 && line < fFile->CountLines()
&& fLineStatements[line] == NULL) {
fLineStatements[line] = statement;
}
statement->AcquireReference();
return B_OK;
} }
int32 int32
FileSourceCode::CountLines() const FileSourceCode::CountLines() const
{ {
return fFile->CountLines(); return fSourceFile->CountLines();
} }
const char* const char*
FileSourceCode::LineAt(int32 index) const FileSourceCode::LineAt(int32 index) const
{ {
return fFile->LineAt(index); return fSourceFile->LineAt(index);
} }
Statement* bool
FileSourceCode::StatementAtLine(int32 index) const FileSourceCode::GetStatementLocationRange(const SourceLocation& location,
SourceLocation& _start, SourceLocation& _end) const
{ {
return index >= 0 && index < CountLines() ? fLineStatements[index] : NULL; int32 lineCount = CountLines();
if (location.Line() >= lineCount)
return false;
bool foundMatch;
int32 index = _FindSourceLocationIndex(location, foundMatch);
if (!foundMatch) {
if (index == 0)
return false;
index--;
}
_start = fSourceLocations[index];
_end = index + 1 < lineCount
? fSourceLocations[index + 1] : SourceLocation(lineCount);
return true;
} }
//Statement* LocatableFile*
//FileSourceCode::StatementAtAddress(target_addr_t address) const FileSourceCode::GetSourceFile() const
//{
// return fStatements.BinarySearchByKey(address, &_CompareAddressStatement);
//}
//TargetAddressRange
//FileSourceCode::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());
//}
/*static*/ int
FileSourceCode::_CompareStatements(const ContiguousStatement* a,
const ContiguousStatement* b)
{ {
target_addr_t addressA = a->AddressRange().Start(); return fFile;
target_addr_t addressB = b->AddressRange().Start();
if (addressA < addressB)
return -1;
return addressA == addressB ? 0 : 1;
} }
/*static*/ int status_t
FileSourceCode::_CompareAddressStatement(const target_addr_t* address, FileSourceCode::GetStatementAtLocation(const SourceLocation& location,
const ContiguousStatement* statement) Statement*& _statement)
{ {
const TargetAddressRange& range = statement->AddressRange(); return B_UNSUPPORTED;
}
if (*address < range.Start())
return -1;
return *address < range.End() ? 0 : 1; int32
FileSourceCode::_FindSourceLocationIndex(const SourceLocation& location,
bool& _foundMatch) const
{
int32 lower = 0;
int32 upper = fSourceLocations.Size();
while (lower < upper) {
int32 mid = (lower + upper) / 2;
if (location <= fSourceLocations[mid])
upper = mid;
else
lower = mid + 1;
}
_foundMatch = lower < fSourceLocations.Size()
&& location == fSourceLocations[lower];
return lower;
} }
+21 -19
View File
@@ -5,46 +5,48 @@
#ifndef FILE_SOURCE_CODE_H #ifndef FILE_SOURCE_CODE_H
#define FILE_SOURCE_CODE_H #define FILE_SOURCE_CODE_H
#include <ObjectList.h>
#include "Array.h"
#include "SourceCode.h" #include "SourceCode.h"
class ContiguousStatement; class LocatableFile;
class SourceFile; class SourceFile;
class FileSourceCode : public SourceCode { class FileSourceCode : public SourceCode {
public: public:
FileSourceCode(SourceFile* file); FileSourceCode(LocatableFile* file,
SourceFile* sourceFile);
virtual ~FileSourceCode(); virtual ~FileSourceCode();
status_t Init(); status_t Init();
status_t AddStatement(ContiguousStatement* statement); status_t AddSourceLocation(
const SourceLocation& location);
virtual int32 CountLines() const; virtual int32 CountLines() const;
virtual const char* LineAt(int32 index) const; virtual const char* LineAt(int32 index) const;
virtual Statement* StatementAtLine(int32 index) const; virtual bool GetStatementLocationRange(
// Statement* StatementAtAddress(target_addr_t address) const; const SourceLocation& location,
SourceLocation& _start,
SourceLocation& _end) const;
// virtual TargetAddressRange StatementAddressRange() const; virtual LocatableFile* GetSourceFile() const;
virtual status_t GetStatementAtLocation(
const SourceLocation& location,
Statement*& _statement);
private: private:
typedef BObjectList<ContiguousStatement> StatementList; int32 _FindSourceLocationIndex(
const SourceLocation& location,
bool& _foundMatch) const;
private: private:
static int _CompareStatements( LocatableFile* fFile;
const ContiguousStatement* a, SourceFile* fSourceFile;
const ContiguousStatement* b); Array<SourceLocation> fSourceLocations;
static int _CompareAddressStatement(
const target_addr_t* address,
const ContiguousStatement* statement);
private:
SourceFile* fFile;
Statement** fLineStatements;
StatementList fStatements;
}; };
+1
View File
@@ -3,6 +3,7 @@
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include "SourceCode.h" #include "SourceCode.h"
+16 -1
View File
@@ -5,11 +5,14 @@
#ifndef SOURCE_CODE_H #ifndef SOURCE_CODE_H
#define SOURCE_CODE_H #define SOURCE_CODE_H
#include <Referenceable.h> #include <Referenceable.h>
#include "TargetAddressRange.h" #include "TargetAddressRange.h"
class LocatableFile;
class SourceLocation;
class Statement; class Statement;
@@ -20,7 +23,19 @@ public:
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;
virtual Statement* StatementAtLine(int32 index) const = 0; virtual bool GetStatementLocationRange(
const SourceLocation& location,
SourceLocation& _start,
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
}; };
+53 -1
View File
@@ -5,12 +5,15 @@
#include "Team.h" #include "Team.h"
#include <stdio.h>
#include <new> #include <new>
#include <AutoLocker.h> #include <AutoLocker.h>
#include "FunctionInstance.h" #include "Function.h"
#include "ImageDebugInfo.h" #include "ImageDebugInfo.h"
#include "SourceCode.h"
#include "SpecificImageDebugInfo.h" #include "SpecificImageDebugInfo.h"
#include "TeamDebugInfo.h" #include "TeamDebugInfo.h"
@@ -208,20 +211,30 @@ status_t
Team::GetStatementAtAddress(target_addr_t address, FunctionInstance*& _function, Team::GetStatementAtAddress(target_addr_t address, FunctionInstance*& _function,
Statement*& _statement) Statement*& _statement)
{ {
printf("Team::GetStatementAtAddress(%#llx)\n", address);
// get the image at the address // get the image at the address
Image* image = ImageByAddress(address); Image* image = ImageByAddress(address);
if (image == NULL) if (image == NULL)
{
printf(" -> no image\n");
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
}
ImageDebugInfo* imageDebugInfo = image->GetImageDebugInfo(); ImageDebugInfo* imageDebugInfo = image->GetImageDebugInfo();
if (imageDebugInfo == NULL) if (imageDebugInfo == NULL)
{
printf(" -> no image debug info\n");
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
}
// get the function // get the function
FunctionInstance* functionInstance FunctionInstance* functionInstance
= imageDebugInfo->FunctionAtAddress(address); = imageDebugInfo->FunctionAtAddress(address);
if (functionInstance == NULL) if (functionInstance == NULL)
{
printf(" -> no function instance\n");
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
}
// get the statement from the image debug info // get the statement from the image debug info
FunctionDebugInfo* functionDebugInfo FunctionDebugInfo* functionDebugInfo
@@ -230,13 +243,52 @@ Team::GetStatementAtAddress(target_addr_t address, FunctionInstance*& _function,
->GetStatement(functionDebugInfo, address, _statement); ->GetStatement(functionDebugInfo, address, _statement);
// TODO: Provide the corresponding SourceCode, if available! // 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");
return error; return error;
}
_function = functionInstance; _function = functionInstance;
return B_OK; return B_OK;
} }
status_t
Team::GetStatementAtSourceLocation(SourceCode* sourceCode,
const SourceLocation& location, Statement*& _statement)
{
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;
// Go the long and stony way over the source file and the team debug info.
// get the source file for the source code
LocatableFile* sourceFile = sourceCode->GetSourceFile();
if (sourceFile == NULL)
return B_ENTRY_NOT_FOUND;
// get the function at the source location
Function* function = fDebugInfo->FunctionAtSourceLocation(sourceFile,
location);
if (function == NULL)
return B_ENTRY_NOT_FOUND;
// Get some function instance and ask its image debug info to provide us
// with a statement.
FunctionInstance* functionInstance = function->FirstInstance();
if (functionInstance == NULL)
return B_ENTRY_NOT_FOUND;
FunctionDebugInfo* functionDebugInfo
= functionInstance->GetFunctionDebugInfo();
return functionDebugInfo->GetSpecificImageDebugInfo()
->GetStatementAtSourceLocation(functionDebugInfo, location, _statement);
}
void void
Team::AddListener(Listener* listener) Team::AddListener(Listener* listener)
{ {
+9
View File
@@ -30,6 +30,8 @@ enum {
class FunctionInstance; class FunctionInstance;
class LocatableFile; class LocatableFile;
class SourceCode;
class SourceLocation;
class Statement; class Statement;
class TeamDebugInfo; class TeamDebugInfo;
@@ -76,6 +78,13 @@ public:
// returns a reference to the statement, // returns a reference to the statement,
// not to the functions instance, though, // not to the functions instance, though,
// caller must lock // caller must lock
status_t GetStatementAtSourceLocation(
SourceCode* sourceCode,
const SourceLocation& location,
Statement*& _statement);
// returns a reference to the statement
// (any matching statement!),
// caller must lock,
void AddListener(Listener* listener); void AddListener(Listener* listener);
void RemoveListener(Listener* listener); void RemoveListener(Listener* listener);
+17 -5
View File
@@ -10,7 +10,7 @@
class SourceLocation { class SourceLocation {
public: public:
SourceLocation(uint32 line = 0, uint32 column = 0) SourceLocation(int32 line = 0, int32 column = 0)
: :
fLine(line), fLine(line),
fColumn(column) fColumn(column)
@@ -41,19 +41,31 @@ public:
return !(*this == other); return !(*this == other);
} }
uint32 Line() const bool operator<(const SourceLocation& other) const
{
return fLine < other.fLine
|| (fLine == other.fLine && fColumn < other.fColumn);
}
bool operator<=(const SourceLocation& other) const
{
return fLine < other.fLine
|| (fLine == other.fLine && fColumn <= other.fColumn);
}
int32 Line() const
{ {
return fLine; return fLine;
} }
uint32 Column() const int32 Column() const
{ {
return fColumn; return fColumn;
} }
private: private:
uint32 fLine; int32 fLine;
uint32 fColumn; int32 fColumn;
}; };