* 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();
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;
+222 -3
View File
@@ -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;
+29 -21
View File
@@ -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
+10 -3
View File
@@ -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);
+63 -70
View File
@@ -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;
}
+21 -19
View File
@@ -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;
};
+1
View File
@@ -3,6 +3,7 @@
* Distributed under the terms of the MIT License.
*/
#include "SourceCode.h"
+16 -1
View File
@@ -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
};
+53 -1
View File
@@ -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)
{
+9
View File
@@ -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);
+17 -5
View File
@@ -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;
};