* Virtualized SourceCode and implemented a derived class DisassembledCode, which
allows to implement StatementAtAddress() in O(log(n). * Added SourceCode::StatementAtLine(). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31174 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -57,6 +57,7 @@ Application Debugger :
|
|||||||
ThreadListView.cpp
|
ThreadListView.cpp
|
||||||
|
|
||||||
# model
|
# model
|
||||||
|
DisassembledCode.cpp
|
||||||
Image.cpp
|
Image.cpp
|
||||||
ImageInfo.cpp
|
ImageInfo.cpp
|
||||||
SourceCode.cpp
|
SourceCode.cpp
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
|
|
||||||
#include "CpuStateX86.h"
|
#include "CpuStateX86.h"
|
||||||
#include "DebuggerInterface.h"
|
#include "DebuggerInterface.h"
|
||||||
|
#include "DisassembledCode.h"
|
||||||
#include "FunctionDebugInfo.h"
|
#include "FunctionDebugInfo.h"
|
||||||
#include "SourceCode.h"
|
|
||||||
#include "StackFrame.h"
|
#include "StackFrame.h"
|
||||||
#include "Statement.h"
|
#include "Statement.h"
|
||||||
|
|
||||||
@@ -150,10 +150,10 @@ status_t
|
|||||||
ArchitectureX86::DisassembleCode(FunctionDebugInfo* function,
|
ArchitectureX86::DisassembleCode(FunctionDebugInfo* function,
|
||||||
const void* buffer, size_t bufferSize, SourceCode*& _sourceCode)
|
const void* buffer, size_t bufferSize, SourceCode*& _sourceCode)
|
||||||
{
|
{
|
||||||
SourceCode* source = new(std::nothrow) SourceCode;
|
DisassembledCode* source = new(std::nothrow) DisassembledCode;
|
||||||
if (source == NULL)
|
if (source == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
Reference<SourceCode> sourceReference(source, true);
|
Reference<DisassembledCode> sourceReference(source, true);
|
||||||
|
|
||||||
// init disassembler
|
// init disassembler
|
||||||
DisassemblerX86 disassembler;
|
DisassemblerX86 disassembler;
|
||||||
@@ -163,9 +163,8 @@ ArchitectureX86::DisassembleCode(FunctionDebugInfo* function,
|
|||||||
|
|
||||||
// add a function name line
|
// add a function name line
|
||||||
BString functionName(function->PrettyName());
|
BString functionName(function->PrettyName());
|
||||||
if (!source->AddLine((functionName << ':').String()))
|
if (!source->AddCommentLine((functionName << ':').String()))
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
uint32 lineIndex = 1;
|
|
||||||
|
|
||||||
// disassemble the instructions
|
// disassemble the instructions
|
||||||
BString line;
|
BString line;
|
||||||
@@ -174,16 +173,10 @@ ArchitectureX86::DisassembleCode(FunctionDebugInfo* function,
|
|||||||
bool breakpointAllowed;
|
bool breakpointAllowed;
|
||||||
while (disassembler.GetNextInstruction(line, instructionAddress,
|
while (disassembler.GetNextInstruction(line, instructionAddress,
|
||||||
instructionSize, breakpointAllowed) == B_OK) {
|
instructionSize, breakpointAllowed) == B_OK) {
|
||||||
Statement* statement = new(std::nothrow) ContiguousStatement(
|
if (!source->AddInstructionLine(line, instructionAddress,
|
||||||
SourceLocation(lineIndex), SourceLocation(lineIndex + 1),
|
instructionSize, breakpointAllowed)) {
|
||||||
TargetAddressRange(instructionAddress, instructionSize));
|
|
||||||
if (statement == NULL)
|
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
if (!source->AddStatement(statement) || !source->AddLine(line.String()))
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
lineIndex++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_sourceCode = sourceReference.Detach();
|
_sourceCode = sourceReference.Detach();
|
||||||
|
|||||||
@@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "DisassembledCode.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#include "Statement.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct DisassembledCode::Line {
|
||||||
|
BString line;
|
||||||
|
ContiguousStatement* statement;
|
||||||
|
|
||||||
|
Line(const BString& line, ContiguousStatement* statement)
|
||||||
|
:
|
||||||
|
line(line),
|
||||||
|
statement(statement)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
DisassembledCode::DisassembledCode()
|
||||||
|
:
|
||||||
|
fLines(20, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DisassembledCode::~DisassembledCode()
|
||||||
|
{
|
||||||
|
for (int32 i = 0; Statement* statement = fStatements.ItemAt(i); i++)
|
||||||
|
statement->RemoveReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
DisassembledCode::CountLines() const
|
||||||
|
{
|
||||||
|
return fLines.CountItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
DisassembledCode::LineAt(int32 index) const
|
||||||
|
{
|
||||||
|
Line* line = fLines.ItemAt(index);
|
||||||
|
return line != NULL ? line->line.String() : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
DisassembledCode::CountStatements() const
|
||||||
|
{
|
||||||
|
return fStatements.CountItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Statement*
|
||||||
|
DisassembledCode::StatementAt(int32 index) const
|
||||||
|
{
|
||||||
|
return fStatements.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Statement*
|
||||||
|
DisassembledCode::StatementAtLine(int32 index) const
|
||||||
|
{
|
||||||
|
Line* line = fLines.ItemAt(index);
|
||||||
|
return line != NULL ? line->statement : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Statement*
|
||||||
|
DisassembledCode::StatementAtAddress(target_addr_t address) const
|
||||||
|
{
|
||||||
|
return fStatements.BinarySearchByKey(address, &_CompareAddressStatement);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
DisassembledCode::AddCommentLine(const BString& line)
|
||||||
|
{
|
||||||
|
return _AddLine(line, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
DisassembledCode::AddInstructionLine(const BString& line, target_addr_t address,
|
||||||
|
target_size_t size, bool breakpointAllowed)
|
||||||
|
{
|
||||||
|
int32 lineIndex = fLines.CountItems();
|
||||||
|
|
||||||
|
ContiguousStatement* statement = new(std::nothrow) ContiguousStatement(
|
||||||
|
SourceLocation(lineIndex), SourceLocation(lineIndex + 1),
|
||||||
|
TargetAddressRange(address, size));
|
||||||
|
// TODO: breakpointAllowed!
|
||||||
|
if (statement == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!fStatements.AddItem(statement)) {
|
||||||
|
delete statement;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_AddLine(line, statement))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
DisassembledCode::_AddLine(const BString& _line, ContiguousStatement* statement)
|
||||||
|
{
|
||||||
|
Line* line = new(std::nothrow) Line(_line, statement);
|
||||||
|
if (line == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!fLines.AddItem(line)) {
|
||||||
|
delete line;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ int
|
||||||
|
DisassembledCode::_CompareAddressStatement(const target_addr_t* address,
|
||||||
|
const ContiguousStatement* statement)
|
||||||
|
{
|
||||||
|
const TargetAddressRange& range = statement->AddressRange();
|
||||||
|
|
||||||
|
if (*address < range.Start())
|
||||||
|
return -1;
|
||||||
|
return *address < range.End() ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef DISASSEMBLED_CODE_H
|
||||||
|
#define DISASSEMBLED_CODE_H
|
||||||
|
|
||||||
|
#include <ObjectList.h>
|
||||||
|
|
||||||
|
#include "SourceCode.h"
|
||||||
|
|
||||||
|
|
||||||
|
class BString;
|
||||||
|
class ContiguousStatement;
|
||||||
|
|
||||||
|
|
||||||
|
class DisassembledCode : public SourceCode {
|
||||||
|
public:
|
||||||
|
DisassembledCode();
|
||||||
|
~DisassembledCode();
|
||||||
|
|
||||||
|
virtual int32 CountLines() const;
|
||||||
|
virtual const char* LineAt(int32 index) const;
|
||||||
|
|
||||||
|
virtual int32 CountStatements() const;
|
||||||
|
virtual Statement* StatementAt(int32 index) const;
|
||||||
|
virtual Statement* StatementAtLine(int32 index) const;
|
||||||
|
virtual Statement* StatementAtAddress(target_addr_t address) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool AddCommentLine(const BString& line);
|
||||||
|
bool AddInstructionLine(const BString& line,
|
||||||
|
target_addr_t address, target_size_t size,
|
||||||
|
bool breakpointAllowed);
|
||||||
|
// instructions must be added in
|
||||||
|
// ascending address order
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Line;
|
||||||
|
|
||||||
|
typedef BObjectList<Line> LineList;
|
||||||
|
typedef BObjectList<ContiguousStatement> StatementList;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _AddLine(const BString& line,
|
||||||
|
ContiguousStatement* statement);
|
||||||
|
static int _CompareAddressStatement(
|
||||||
|
const target_addr_t* address,
|
||||||
|
const ContiguousStatement* statement);
|
||||||
|
|
||||||
|
private:
|
||||||
|
LineList fLines;
|
||||||
|
StatementList fStatements;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // DISASSEMBLED_CODE_H
|
||||||
@@ -5,89 +5,7 @@
|
|||||||
|
|
||||||
#include "SourceCode.h"
|
#include "SourceCode.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "Statement.h"
|
|
||||||
|
|
||||||
|
|
||||||
SourceCode::SourceCode()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SourceCode::~SourceCode()
|
SourceCode::~SourceCode()
|
||||||
{
|
{
|
||||||
for (int32 i = 0; char* line = fLines.ItemAt(i); i++)
|
|
||||||
free(line);
|
|
||||||
for (int32 i = 0; Statement* statement = fStatements.ItemAt(i); i++)
|
|
||||||
statement->RemoveReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int32
|
|
||||||
SourceCode::CountLines() const
|
|
||||||
{
|
|
||||||
return fLines.CountItems();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char*
|
|
||||||
SourceCode::LineAt(int32 index) const
|
|
||||||
{
|
|
||||||
return fLines.ItemAt(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int32
|
|
||||||
SourceCode::CountStatements() const
|
|
||||||
{
|
|
||||||
return fStatements.CountItems();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Statement*
|
|
||||||
SourceCode::StatementAt(int32 index) const
|
|
||||||
{
|
|
||||||
return fStatements.ItemAt(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Statement*
|
|
||||||
SourceCode::StatementAtAddress(target_addr_t address) const
|
|
||||||
{
|
|
||||||
// TODO: Optimize!
|
|
||||||
for (int32 i = 0; Statement* statement = fStatements.ItemAt(i); i++) {
|
|
||||||
if (statement->ContainsAddress(address))
|
|
||||||
return statement;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
SourceCode::AddLine(const char* _line)
|
|
||||||
{
|
|
||||||
char* line = strdup(_line);
|
|
||||||
if (line == NULL)
|
|
||||||
return false;
|
|
||||||
if (!fLines.AddItem(line)) {
|
|
||||||
free(line);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
SourceCode::AddStatement(Statement* statement)
|
|
||||||
{
|
|
||||||
if (!fStatements.AddItem(statement)) {
|
|
||||||
statement->RemoveReference();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#ifndef SOURCE_CODE_H
|
#ifndef SOURCE_CODE_H
|
||||||
#define SOURCE_CODE_H
|
#define SOURCE_CODE_H
|
||||||
|
|
||||||
#include <ObjectList.h>
|
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
|
|
||||||
#include "ArchitectureTypes.h"
|
#include "ArchitectureTypes.h"
|
||||||
@@ -16,28 +15,16 @@ class Statement;
|
|||||||
|
|
||||||
class SourceCode : public Referenceable {
|
class SourceCode : public Referenceable {
|
||||||
public:
|
public:
|
||||||
SourceCode();
|
virtual ~SourceCode();
|
||||||
~SourceCode();
|
|
||||||
|
|
||||||
int32 CountLines() const;
|
virtual int32 CountLines() const = 0;
|
||||||
const char* LineAt(int32 index) const;
|
virtual const char* LineAt(int32 index) const = 0;
|
||||||
|
|
||||||
int32 CountStatements() const;
|
virtual int32 CountStatements() const = 0;
|
||||||
Statement* StatementAt(int32 index) const;
|
virtual Statement* StatementAt(int32 index) const = 0;
|
||||||
Statement* StatementAtAddress(target_addr_t address) const;
|
virtual Statement* StatementAtLine(int32 index) const = 0;
|
||||||
|
virtual Statement* StatementAtAddress(target_addr_t address)
|
||||||
bool AddLine(const char* line);
|
const = 0;
|
||||||
// clones
|
|
||||||
bool AddStatement(Statement* statement);
|
|
||||||
// takes over reference
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef BObjectList<char> LineList;
|
|
||||||
typedef BObjectList<Statement> StatementList;
|
|
||||||
|
|
||||||
private:
|
|
||||||
LineList fLines;
|
|
||||||
StatementList fStatements;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user