* 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:
@@ -879,14 +879,7 @@ printf(" function: %p\n", function);
|
||||
= functionInstance->GetFunctionDebugInfo();
|
||||
SourceLocation sourceLocation;
|
||||
Statement* breakpointStatement = NULL;
|
||||
// if (SourceCode* sourceCode = functionDebugInfo->GetSourceCode()) {
|
||||
// breakpointStatement = sourceCode->StatementAtAddress(address);
|
||||
// if (breakpointStatement != NULL)
|
||||
// sourceLocation = breakpointStatement->StartSourceLocation();
|
||||
// }
|
||||
|
||||
if (breakpointStatement == NULL
|
||||
&& functionDebugInfo->GetSpecificImageDebugInfo()->GetStatement(
|
||||
if (functionDebugInfo->GetSpecificImageDebugInfo()->GetStatement(
|
||||
functionDebugInfo, address, breakpointStatement) != B_OK) {
|
||||
return;
|
||||
}
|
||||
@@ -920,7 +913,7 @@ printf(" function instance %p: range: %#llx - %#llx\n", instance, instance->Add
|
||||
Statement* statement = NULL;
|
||||
functionDebugInfo = instance->GetFunctionDebugInfo();
|
||||
functionDebugInfo->GetSpecificImageDebugInfo()
|
||||
->GetStatementForSourceLocation(functionDebugInfo,
|
||||
->GetStatementAtSourceLocation(functionDebugInfo,
|
||||
sourceLocation, statement);
|
||||
if (statement != NULL) {
|
||||
instanceAddress = statement->CoveringAddressRange().Start();
|
||||
|
||||
@@ -119,7 +119,7 @@ DebuggerImageDebugInfo::GetStatement(FunctionDebugInfo* function,
|
||||
|
||||
|
||||
status_t
|
||||
DebuggerImageDebugInfo::GetStatementForSourceLocation(
|
||||
DebuggerImageDebugInfo::GetStatementAtSourceLocation(
|
||||
FunctionDebugInfo* function, const SourceLocation& sourceLocation,
|
||||
Statement*& _statement)
|
||||
{
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
virtual status_t GetStatement(FunctionDebugInfo* function,
|
||||
target_addr_t address,
|
||||
Statement*& _statement);
|
||||
virtual status_t GetStatementForSourceLocation(
|
||||
virtual status_t GetStatementAtSourceLocation(
|
||||
FunctionDebugInfo* function,
|
||||
const SourceLocation& sourceLocation,
|
||||
Statement*& _statement);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <new>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
@@ -34,30 +35,29 @@
|
||||
|
||||
struct DwarfImageDebugInfo::SourceCodeKey {
|
||||
CompilationUnit* unit;
|
||||
BString filePath;
|
||||
|
||||
SourceCodeKey(CompilationUnit* unit, const BString& filePath)
|
||||
:
|
||||
unit(unit),
|
||||
filePath(filePath)
|
||||
{
|
||||
}
|
||||
LocatableFile* file;
|
||||
|
||||
SourceCodeKey(CompilationUnit* unit, LocatableFile* file)
|
||||
:
|
||||
unit(unit)
|
||||
unit(unit),
|
||||
file(file)
|
||||
{
|
||||
file->GetLocatedPath(filePath);
|
||||
file->AcquireReference();
|
||||
}
|
||||
|
||||
~SourceCodeKey()
|
||||
{
|
||||
file->ReleaseReference();
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
= new(std::nothrow) DwarfFunctionDebugInfo(this, unit,
|
||||
subprogramEntry, rangeList, name, file,
|
||||
SourceLocation(line, column));
|
||||
SourceLocation(line, std::max(column, 0L)));
|
||||
if (function == NULL || !functions.AddItem(function)) {
|
||||
delete function;
|
||||
return B_NO_MEMORY;
|
||||
@@ -292,7 +292,6 @@ DwarfImageDebugInfo::LoadSourceCode(FunctionDebugInfo* function,
|
||||
{
|
||||
AutoLocker<BLocker> locker(fLock);
|
||||
|
||||
// TODO: Load the actual source code!
|
||||
status_t error = _LoadSourceCode(function, _sourceCode);
|
||||
if (error == B_OK)
|
||||
return B_OK;
|
||||
@@ -323,30 +322,26 @@ status_t
|
||||
DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function,
|
||||
target_addr_t address, Statement*& _statement)
|
||||
{
|
||||
printf("DwarfImageDebugInfo::GetStatement(function: %p, address: %#llx)\n",
|
||||
_function, address);
|
||||
DwarfFunctionDebugInfo* function
|
||||
= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
|
||||
if (function == NULL)
|
||||
{
|
||||
printf(" -> no dwarf function\n");
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
AutoLocker<BLocker> locker(fLock);
|
||||
|
||||
// get the source file
|
||||
LocatableFile* file = function->SourceFile();
|
||||
if (file == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
// maybe the source code is already loaded -- this will simplify things
|
||||
// check whether we have the source code
|
||||
CompilationUnit* unit = function->GetCompilationUnit();
|
||||
// FileSourceCode* sourceCode = _LookupSourceCode(unit, file);
|
||||
// if (sourceCode) {
|
||||
// Statement* statement = sourceCode->StatementAtAddress(address);
|
||||
// if (statement == NULL)
|
||||
// return B_ENTRY_NOT_FOUND;
|
||||
//
|
||||
// statement->AcquireReference();
|
||||
// _statement = statement;
|
||||
// return B_OK;
|
||||
// }
|
||||
LocatableFile* file = function->SourceFile();
|
||||
if (file == NULL) {
|
||||
printf(" -> no source file\n");
|
||||
// no source code -- rather return the assembly statement
|
||||
return fArchitecture->GetStatement(function, address, _statement);
|
||||
}
|
||||
|
||||
// get the index of the source file in the compilation unit for cheaper
|
||||
// comparison below
|
||||
@@ -356,7 +351,13 @@ DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function,
|
||||
// compilation unit.
|
||||
LineNumberProgram& program = unit->GetLineNumberProgram();
|
||||
if (!program.IsValid())
|
||||
{
|
||||
printf(" -> no line number program\n");
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
// adjust address
|
||||
address -= fRelocationDelta;
|
||||
|
||||
LineNumberProgram::State state;
|
||||
program.GetInitialState(state);
|
||||
@@ -393,26 +394,27 @@ DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function,
|
||||
if (state.isStatement) {
|
||||
statementAddress = state.address;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DwarfImageDebugInfo::GetStatementForSourceLocation(FunctionDebugInfo* _function,
|
||||
DwarfImageDebugInfo::GetStatementAtSourceLocation(FunctionDebugInfo* _function,
|
||||
const SourceLocation& sourceLocation, Statement*& _statement)
|
||||
{
|
||||
DwarfFunctionDebugInfo* function
|
||||
= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
|
||||
if (function == NULL)
|
||||
return B_BAD_VALUE;
|
||||
target_addr_t functionStartAddress = function->Address();
|
||||
target_addr_t functionStartAddress = function->Address() - fRelocationDelta;
|
||||
target_addr_t functionEndAddress = functionStartAddress + function->Size();
|
||||
printf("DwarfImageDebugInfo::GetStatementForSourceLocation(%p): function range: %#llx - %#llx\n",
|
||||
function, functionStartAddress, functionEndAddress);
|
||||
printf("DwarfImageDebugInfo::GetStatementAtSourceLocation(%p, (%ld, %ld)): function range: %#llx - %#llx\n",
|
||||
function, sourceLocation.Line(), sourceLocation.Column(), functionStartAddress, functionEndAddress);
|
||||
|
||||
AutoLocker<BLocker> locker(fLock);
|
||||
|
||||
@@ -421,26 +423,13 @@ function, functionStartAddress, functionEndAddress);
|
||||
if (file == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
// maybe the source code is already loaded -- this will simplify things
|
||||
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
|
||||
// comparison below
|
||||
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();
|
||||
|
||||
// Get the statement by executing the line number program for the
|
||||
@@ -461,11 +450,15 @@ function, functionStartAddress, functionEndAddress);
|
||||
if (statementAddress != 0
|
||||
&& (!isOurFile || state.isStatement || state.isSequenceEnd)) {
|
||||
target_addr_t endAddress = state.address;
|
||||
if (statementAddress < endAddress) {
|
||||
printf(" statement: %#llx - %#llx, location: (%ld, %ld)\n", statementAddress, endAddress, statementLine, statementColumn);
|
||||
}
|
||||
if (statementAddress < endAddress
|
||||
&& statementAddress >= functionStartAddress
|
||||
&& statementAddress < functionEndAddress
|
||||
&& statementLine == (int32)sourceLocation.Line()
|
||||
&& statementColumn == (int32)sourceLocation.Column()) {
|
||||
printf(" -> found statement!\n");
|
||||
ContiguousStatement* statement = new(std::nothrow)
|
||||
ContiguousStatement(
|
||||
SourceLocation(statementLine, statementColumn),
|
||||
@@ -488,7 +481,7 @@ function, functionStartAddress, functionEndAddress);
|
||||
if (state.isStatement) {
|
||||
statementAddress = state.address;
|
||||
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;
|
||||
|
||||
// create the source code
|
||||
sourceCode = new(std::nothrow) FileSourceCode(sourceFile);
|
||||
sourceCode = new(std::nothrow) FileSourceCode(file, sourceFile);
|
||||
sourceFile->ReleaseReference();
|
||||
if (sourceCode == NULL)
|
||||
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
|
||||
&& (!isOurFile || state.isStatement || state.isSequenceEnd)) {
|
||||
target_addr_t endAddress = state.address;
|
||||
if (endAddress > statementAddress) {
|
||||
if (endAddress > statementAddress) {
|
||||
// add the statement
|
||||
ContiguousStatement* statement = new(std::nothrow)
|
||||
ContiguousStatement(
|
||||
SourceLocation(statementLine, statementColumn),
|
||||
TargetAddressRange(fRelocationDelta + statementAddress,
|
||||
endAddress - statementAddress));
|
||||
if (statement == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
error = sourceCode->AddStatement(statement);
|
||||
if (error != B_OK) {
|
||||
delete statement;
|
||||
error = sourceCode->AddSourceLocation(
|
||||
SourceLocation(statementLine, statementColumn));
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
}
|
||||
printf(" -> statement: %#llx - %#llx, line: %ld\n", statement->AddressRange().Start(),
|
||||
statement->AddressRange().End(), statementLine);
|
||||
printf(" -> statement: %#llx - %#llx, source location: (%ld, %ld)\n", statementAddress, endAddress, statementLine, statementColumn);
|
||||
}
|
||||
|
||||
statementAddress = 0;
|
||||
@@ -593,7 +576,7 @@ statement->AddressRange().End(), statementLine);
|
||||
if (state.isStatement) {
|
||||
statementAddress = state.address;
|
||||
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,
|
||||
target_addr_t address,
|
||||
Statement*& _statement);
|
||||
virtual status_t GetStatementForSourceLocation(
|
||||
virtual status_t GetStatementAtSourceLocation(
|
||||
FunctionDebugInfo* function,
|
||||
const SourceLocation& sourceLocation,
|
||||
Statement*& _statement);
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
target_addr_t address,
|
||||
Statement*& _statement) = 0;
|
||||
// returns reference
|
||||
virtual status_t GetStatementForSourceLocation(
|
||||
virtual status_t GetStatementAtSourceLocation(
|
||||
FunctionDebugInfo* function,
|
||||
const SourceLocation& sourceLocation,
|
||||
Statement*& _statement) = 0;
|
||||
|
||||
@@ -3,8 +3,11 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "TeamDebugInfo.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
@@ -13,6 +16,7 @@
|
||||
#include "DwarfTeamDebugInfo.h"
|
||||
#include "Function.h"
|
||||
#include "ImageDebugInfo.h"
|
||||
#include "LocatableFile.h"
|
||||
#include "SpecificImageDebugInfo.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
|
||||
|
||||
|
||||
@@ -76,13 +205,25 @@ TeamDebugInfo::TeamDebugInfo(DebuggerInterface* debuggerInterface,
|
||||
fArchitecture(architecture),
|
||||
fFileManager(fileManager),
|
||||
fSpecificInfos(10, true),
|
||||
fFunctions(NULL)
|
||||
fFunctions(NULL),
|
||||
fSourceFiles(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
Function* function = fFunctions->Clear(true);
|
||||
while (function != NULL) {
|
||||
@@ -108,6 +249,15 @@ TeamDebugInfo::Init()
|
||||
if (error != B_OK)
|
||||
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
|
||||
// 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);
|
||||
function->AddInstance(instance);
|
||||
instance->SetFunction(function);
|
||||
fFunctions->Insert(function);
|
||||
|
||||
status_t error = _AddFunction(function);
|
||||
// Insert after adding the instance. Otherwise the function
|
||||
// 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
|
||||
// the instance, since otherwise the function cannot be compared
|
||||
// anymore.
|
||||
fFunctions->Remove(function);
|
||||
_RemoveFunction(function);
|
||||
function->ReleaseReference();
|
||||
// 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
|
||||
#define TEAM_DEBUG_INFO_H
|
||||
|
||||
|
||||
#include <ObjectList.h>
|
||||
#include <Referenceable.h>
|
||||
#include <util/OpenHashTable.h>
|
||||
@@ -20,6 +21,7 @@ class FunctionInstance;
|
||||
class ImageDebugInfo;
|
||||
class ImageInfo;
|
||||
class LocatableFile;
|
||||
class SourceLocation;
|
||||
class SpecificTeamDebugInfo;
|
||||
|
||||
|
||||
@@ -43,11 +45,21 @@ public:
|
||||
void RemoveImageDebugInfo(
|
||||
ImageDebugInfo* imageDebugInfo);
|
||||
|
||||
Function* FunctionAtSourceLocation(LocatableFile* file,
|
||||
const SourceLocation& location);
|
||||
|
||||
private:
|
||||
struct FunctionHashDefinition;
|
||||
struct SourceFileEntry;
|
||||
struct SourceFileHashDefinition;
|
||||
|
||||
typedef BObjectList<SpecificTeamDebugInfo> SpecificInfoList;
|
||||
typedef OpenHashTable<FunctionHashDefinition> FunctionTable;
|
||||
typedef OpenHashTable<SourceFileHashDefinition> SourceFileTable;
|
||||
|
||||
private:
|
||||
status_t _AddFunction(Function* function);
|
||||
void _RemoveFunction(Function* function);
|
||||
|
||||
private:
|
||||
DebuggerInterface* fDebuggerInterface;
|
||||
@@ -55,6 +67,7 @@ private:
|
||||
FileManager* fFileManager;
|
||||
SpecificInfoList fSpecificInfos;
|
||||
FunctionTable* fFunctions;
|
||||
SourceFileTable* fSourceFiles;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -518,9 +518,11 @@ SourceView::MarkerView::Draw(BRect updateRect)
|
||||
if (!drawBreakpointOptionMarker)
|
||||
continue;
|
||||
|
||||
Statement* statement = fSourceCode->StatementAtLine(line);
|
||||
if (statement == NULL
|
||||
|| statement->StartSourceLocation().Line() != (uint32)line) {
|
||||
|
||||
SourceLocation statementStart, statementEnd;
|
||||
if (!fSourceCode->GetStatementLocationRange(SourceLocation(line),
|
||||
statementStart, statementEnd)
|
||||
|| statementStart.Line() != line) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -541,11 +543,15 @@ SourceView::MarkerView::MouseDown(BPoint where)
|
||||
if (line < 0)
|
||||
return;
|
||||
|
||||
Statement* statement = fSourceCode->StatementAtLine(line);
|
||||
if (statement == NULL
|
||||
|| statement->StartSourceLocation().Line() != (uint32)line) {
|
||||
AutoLocker<TeamDebugModel> locker(fDebugModel);
|
||||
Statement* statement;
|
||||
if (fDebugModel->GetTeam()->GetStatementAtSourceLocation(fSourceCode,
|
||||
SourceLocation(line), statement) != B_OK) {
|
||||
return;
|
||||
}
|
||||
Reference<Statement> statementReference(statement, true);
|
||||
if (statement->StartSourceLocation().Line() != line)
|
||||
return;
|
||||
|
||||
int32 modifiers;
|
||||
if (Looper()->CurrentMessage()->FindInt32("modifiers", &modifiers) != B_OK)
|
||||
@@ -1005,6 +1011,7 @@ SourceView::UserBreakpointChanged(target_addr_t address)
|
||||
bool
|
||||
SourceView::ScrollToAddress(target_addr_t address)
|
||||
{
|
||||
printf("SourceView::ScrollToAddress(%#llx)\n", address);
|
||||
if (fSourceCode == NULL)
|
||||
return false;
|
||||
|
||||
@@ -1025,6 +1032,7 @@ SourceView::ScrollToAddress(target_addr_t address)
|
||||
bool
|
||||
SourceView::ScrollToLine(uint32 line)
|
||||
{
|
||||
printf("SourceView::ScrollToLine(%lu)\n", line);
|
||||
if (fSourceCode == NULL || line >= (uint32)fSourceCode->CountLines())
|
||||
return false;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "DisassembledCode.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -57,33 +58,40 @@ DisassembledCode::LineAt(int32 index) const
|
||||
}
|
||||
|
||||
|
||||
Statement*
|
||||
DisassembledCode::StatementAtLine(int32 index) const
|
||||
bool
|
||||
DisassembledCode::GetStatementLocationRange(const SourceLocation& location,
|
||||
SourceLocation& _start, SourceLocation& _end) const
|
||||
{
|
||||
Line* line = fLines.ItemAt(index);
|
||||
return line != NULL ? line->statement : NULL;
|
||||
Line* line = fLines.ItemAt(location.Line());
|
||||
if (line == NULL || line->statement == NULL)
|
||||
return false;
|
||||
|
||||
_start = line->statement->StartSourceLocation();
|
||||
_end = SourceLocation(_start.Line() + 1);
|
||||
// TODO: Multi-line instructions!
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//Statement*
|
||||
//DisassembledCode::StatementAtAddress(target_addr_t address) const
|
||||
//{
|
||||
// return fStatements.BinarySearchByKey(address, &_CompareAddressStatement);
|
||||
//}
|
||||
LocatableFile*
|
||||
DisassembledCode::GetSourceFile() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//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());
|
||||
//}
|
||||
status_t
|
||||
DisassembledCode::GetStatementAtLocation(const SourceLocation& location,
|
||||
Statement*& _statement)
|
||||
{
|
||||
Line* line = fLines.ItemAt(location.Line());
|
||||
if (line == NULL || line->statement == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
_statement = line->statement;
|
||||
_statement->AcquireReference();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#ifndef DISASSEMBLED_CODE_H
|
||||
#define DISASSEMBLED_CODE_H
|
||||
|
||||
|
||||
#include <ObjectList.h>
|
||||
|
||||
#include "SourceCode.h"
|
||||
@@ -22,10 +23,16 @@ public:
|
||||
virtual int32 CountLines() const;
|
||||
virtual const char* LineAt(int32 index) const;
|
||||
|
||||
virtual Statement* StatementAtLine(int32 index) const;
|
||||
// Statement* StatementAtAddress(target_addr_t address) const;
|
||||
virtual bool GetStatementLocationRange(
|
||||
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:
|
||||
bool AddCommentLine(const BString& line);
|
||||
|
||||
@@ -3,33 +3,29 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "FileSourceCode.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "LocatableFile.h"
|
||||
#include "SourceFile.h"
|
||||
#include "Statement.h"
|
||||
#include "SourceLocation.h"
|
||||
|
||||
|
||||
// TODO: Lot's of code duplication from DissassembledCode!
|
||||
|
||||
|
||||
FileSourceCode::FileSourceCode(SourceFile* file)
|
||||
FileSourceCode::FileSourceCode(LocatableFile* file, SourceFile* sourceFile)
|
||||
:
|
||||
fFile(file),
|
||||
fLineStatements(NULL)
|
||||
fSourceFile(sourceFile)
|
||||
{
|
||||
fFile->AcquireReference();
|
||||
fSourceFile->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
FileSourceCode::~FileSourceCode()
|
||||
{
|
||||
for (int32 i = 0; Statement* statement = fStatements.ItemAt(i); i++)
|
||||
statement->RemoveReference();
|
||||
|
||||
delete[] fLineStatements;
|
||||
|
||||
fSourceFile->ReleaseReference();
|
||||
fFile->ReleaseReference();
|
||||
}
|
||||
|
||||
@@ -37,94 +33,91 @@ FileSourceCode::~FileSourceCode()
|
||||
status_t
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
FileSourceCode::AddStatement(ContiguousStatement* statement)
|
||||
FileSourceCode::AddSourceLocation(const SourceLocation& location)
|
||||
{
|
||||
if (!fStatements.BinaryInsert(statement, &_CompareStatements))
|
||||
return B_NO_MEMORY;
|
||||
// Find the insertion index; don't insert twice.
|
||||
bool foundMatch;
|
||||
int32 index = _FindSourceLocationIndex(location, foundMatch);
|
||||
if (foundMatch)
|
||||
return B_OK;
|
||||
|
||||
int32 line = statement->StartSourceLocation().Line();
|
||||
if (line >= 0 && line < fFile->CountLines()
|
||||
&& fLineStatements[line] == NULL) {
|
||||
fLineStatements[line] = statement;
|
||||
}
|
||||
|
||||
statement->AcquireReference();
|
||||
return B_OK;
|
||||
return fSourceLocations.Insert(location, index) ? B_OK : B_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
FileSourceCode::CountLines() const
|
||||
{
|
||||
return fFile->CountLines();
|
||||
return fSourceFile->CountLines();
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
FileSourceCode::LineAt(int32 index) const
|
||||
{
|
||||
return fFile->LineAt(index);
|
||||
return fSourceFile->LineAt(index);
|
||||
}
|
||||
|
||||
|
||||
Statement*
|
||||
FileSourceCode::StatementAtLine(int32 index) const
|
||||
bool
|
||||
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*
|
||||
//FileSourceCode::StatementAtAddress(target_addr_t address) 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)
|
||||
LocatableFile*
|
||||
FileSourceCode::GetSourceFile() const
|
||||
{
|
||||
target_addr_t addressA = a->AddressRange().Start();
|
||||
target_addr_t addressB = b->AddressRange().Start();
|
||||
if (addressA < addressB)
|
||||
return -1;
|
||||
return addressA == addressB ? 0 : 1;
|
||||
return fFile;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ int
|
||||
FileSourceCode::_CompareAddressStatement(const target_addr_t* address,
|
||||
const ContiguousStatement* statement)
|
||||
status_t
|
||||
FileSourceCode::GetStatementAtLocation(const SourceLocation& location,
|
||||
Statement*& _statement)
|
||||
{
|
||||
const TargetAddressRange& range = statement->AddressRange();
|
||||
|
||||
if (*address < range.Start())
|
||||
return -1;
|
||||
return *address < range.End() ? 0 : 1;
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -5,46 +5,48 @@
|
||||
#ifndef FILE_SOURCE_CODE_H
|
||||
#define FILE_SOURCE_CODE_H
|
||||
|
||||
#include <ObjectList.h>
|
||||
|
||||
#include "Array.h"
|
||||
#include "SourceCode.h"
|
||||
|
||||
|
||||
class ContiguousStatement;
|
||||
class LocatableFile;
|
||||
class SourceFile;
|
||||
|
||||
|
||||
class FileSourceCode : public SourceCode {
|
||||
public:
|
||||
FileSourceCode(SourceFile* file);
|
||||
FileSourceCode(LocatableFile* file,
|
||||
SourceFile* sourceFile);
|
||||
virtual ~FileSourceCode();
|
||||
|
||||
status_t Init();
|
||||
status_t AddStatement(ContiguousStatement* statement);
|
||||
status_t AddSourceLocation(
|
||||
const SourceLocation& location);
|
||||
|
||||
virtual int32 CountLines() const;
|
||||
virtual const char* LineAt(int32 index) const;
|
||||
|
||||
virtual Statement* StatementAtLine(int32 index) const;
|
||||
// Statement* StatementAtAddress(target_addr_t address) const;
|
||||
virtual bool GetStatementLocationRange(
|
||||
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:
|
||||
typedef BObjectList<ContiguousStatement> StatementList;
|
||||
int32 _FindSourceLocationIndex(
|
||||
const SourceLocation& location,
|
||||
bool& _foundMatch) const;
|
||||
|
||||
private:
|
||||
static int _CompareStatements(
|
||||
const ContiguousStatement* a,
|
||||
const ContiguousStatement* b);
|
||||
static int _CompareAddressStatement(
|
||||
const target_addr_t* address,
|
||||
const ContiguousStatement* statement);
|
||||
|
||||
private:
|
||||
SourceFile* fFile;
|
||||
Statement** fLineStatements;
|
||||
StatementList fStatements;
|
||||
LocatableFile* fFile;
|
||||
SourceFile* fSourceFile;
|
||||
Array<SourceLocation> fSourceLocations;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "SourceCode.h"
|
||||
|
||||
|
||||
|
||||
@@ -5,11 +5,14 @@
|
||||
#ifndef SOURCE_CODE_H
|
||||
#define SOURCE_CODE_H
|
||||
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "TargetAddressRange.h"
|
||||
|
||||
|
||||
class LocatableFile;
|
||||
class SourceLocation;
|
||||
class Statement;
|
||||
|
||||
|
||||
@@ -20,7 +23,19 @@ public:
|
||||
virtual int32 CountLines() 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
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -5,12 +5,15 @@
|
||||
|
||||
#include "Team.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <AutoLocker.h>
|
||||
|
||||
#include "FunctionInstance.h"
|
||||
#include "Function.h"
|
||||
#include "ImageDebugInfo.h"
|
||||
#include "SourceCode.h"
|
||||
#include "SpecificImageDebugInfo.h"
|
||||
#include "TeamDebugInfo.h"
|
||||
|
||||
@@ -208,20 +211,30 @@ status_t
|
||||
Team::GetStatementAtAddress(target_addr_t address, FunctionInstance*& _function,
|
||||
Statement*& _statement)
|
||||
{
|
||||
printf("Team::GetStatementAtAddress(%#llx)\n", address);
|
||||
// get the image at the address
|
||||
Image* image = ImageByAddress(address);
|
||||
if (image == NULL)
|
||||
{
|
||||
printf(" -> no image\n");
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
ImageDebugInfo* imageDebugInfo = image->GetImageDebugInfo();
|
||||
if (imageDebugInfo == NULL)
|
||||
{
|
||||
printf(" -> no image debug info\n");
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
// get the function
|
||||
FunctionInstance* functionInstance
|
||||
= imageDebugInfo->FunctionAtAddress(address);
|
||||
if (functionInstance == NULL)
|
||||
{
|
||||
printf(" -> no function instance\n");
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
// get the statement from the image debug info
|
||||
FunctionDebugInfo* functionDebugInfo
|
||||
@@ -230,13 +243,52 @@ Team::GetStatementAtAddress(target_addr_t address, FunctionInstance*& _function,
|
||||
->GetStatement(functionDebugInfo, address, _statement);
|
||||
// TODO: Provide the corresponding SourceCode, if available!
|
||||
if (error != B_OK)
|
||||
{
|
||||
printf(" -> no statement from the specific image debug info\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
_function = functionInstance;
|
||||
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
|
||||
Team::AddListener(Listener* listener)
|
||||
{
|
||||
|
||||
@@ -30,6 +30,8 @@ enum {
|
||||
|
||||
class FunctionInstance;
|
||||
class LocatableFile;
|
||||
class SourceCode;
|
||||
class SourceLocation;
|
||||
class Statement;
|
||||
class TeamDebugInfo;
|
||||
|
||||
@@ -76,6 +78,13 @@ public:
|
||||
// returns a reference to the statement,
|
||||
// not to the functions instance, though,
|
||||
// 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 RemoveListener(Listener* listener);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
class SourceLocation {
|
||||
public:
|
||||
SourceLocation(uint32 line = 0, uint32 column = 0)
|
||||
SourceLocation(int32 line = 0, int32 column = 0)
|
||||
:
|
||||
fLine(line),
|
||||
fColumn(column)
|
||||
@@ -41,19 +41,31 @@ public:
|
||||
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;
|
||||
}
|
||||
|
||||
uint32 Column() const
|
||||
int32 Column() const
|
||||
{
|
||||
return fColumn;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 fLine;
|
||||
uint32 fColumn;
|
||||
int32 fLine;
|
||||
int32 fColumn;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user