* 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:
@@ -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
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-31
@@ -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 {
|
||||||
|
public:
|
||||||
|
virtual ~JobKey();
|
||||||
|
|
||||||
|
virtual uint32 HashValue() const = 0;
|
||||||
|
|
||||||
|
virtual bool operator==(const JobKey& other) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct SimpleJobKey : public JobKey {
|
||||||
void* object;
|
void* object;
|
||||||
uint32 type;
|
uint32 type;
|
||||||
|
|
||||||
JobKey(void* object, uint32 type)
|
public:
|
||||||
:
|
SimpleJobKey(void* object, uint32 type);
|
||||||
object(object),
|
SimpleJobKey(const SimpleJobKey& other);
|
||||||
type(type)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
JobKey(const JobKey& other)
|
virtual uint32 HashValue() const;
|
||||||
:
|
|
||||||
object(other.object),
|
|
||||||
type(other.type)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
JobKey& operator=(const JobKey& other)
|
virtual bool operator==(const JobKey& other) const;
|
||||||
{
|
|
||||||
object = other.object;
|
|
||||||
type = other.type;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const JobKey& other) const
|
SimpleJobKey& operator=(const SimpleJobKey& other);
|
||||||
{
|
|
||||||
return object == other.object && type == other.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t HashValue() const
|
|
||||||
{
|
|
||||||
return (size_t)(addr_t)object ^ (size_t)type;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -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()
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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:
|
||||||
|
Thread* fThread;
|
||||||
StackFrame* fStackFrame;
|
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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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,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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user