* Worker:

- Made Job Referenceable.
  - Turned JobKey into an abstract base class to add flexibility. The new
    SimpleJobKey is a subclass with the former functionality.
* TeamWindow: Removed the TeamWindow* parameter from the listener hooks. The
  TeamDebugger knows anyway.
* Added IDs to Variable, Function, and FunctionInstance. The latter two generate
  the ID on the fly, Variable stores it.
* SpecificImageDebugInfo::CreateFrame(): Changed FunctionDebugInfo* debug
  parameter to FunctionInstance* to provide more info (the function ID).
* DwarfInterfaceFactory/DwarfImageDebugInfo:
  - Added class DwarfFunctionParameterID, an ID class implementation for
    function parameters and set the IDs on the parameter objects.
  - Retrieve the size of a type (i.e. the size of its objects) and store it in
    DwarfType.
  - If a parameter's ValueLocation doesn't have a size, set that of the
    respective type.
  - Map the register indicies in the parameters' ValueLocations from DWARF to
    our indices.
* Added class TypeComponentPath for identifying subcomponents in types.
* Added class StackFrameValues, a container associating variables and their
  subcomponents with values.
* StackFrame does now have a StackFrameValues object for parameters and local
  variables and a mechanism to notify listeners when values have been retrieved.
* Added GetStackFrameValueJob to retrieve variable values. Lots of functionality
  is missing yet. Most notably it doesn't retrieves values for subcomponents.
* Wired everything to trigger loading of variable values and getting notified
  when done.
* VariablesView: Added a value column. This is all very basic and has to be
  done differently, but at least values for the parameters can be seen already.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31636 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-07-18 23:52:16 +00:00
parent bcbd46eba3
commit da4d62db94
34 changed files with 1792 additions and 151 deletions
+10
View File
@@ -13,6 +13,7 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) files ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) files ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) gui team_window ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) gui team_window ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) ids ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) source_language ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) source_language ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) types ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) types ] ;
@@ -93,6 +94,12 @@ Application Debugger :
ThreadListView.cpp ThreadListView.cpp
VariablesView.cpp VariablesView.cpp
# ids
FunctionID.cpp
LocalVariableID.cpp
ObjectID.cpp
FunctionParameterID.cpp
# model # model
Breakpoint.cpp Breakpoint.cpp
DisassembledCode.cpp DisassembledCode.cpp
@@ -101,6 +108,7 @@ Application Debugger :
ImageInfo.cpp ImageInfo.cpp
SourceCode.cpp SourceCode.cpp
StackFrame.cpp StackFrame.cpp
StackFrameValues.cpp
StackTrace.cpp StackTrace.cpp
Statement.cpp Statement.cpp
SymbolInfo.cpp SymbolInfo.cpp
@@ -111,6 +119,7 @@ Application Debugger :
Thread.cpp Thread.cpp
ThreadInfo.cpp ThreadInfo.cpp
Type.cpp Type.cpp
TypeComponentPath.cpp
Variable.cpp Variable.cpp
# source_language # source_language
@@ -127,6 +136,7 @@ Application Debugger :
ValueLocation.cpp ValueLocation.cpp
# util # util
BitBuffer.cpp
StringUtils.cpp StringUtils.cpp
: :
+339 -28
View File
@@ -10,6 +10,7 @@
#include <AutoLocker.h> #include <AutoLocker.h>
#include "Architecture.h" #include "Architecture.h"
#include "BitBuffer.h"
#include "CpuState.h" #include "CpuState.h"
#include "DebuggerInterface.h" #include "DebuggerInterface.h"
#include "DisassembledCode.h" #include "DisassembledCode.h"
@@ -17,12 +18,19 @@
#include "Function.h" #include "Function.h"
#include "Image.h" #include "Image.h"
#include "ImageDebugInfo.h" #include "ImageDebugInfo.h"
#include "Register.h"
#include "SourceCode.h" #include "SourceCode.h"
#include "SpecificImageDebugInfo.h" #include "SpecificImageDebugInfo.h"
#include "StackFrameValues.h"
#include "StackTrace.h" #include "StackTrace.h"
#include "Team.h" #include "Team.h"
#include "TeamDebugInfo.h" #include "TeamDebugInfo.h"
#include "TeamDebugModel.h"
#include "Thread.h" #include "Thread.h"
#include "Type.h"
#include "TypeComponentPath.h"
#include "ValueLocation.h"
#include "Variable.h"
// #pragma mark - GetThreadStateJob // #pragma mark - GetThreadStateJob
@@ -31,23 +39,24 @@
GetThreadStateJob::GetThreadStateJob(DebuggerInterface* debuggerInterface, GetThreadStateJob::GetThreadStateJob(DebuggerInterface* debuggerInterface,
Thread* thread) Thread* thread)
: :
fKey(thread, JOB_TYPE_GET_THREAD_STATE),
fDebuggerInterface(debuggerInterface), fDebuggerInterface(debuggerInterface),
fThread(thread) fThread(thread)
{ {
fThread->AddReference(); fThread->AcquireReference();
} }
GetThreadStateJob::~GetThreadStateJob() GetThreadStateJob::~GetThreadStateJob()
{ {
fThread->RemoveReference(); fThread->ReleaseReference();
} }
JobKey const JobKey&
GetThreadStateJob::Key() const GetThreadStateJob::Key() const
{ {
return JobKey(fThread, JOB_TYPE_GET_THREAD_STATE); return fKey;
} }
@@ -81,23 +90,24 @@ GetThreadStateJob::Do()
GetCpuStateJob::GetCpuStateJob(DebuggerInterface* debuggerInterface, GetCpuStateJob::GetCpuStateJob(DebuggerInterface* debuggerInterface,
Thread* thread) Thread* thread)
: :
fKey(thread, JOB_TYPE_GET_CPU_STATE),
fDebuggerInterface(debuggerInterface), fDebuggerInterface(debuggerInterface),
fThread(thread) fThread(thread)
{ {
fThread->AddReference(); fThread->AcquireReference();
} }
GetCpuStateJob::~GetCpuStateJob() GetCpuStateJob::~GetCpuStateJob()
{ {
fThread->RemoveReference(); fThread->ReleaseReference();
} }
JobKey const JobKey&
GetCpuStateJob::Key() const GetCpuStateJob::Key() const
{ {
return JobKey(fThread, JOB_TYPE_GET_CPU_STATE); return fKey;
} }
@@ -125,31 +135,32 @@ GetCpuStateJob::Do()
GetStackTraceJob::GetStackTraceJob(DebuggerInterface* debuggerInterface, GetStackTraceJob::GetStackTraceJob(DebuggerInterface* debuggerInterface,
Architecture* architecture, Thread* thread) Architecture* architecture, Thread* thread)
: :
fKey(thread, JOB_TYPE_GET_STACK_TRACE),
fDebuggerInterface(debuggerInterface), fDebuggerInterface(debuggerInterface),
fArchitecture(architecture), fArchitecture(architecture),
fThread(thread) fThread(thread)
{ {
fThread->AddReference(); fThread->AcquireReference();
fCpuState = fThread->GetCpuState(); fCpuState = fThread->GetCpuState();
if (fCpuState != NULL) if (fCpuState != NULL)
fCpuState->AddReference(); fCpuState->AcquireReference();
} }
GetStackTraceJob::~GetStackTraceJob() GetStackTraceJob::~GetStackTraceJob()
{ {
if (fCpuState != NULL) if (fCpuState != NULL)
fCpuState->RemoveReference(); fCpuState->ReleaseReference();
fThread->RemoveReference(); fThread->ReleaseReference();
} }
JobKey const JobKey&
GetStackTraceJob::Key() const GetStackTraceJob::Key() const
{ {
return JobKey(fThread, JOB_TYPE_GET_CPU_STATE); return fKey;
} }
@@ -198,7 +209,7 @@ GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info)
teamLocker.Unlock(); teamLocker.Unlock();
// wait for the job to finish // wait for the job to finish
switch (WaitFor(JobKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO))) { switch (WaitFor(SimpleJobKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO))) {
case JOB_DEPENDENCY_SUCCEEDED: case JOB_DEPENDENCY_SUCCEEDED:
case JOB_DEPENDENCY_NOT_FOUND: case JOB_DEPENDENCY_NOT_FOUND:
// "Not found" can happen due to a race condition between // "Not found" can happen due to a race condition between
@@ -214,7 +225,7 @@ GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info)
} }
_info = image->GetImageDebugInfo(); _info = image->GetImageDebugInfo();
_info->AddReference(); _info->AcquireReference();
return B_OK; return B_OK;
} }
@@ -225,22 +236,23 @@ GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info)
LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image) LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image)
: :
fKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO),
fImage(image) fImage(image)
{ {
fImage->AddReference(); fImage->AcquireReference();
} }
LoadImageDebugInfoJob::~LoadImageDebugInfoJob() LoadImageDebugInfoJob::~LoadImageDebugInfoJob()
{ {
fImage->RemoveReference(); fImage->ReleaseReference();
} }
JobKey const JobKey&
LoadImageDebugInfoJob::Key() const LoadImageDebugInfoJob::Key() const
{ {
return JobKey(fImage, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO); return fKey;
} }
@@ -261,7 +273,7 @@ LoadImageDebugInfoJob::Do()
locker.Lock(); locker.Lock();
if (error == B_OK) { if (error == B_OK) {
error = fImage->SetImageDebugInfo(debugInfo, IMAGE_DEBUG_INFO_LOADED); error = fImage->SetImageDebugInfo(debugInfo, IMAGE_DEBUG_INFO_LOADED);
debugInfo->RemoveReference(); debugInfo->ReleaseReference();
} else { } else {
fImage->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE); fImage->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE);
delete debugInfo; delete debugInfo;
@@ -281,7 +293,7 @@ LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image,
if (image->GetImageDebugInfo() != NULL) { if (image->GetImageDebugInfo() != NULL) {
if (_imageDebugInfo != NULL) { if (_imageDebugInfo != NULL) {
*_imageDebugInfo = image->GetImageDebugInfo(); *_imageDebugInfo = image->GetImageDebugInfo();
(*_imageDebugInfo)->AddReference(); (*_imageDebugInfo)->AcquireReference();
} }
return B_OK; return B_OK;
} }
@@ -323,26 +335,27 @@ LoadSourceCodeJob::LoadSourceCodeJob(
DebuggerInterface* debuggerInterface, Architecture* architecture, DebuggerInterface* debuggerInterface, Architecture* architecture,
Team* team, FunctionInstance* functionInstance, bool loadForFunction) Team* team, FunctionInstance* functionInstance, bool loadForFunction)
: :
fKey(functionInstance, JOB_TYPE_LOAD_SOURCE_CODE),
fDebuggerInterface(debuggerInterface), fDebuggerInterface(debuggerInterface),
fArchitecture(architecture), fArchitecture(architecture),
fTeam(team), fTeam(team),
fFunctionInstance(functionInstance), fFunctionInstance(functionInstance),
fLoadForFunction(loadForFunction) fLoadForFunction(loadForFunction)
{ {
fFunctionInstance->AddReference(); fFunctionInstance->AcquireReference();
} }
LoadSourceCodeJob::~LoadSourceCodeJob() LoadSourceCodeJob::~LoadSourceCodeJob()
{ {
fFunctionInstance->RemoveReference(); fFunctionInstance->ReleaseReference();
} }
JobKey const JobKey&
LoadSourceCodeJob::Key() const LoadSourceCodeJob::Key() const
{ {
return JobKey(fFunctionInstance, JOB_TYPE_LOAD_SOURCE_CODE); return fKey;
} }
@@ -360,7 +373,7 @@ LoadSourceCodeJob::Do()
if (error == B_OK) { if (error == B_OK) {
function->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED); function->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED);
sourceCode->RemoveReference(); sourceCode->ReleaseReference();
return B_OK; return B_OK;
} }
@@ -384,10 +397,308 @@ LoadSourceCodeJob::Do()
if (fFunctionInstance->SourceCodeState() == FUNCTION_SOURCE_LOADING) { if (fFunctionInstance->SourceCodeState() == FUNCTION_SOURCE_LOADING) {
fFunctionInstance->SetSourceCode(sourceCode, fFunctionInstance->SetSourceCode(sourceCode,
FUNCTION_SOURCE_LOADED); FUNCTION_SOURCE_LOADED);
sourceCode->RemoveReference(); sourceCode->ReleaseReference();
} }
} else } else
fFunctionInstance->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE); fFunctionInstance->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
return error; return error;
} }
// #pragma mark - GetStackFrameValueJobKey
GetStackFrameValueJobKey::GetStackFrameValueJobKey(StackFrame* stackFrame,
Variable* variable, TypeComponentPath* path)
:
stackFrame(stackFrame),
variable(variable),
path(path)
{
}
uint32
GetStackFrameValueJobKey::HashValue() const
{
uint32 hash = (uint32)(addr_t)stackFrame;
hash = hash * 13 + (uint32)(addr_t)variable;
return hash * 13 + path->HashValue();
}
bool
GetStackFrameValueJobKey::operator==(const JobKey& other) const
{
const GetStackFrameValueJobKey* otherKey
= dynamic_cast<const GetStackFrameValueJobKey*>(&other);
return otherKey != NULL && stackFrame == otherKey->stackFrame
&& variable == otherKey->variable && *path == *otherKey->path;
}
// #pragma mark - GetStackFrameValueJob
GetStackFrameValueJob::GetStackFrameValueJob(
DebuggerInterface* debuggerInterface, Architecture* architecture,
TeamDebugModel* debugModel, Thread* thread, StackFrame* stackFrame,
Variable* variable, TypeComponentPath* path)
:
fKey(stackFrame, variable, path),
fDebuggerInterface(debuggerInterface),
fArchitecture(architecture),
fDebugModel(debugModel),
fThread(thread),
fStackFrame(stackFrame),
fVariable(variable),
fPath(path)
{
fThread->AcquireReference();
fStackFrame->AcquireReference();
fVariable->AcquireReference();
fPath->AcquireReference();
}
GetStackFrameValueJob::~GetStackFrameValueJob()
{
fThread->ReleaseReference();
fStackFrame->ReleaseReference();
fVariable->ReleaseReference();
fPath->ReleaseReference();
}
const JobKey&
GetStackFrameValueJob::Key() const
{
return fKey;
}
status_t
GetStackFrameValueJob::Do()
{
status_t error = _GetValue();
if (error == B_OK)
return B_OK;
// in case of error, set the value to invalid to avoid triggering this job
// again
AutoLocker<TeamDebugModel> locker(fDebugModel);
fStackFrame->Values()->SetValue(fVariable->ID(), fPath, BVariant());
return error;
}
status_t
GetStackFrameValueJob::_GetValue()
{
printf("GetStackFrameValueJob::_GetValue()\n");
if (fPath->CountComponents() > 0)
{
printf(" -> non-empty path\n");
return B_UNSUPPORTED;
// TODO: Implement!
}
// find out the type of the data we want to read
Type* type = fVariable->GetType();
type_code valueType = 0;
while (valueType == 0) {
switch (type->Kind()) {
case TYPE_PRIMITIVE:
valueType = dynamic_cast<PrimitiveType*>(type)->TypeConstant();
printf(" TYPE_PRIMITIVE: '%c%c%c%c'\n", int(valueType >> 24),
int(valueType >> 16), int(valueType >> 8), int(valueType));
if (valueType == 0)
{
printf(" -> unknown type constant\n");
return B_BAD_VALUE;
}
break;
case TYPE_MODIFIED:
printf(" TYPE_MODIFIED\n");
// ignore modifiers
type = dynamic_cast<ModifiedType*>(type)->BaseType();
break;
case TYPE_TYPEDEF:
printf(" TYPE_TYPEDEF\n");
type = dynamic_cast<TypedefType*>(type)->BaseType();
break;
case TYPE_ADDRESS:
printf(" TYPE_ADDRESS\n");
if (fArchitecture->AddressSize() == 4)
{
valueType = B_UINT32_TYPE;
printf(" -> 32 bit\n");
}
else
{
valueType = B_UINT64_TYPE;
printf(" -> 64 bit\n");
}
break;
case TYPE_COMPOUND:
case TYPE_ARRAY:
default:
printf(" TYPE_COMPOUND/TYPE_ARRAY/default\n");
// TODO:...
printf(" -> unsupported\n");
return B_UNSUPPORTED;
}
}
if (valueType == B_STRING_TYPE)
{
printf(" -> B_STRING_TYPE: unsupported\n");
return B_UNSUPPORTED;
// TODO:...
}
// check whether we know the complete location
ValueLocation* location = fVariable->Location();
int32 count = location->CountPieces();
printf(" location: %p, %ld pieces\n", location, count);
if (count == 0)
{
printf(" -> no location\n");
return B_ENTRY_NOT_FOUND;
}
target_size_t totalSize = 0;
uint64 totalBitSize = 0;
for (int32 i = 0; i < count; i++) {
ValuePieceLocation piece = location->PieceAt(i);
switch (piece.type) {
case VALUE_PIECE_LOCATION_INVALID:
case VALUE_PIECE_LOCATION_UNKNOWN:
return B_ENTRY_NOT_FOUND;
case VALUE_PIECE_LOCATION_MEMORY:
case VALUE_PIECE_LOCATION_REGISTER:
break;
}
totalSize += piece.size;
totalBitSize += piece.bitSize;
}
printf(" -> totalSize: %llu, totalBitSize: %llu\n", totalSize, totalBitSize);
if (totalSize == 0 && totalBitSize == 0)
{
printf(" -> no size\n");
return B_ENTRY_NOT_FOUND;
}
if (totalSize > 8 || totalSize + (totalBitSize + 7) / 8 > 8)
{
printf(" -> longer than 8 bytes: unsupported\n");
return B_UNSUPPORTED;
}
if (totalSize + (totalBitSize + 7) / 8 < BVariant::SizeOfType(valueType))
{
printf(" -> too short for value type (%llu vs. %lu)\n",
totalSize + (totalBitSize + 7) / 8, BVariant::SizeOfType(valueType));
return B_BAD_VALUE;
}
// load the data
BitBuffer valueBuffer;
// If the total bit size is not byte aligned, push the respective number of
// 0 bits on a big endian architecture to get an immediately usable value.
// On a little endian architecture we'll play with the last read byte
// instead.
if (fArchitecture->IsBigEndian() && totalBitSize % 8 != 0) {
const uint8 zero = 0;
valueBuffer.AddBits(&zero, 8 - totalBitSize % 8, 0);
}
const Register* registers = fArchitecture->Registers();
for (int32 i = 0; i < count; i++) {
ValuePieceLocation piece = location->PieceAt(i);
uint8 bitOffset = piece.bitOffset;
uint32 bitSize = piece.size * 8 + piece.bitSize;
uint32 bytesToRead = (bitSize + 7) / 8;
switch (piece.type) {
case VALUE_PIECE_LOCATION_INVALID:
case VALUE_PIECE_LOCATION_UNKNOWN:
return B_ENTRY_NOT_FOUND;
case VALUE_PIECE_LOCATION_MEMORY:
{
target_addr_t address = piece.address + bitOffset / 8;
printf(" piece %ld: memory address: %#llx, bits: %lu\n", i, address, bitSize);
bitOffset %= 8;
uint8 pieceBuffer[8];
ssize_t bytesRead = fDebuggerInterface->ReadMemory(address,
pieceBuffer, bytesToRead);
if (bytesRead < 0)
return bytesRead;
if ((uint32)bytesRead != bytesToRead)
return B_BAD_ADDRESS;
printf(" -> read: ");
for (ssize_t k = 0; k < bytesRead; k++)
printf("%02x", pieceBuffer[k]);
printf("\n");
valueBuffer.AddBits(pieceBuffer, bitSize, bitOffset);
break;
}
case VALUE_PIECE_LOCATION_REGISTER:
{
printf(" piece %ld: register: %lu, bits: %lu\n", i, piece.reg, bitSize);
BVariant registerValue;
if (!fStackFrame->GetCpuState()->GetRegisterValue(
registers + piece.reg, registerValue)) {
return B_ENTRY_NOT_FOUND;
}
if (registerValue.Size() < bytesToRead)
return B_ENTRY_NOT_FOUND;
if (!fArchitecture->IsHostEndian())
registerValue.SwapEndianess();
valueBuffer.AddBits(registerValue.Bytes(), bitSize, bitOffset);
break;
}
}
}
// If the total bit size is not byte aligned, shift the last byte by the
// respective number of bits on a little endian architecture to get a usable
// value.
if (!fArchitecture->IsBigEndian() && totalBitSize % 8 != 0)
valueBuffer.Bytes()[totalBitSize / 8] >>= 8 - totalBitSize % 8;
// TODO: Verify that this is the way to handle it!
// convert the bits into something we can work with
BVariant value;
status_t error = value.SetToTypedData(valueBuffer.Bytes(), valueType);
if (error != B_OK)
{
printf(" -> failed to set typed data: %s\n", strerror(error));
return error;
}
if (!fArchitecture->IsHostEndian())
value.SwapEndianess();
// set the value
AutoLocker<TeamDebugModel> locker(fDebugModel);
StackFrameValues* values = fStackFrame->Values();
error = values->SetValue(fVariable->ID(), fPath, value);
if (error != B_OK)
{
printf(" -> failed to set value: %s\n", strerror(error));
return error;
}
fStackFrame->NotifyValueRetrieved(fVariable, fPath);
return B_OK;
}
+67 -6
View File
@@ -5,6 +5,7 @@
#ifndef JOBS_H #ifndef JOBS_H
#define JOBS_H #define JOBS_H
#include "ImageDebugInfoProvider.h" #include "ImageDebugInfoProvider.h"
#include "Worker.h" #include "Worker.h"
@@ -16,8 +17,12 @@ class Function;
class FunctionInstance; class FunctionInstance;
class Image; class Image;
class StackFrame; class StackFrame;
class StackFrameValues;
class Team; class Team;
class TeamDebugModel;
class Thread; class Thread;
class TypeComponentPath;
class Variable;
// job types // job types
@@ -26,7 +31,8 @@ enum {
JOB_TYPE_GET_CPU_STATE, JOB_TYPE_GET_CPU_STATE,
JOB_TYPE_GET_STACK_TRACE, JOB_TYPE_GET_STACK_TRACE,
JOB_TYPE_LOAD_IMAGE_DEBUG_INFO, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO,
JOB_TYPE_LOAD_SOURCE_CODE JOB_TYPE_LOAD_SOURCE_CODE,
JOB_TYPE_GET_STACK_FRAME_VALUE
}; };
@@ -37,10 +43,11 @@ public:
Thread* thread); Thread* thread);
virtual ~GetThreadStateJob(); virtual ~GetThreadStateJob();
virtual JobKey Key() const; virtual const JobKey& Key() const;
virtual status_t Do(); virtual status_t Do();
private: private:
SimpleJobKey fKey;
DebuggerInterface* fDebuggerInterface; DebuggerInterface* fDebuggerInterface;
Thread* fThread; Thread* fThread;
}; };
@@ -53,10 +60,11 @@ public:
Thread* thread); Thread* thread);
virtual ~GetCpuStateJob(); virtual ~GetCpuStateJob();
virtual JobKey Key() const; virtual const JobKey& Key() const;
virtual status_t Do(); virtual status_t Do();
private: private:
SimpleJobKey fKey;
DebuggerInterface* fDebuggerInterface; DebuggerInterface* fDebuggerInterface;
Thread* fThread; Thread* fThread;
}; };
@@ -69,7 +77,7 @@ public:
Architecture* architecture, Thread* thread); Architecture* architecture, Thread* thread);
virtual ~GetStackTraceJob(); virtual ~GetStackTraceJob();
virtual JobKey Key() const; virtual const JobKey& Key() const;
virtual status_t Do(); virtual status_t Do();
private: private:
@@ -78,6 +86,7 @@ private:
ImageDebugInfo*& _info); ImageDebugInfo*& _info);
private: private:
SimpleJobKey fKey;
DebuggerInterface* fDebuggerInterface; DebuggerInterface* fDebuggerInterface;
Architecture* fArchitecture; Architecture* fArchitecture;
Thread* fThread; Thread* fThread;
@@ -90,7 +99,7 @@ public:
LoadImageDebugInfoJob(Image* image); LoadImageDebugInfoJob(Image* image);
virtual ~LoadImageDebugInfoJob(); virtual ~LoadImageDebugInfoJob();
virtual JobKey Key() const; virtual const JobKey& Key() const;
virtual status_t Do(); virtual status_t Do();
static status_t ScheduleIfNecessary(Worker* worker, static status_t ScheduleIfNecessary(Worker* worker,
@@ -105,6 +114,7 @@ public:
// earlier. // earlier.
private: private:
SimpleJobKey fKey;
Image* fImage; Image* fImage;
}; };
@@ -118,10 +128,11 @@ public:
bool loadForFunction); bool loadForFunction);
virtual ~LoadSourceCodeJob(); virtual ~LoadSourceCodeJob();
virtual JobKey Key() const; virtual const JobKey& Key() const;
virtual status_t Do(); virtual status_t Do();
private: private:
SimpleJobKey fKey;
DebuggerInterface* fDebuggerInterface; DebuggerInterface* fDebuggerInterface;
Architecture* fArchitecture; Architecture* fArchitecture;
Team* fTeam; Team* fTeam;
@@ -130,4 +141,54 @@ private:
}; };
struct GetStackFrameValueJobKey : JobKey {
StackFrame* stackFrame;
Variable* variable;
TypeComponentPath* path;
public:
GetStackFrameValueJobKey(
StackFrame* stackFrame,
Variable* variable,
TypeComponentPath* path);
virtual uint32 HashValue() const;
virtual bool operator==(const JobKey& other) const;
};
class GetStackFrameValueJob : public Job {
public:
GetStackFrameValueJob(
DebuggerInterface* debuggerInterface,
Architecture* architecture,
TeamDebugModel* debugModel,
Thread* thread, StackFrame* stackFrame,
Variable* variable,
TypeComponentPath* path);
virtual ~GetStackFrameValueJob();
virtual const JobKey& Key() const;
virtual status_t Do();
private:
struct ValueJobKey;
private:
status_t _GetValue();
private:
GetStackFrameValueJobKey fKey;
DebuggerInterface* fDebuggerInterface;
Architecture* fArchitecture;
TeamDebugModel* fDebugModel;
Thread* fThread;
StackFrame* fStackFrame;
Variable* fVariable;
TypeComponentPath* fPath;
};
#endif // JOBS_H #endif // JOBS_H
+1
View File
@@ -18,6 +18,7 @@ enum {
MSG_THREAD_STATE_CHANGED = 'tsch', MSG_THREAD_STATE_CHANGED = 'tsch',
MSG_THREAD_CPU_STATE_CHANGED = 'tcsc', MSG_THREAD_CPU_STATE_CHANGED = 'tcsc',
MSG_THREAD_STACK_TRACE_CHANGED = 'tstc', MSG_THREAD_STACK_TRACE_CHANGED = 'tstc',
MSG_STACK_FRAME_VALUE_RETRIEVED = 'sfvr',
MSG_IMAGE_DEBUG_INFO_CHANGED = 'idic', MSG_IMAGE_DEBUG_INFO_CHANGED = 'idic',
MSG_IMAGE_FILE_CHANGED = 'ifch', MSG_IMAGE_FILE_CHANGED = 'ifch',
MSG_FUNCTION_SOURCE_CODE_CHANGED = 'fnsc', MSG_FUNCTION_SOURCE_CODE_CHANGED = 'fnsc',
+32 -5
View File
@@ -28,10 +28,13 @@
#include "MessageCodes.h" #include "MessageCodes.h"
#include "SourceCode.h" #include "SourceCode.h"
#include "SpecificImageDebugInfo.h" #include "SpecificImageDebugInfo.h"
#include "StackFrame.h"
#include "StackFrameValues.h"
#include "Statement.h" #include "Statement.h"
#include "SymbolInfo.h" #include "SymbolInfo.h"
#include "TeamDebugInfo.h" #include "TeamDebugInfo.h"
#include "TeamDebugModel.h" #include "TeamDebugModel.h"
#include "Variable.h"
// #pragma mark - ImageHandler // #pragma mark - ImageHandler
@@ -482,8 +485,7 @@ TeamDebugger::MessageReceived(BMessage* message)
void void
TeamDebugger::FunctionSourceCodeRequested(TeamWindow* window, TeamDebugger::FunctionSourceCodeRequested(FunctionInstance* functionInstance)
FunctionInstance* functionInstance)
{ {
Function* function = functionInstance->GetFunction(); Function* function = functionInstance->GetFunction();
@@ -520,14 +522,39 @@ TeamDebugger::FunctionSourceCodeRequested(TeamWindow* window,
void void
TeamDebugger::ImageDebugInfoRequested(TeamWindow* window, Image* image) TeamDebugger::ImageDebugInfoRequested(Image* image)
{ {
LoadImageDebugInfoJob::ScheduleIfNecessary(fWorker, image); LoadImageDebugInfoJob::ScheduleIfNecessary(fWorker, image);
} }
void void
TeamDebugger::ThreadActionRequested(TeamWindow* window, thread_id threadID, TeamDebugger::StackFrameValueRequested(::Thread* thread, StackFrame* stackFrame,
Variable* variable, TypeComponentPath* path)
{
// the team is already locked
// check whether a job is already in progress
AutoLocker<Worker> workerLocker(fWorker);
GetStackFrameValueJobKey jobKey(stackFrame, variable, path);
if (fWorker->GetJob(jobKey) != NULL)
return;
workerLocker.Unlock();
// schedule the job
if (fWorker->ScheduleJob(
new(std::nothrow) GetStackFrameValueJob(fDebuggerInterface,
fDebuggerInterface->GetArchitecture(), fDebugModel, thread,
stackFrame, variable, path),
this) != B_OK) {
// scheduling failed -- set the value to invalid
stackFrame->Values()->SetValue(variable->ID(), path, BVariant());
}
}
void
TeamDebugger::ThreadActionRequested(thread_id threadID,
uint32 action) uint32 action)
{ {
BMessage message(action); BMessage message(action);
@@ -556,7 +583,7 @@ TeamDebugger::ClearBreakpointRequested(target_addr_t address)
bool bool
TeamDebugger::TeamWindowQuitRequested(TeamWindow* window) TeamDebugger::TeamWindowQuitRequested()
{ {
AutoLocker< ::Team> locker(fTeam); AutoLocker< ::Team> locker(fTeam);
BString name(fTeam->Name()); BString name(fTeam->Name());
+8 -6
View File
@@ -41,16 +41,18 @@ public:
private: private:
// TeamWindow::Listener // TeamWindow::Listener
virtual void FunctionSourceCodeRequested(TeamWindow* window, virtual void FunctionSourceCodeRequested(
FunctionInstance* function); FunctionInstance* function);
virtual void ImageDebugInfoRequested(TeamWindow* window, virtual void ImageDebugInfoRequested(Image* image);
Image* image); virtual void StackFrameValueRequested(::Thread* thread,
virtual void ThreadActionRequested(TeamWindow* window, StackFrame* stackFrame, Variable* variable,
thread_id threadID, uint32 action); TypeComponentPath* path);
virtual void ThreadActionRequested(thread_id threadID,
uint32 action);
virtual void SetBreakpointRequested(target_addr_t address, virtual void SetBreakpointRequested(target_addr_t address,
bool enabled); bool enabled);
virtual void ClearBreakpointRequested(target_addr_t address); virtual void ClearBreakpointRequested(target_addr_t address);
virtual bool TeamWindowQuitRequested(TeamWindow* window); virtual bool TeamWindowQuitRequested();
// JobListener // JobListener
virtual void JobDone(Job* job); virtual void JobDone(Job* job);
+3 -3
View File
@@ -304,8 +304,8 @@ ThreadHandler::HandleThreadStateChanged()
AutoLocker<TeamDebugModel> locker(fDebugModel); AutoLocker<TeamDebugModel> locker(fDebugModel);
// cancel jobs for this thread // cancel jobs for this thread
fWorker->AbortJob(JobKey(fThread, JOB_TYPE_GET_CPU_STATE)); fWorker->AbortJob(SimpleJobKey(fThread, JOB_TYPE_GET_CPU_STATE));
fWorker->AbortJob(JobKey(fThread, JOB_TYPE_GET_STACK_TRACE)); fWorker->AbortJob(SimpleJobKey(fThread, JOB_TYPE_GET_STACK_TRACE));
// If the thread is stopped and has no CPU state yet, schedule a job. // If the thread is stopped and has no CPU state yet, schedule a job.
if (fThread->State() == THREAD_STATE_STOPPED if (fThread->State() == THREAD_STATE_STOPPED
@@ -322,7 +322,7 @@ ThreadHandler::HandleCpuStateChanged()
AutoLocker<TeamDebugModel> locker(fDebugModel); AutoLocker<TeamDebugModel> locker(fDebugModel);
// cancel stack trace job for this thread // cancel stack trace job for this thread
fWorker->AbortJob(JobKey(fThread, JOB_TYPE_GET_STACK_TRACE)); fWorker->AbortJob(SimpleJobKey(fThread, JOB_TYPE_GET_STACK_TRACE));
// If the thread has a CPU state, but no stack trace yet, schedule a job. // If the thread has a CPU state, but no stack trace yet, schedule a job.
if (fThread->GetCpuState() != NULL && fThread->GetStackTrace() == NULL) { if (fThread->GetCpuState() != NULL && fThread->GetStackTrace() == NULL) {
+55 -4
View File
@@ -9,6 +9,58 @@
#include <AutoLocker.h> #include <AutoLocker.h>
// pragma mark - JobKey
JobKey::~JobKey()
{
}
// pragma mark - SimpleJobKey
SimpleJobKey::SimpleJobKey(void* object, uint32 type)
:
object(object),
type(type)
{
}
SimpleJobKey::SimpleJobKey(const SimpleJobKey& other)
:
object(other.object),
type(other.type)
{
}
size_t
SimpleJobKey::HashValue() const
{
return (size_t)(addr_t)object ^ (size_t)type;
}
bool
SimpleJobKey::operator==(const JobKey& other) const
{
const SimpleJobKey* otherKey = dynamic_cast<const SimpleJobKey*>(&other);
return otherKey != NULL && object == otherKey->object
&& type == otherKey->type;
}
SimpleJobKey&
SimpleJobKey::operator=(const SimpleJobKey& other)
{
object = other.object;
type = other.type;
return *this;
}
// #pragma mark - JobListener // #pragma mark - JobListener
@@ -207,7 +259,7 @@ Worker::ScheduleJob(Job* job, JobListener* listener)
if (job == NULL) if (job == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
ObjectDeleter<Job> jobDeleter(job); Reference<Job> jobReference(job, true);
AutoLocker<Worker> locker(this); AutoLocker<Worker> locker(this);
if (fTerminating) if (fTerminating)
@@ -224,8 +276,7 @@ Worker::ScheduleJob(Job* job, JobListener* listener)
job->SetWorker(this); job->SetWorker(this);
job->SetState(JOB_STATE_UNSCHEDULED); job->SetState(JOB_STATE_UNSCHEDULED);
fJobs.Insert(job); fJobs.Insert(job);
fUnscheduledJobs.Add(job); fUnscheduledJobs.Add(jobReference.Detach());
jobDeleter.Detach();
if (notify) if (notify)
release_sem(fWorkToDoSem); release_sem(fWorkToDoSem);
@@ -447,5 +498,5 @@ Worker::_FinishJob(Job* job)
if (job->State() != JOB_STATE_ABORTED) if (job->State() != JOB_STATE_ABORTED)
fJobs.Remove(job); fJobs.Remove(job);
job->NotifyListeners(); job->NotifyListeners();
delete job; job->ReleaseReference();
} }
+23 -32
View File
@@ -8,6 +8,7 @@
#include <Locker.h> #include <Locker.h>
#include <ObjectList.h> #include <ObjectList.h>
#include <Referenceable.h>
#include <util/DoublyLinkedList.h> #include <util/DoublyLinkedList.h>
#include <util/OpenHashTable.h> #include <util/OpenHashTable.h>
@@ -35,40 +36,29 @@ enum job_wait_status {
}; };
struct JobKey { class JobKey {
void* object; public:
uint32 type; virtual ~JobKey();
JobKey(void* object, uint32 type) virtual uint32 HashValue() const = 0;
:
object(object),
type(type)
{
}
JobKey(const JobKey& other) virtual bool operator==(const JobKey& other) const = 0;
: };
object(other.object),
type(other.type)
{
}
JobKey& operator=(const JobKey& other)
{
object = other.object;
type = other.type;
return *this;
}
bool operator==(const JobKey& other) const struct SimpleJobKey : public JobKey {
{ void* object;
return object == other.object && type == other.type; uint32 type;
}
size_t HashValue() const public:
{ SimpleJobKey(void* object, uint32 type);
return (size_t)(addr_t)object ^ (size_t)type; SimpleJobKey(const SimpleJobKey& other);
}
virtual uint32 HashValue() const;
virtual bool operator==(const JobKey& other) const;
SimpleJobKey& operator=(const SimpleJobKey& other);
}; };
@@ -85,12 +75,13 @@ public:
typedef DoublyLinkedList<Job> JobList; typedef DoublyLinkedList<Job> JobList;
class Job : public DoublyLinkedListLinkImpl<Job>, public HashTableLink<Job> { class Job : public Referenceable, public DoublyLinkedListLinkImpl<Job>,
public HashTableLink<Job> {
public: public:
Job(); Job();
virtual ~Job(); virtual ~Job();
virtual JobKey Key() const = 0; virtual const JobKey& Key() const = 0;
virtual status_t Do() = 0; virtual status_t Do() = 0;
Worker* GetWorker() const { return fWorker; } Worker* GetWorker() const { return fWorker; }
@@ -144,7 +135,7 @@ public:
status_t ScheduleJob(Job* job, status_t ScheduleJob(Job* job,
JobListener* listener = NULL); JobListener* listener = NULL);
// always takes over ownership // always takes over reference
void AbortJob(const JobKey& key); void AbortJob(const JobKey& key);
Job* GetJob(const JobKey& key); Job* GetJob(const JobKey& key);
@@ -79,9 +79,9 @@ DebuggerImageDebugInfo::GetFunctions(BObjectList<FunctionDebugInfo>& functions)
status_t status_t
DebuggerImageDebugInfo::CreateFrame(Image* image, FunctionDebugInfo* function, DebuggerImageDebugInfo::CreateFrame(Image* image,
CpuState* cpuState, StackFrame*& _previousFrame, FunctionInstance* functionInstance, CpuState* cpuState,
CpuState*& _previousCpuState) StackFrame*& _previousFrame, CpuState*& _previousCpuState)
{ {
return B_UNSUPPORTED; return B_UNSUPPORTED;
} }
@@ -27,7 +27,7 @@ public:
virtual status_t GetFunctions( virtual status_t GetFunctions(
BObjectList<FunctionDebugInfo>& functions); BObjectList<FunctionDebugInfo>& functions);
virtual status_t CreateFrame(Image* image, virtual status_t CreateFrame(Image* image,
FunctionDebugInfo* function, FunctionInstance* functionInstance,
CpuState* cpuState, CpuState* cpuState,
StackFrame*& _previousFrame, StackFrame*& _previousFrame,
CpuState*& _previousCpuState); CpuState*& _previousCpuState);
@@ -31,6 +31,8 @@
#include "ElfFile.h" #include "ElfFile.h"
#include "FileManager.h" #include "FileManager.h"
#include "FileSourceCode.h" #include "FileSourceCode.h"
#include "FunctionID.h"
#include "FunctionInstance.h"
#include "LocatableFile.h" #include "LocatableFile.h"
#include "Register.h" #include "Register.h"
#include "RegisterMap.h" #include "RegisterMap.h"
@@ -303,12 +305,12 @@ printf(" %ld compilation units\n", fFile->CountCompilationUnits());
status_t status_t
DwarfImageDebugInfo::CreateFrame(Image* image, FunctionDebugInfo* _function, DwarfImageDebugInfo::CreateFrame(Image* image,
CpuState* cpuState, StackFrame*& _previousFrame, FunctionInstance* functionInstance, CpuState* cpuState,
CpuState*& _previousCpuState) StackFrame*& _previousFrame, CpuState*& _previousCpuState)
{ {
DwarfFunctionDebugInfo* function DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>(
= dynamic_cast<DwarfFunctionDebugInfo*>(_function); functionInstance->GetFunctionDebugInfo());
if (function == NULL) if (function == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -365,14 +367,24 @@ if (previousCpuState->GetRegisterValue(reg, value)) {
return B_NO_MEMORY; return B_NO_MEMORY;
Reference<StackFrame> frameReference(frame, true); Reference<StackFrame> frameReference(frame, true);
error = frame->Init();
if (error != B_OK)
return error;
frame->SetReturnAddress(previousCpuState->InstructionPointer()); frame->SetReturnAddress(previousCpuState->InstructionPointer());
// Note, this is correct, since we actually retrieved the return // Note, this is correct, since we actually retrieved the return
// address. Our caller will fix the IP for us. // address. Our caller will fix the IP for us.
FunctionID* functionID = functionInstance->GetFunctionID();
if (functionID == NULL)
return B_NO_MEMORY;
Reference<FunctionID> functionIDReference(functionID, true);
// create function parameter objects // create function parameter objects
DIESubprogram* subprogramEntry = function->SubprogramEntry(); DIESubprogram* subprogramEntry = function->SubprogramEntry();
DwarfInterfaceFactory factory(fFile, function->GetCompilationUnit(), DwarfInterfaceFactory factory(fFile, function->GetCompilationUnit(),
subprogramEntry, instructionPointer, framePointer, &inputInterface); subprogramEntry, instructionPointer, framePointer, &inputInterface,
fromDwarfMap);
error = factory.Init(); error = factory.Init();
if (error != B_OK) if (error != B_OK)
return error; return error;
@@ -387,8 +399,10 @@ if (previousCpuState->GetRegisterValue(reg, value)) {
DIEFormalParameter* parameterEntry DIEFormalParameter* parameterEntry
= dynamic_cast<DIEFormalParameter*>(entry); = dynamic_cast<DIEFormalParameter*>(entry);
Variable* parameter; Variable* parameter;
if (factory.CreateParameter(parameterEntry, parameter) != B_OK) if (factory.CreateParameter(functionID, parameterEntry, parameter)
!= B_OK) {
continue; continue;
}
if (!frame->AddParameter(parameter)) { if (!frame->AddParameter(parameter)) {
parameter->ReleaseReference(); parameter->ReleaseReference();
@@ -42,7 +42,7 @@ public:
virtual status_t GetFunctions( virtual status_t GetFunctions(
BObjectList<FunctionDebugInfo>& functions); BObjectList<FunctionDebugInfo>& functions);
virtual status_t CreateFrame(Image* image, virtual status_t CreateFrame(Image* image,
FunctionDebugInfo* function, FunctionInstance* functionInstance,
CpuState* cpuState, CpuState* cpuState,
StackFrame*& _previousFrame, StackFrame*& _previousFrame,
CpuState*& _previousCpuState); CpuState*& _previousCpuState);
@@ -10,14 +10,59 @@
#include <Variant.h> #include <Variant.h>
#include "CompilationUnit.h"
#include "DebugInfoEntries.h" #include "DebugInfoEntries.h"
#include "Dwarf.h" #include "Dwarf.h"
#include "DwarfFile.h" #include "DwarfFile.h"
#include "DwarfUtils.h" #include "DwarfUtils.h"
#include "FunctionID.h"
#include "FunctionParameterID.h"
#include "RegisterMap.h"
#include "StringUtils.h"
#include "ValueLocation.h" #include "ValueLocation.h"
#include "Variable.h" #include "Variable.h"
// #pragma mark - DwarfFunctionParameterID
struct DwarfInterfaceFactory::DwarfFunctionParameterID
: public FunctionParameterID {
DwarfFunctionParameterID(FunctionID* functionID, const BString& name)
:
fFunctionID(functionID),
fName(name)
{
fFunctionID->AcquireReference();
}
virtual ~DwarfFunctionParameterID()
{
fFunctionID->ReleaseReference();
}
virtual bool operator==(const ObjectID& other) const
{
const DwarfFunctionParameterID* parameterID
= dynamic_cast<const DwarfFunctionParameterID*>(&other);
return parameterID != NULL && *fFunctionID == *parameterID->fFunctionID
&& fName == parameterID->fName;
}
protected:
virtual uint32 ComputeHashValue() const
{
uint32 hash = fFunctionID->HashValue();
return hash * 19 + StringUtils::HashValue(fName);
}
private:
FunctionID* fFunctionID;
const BString fName;
};
// #pragma mark - DwarfType // #pragma mark - DwarfType
@@ -26,7 +71,8 @@ struct DwarfInterfaceFactory::DwarfType : virtual Type,
public: public:
DwarfType(const BString& name) DwarfType(const BString& name)
: :
fName(name) fName(name),
fByteSize(0)
{ {
} }
@@ -35,10 +81,21 @@ public:
return fName.Length() > 0 ? fName.String() : NULL; return fName.Length() > 0 ? fName.String() : NULL;
} }
uint64 ByteSize() const
{
return fByteSize;
}
void SetByteSize(uint64 size)
{
fByteSize = size;
}
virtual DIEType* GetDIEType() const = 0; virtual DIEType* GetDIEType() const = 0;
private: private:
BString fName; BString fName;
uint64 fByteSize;
}; };
@@ -394,7 +451,7 @@ struct DwarfInterfaceFactory::DwarfTypeHashDefinition {
DwarfInterfaceFactory::DwarfInterfaceFactory(DwarfFile* file, DwarfInterfaceFactory::DwarfInterfaceFactory(DwarfFile* file,
CompilationUnit* compilationUnit, DIESubprogram* subprogramEntry, CompilationUnit* compilationUnit, DIESubprogram* subprogramEntry,
target_addr_t instructionPointer, target_addr_t framePointer, target_addr_t instructionPointer, target_addr_t framePointer,
DwarfTargetInterface* targetInterface) DwarfTargetInterface* targetInterface, RegisterMap* fromDwarfRegisterMap)
: :
fFile(file), fFile(file),
fCompilationUnit(compilationUnit), fCompilationUnit(compilationUnit),
@@ -402,6 +459,7 @@ DwarfInterfaceFactory::DwarfInterfaceFactory(DwarfFile* file,
fInstructionPointer(instructionPointer), fInstructionPointer(instructionPointer),
fFramePointer(framePointer), fFramePointer(framePointer),
fTargetInterface(targetInterface), fTargetInterface(targetInterface),
fFromDwarfRegisterMap(fromDwarfRegisterMap),
fTypes(NULL) fTypes(NULL)
{ {
} }
@@ -447,12 +505,21 @@ DwarfInterfaceFactory::CreateType(DIEType* typeEntry, Type*& _type)
status_t status_t
DwarfInterfaceFactory::CreateParameter(DIEFormalParameter* parameterEntry, DwarfInterfaceFactory::CreateParameter(FunctionID* functionID,
Variable*& _parameter) DIEFormalParameter* parameterEntry, Variable*& _parameter)
{ {
// get the name // get the name
BString name; BString name;
DwarfUtils::GetFullyQualifiedDIEName(parameterEntry, name); DwarfUtils::GetDIEName(parameterEntry, name);
printf("DwarfInterfaceFactory::CreateParameter(DIE: %p): name: \"%s\"\n",
parameterEntry, name.String());
// create the ID
DwarfFunctionParameterID* id = new(std::nothrow) DwarfFunctionParameterID(
functionID, name);
if (id == NULL)
return B_NO_MEMORY;
Reference<DwarfFunctionParameterID> idReference(id, true);
// get the type entry // get the type entry
DIEFormalParameter* typeOwnerEntry = parameterEntry; DIEFormalParameter* typeOwnerEntry = parameterEntry;
@@ -490,6 +557,7 @@ DwarfInterfaceFactory::CreateParameter(DIEFormalParameter* parameterEntry,
fFile->ResolveLocation(fCompilationUnit, fFile->ResolveLocation(fCompilationUnit,
fSubprogramEntry, locationDescription, fTargetInterface, fSubprogramEntry, locationDescription, fTargetInterface,
fInstructionPointer, 0, fFramePointer, *location); fInstructionPointer, 0, fFramePointer, *location);
location->Dump();
} }
// create the type // create the type
@@ -499,8 +567,10 @@ DwarfInterfaceFactory::CreateParameter(DIEFormalParameter* parameterEntry,
return error; return error;
Reference<DwarfType> typeReference(type, true); Reference<DwarfType> typeReference(type, true);
_FixLocation(location, type);
// create the variable // create the variable
Variable* variable = new(std::nothrow) Variable(name, type, location); Variable* variable = new(std::nothrow) Variable(id, name, type, location);
if (variable == NULL) if (variable == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -521,6 +591,11 @@ DwarfInterfaceFactory::_CreateType(DIEType* typeEntry, DwarfType*& _type)
return error; return error;
fTypes->Insert(type); fTypes->Insert(type);
// try to get the type's size
uint64 size;
if (_ResolveTypeByteSize(typeEntry, size) == B_OK)
type->SetByteSize(size);
} }
type->AcquireReference(); type->AcquireReference();
@@ -1011,3 +1086,121 @@ DwarfInterfaceFactory::_ResolveTypedef(DIETypedef* entry,
} }
} }
status_t
DwarfInterfaceFactory::_ResolveTypeByteSize(DIEType* typeEntry, uint64& _size)
{
printf("DwarfInterfaceFactory::_ResolveTypeByteSize(%p)\n", typeEntry);
// get the size attribute
const DynamicAttributeValue* sizeValue;
while (true) {
// resolve a typedef
if (typeEntry->Tag() == DW_TAG_typedef) {
printf(" resolving typedef...\n");
status_t error = _ResolveTypedef(
dynamic_cast<DIETypedef*>(typeEntry), typeEntry);
if (error != B_OK)
return error;
}
sizeValue = typeEntry->ByteSize();
if (sizeValue != NULL && sizeValue->IsValid())
break;
// resolve abstract origin
if (DIEType* abstractOrigin = dynamic_cast<DIEType*>(
typeEntry->AbstractOrigin())) {
printf(" resolving abstract origin (%p)...\n", abstractOrigin);
typeEntry = abstractOrigin;
sizeValue = typeEntry->ByteSize();
if (sizeValue != NULL && sizeValue->IsValid())
break;
}
// resolve specification
if (DIEType* specification = dynamic_cast<DIEType*>(
typeEntry->Specification())) {
printf(" resolving specification (%p)...\n", specification);
typeEntry = specification;
sizeValue = typeEntry->ByteSize();
if (sizeValue != NULL && sizeValue->IsValid())
break;
}
// For some types we have a special handling. For modified types we
// follow the base type, for address types we know the size anyway.
printf(" nothing yet, special type handling\n");
switch (typeEntry->Tag()) {
case DW_TAG_const_type:
case DW_TAG_packed_type:
case DW_TAG_volatile_type:
case DW_TAG_restrict_type:
case DW_TAG_shared_type:
typeEntry = dynamic_cast<DIEModifiedType*>(typeEntry)
->GetType();
printf(" following modified type -> %p\n", typeEntry);
if (typeEntry == NULL)
return B_ENTRY_NOT_FOUND;
break;
case DW_TAG_pointer_type:
case DW_TAG_reference_type:
_size = fCompilationUnit->AddressSize();
printf(" pointer/reference type: size: %llu\n", _size);
return B_OK;
default:
return B_ENTRY_NOT_FOUND;
}
}
printf(" found attribute\n");
// get the actual value
BVariant size;
status_t error = fFile->EvaluateDynamicValue(fCompilationUnit,
fSubprogramEntry, sizeValue, fTargetInterface, fInstructionPointer,
fFramePointer, size);
if (error != B_OK)
{
printf(" failed to resolve attribute: %s\n", strerror(error));
return error;
}
_size = size.ToUInt64();
printf(" -> size: %llu\n", _size);
return B_OK;
}
void
DwarfInterfaceFactory::_FixLocation(ValueLocation* location, DwarfType* type)
{
printf("DwarfInterfaceFactory::_FixLocation(%p, %p), type entry: %p\n",
location, type, type->GetDIEType());
// translate the DWARF register indices
int32 count = location->CountPieces();
for (int32 i = 0; i < count; i++) {
ValuePieceLocation piece = location->PieceAt(i);
if (piece.type == VALUE_PIECE_LOCATION_REGISTER) {
int32 reg = fFromDwarfRegisterMap->MapRegisterIndex(piece.reg);
if (reg >= 0)
piece.reg = reg;
else
piece.SetToUnknown();
location->SetPieceAt(i, piece);
}
}
// If we only have one piece and that doesn't have a size, try to retrieve
// the size of the type.
if (count == 1) {
ValuePieceLocation piece = location->PieceAt(0);
if (piece.IsValid() && piece.size == 0 && piece.bitSize == 0)
{
piece.SetSize(type->ByteSize());
location->SetPieceAt(0, piece);
printf(" set single piece size to %llu\n", type->ByteSize());
}
}
}
@@ -25,7 +25,10 @@ class DIEType;
class DIETypedef; class DIETypedef;
class DwarfFile; class DwarfFile;
class DwarfTargetInterface; class DwarfTargetInterface;
class FunctionID;
class RegisterMap;
class Type; class Type;
class ValueLocation;
class Variable; class Variable;
@@ -36,19 +39,21 @@ public:
DIESubprogram* subprogramEntry, DIESubprogram* subprogramEntry,
target_addr_t instructionPointer, target_addr_t instructionPointer,
target_addr_t framePointer, target_addr_t framePointer,
DwarfTargetInterface* targetInterface); DwarfTargetInterface* targetInterface,
RegisterMap* fromDwarfRegisterMap);
~DwarfInterfaceFactory(); ~DwarfInterfaceFactory();
status_t Init(); status_t Init();
status_t CreateType(DIEType* typeEntry, Type*& _type); status_t CreateType(DIEType* typeEntry, Type*& _type);
// returns reference // returns reference
status_t CreateParameter( status_t CreateParameter(FunctionID* functionID,
DIEFormalParameter* parameterEntry, DIEFormalParameter* parameterEntry,
Variable*& _parameter); Variable*& _parameter);
// returns reference // returns reference
private: private:
struct DwarfFunctionParameterID;
struct DwarfType; struct DwarfType;
struct DwarfDataMember; struct DwarfDataMember;
struct DwarfPrimitiveType; struct DwarfPrimitiveType;
@@ -88,6 +93,11 @@ private:
status_t _ResolveTypedef(DIETypedef* entry, status_t _ResolveTypedef(DIETypedef* entry,
DIEType*& _baseTypeEntry); DIEType*& _baseTypeEntry);
status_t _ResolveTypeByteSize(DIEType* typeEntry,
uint64& _size);
void _FixLocation(ValueLocation* location,
DwarfType* type);
private: private:
DwarfFile* fFile; DwarfFile* fFile;
@@ -96,6 +106,7 @@ private:
target_addr_t fInstructionPointer; target_addr_t fInstructionPointer;
target_addr_t fFramePointer; target_addr_t fFramePointer;
DwarfTargetInterface* fTargetInterface; DwarfTargetInterface* fTargetInterface;
RegisterMap* fFromDwarfRegisterMap;
TypeTable* fTypes; TypeTable* fTypes;
}; };
@@ -6,6 +6,7 @@
#include "Function.h" #include "Function.h"
#include "FileSourceCode.h" #include "FileSourceCode.h"
#include "FunctionID.h"
Function::Function() Function::Function()
+5 -1
View File
@@ -22,7 +22,7 @@ public:
Function(); Function();
~Function(); ~Function();
// team must be locked ot access the instances // team must be locked to access the instances
FunctionInstance* FirstInstance() const FunctionInstance* FirstInstance() const
{ return fInstances.Head(); } { return fInstances.Head(); }
FunctionInstance* LastInstance() const FunctionInstance* LastInstance() const
@@ -40,6 +40,10 @@ public:
{ return FirstInstance() { return FirstInstance()
->GetSourceLocation(); } ->GetSourceLocation(); }
FunctionID* GetFunctionID() const
{ return FirstInstance()->GetFunctionID(); }
// returns a reference
// mutable attributes follow (locking required) // mutable attributes follow (locking required)
FileSourceCode* GetSourceCode() const { return fSourceCode; } FileSourceCode* GetSourceCode() const { return fSourceCode; }
function_source_state SourceCodeState() const function_source_state SourceCodeState() const
@@ -5,8 +5,13 @@
#include "FunctionInstance.h" #include "FunctionInstance.h"
#include <new>
#include "DisassembledCode.h" #include "DisassembledCode.h"
#include "Function.h" #include "Function.h"
#include "FunctionID.h"
#include "ImageDebugInfo.h"
#include "LocatableFile.h"
FunctionInstance::FunctionInstance(ImageDebugInfo* imageDebugInfo, FunctionInstance::FunctionInstance(ImageDebugInfo* imageDebugInfo,
@@ -31,6 +36,25 @@ FunctionInstance::~FunctionInstance()
} }
FunctionID*
FunctionInstance::GetFunctionID() const
{
BString idString;
BString path;
if (LocatableFile* file = SourceFile()) {
idString << "s:";
file->GetPath(path);
} else {
idString << "i:";
path << GetImageDebugInfo()->GetImageInfo().Name();
}
idString << path << "//" << Name();
return new(std::nothrow) FunctionID(idString);
}
void void
FunctionInstance::SetFunction(Function* function) FunctionInstance::SetFunction(Function* function)
{ {
@@ -21,6 +21,7 @@ enum function_source_state {
class DisassembledCode; class DisassembledCode;
class Function; class Function;
class FunctionDebugInfo; class FunctionDebugInfo;
class FunctionID;
class ImageDebugInfo; class ImageDebugInfo;
@@ -52,6 +53,9 @@ public:
{ return fFunctionDebugInfo { return fFunctionDebugInfo
->SourceStartLocation(); } ->SourceStartLocation(); }
FunctionID* GetFunctionID() const;
// returns a reference
void SetFunction(Function* function); void SetFunction(Function* function);
// package private // package private
@@ -28,6 +28,8 @@ public:
ImageDebugInfo(const ImageInfo& imageInfo); ImageDebugInfo(const ImageInfo& imageInfo);
~ImageDebugInfo(); ~ImageDebugInfo();
const ImageInfo& GetImageInfo() const { return fImageInfo; }
bool AddSpecificInfo(SpecificImageDebugInfo* info); bool AddSpecificInfo(SpecificImageDebugInfo* info);
status_t FinishInit(); status_t FinishInit();
@@ -16,6 +16,7 @@ class CpuState;
class DebuggerInterface; class DebuggerInterface;
class FileSourceCode; class FileSourceCode;
class FunctionDebugInfo; class FunctionDebugInfo;
class FunctionInstance;
class Image; class Image;
class LocatableFile; class LocatableFile;
class SourceLanguage; class SourceLanguage;
@@ -34,7 +35,7 @@ public:
// returns references // returns references
virtual status_t CreateFrame(Image* image, virtual status_t CreateFrame(Image* image,
FunctionDebugInfo* function, FunctionInstance* functionInstance,
CpuState* cpuState, CpuState* cpuState,
StackFrame*& _previousFrame, StackFrame*& _previousFrame,
CpuState*& _previousCpuState) = 0; CpuState*& _previousCpuState) = 0;
@@ -3,6 +3,7 @@
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include "TeamWindow.h" #include "TeamWindow.h"
#include <stdio.h> #include <stdio.h>
@@ -29,7 +30,8 @@
#include "RegistersView.h" #include "RegistersView.h"
#include "StackTrace.h" #include "StackTrace.h"
#include "StackTraceView.h" #include "StackTraceView.h"
#include "VariablesView.h" #include "TypeComponentPath.h"
#include "Variable.h"
enum { enum {
@@ -129,15 +131,15 @@ TeamWindow::DispatchMessage(BMessage* message, BHandler* handler)
== B_OK) { == B_OK) {
switch (key) { switch (key) {
case B_F10_KEY: case B_F10_KEY:
fListener->ThreadActionRequested(this, fListener->ThreadActionRequested(
fActiveThread->ID(), MSG_THREAD_STEP_OVER); fActiveThread->ID(), MSG_THREAD_STEP_OVER);
break; break;
case B_F11_KEY: case B_F11_KEY:
if ((modifiers & B_SHIFT_KEY) != 0) { if ((modifiers & B_SHIFT_KEY) != 0) {
fListener->ThreadActionRequested(this, fListener->ThreadActionRequested(
fActiveThread->ID(), MSG_THREAD_STEP_OUT); fActiveThread->ID(), MSG_THREAD_STEP_OUT);
} else { } else {
fListener->ThreadActionRequested(this, fListener->ThreadActionRequested(
fActiveThread->ID(), MSG_THREAD_STEP_INTO); fActiveThread->ID(), MSG_THREAD_STEP_INTO);
} }
break; break;
@@ -169,7 +171,7 @@ TeamWindow::MessageReceived(BMessage* message)
case MSG_THREAD_STEP_INTO: case MSG_THREAD_STEP_INTO:
case MSG_THREAD_STEP_OUT: case MSG_THREAD_STEP_OUT:
if (fActiveThread != NULL) { if (fActiveThread != NULL) {
fListener->ThreadActionRequested(this, fActiveThread->ID(), fListener->ThreadActionRequested(fActiveThread->ID(),
message->what); message->what);
} }
break; break;
@@ -203,6 +205,24 @@ TeamWindow::MessageReceived(BMessage* message)
break; break;
} }
case MSG_STACK_FRAME_VALUE_RETRIEVED:
{
void* _stackFrame;
void* _variable;
void* _path;
if (message->FindPointer("stackFrame", &_stackFrame) == B_OK
&& message->FindPointer("variable", &_variable) == B_OK
&& message->FindPointer("path", &_path) == B_OK) {
StackFrame* stackFrame = (StackFrame*)_stackFrame;
Variable* variable = (Variable*)_variable;
TypeComponentPath* path = (TypeComponentPath*)_path;
_HandleStackFrameValueRetrieved(stackFrame, variable, path);
path->ReleaseReference();
variable->ReleaseReference();
stackFrame->ReleaseReference();
}
}
case MSG_IMAGE_DEBUG_INFO_CHANGED: case MSG_IMAGE_DEBUG_INFO_CHANGED:
{ {
int32 imageID; int32 imageID;
@@ -239,7 +259,7 @@ TeamWindow::MessageReceived(BMessage* message)
bool bool
TeamWindow::QuitRequested() TeamWindow::QuitRequested()
{ {
return fListener->TeamWindowQuitRequested(this); return fListener->TeamWindowQuitRequested();
} }
@@ -285,6 +305,14 @@ TeamWindow::ClearBreakpointRequested(target_addr_t address)
} }
void
TeamWindow::StackFrameValueRequested(::Thread* thread, StackFrame* stackFrame,
Variable* variable, TypeComponentPath* path)
{
fListener->StackFrameValueRequested(thread, stackFrame, variable, path);
}
void void
TeamWindow::ThreadStateChanged(const Team::ThreadEvent& event) TeamWindow::ThreadStateChanged(const Team::ThreadEvent& event)
{ {
@@ -339,6 +367,22 @@ function, function->GetSourceCode(), function->SourceCodeState());
} }
void
TeamWindow::StackFrameValueRetrieved(StackFrame* stackFrame, Variable* variable,
TypeComponentPath* path)
{
BMessage message(MSG_STACK_FRAME_VALUE_RETRIEVED);
if (message.AddPointer("stackFrame", stackFrame) == B_OK
&& message.AddPointer("variable", variable) == B_OK
&& message.AddPointer("path", path) == B_OK
&& PostMessage(&message) == B_OK) {
stackFrame->AcquireReference();
variable->AcquireReference();
path->AcquireReference();
}
}
void void
TeamWindow::_Init() TeamWindow::_Init()
{ {
@@ -388,7 +432,7 @@ TeamWindow::_Init()
.Add(fImageFunctionsView = ImageFunctionsView::Create(this)); .Add(fImageFunctionsView = ImageFunctionsView::Create(this));
// add local variables tab // add local variables tab
BView* tab = fVariablesView = VariablesView::Create(); BView* tab = fVariablesView = VariablesView::Create(this);
fLocalsTabView->AddTab(tab); fLocalsTabView->AddTab(tab);
// add registers tab // add registers tab
@@ -481,7 +525,7 @@ TeamWindow::_SetActiveImage(Image* image)
// If the debug info is not loaded yet, request it. // If the debug info is not loaded yet, request it.
if (fActiveImage->ImageDebugInfoState() == IMAGE_DEBUG_INFO_NOT_LOADED) if (fActiveImage->ImageDebugInfoState() == IMAGE_DEBUG_INFO_NOT_LOADED)
fListener->ImageDebugInfoRequested(this, fActiveImage); fListener->ImageDebugInfoRequested(fActiveImage);
} }
locker.Unlock(); locker.Unlock();
@@ -519,20 +563,33 @@ TeamWindow::_SetActiveStackFrame(StackFrame* frame)
if (frame == fActiveStackFrame) if (frame == fActiveStackFrame)
return; return;
if (fActiveStackFrame != NULL) if (fActiveStackFrame != NULL) {
AutoLocker<TeamDebugModel> locker(fDebugModel);
fActiveStackFrame->RemoveListener(this);
locker.Unlock();
fActiveStackFrame->RemoveReference(); fActiveStackFrame->RemoveReference();
}
fActiveStackFrame = frame; fActiveStackFrame = frame;
if (fActiveStackFrame != NULL) { if (fActiveStackFrame != NULL) {
fActiveStackFrame->AddReference(); fActiveStackFrame->AddReference();
AutoLocker<TeamDebugModel> locker(fDebugModel);
fActiveStackFrame->AddListener(this);
locker.Unlock();
_SetActiveFunction(fActiveStackFrame->Function()); _SetActiveFunction(fActiveStackFrame->Function());
} }
_UpdateCpuState(); _UpdateCpuState();
fStackTraceView->SetStackFrame(fActiveStackFrame); fStackTraceView->SetStackFrame(fActiveStackFrame);
fVariablesView->SetStackFrame(fActiveStackFrame); if (fActiveStackFrame != NULL)
fVariablesView->SetStackFrame(fActiveThread, fActiveStackFrame);
else
fVariablesView->SetStackFrame(NULL, NULL);
fSourceView->SetStackFrame(fActiveStackFrame); fSourceView->SetStackFrame(fActiveStackFrame);
} }
@@ -580,7 +637,7 @@ TeamWindow::_SetActiveFunction(FunctionInstance* functionInstance)
// If the source code is not loaded yet, request it. // If the source code is not loaded yet, request it.
if (function->SourceCodeState() == FUNCTION_SOURCE_NOT_LOADED) if (function->SourceCodeState() == FUNCTION_SOURCE_NOT_LOADED)
fListener->FunctionSourceCodeRequested(this, fActiveFunction); fListener->FunctionSourceCodeRequested(fActiveFunction);
} }
locker.Unlock(); locker.Unlock();
@@ -741,6 +798,17 @@ TeamWindow::_HandleStackTraceChanged(thread_id threadID)
} }
void
TeamWindow::_HandleStackFrameValueRetrieved(StackFrame* stackFrame,
Variable* variable, TypeComponentPath* path)
{
if (stackFrame != fActiveStackFrame)
return;
fVariablesView->StackFrameValueRetrieved(stackFrame, variable, path);
}
void void
TeamWindow::_HandleImageDebugInfoChanged(image_id imageID) TeamWindow::_HandleImageDebugInfoChanged(image_id imageID)
{ {
+28 -8
View File
@@ -5,6 +5,7 @@
#ifndef TEAM_WINDOW_H #ifndef TEAM_WINDOW_H
#define TEAM_WINDOW_H #define TEAM_WINDOW_H
#include <String.h> #include <String.h>
#include <Window.h> #include <Window.h>
@@ -12,10 +13,12 @@
#include "Function.h" #include "Function.h"
#include "ImageFunctionsView.h" #include "ImageFunctionsView.h"
#include "ImageListView.h" #include "ImageListView.h"
#include "StackFrame.h"
#include "StackTraceView.h" #include "StackTraceView.h"
#include "Team.h" #include "Team.h"
#include "TeamDebugModel.h" #include "TeamDebugModel.h"
#include "ThreadListView.h" #include "ThreadListView.h"
#include "VariablesView.h"
class BButton; class BButton;
@@ -30,8 +33,9 @@ class VariablesView;
class TeamWindow : public BWindow, ThreadListView::Listener, class TeamWindow : public BWindow, ThreadListView::Listener,
ImageListView::Listener, StackTraceView::Listener, ImageListView::Listener, StackTraceView::Listener,
ImageFunctionsView::Listener, SourceView::Listener, Team::Listener, ImageFunctionsView::Listener, SourceView::Listener, VariablesView::Listener,
TeamDebugModel::Listener, Function::Listener { Team::Listener, TeamDebugModel::Listener, Function::Listener,
StackFrame::Listener {
public: public:
class Listener; class Listener;
@@ -68,6 +72,11 @@ private:
bool enabled); bool enabled);
virtual void ClearBreakpointRequested(target_addr_t address); virtual void ClearBreakpointRequested(target_addr_t address);
// VariablesView::Listener
virtual void StackFrameValueRequested(::Thread* thread,
StackFrame* stackFrame, Variable* variable,
TypeComponentPath* path);
// Team::Listener // Team::Listener
virtual void ThreadStateChanged( virtual void ThreadStateChanged(
const Team::ThreadEvent& event); const Team::ThreadEvent& event);
@@ -86,6 +95,11 @@ private:
// Function::Listener // Function::Listener
virtual void FunctionSourceCodeChanged(Function* function); virtual void FunctionSourceCodeChanged(Function* function);
// StackFrame::Listener
virtual void StackFrameValueRetrieved(StackFrame* stackFrame,
Variable* variable,
TypeComponentPath* path);
void _Init(); void _Init();
void _SetActiveThread(::Thread* thread); void _SetActiveThread(::Thread* thread);
@@ -101,6 +115,9 @@ private:
void _HandleThreadStateChanged(thread_id threadID); void _HandleThreadStateChanged(thread_id threadID);
void _HandleCpuStateChanged(thread_id threadID); void _HandleCpuStateChanged(thread_id threadID);
void _HandleStackTraceChanged(thread_id threadID); void _HandleStackTraceChanged(thread_id threadID);
void _HandleStackFrameValueRetrieved(
StackFrame* stackFrame, Variable* variable,
TypeComponentPath* path);
void _HandleImageDebugInfoChanged(image_id imageID); void _HandleImageDebugInfoChanged(image_id imageID);
void _HandleSourceCodeChanged(); void _HandleSourceCodeChanged();
void _HandleUserBreakpointChanged( void _HandleUserBreakpointChanged(
@@ -136,17 +153,20 @@ class TeamWindow::Listener {
public: public:
virtual ~Listener(); virtual ~Listener();
virtual void FunctionSourceCodeRequested(TeamWindow* window, virtual void FunctionSourceCodeRequested(
FunctionInstance* function) = 0; FunctionInstance* function) = 0;
virtual void ImageDebugInfoRequested(TeamWindow* window, virtual void ImageDebugInfoRequested(Image* image) = 0;
Image* image) = 0; virtual void StackFrameValueRequested(::Thread* thread,
virtual void ThreadActionRequested(TeamWindow* window, StackFrame* stackFrame, Variable* variable,
thread_id threadID, uint32 action) = 0; TypeComponentPath* path) = 0;
// called with team locked
virtual void ThreadActionRequested(thread_id threadID,
uint32 action) = 0;
virtual void SetBreakpointRequested(target_addr_t address, virtual void SetBreakpointRequested(target_addr_t address,
bool enabled) = 0; bool enabled) = 0;
virtual void ClearBreakpointRequested( virtual void ClearBreakpointRequested(
target_addr_t address) = 0; target_addr_t address) = 0;
virtual bool TeamWindowQuitRequested(TeamWindow* window) = 0; virtual bool TeamWindowQuitRequested() = 0;
}; };
@@ -10,30 +10,136 @@
#include <new> #include <new>
#include <AutoLocker.h>
#include "table/TableColumns.h" #include "table/TableColumns.h"
#include "Architecture.h" #include "Architecture.h"
#include "StackFrame.h" #include "StackFrame.h"
#include "StackFrameValues.h"
#include "Team.h"
#include "Thread.h"
#include "TypeComponentPath.h"
#include "Variable.h" #include "Variable.h"
// #pragma mark - VariableValueColumn
class VariablesView::VariableValueColumn : public StringTableColumn {
public:
VariableValueColumn(int32 modelIndex, const char* title, float width,
float minWidth, float maxWidth, uint32 truncate = B_TRUNCATE_MIDDLE,
alignment align = B_ALIGN_RIGHT)
:
StringTableColumn(modelIndex, title, width, minWidth, maxWidth,
truncate, align)
{
}
protected:
virtual BField* PrepareField(const BVariant& value) const
{
char buffer[64];
return StringTableColumn::PrepareField(
BVariant(_ToString(value, buffer, sizeof(buffer)),
B_VARIANT_DONT_COPY_DATA));
}
virtual int CompareValues(const BVariant& a, const BVariant& b)
{
// If neither value is a number, compare the strings. If only one value
// is a number, it is considered to be greater.
if (!a.IsNumber()) {
if (b.IsNumber())
return -1;
char bufferA[64];
char bufferB[64];
return StringTableColumn::CompareValues(
BVariant(_ToString(a, bufferA, sizeof(bufferA)),
B_VARIANT_DONT_COPY_DATA),
BVariant(_ToString(b, bufferB, sizeof(bufferB)),
B_VARIANT_DONT_COPY_DATA));
}
if (!b.IsNumber())
return 1;
// If either value is floating point, we compare floating point values.
if (a.IsFloat() || b.IsFloat()) {
double valueA = a.ToDouble();
double valueB = b.ToDouble();
return valueA < valueB ? -1 : (valueA == valueB ? 0 : 1);
}
uint64 valueA = a.ToUInt64();
uint64 valueB = b.ToUInt64();
return valueA < valueB ? -1 : (valueA == valueB ? 0 : 1);
}
private:
const char* _ToString(const BVariant& value, char* buffer,
size_t bufferSize) const
{
switch (value.Type()) {
case B_BOOL_TYPE:
return value.ToBool() ? "true" : "false";
case B_FLOAT_TYPE:
case B_DOUBLE_TYPE:
snprintf(buffer, bufferSize, "%g", value.ToDouble());
break;
case B_INT8_TYPE:
case B_UINT8_TYPE:
snprintf(buffer, bufferSize, "0x%02x", value.ToUInt8());
break;
case B_INT16_TYPE:
case B_UINT16_TYPE:
snprintf(buffer, bufferSize, "0x%04x", value.ToUInt16());
break;
case B_INT32_TYPE:
case B_UINT32_TYPE:
snprintf(buffer, bufferSize, "0x%08lx", value.ToUInt32());
break;
case B_INT64_TYPE:
case B_UINT64_TYPE:
snprintf(buffer, bufferSize, "0x%016llx", value.ToUInt64());
break;
case B_STRING_TYPE:
return value.ToString();
default:
return NULL;
}
return buffer;
}
};
// #pragma mark - VariableTableModel // #pragma mark - VariableTableModel
#include "ObjectID.h"
class VariablesView::VariableTableModel : public TableModel { class VariablesView::VariableTableModel : public TableModel {
public: public:
VariableTableModel() VariableTableModel()
: :
fStackFrame(NULL) fStackFrame(NULL),
fValues(NULL)
{ {
} }
~VariableTableModel() ~VariableTableModel()
{ {
SetStackFrame(NULL, NULL);
} }
void SetStackFrame(StackFrame* stackFrame) void SetStackFrame(Thread* thread, StackFrame* stackFrame)
{ {
if (fValues != NULL) {
fValues->ReleaseReference();
fValues = NULL;
}
if (fStackFrame != NULL) { if (fStackFrame != NULL) {
int32 rowCount = CountRows(); int32 rowCount = CountRows();
fStackFrame = NULL; fStackFrame = NULL;
@@ -41,14 +147,38 @@ public:
} }
fStackFrame = stackFrame; fStackFrame = stackFrame;
fThread = thread;
if (fStackFrame != NULL) {
try {
AutoLocker<Team> locker(fThread->GetTeam());
fValues = new StackFrameValues(*fStackFrame->Values());
} catch (std::bad_alloc) {
}
if (fStackFrame != NULL)
NotifyRowsAdded(0, CountRows()); NotifyRowsAdded(0, CountRows());
}
}
void StackFrameValueRetrieved(StackFrame* stackFrame, Variable* variable,
TypeComponentPath* path)
{
if (stackFrame != fStackFrame || fValues == NULL)
return;
// update the respective value
AutoLocker<Team> locker(fThread->GetTeam());
BVariant value;
if (fStackFrame->Values()->GetValue(variable->ID(), path, value)) {
fValues->SetValue(variable->ID(), path, value);
NotifyRowsChanged(0, CountRows());
// TODO: Only notify for the respective node.
}
} }
virtual int32 CountColumns() const virtual int32 CountColumns() const
{ {
return 1; return 2;
} }
virtual int32 CountRows() const virtual int32 CountRows() const
@@ -59,7 +189,7 @@ public:
: 0; : 0;
} }
virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, BVariant& value) virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, BVariant& _value)
{ {
if (fStackFrame == NULL) if (fStackFrame == NULL)
return false; return false;
@@ -70,30 +200,49 @@ public:
: fStackFrame->LocalVariableAt(rowIndex - parameterCount); : fStackFrame->LocalVariableAt(rowIndex - parameterCount);
if (variable == NULL) if (variable == NULL)
return false; return false;
printf("VariablesView::VariableTableModel::GetValueAt(%ld, %ld): "
"variable id: %p, hash: %lu\n", rowIndex, columnIndex, variable->ID(),
variable->ID()->HashValue());
switch (columnIndex) { switch (columnIndex) {
case 0: case 0:
value.SetTo(variable->Name(), B_VARIANT_DONT_COPY_DATA); _value.SetTo(variable->Name(), B_VARIANT_DONT_COPY_DATA);
return true; return true;
case 1:
if (fValues == NULL)
return false;
// return fValues->GetValue(variable->ID(), TypeComponentPath(),
// _value);
{
bool success = fValues->GetValue(variable->ID(), TypeComponentPath(), _value);
if (!success)
return false;
printf(" -> %llx\n", _value.ToUInt64());
return true;
}
default: default:
return false; return false;
} }
} }
private: private:
StackFrame* fStackFrame; Thread* fThread;
StackFrame* fStackFrame;
StackFrameValues* fValues;
}; };
// #pragma mark - VariablesView // #pragma mark - VariablesView
VariablesView::VariablesView() VariablesView::VariablesView(Listener* listener)
: :
BGroupView(B_VERTICAL), BGroupView(B_VERTICAL),
fThread(NULL),
fStackFrame(NULL), fStackFrame(NULL),
fVariableTable(NULL), fVariableTable(NULL),
fVariableTableModel(NULL) fVariableTableModel(NULL),
fListener(listener)
{ {
SetName("Variables"); SetName("Variables");
} }
@@ -101,16 +250,16 @@ VariablesView::VariablesView()
VariablesView::~VariablesView() VariablesView::~VariablesView()
{ {
SetStackFrame(NULL); SetStackFrame(NULL, NULL);
fVariableTable->SetTableModel(NULL); fVariableTable->SetTableModel(NULL);
delete fVariableTableModel; delete fVariableTableModel;
} }
/*static*/ VariablesView* /*static*/ VariablesView*
VariablesView::Create() VariablesView::Create(Listener* listener)
{ {
VariablesView* self = new VariablesView; VariablesView* self = new VariablesView(listener);
try { try {
self->_Init(); self->_Init();
@@ -124,20 +273,46 @@ VariablesView::Create()
void void
VariablesView::SetStackFrame(StackFrame* stackFrame) VariablesView::SetStackFrame(Thread* thread, StackFrame* stackFrame)
{ {
if (stackFrame == fStackFrame) if (thread == fThread && stackFrame == fStackFrame)
return; return;
if (fThread != NULL)
fThread->ReleaseReference();
if (fStackFrame != NULL) if (fStackFrame != NULL)
fStackFrame->RemoveReference(); fStackFrame->ReleaseReference();
fThread = thread;
fStackFrame = stackFrame; fStackFrame = stackFrame;
if (fThread != NULL)
fThread->AcquireReference();
if (fStackFrame != NULL) if (fStackFrame != NULL)
fStackFrame->AddReference(); fStackFrame->AcquireReference();
fVariableTableModel->SetStackFrame(fStackFrame); fVariableTableModel->SetStackFrame(fThread, fStackFrame);
// request loading the parameter and variable values
if (fThread != NULL && fStackFrame != NULL) {
AutoLocker<Team> locker(fThread->GetTeam());
for (int32 i = 0; Variable* variable = fStackFrame->ParameterAt(i); i++)
_RequestVariableValue(variable);
for (int32 i = 0; Variable* variable = fStackFrame->LocalVariableAt(i);
i++) {
_RequestVariableValue(variable);
}
}
}
void
VariablesView::StackFrameValueRetrieved(StackFrame* stackFrame,
Variable* variable, TypeComponentPath* path)
{
fVariableTableModel->StackFrameValueRetrieved(stackFrame, variable, path);
} }
@@ -150,11 +325,36 @@ VariablesView::_Init()
// columns // columns
fVariableTable->AddColumn(new StringTableColumn(0, "Variable", 80, 40, 1000, fVariableTable->AddColumn(new StringTableColumn(0, "Variable", 80, 40, 1000,
B_TRUNCATE_END, B_ALIGN_LEFT)); B_TRUNCATE_END, B_ALIGN_LEFT));
// fVariableTable->AddColumn(new VariableValueColumn(1, "Value", 80, 40, 1000, fVariableTable->AddColumn(new VariableValueColumn(1, "Value", 80, 40, 1000,
// B_TRUNCATE_END, B_ALIGN_RIGHT)); B_TRUNCATE_END, B_ALIGN_RIGHT));
fVariableTableModel = new VariableTableModel; fVariableTableModel = new VariableTableModel;
fVariableTable->SetTableModel(fVariableTableModel); fVariableTable->SetTableModel(fVariableTableModel);
fVariableTable->AddTableListener(this); fVariableTable->AddTableListener(this);
} }
void
VariablesView::_RequestVariableValue(Variable* variable)
{
StackFrameValues* values = fStackFrame->Values();
if (values->HasValue(variable->ID(), TypeComponentPath()))
return;
TypeComponentPath* path = new(std::nothrow) TypeComponentPath;
if (path == NULL)
return;
Reference<TypeComponentPath> pathReference(path, true);
fListener->StackFrameValueRequested(fThread, fStackFrame,
variable, path);
}
// #pragma mark - Listener
VariablesView::Listener::~Listener()
{
}
@@ -12,29 +12,54 @@
class StackFrame; class StackFrame;
class Thread;
class TypeComponentPath;
class Variable; class Variable;
class VariablesView : public BGroupView, private TableListener { class VariablesView : public BGroupView, private TableListener {
public: public:
VariablesView(); class Listener;
public:
VariablesView(Listener* listener);
~VariablesView(); ~VariablesView();
static VariablesView* Create(); static VariablesView* Create(Listener* listener);
// throws // throws
void SetStackFrame(StackFrame* stackFrame); void SetStackFrame(Thread* thread,
StackFrame* stackFrame);
void StackFrameValueRetrieved(StackFrame* stackFrame,
Variable* variable,
TypeComponentPath* path);
private: private:
class VariableValueColumn;
class VariableTableModel; class VariableTableModel;
private: private:
void _Init(); void _Init();
void _RequestVariableValue(Variable* variable);
private: private:
Thread* fThread;
StackFrame* fStackFrame; StackFrame* fStackFrame;
Table* fVariableTable; Table* fVariableTable;
VariableTableModel* fVariableTableModel; VariableTableModel* fVariableTableModel;
Listener* fListener;
};
class VariablesView::Listener {
public:
virtual ~Listener();
virtual void StackFrameValueRequested(Thread* thread,
StackFrame* stackFrame, Variable* variable,
TypeComponentPath* path) = 0;
// called with team locked
}; };
+55 -1
View File
@@ -5,9 +5,12 @@
#include "StackFrame.h" #include "StackFrame.h"
#include <new>
#include "CpuState.h" #include "CpuState.h"
#include "FunctionInstance.h" #include "FunctionInstance.h"
#include "Image.h" #include "Image.h"
#include "StackFrameValues.h"
#include "Variable.h" #include "Variable.h"
@@ -23,7 +26,8 @@ StackFrame::StackFrame(stack_frame_type type, CpuState* cpuState,
fInstructionPointer(instructionPointer), fInstructionPointer(instructionPointer),
fReturnAddress(0), fReturnAddress(0),
fImage(NULL), fImage(NULL),
fFunction(NULL) fFunction(NULL),
fValues(NULL)
{ {
fCpuState->AcquireReference(); fCpuState->AcquireReference();
} }
@@ -43,6 +47,17 @@ StackFrame::~StackFrame()
} }
status_t
StackFrame::Init()
{
fValues = new(std::nothrow) StackFrameValues;
if (fValues == NULL)
return B_NO_MEMORY;
return fValues->Init();
}
void void
StackFrame::SetReturnAddress(target_addr_t address) StackFrame::SetReturnAddress(target_addr_t address)
{ {
@@ -124,3 +139,42 @@ StackFrame::AddLocalVariable(Variable* variable)
variable->AcquireReference(); variable->AcquireReference();
return true; return true;
} }
void
StackFrame::AddListener(Listener* listener)
{
fListeners.Add(listener);
}
void
StackFrame::RemoveListener(Listener* listener)
{
fListeners.Remove(listener);
}
void
StackFrame::NotifyValueRetrieved(Variable* variable, TypeComponentPath* path)
{
for (ListenerList::Iterator it = fListeners.GetIterator();
Listener* listener = it.Next();) {
listener->StackFrameValueRetrieved(this, variable, path);
}
}
// #pragma mark - StackFrame
StackFrame::Listener::~Listener()
{
}
void
StackFrame::Listener::StackFrameValueRetrieved(StackFrame* stackFrame,
Variable* variable, TypeComponentPath* path)
{
}
+32
View File
@@ -5,10 +5,12 @@
#ifndef STACK_FRAME_H #ifndef STACK_FRAME_H
#define STACK_FRAME_H #define STACK_FRAME_H
#include <OS.h> #include <OS.h>
#include <ObjectList.h> #include <ObjectList.h>
#include <Referenceable.h> #include <Referenceable.h>
#include <util/DoublyLinkedList.h>
#include "Types.h" #include "Types.h"
@@ -24,10 +26,15 @@ enum stack_frame_type {
class CpuState; class CpuState;
class Image; class Image;
class FunctionInstance; class FunctionInstance;
class StackFrameValues;
class TypeComponentPath;
class Variable; class Variable;
class StackFrame : public Referenceable { class StackFrame : public Referenceable {
public:
class Listener;
public: public:
StackFrame(stack_frame_type type, StackFrame(stack_frame_type type,
CpuState* cpuState, CpuState* cpuState,
@@ -35,6 +42,8 @@ public:
target_addr_t instructionPointer); target_addr_t instructionPointer);
~StackFrame(); ~StackFrame();
status_t Init();
stack_frame_type Type() const { return fType; } stack_frame_type Type() const { return fType; }
CpuState* GetCpuState() const { return fCpuState; } CpuState* GetCpuState() const { return fCpuState; }
target_addr_t FrameAddress() const { return fFrameAddress; } target_addr_t FrameAddress() const { return fFrameAddress; }
@@ -59,8 +68,18 @@ public:
Variable* LocalVariableAt(int32 index) const; Variable* LocalVariableAt(int32 index) const;
bool AddLocalVariable(Variable* variable); bool AddLocalVariable(Variable* variable);
StackFrameValues* Values() const { return fValues; }
// team lock must be held
void AddListener(Listener* listener);
void RemoveListener(Listener* listener);
void NotifyValueRetrieved(Variable* variable,
TypeComponentPath* path);
private: private:
typedef BObjectList<Variable> VariableList; typedef BObjectList<Variable> VariableList;
typedef DoublyLinkedList<Listener> ListenerList;
private: private:
stack_frame_type fType; stack_frame_type fType;
@@ -72,6 +91,19 @@ private:
FunctionInstance* fFunction; FunctionInstance* fFunction;
VariableList fParameters; VariableList fParameters;
VariableList fLocalVariables; VariableList fLocalVariables;
StackFrameValues* fValues;
ListenerList fListeners;
};
class StackFrame::Listener : public DoublyLinkedListLinkImpl<Listener> {
public:
virtual ~Listener();
virtual void StackFrameValueRetrieved(StackFrame* stackFrame,
Variable* variable,
TypeComponentPath* path);
// called with lock held
}; };
@@ -0,0 +1,183 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "StackFrameValues.h"
#include <new>
#include "FunctionID.h"
#include "TypeComponentPath.h"
struct StackFrameValues::Key {
ObjectID* variable;
TypeComponentPath* path;
Key(ObjectID* variable, TypeComponentPath* path)
:
variable(variable),
path(path)
{
}
uint32 HashValue() const
{
return variable->HashValue() ^ path->HashValue();
}
bool operator==(const Key& other) const
{
return *variable == *other.variable && *path == *other.path;
}
};
struct StackFrameValues::ValueEntry : Key, HashTableLink<ValueEntry> {
BVariant value;
ValueEntry(ObjectID* variable, TypeComponentPath* path)
:
Key(variable, path)
{
variable->AcquireReference();
path->AcquireReference();
}
~ValueEntry()
{
variable->ReleaseReference();
path->ReleaseReference();
}
};
struct StackFrameValues::ValueEntryHashDefinition {
typedef Key KeyType;
typedef ValueEntry ValueType;
size_t HashKey(const Key& key) const
{
return key.HashValue();
}
size_t Hash(const ValueEntry* value) const
{
return value->HashValue();
}
bool Compare(const Key& key, const ValueEntry* value) const
{
return key == *value;
}
HashTableLink<ValueEntry>* GetLink(ValueEntry* value) const
{
return value;
}
};
StackFrameValues::StackFrameValues()
:
fValues(NULL)
{
}
StackFrameValues::StackFrameValues(const StackFrameValues& other)
:
fValues(NULL)
{
try {
// init
if (Init() != B_OK)
throw std::bad_alloc();
// clone all values
for (ValueTable::Iterator it = other.fValues->GetIterator();
ValueEntry* entry = it.Next();) {
if (SetValue(entry->variable, entry->path, entry->value) != B_OK)
throw std::bad_alloc();
}
} catch (...) {
_Cleanup();
throw;
}
}
StackFrameValues::~StackFrameValues()
{
_Cleanup();
}
status_t
StackFrameValues::Init()
{
fValues = new(std::nothrow) ValueTable;
if (fValues == NULL)
return B_NO_MEMORY;
return fValues->Init();
}
bool
StackFrameValues::GetValue(ObjectID* variable, const TypeComponentPath* path,
BVariant& _value) const
{
ValueEntry* entry = fValues->Lookup(
Key(variable, (TypeComponentPath*)path));
if (entry == NULL)
return false;
_value = entry->value;
return true;
}
bool
StackFrameValues::HasValue(ObjectID* variable, const TypeComponentPath* path)
const
{
return fValues->Lookup(Key(variable, (TypeComponentPath*)path)) != NULL;
}
status_t
StackFrameValues::SetValue(ObjectID* variable, TypeComponentPath* path,
const BVariant& value)
{
ValueEntry* entry = fValues->Lookup(Key(variable, path));
if (entry == NULL) {
entry = new(std::nothrow) ValueEntry(variable, path);
if (entry == NULL)
return B_NO_MEMORY;
fValues->Insert(entry);
}
entry->value = value;
return B_OK;
}
void
StackFrameValues::_Cleanup()
{
if (fValues != NULL) {
ValueEntry* entry = fValues->Clear(true);
while (entry != NULL) {
ValueEntry* next = entry->fNext;
delete entry;
entry = next;
}
delete fValues;
fValues = NULL;
}
}
@@ -0,0 +1,74 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef STACK_FRAME_VALUES_H
#define STACK_FRAME_VALUES_H
#include <Referenceable.h>
#include <util/OpenHashTable.h>
#include <Variant.h>
class ObjectID;
class TypeComponentPath;
class StackFrameValues : public Referenceable {
public:
StackFrameValues();
StackFrameValues(const StackFrameValues& other);
// throws std::bad_alloc
virtual ~StackFrameValues();
status_t Init();
bool GetValue(ObjectID* variable,
const TypeComponentPath* path,
BVariant& _value) const;
inline bool GetValue(ObjectID* variable,
const TypeComponentPath& path,
BVariant& _value) const;
bool HasValue(ObjectID* variable,
const TypeComponentPath* path) const;
inline bool HasValue(ObjectID* variable,
const TypeComponentPath& path) const;
status_t SetValue(ObjectID* variable,
TypeComponentPath* path,
const BVariant& value);
private:
struct Key;
struct ValueEntry;
struct ValueEntryHashDefinition;
typedef OpenHashTable<ValueEntryHashDefinition> ValueTable;
private:
StackFrameValues& operator=(const StackFrameValues& other);
void _Cleanup();
private:
ValueTable* fValues;
};
bool
StackFrameValues::GetValue(ObjectID* variable, const TypeComponentPath& path,
BVariant& _value) const
{
return GetValue(variable, &path, _value);
}
bool
StackFrameValues::HasValue(ObjectID* variable, const TypeComponentPath& path)
const
{
return HasValue(variable, &path);
}
#endif // STACK_FRAME_VALUES_H
+1
View File
@@ -22,6 +22,7 @@ enum {
class Architecture; class Architecture;
class Breakpoint; class Breakpoint;
class FunctionID;
class SourceCode; class SourceCode;
class TeamMemory; class TeamMemory;
class UserBreakpoint; class UserBreakpoint;
@@ -0,0 +1,139 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "TypeComponentPath.h"
#include <new>
#include "StringUtils.h"
// #pragma mark - TypeComponent
uint32
TypeComponent::HashValue() const
{
uint32 hash = ((uint32)index << 8) | (componentKind << 4) | typeKind;
return StringUtils::HashValue(name) * 13 + hash;
}
bool
TypeComponent::operator==(const TypeComponent& other) const
{
return componentKind == other.componentKind
&& typeKind == other.typeKind
&& index == other.index
&& name == other.name;
}
// #pragma mark - TypeComponentPath
TypeComponentPath::TypeComponentPath()
:
fComponents(10, true)
{
}
TypeComponentPath::TypeComponentPath(const TypeComponentPath& other)
:
fComponents(10, true)
{
*this = other;
}
TypeComponentPath::~TypeComponentPath()
{
}
int32
TypeComponentPath::CountComponents() const
{
return fComponents.CountItems();
}
TypeComponent
TypeComponentPath::ComponentAt(int32 index) const
{
TypeComponent* component = fComponents.ItemAt(index);
return component != NULL ? *component : TypeComponent();
}
bool
TypeComponentPath::AddComponent(const TypeComponent& component)
{
TypeComponent* myComponent = new(std::nothrow) TypeComponent(component);
if (myComponent == NULL || !fComponents.AddItem(myComponent)) {
delete myComponent;
return false;
}
return true;
}
void
TypeComponentPath::Clear()
{
fComponents.MakeEmpty();
}
uint32
TypeComponentPath::HashValue() const
{
int32 count = fComponents.CountItems();
if (count == 0)
return 0;
uint32 hash = fComponents.ItemAt(0)->HashValue();
for (int32 i = 1; i < count; i++)
hash = hash * 17 + fComponents.ItemAt(i)->HashValue();
return hash;
}
TypeComponentPath&
TypeComponentPath::operator=(const TypeComponentPath& other)
{
if (this != &other) {
fComponents.MakeEmpty();
for (int32 i = 0;
TypeComponent* component = other.fComponents.ItemAt(i); i++) {
if (!AddComponent(*component))
break;
}
}
return *this;
}
bool
TypeComponentPath::operator==(const TypeComponentPath& other) const
{
int32 count = fComponents.CountItems();
if (count != other.fComponents.CountItems())
return false;
for (int32 i = 0; i < count; i++) {
if (*fComponents.ItemAt(i) != *other.fComponents.ItemAt(i))
return false;
}
return true;
}
+129
View File
@@ -0,0 +1,129 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef TYPE_COMPONENT_PATH_H
#define TYPE_COMPONENT_PATH_H
#include <String.h>
#include <ObjectList.h>
#include <Referenceable.h>
#include "Type.h"
enum type_component_kind {
TYPE_COMPONENT_UNDEFINED,
TYPE_COMPONENT_BASE_TYPE,
TYPE_COMPONENT_DATA_MEMBER,
TYPE_COMPONENT_ARRAY_ELEMENT
};
struct TypeComponent {
uint64 index;
BString name;
type_component_kind componentKind;
type_kind typeKind;
TypeComponent()
:
componentKind(TYPE_COMPONENT_UNDEFINED)
{
}
TypeComponent(const TypeComponent& other)
:
index(other.index),
name(other.name),
componentKind(other.componentKind),
typeKind(other.typeKind)
{
}
bool IsValid() const
{
return componentKind != TYPE_COMPONENT_UNDEFINED;
}
void SetToBaseType(type_kind typeKind, uint64 index = 0,
const BString& name = BString())
{
this->componentKind = TYPE_COMPONENT_BASE_TYPE;
this->typeKind = typeKind;
this->index = index;
this->name = name;
}
void SetToDataMember(type_kind typeKind, uint64 index,
const BString& name)
{
this->componentKind = TYPE_COMPONENT_DATA_MEMBER;
this->typeKind = typeKind;
this->index = index;
this->name = name;
}
void SetToArrayElement(type_kind typeKind, uint64 index)
{
this->componentKind = TYPE_COMPONENT_ARRAY_ELEMENT;
this->typeKind = typeKind;
this->index = index;
this->name = name;
}
uint32 HashValue() const;
TypeComponent& operator=(const TypeComponent& other)
{
index = other.index;
name = other.name;
componentKind = other.componentKind;
typeKind = other.typeKind;
return *this;
}
bool operator==(const TypeComponent& other) const;
bool operator!=(const TypeComponent& other) const
{
return !(*this == other);
}
};
class TypeComponentPath : public Referenceable {
public:
TypeComponentPath();
TypeComponentPath(
const TypeComponentPath& other);
virtual ~TypeComponentPath();
int32 CountComponents() const;
TypeComponent ComponentAt(int32 index) const;
bool AddComponent(const TypeComponent& component);
void Clear();
uint32 HashValue() const;
TypeComponentPath& operator=(const TypeComponentPath& other);
bool operator==(const TypeComponentPath& other) const;
bool operator!=(const TypeComponentPath& other) const
{ return !(*this == other); }
private:
typedef BObjectList<TypeComponent> ComponentList;
private:
ComponentList fComponents;
};
#endif // TYPE_COMPONENT_PATH_H
+6 -1
View File
@@ -6,16 +6,20 @@
#include "Variable.h" #include "Variable.h"
#include "ObjectID.h"
#include "Type.h" #include "Type.h"
#include "ValueLocation.h" #include "ValueLocation.h"
Variable::Variable(const BString& name, Type* type, ValueLocation* location) Variable::Variable(ObjectID* id, const BString& name, Type* type,
ValueLocation* location)
: :
fID(id),
fName(name), fName(name),
fType(type), fType(type),
fLocation(location) fLocation(location)
{ {
fID->AcquireReference();
fType->AcquireReference(); fType->AcquireReference();
fLocation->AcquireReference(); fLocation->AcquireReference();
} }
@@ -23,6 +27,7 @@ Variable::Variable(const BString& name, Type* type, ValueLocation* location)
Variable::~Variable() Variable::~Variable()
{ {
fID->ReleaseReference();
fType->ReleaseReference(); fType->ReleaseReference();
fLocation->ReleaseReference(); fLocation->ReleaseReference();
} }
+5 -2
View File
@@ -11,21 +11,24 @@
#include <Referenceable.h> #include <Referenceable.h>
class ObjectID;
class Type; class Type;
class ValueLocation; class ValueLocation;
class Variable : public Referenceable { class Variable : public Referenceable {
public: public:
Variable(const BString& name, Type* type, Variable(ObjectID* id, const BString& name,
ValueLocation* location); Type* type, ValueLocation* location);
~Variable(); ~Variable();
ObjectID* ID() const { return fID; }
const BString& Name() const { return fName; } const BString& Name() const { return fName; }
Type* GetType() const { return fType; } Type* GetType() const { return fType; }
ValueLocation* Location() const { return fLocation; } ValueLocation* Location() const { return fLocation; }
private: private:
ObjectID* fID;
BString fName; BString fName;
Type* fType; Type* fType;
ValueLocation* fLocation; ValueLocation* fLocation;