* More work on retrieving local variable values. Address and compound types can
now be inspected. Still work in progress -- bit fields and arrays don't work correctly yet nor does type lookup beyond the current compilation unit. * Made most of the debugger output configurable via a config header. By default it's much less noisy now. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33217 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,44 @@
|
|||||||
|
#ifndef APPS_DEBUGGER_CONFIG_H
|
||||||
|
#define APPS_DEBUGGER_CONFIG_H
|
||||||
|
|
||||||
|
|
||||||
|
// trace DWARF debug info entry parsing
|
||||||
|
#define APPS_DEBUGGER_TRACE_DWARF_DIE 0
|
||||||
|
|
||||||
|
// trace DWARF line info:
|
||||||
|
// 1: general info only
|
||||||
|
// 2: line number program execution
|
||||||
|
#define APPS_DEBUGGER_TRACE_DWARF_LINE_INFO 0
|
||||||
|
|
||||||
|
// trace DWARF expression evaluation
|
||||||
|
#define APPS_DEBUGGER_TRACE_DWARF_EXPRESSIONS 0
|
||||||
|
|
||||||
|
// dump DWARF public types section
|
||||||
|
#define APPS_DEBUGGER_TRACE_DWARF_PUBLIC_TYPES 0
|
||||||
|
|
||||||
|
// trace (DWARF) canonical frame info parsing/evaluation
|
||||||
|
#define APPS_DEBUGGER_TRACE_CFI 0
|
||||||
|
|
||||||
|
// trace retrieving of stack frame local variable types and values
|
||||||
|
#define APPS_DEBUGGER_TRACE_STACK_FRAME_LOCALS 0
|
||||||
|
|
||||||
|
// trace image loading and changes
|
||||||
|
#define APPS_DEBUGGER_TRACE_IMAGES 0
|
||||||
|
|
||||||
|
// trace program code reading/analyzing
|
||||||
|
#define APPS_DEBUGGER_TRACE_CODE 0
|
||||||
|
|
||||||
|
// trace general job handling
|
||||||
|
#define APPS_DEBUGGER_TRACE_JOBS 0
|
||||||
|
|
||||||
|
// trace debug events
|
||||||
|
#define APPS_DEBUGGER_TRACE_DEBUG_EVENTS 0
|
||||||
|
|
||||||
|
// trace controlling the debugged team (stepping, breakpoints,...)
|
||||||
|
#define APPS_DEBUGGER_TRACE_TEAM_CONTROL 0
|
||||||
|
|
||||||
|
// trace GUI operations
|
||||||
|
#define APPS_DEBUGGER_TRACE_GUI 0
|
||||||
|
|
||||||
|
|
||||||
|
#endif // APPS_DEBUGGER_CONFIG_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "SpecificImageDebugInfo.h"
|
#include "SpecificImageDebugInfo.h"
|
||||||
#include "Statement.h"
|
#include "Statement.h"
|
||||||
#include "Team.h"
|
#include "Team.h"
|
||||||
|
#include "Tracing.h"
|
||||||
|
|
||||||
|
|
||||||
BreakpointManager::BreakpointManager(Team* team,
|
BreakpointManager::BreakpointManager(Team* team,
|
||||||
@@ -44,36 +45,41 @@ status_t
|
|||||||
BreakpointManager::InstallUserBreakpoint(UserBreakpoint* userBreakpoint,
|
BreakpointManager::InstallUserBreakpoint(UserBreakpoint* userBreakpoint,
|
||||||
bool enabled)
|
bool enabled)
|
||||||
{
|
{
|
||||||
printf("BreakpointManager::InstallUserBreakpoint(%p, %d)\n", userBreakpoint, enabled);
|
TRACE_CONTROL("BreakpointManager::InstallUserBreakpoint(%p, %d)\n",
|
||||||
|
userBreakpoint, enabled);
|
||||||
|
|
||||||
AutoLocker<BLocker> installLocker(fLock);
|
AutoLocker<BLocker> installLocker(fLock);
|
||||||
AutoLocker<Team> teamLocker(fTeam);
|
AutoLocker<Team> teamLocker(fTeam);
|
||||||
|
|
||||||
bool oldEnabled = userBreakpoint->IsEnabled();
|
bool oldEnabled = userBreakpoint->IsEnabled();
|
||||||
if (userBreakpoint->IsValid() && enabled == oldEnabled)
|
if (userBreakpoint->IsValid() && enabled == oldEnabled) {
|
||||||
{
|
TRACE_CONTROL(" user breakpoint already valid and with same enabled "
|
||||||
printf(" user breakpoint already valid and with same enabled state\n");
|
"state\n");
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get/create the breakpoints for all instances
|
// get/create the breakpoints for all instances
|
||||||
printf(" creating breakpoints for breakpoint instances\n");
|
TRACE_CONTROL(" creating breakpoints for breakpoint instances\n");
|
||||||
|
|
||||||
status_t error = B_OK;
|
status_t error = B_OK;
|
||||||
for (int32 i = 0;
|
for (int32 i = 0;
|
||||||
UserBreakpointInstance* instance = userBreakpoint->InstanceAt(i); i++) {
|
UserBreakpointInstance* instance = userBreakpoint->InstanceAt(i); i++) {
|
||||||
printf(" breakpoint instance %p\n", instance);
|
|
||||||
if (instance->GetBreakpoint() != NULL)
|
TRACE_CONTROL(" breakpoint instance %p\n", instance);
|
||||||
{
|
|
||||||
printf(" -> already has breakpoint\n");
|
if (instance->GetBreakpoint() != NULL) {
|
||||||
|
TRACE_CONTROL(" -> already has breakpoint\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
target_addr_t address = instance->Address();
|
target_addr_t address = instance->Address();
|
||||||
Breakpoint* breakpoint = fTeam->BreakpointAtAddress(address);
|
Breakpoint* breakpoint = fTeam->BreakpointAtAddress(address);
|
||||||
if (breakpoint == NULL) {
|
if (breakpoint == NULL) {
|
||||||
printf(" -> no breakpoint at that address yet\n");
|
TRACE_CONTROL(" -> no breakpoint at that address yet\n");
|
||||||
|
|
||||||
Image* image = fTeam->ImageByAddress(address);
|
Image* image = fTeam->ImageByAddress(address);
|
||||||
if (image == NULL) {
|
if (image == NULL) {
|
||||||
printf(" -> no image at that address\n");
|
TRACE_CONTROL(" -> no image at that address\n");
|
||||||
error = B_BAD_ADDRESS;
|
error = B_BAD_ADDRESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -86,7 +92,8 @@ printf(" -> no image at that address\n");
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" -> adding instance to breakpoint %p\n", breakpoint);
|
TRACE_CONTROL(" -> adding instance to breakpoint %p\n", breakpoint);
|
||||||
|
|
||||||
breakpoint->AddUserBreakpoint(instance);
|
breakpoint->AddUserBreakpoint(instance);
|
||||||
instance->SetBreakpoint(breakpoint);
|
instance->SetBreakpoint(breakpoint);
|
||||||
}
|
}
|
||||||
@@ -108,12 +115,14 @@ printf(" -> adding instance to breakpoint %p\n", breakpoint);
|
|||||||
teamLocker.Unlock();
|
teamLocker.Unlock();
|
||||||
|
|
||||||
// install/uninstall the breakpoints as needed
|
// install/uninstall the breakpoints as needed
|
||||||
printf(" updating breakpoints\n");
|
TRACE_CONTROL(" updating breakpoints\n");
|
||||||
|
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
for (int32 i = 0;
|
for (int32 i = 0;
|
||||||
UserBreakpointInstance* instance = userBreakpoint->InstanceAt(i);
|
UserBreakpointInstance* instance = userBreakpoint->InstanceAt(i);
|
||||||
i++) {
|
i++) {
|
||||||
printf(" breakpoint instance %p\n", instance);
|
TRACE_CONTROL(" breakpoint instance %p\n", instance);
|
||||||
|
|
||||||
error = _UpdateBreakpointInstallation(instance->GetBreakpoint());
|
error = _UpdateBreakpointInstallation(instance->GetBreakpoint());
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
break;
|
break;
|
||||||
@@ -121,7 +130,8 @@ printf(" breakpoint instance %p\n", instance);
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
printf(" success, marking user breakpoint valid\n");
|
TRACE_CONTROL(" success, marking user breakpoint valid\n");
|
||||||
|
|
||||||
// everything went fine -- mark the user breakpoint valid
|
// everything went fine -- mark the user breakpoint valid
|
||||||
if (!userBreakpoint->IsValid()) {
|
if (!userBreakpoint->IsValid()) {
|
||||||
teamLocker.Lock();
|
teamLocker.Lock();
|
||||||
@@ -132,7 +142,8 @@ printf(" success, marking user breakpoint valid\n");
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// something went wrong -- revert the situation
|
// something went wrong -- revert the situation
|
||||||
printf(" error, reverting\n");
|
TRACE_CONTROL(" error, reverting\n");
|
||||||
|
|
||||||
teamLocker.Lock();
|
teamLocker.Lock();
|
||||||
userBreakpoint->SetEnabled(oldEnabled);
|
userBreakpoint->SetEnabled(oldEnabled);
|
||||||
teamLocker.Unlock();
|
teamLocker.Unlock();
|
||||||
@@ -471,7 +482,11 @@ status_t
|
|||||||
BreakpointManager::_UpdateBreakpointInstallation(Breakpoint* breakpoint)
|
BreakpointManager::_UpdateBreakpointInstallation(Breakpoint* breakpoint)
|
||||||
{
|
{
|
||||||
bool shouldBeInstalled = breakpoint->ShouldBeInstalled();
|
bool shouldBeInstalled = breakpoint->ShouldBeInstalled();
|
||||||
printf("BreakpointManager::_UpdateBreakpointInstallation(%p): should be installed: %d, is installed: %d\n", breakpoint, shouldBeInstalled, breakpoint->IsInstalled());
|
|
||||||
|
TRACE_CONTROL("BreakpointManager::_UpdateBreakpointInstallation(%p): "
|
||||||
|
"should be installed: %d, is installed: %d\n", breakpoint,
|
||||||
|
shouldBeInstalled, breakpoint->IsInstalled());
|
||||||
|
|
||||||
if (shouldBeInstalled == breakpoint->IsInstalled())
|
if (shouldBeInstalled == breakpoint->IsInstalled())
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
@@ -481,12 +496,18 @@ printf("BreakpointManager::_UpdateBreakpointInstallation(%p): should be installe
|
|||||||
breakpoint->Address());
|
breakpoint->Address());
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
printf("BREAKPOINT at %#llx installed: %s\n", breakpoint->Address(), strerror(error));
|
|
||||||
|
TRACE_CONTROL("BREAKPOINT at %#llx installed: %s\n",
|
||||||
|
breakpoint->Address(), strerror(error));
|
||||||
|
|
||||||
breakpoint->SetInstalled(true);
|
breakpoint->SetInstalled(true);
|
||||||
} else {
|
} else {
|
||||||
// uninstall
|
// uninstall
|
||||||
fDebuggerInterface->UninstallBreakpoint(breakpoint->Address());
|
fDebuggerInterface->UninstallBreakpoint(breakpoint->Address());
|
||||||
printf("BREAKPOINT at %#llx uninstalled\n", breakpoint->Address());
|
|
||||||
|
TRACE_CONTROL("BREAKPOINT at %#llx uninstalled\n",
|
||||||
|
breakpoint->Address());
|
||||||
|
|
||||||
breakpoint->SetInstalled(false);
|
breakpoint->SetInstalled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ SubDirHdrs [ FDirName $(debugAnalyzerSources) gui ] ;
|
|||||||
SourceHdrs
|
SourceHdrs
|
||||||
DwarfFunctionDebugInfo.cpp
|
DwarfFunctionDebugInfo.cpp
|
||||||
DwarfImageDebugInfo.cpp
|
DwarfImageDebugInfo.cpp
|
||||||
|
DwarfStackFrameDebugInfo.cpp
|
||||||
DwarfTeamDebugInfo.cpp
|
DwarfTeamDebugInfo.cpp
|
||||||
DwarfInterfaceFactory.cpp
|
|
||||||
: [ FDirName $(SUBDIR) dwarf ]
|
: [ FDirName $(SUBDIR) dwarf ]
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -60,15 +60,17 @@ Application Debugger :
|
|||||||
DebuggerTeamDebugInfo.cpp
|
DebuggerTeamDebugInfo.cpp
|
||||||
DwarfFunctionDebugInfo.cpp
|
DwarfFunctionDebugInfo.cpp
|
||||||
DwarfImageDebugInfo.cpp
|
DwarfImageDebugInfo.cpp
|
||||||
|
DwarfStackFrameDebugInfo.cpp
|
||||||
DwarfTeamDebugInfo.cpp
|
DwarfTeamDebugInfo.cpp
|
||||||
DwarfInterfaceFactory.cpp
|
|
||||||
Function.cpp
|
Function.cpp
|
||||||
FunctionDebugInfo.cpp
|
FunctionDebugInfo.cpp
|
||||||
FunctionInstance.cpp
|
FunctionInstance.cpp
|
||||||
ImageDebugInfo.cpp
|
ImageDebugInfo.cpp
|
||||||
ImageDebugInfoProvider.cpp
|
ImageDebugInfoProvider.cpp
|
||||||
|
NoOpStackFrameDebugInfo.cpp
|
||||||
SpecificImageDebugInfo.cpp
|
SpecificImageDebugInfo.cpp
|
||||||
SpecificTeamDebugInfo.cpp
|
SpecificTeamDebugInfo.cpp
|
||||||
|
StackFrameDebugInfo.cpp
|
||||||
TeamDebugInfo.cpp
|
TeamDebugInfo.cpp
|
||||||
|
|
||||||
# debugger_interface
|
# debugger_interface
|
||||||
@@ -110,6 +112,7 @@ Application Debugger :
|
|||||||
SourceCode.cpp
|
SourceCode.cpp
|
||||||
StackFrame.cpp
|
StackFrame.cpp
|
||||||
StackFrameValues.cpp
|
StackFrameValues.cpp
|
||||||
|
StackFrameValueInfos.cpp
|
||||||
StackTrace.cpp
|
StackTrace.cpp
|
||||||
Statement.cpp
|
Statement.cpp
|
||||||
SymbolInfo.cpp
|
SymbolInfo.cpp
|
||||||
|
|||||||
+332
-72
@@ -5,8 +5,6 @@
|
|||||||
|
|
||||||
#include "Jobs.h"
|
#include "Jobs.h"
|
||||||
|
|
||||||
#include <new>
|
|
||||||
|
|
||||||
#include <AutoLocker.h>
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
#include "Architecture.h"
|
#include "Architecture.h"
|
||||||
@@ -21,11 +19,14 @@
|
|||||||
#include "Register.h"
|
#include "Register.h"
|
||||||
#include "SourceCode.h"
|
#include "SourceCode.h"
|
||||||
#include "SpecificImageDebugInfo.h"
|
#include "SpecificImageDebugInfo.h"
|
||||||
|
#include "StackFrameDebugInfo.h"
|
||||||
|
#include "StackFrameValueInfos.h"
|
||||||
#include "StackFrameValues.h"
|
#include "StackFrameValues.h"
|
||||||
#include "StackTrace.h"
|
#include "StackTrace.h"
|
||||||
#include "Team.h"
|
#include "Team.h"
|
||||||
#include "TeamDebugInfo.h"
|
#include "TeamDebugInfo.h"
|
||||||
#include "Thread.h"
|
#include "Thread.h"
|
||||||
|
#include "Tracing.h"
|
||||||
#include "Type.h"
|
#include "Type.h"
|
||||||
#include "TypeComponentPath.h"
|
#include "TypeComponentPath.h"
|
||||||
#include "ValueLocation.h"
|
#include "ValueLocation.h"
|
||||||
@@ -495,77 +496,110 @@ GetStackFrameValueJob::Do()
|
|||||||
status_t
|
status_t
|
||||||
GetStackFrameValueJob::_GetValue()
|
GetStackFrameValueJob::_GetValue()
|
||||||
{
|
{
|
||||||
printf("GetStackFrameValueJob::_GetValue()\n");
|
TRACE_LOCALS_ONLY(
|
||||||
if (fPath->CountComponents() > 0)
|
TRACE_LOCALS("GetStackFrameValueJob::_GetValue(): %s ",
|
||||||
{
|
fVariable->Name().String());
|
||||||
printf(" -> non-empty path\n");
|
fPath->Dump();
|
||||||
return B_UNSUPPORTED;
|
TRACE_LOCALS("\n");
|
||||||
// TODO: Implement!
|
)
|
||||||
}
|
|
||||||
|
Type* type;
|
||||||
|
ValueLocation* location;
|
||||||
|
bool valueResolved;
|
||||||
|
status_t error = _ResolveTypeAndLocation(type, location, valueResolved);
|
||||||
|
if (error != B_OK || valueResolved) {
|
||||||
|
TRACE_LOCALS(" -> error: %#lx, valueResolved: %d\n", error,
|
||||||
|
valueResolved);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
Type* actualType = type;
|
||||||
|
Reference<Type> typeReference(type);
|
||||||
|
Reference<Type> actualTypeReference(actualType);
|
||||||
|
Reference<ValueLocation> locationReference(location);
|
||||||
|
|
||||||
// find out the type of the data we want to read
|
// find out the type of the data we want to read
|
||||||
Type* type = fVariable->GetType();
|
|
||||||
type_code valueType = 0;
|
type_code valueType = 0;
|
||||||
while (valueType == 0) {
|
while (valueType == 0) {
|
||||||
switch (type->Kind()) {
|
switch (type->Kind()) {
|
||||||
case TYPE_PRIMITIVE:
|
case TYPE_PRIMITIVE:
|
||||||
valueType = dynamic_cast<PrimitiveType*>(type)->TypeConstant();
|
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));
|
TRACE_LOCALS(" TYPE_PRIMITIVE: '%c%c%c%c'\n",
|
||||||
if (valueType == 0)
|
int(valueType >> 24), int(valueType >> 16),
|
||||||
{
|
int(valueType >> 8), int(valueType));
|
||||||
printf(" -> unknown type constant\n");
|
|
||||||
|
if (valueType == 0) {
|
||||||
|
TRACE_LOCALS(" -> unknown type constant\n");
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TYPE_MODIFIED:
|
case TYPE_MODIFIED:
|
||||||
printf(" TYPE_MODIFIED\n");
|
TRACE_LOCALS(" TYPE_MODIFIED\n");
|
||||||
// ignore modifiers
|
// ignore modifiers
|
||||||
type = dynamic_cast<ModifiedType*>(type)->BaseType();
|
type = dynamic_cast<ModifiedType*>(type)->BaseType();
|
||||||
break;
|
break;
|
||||||
case TYPE_TYPEDEF:
|
case TYPE_TYPEDEF:
|
||||||
printf(" TYPE_TYPEDEF\n");
|
TRACE_LOCALS(" TYPE_TYPEDEF\n");
|
||||||
type = dynamic_cast<TypedefType*>(type)->BaseType();
|
type = dynamic_cast<TypedefType*>(type)->BaseType();
|
||||||
break;
|
break;
|
||||||
case TYPE_ADDRESS:
|
case TYPE_ADDRESS:
|
||||||
printf(" TYPE_ADDRESS\n");
|
TRACE_LOCALS(" TYPE_ADDRESS\n");
|
||||||
if (fArchitecture->AddressSize() == 4)
|
if (fArchitecture->AddressSize() == 4) {
|
||||||
{
|
|
||||||
valueType = B_UINT32_TYPE;
|
valueType = B_UINT32_TYPE;
|
||||||
printf(" -> 32 bit\n");
|
TRACE_LOCALS(" -> 32 bit\n");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
valueType = B_UINT64_TYPE;
|
valueType = B_UINT64_TYPE;
|
||||||
printf(" -> 64 bit\n");
|
TRACE_LOCALS(" -> 64 bit\n");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TYPE_COMPOUND:
|
case TYPE_COMPOUND:
|
||||||
case TYPE_ARRAY:
|
case TYPE_ARRAY:
|
||||||
|
TRACE_LOCALS(" TYPE_COMPOUND/TYPE_ARRAY\n");
|
||||||
|
// We can't retrieve the actual value of the compound object/
|
||||||
|
// array (just of its components/elements), but to make the
|
||||||
|
// recursion work smoothly, we have to set the type and
|
||||||
|
// location at least.
|
||||||
|
return _SetValue(BVariant(), actualType, location);
|
||||||
default:
|
default:
|
||||||
printf(" TYPE_COMPOUND/TYPE_ARRAY/default\n");
|
TRACE_LOCALS(" default -> unsupported\n");
|
||||||
// TODO:...
|
|
||||||
printf(" -> unsupported\n");
|
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valueType == B_STRING_TYPE)
|
// update the reference in case the type has changed
|
||||||
{
|
typeReference.SetTo(type);
|
||||||
printf(" -> B_STRING_TYPE: unsupported\n");
|
|
||||||
|
if (valueType == B_STRING_TYPE) {
|
||||||
|
TRACE_LOCALS(" -> B_STRING_TYPE: unsupported\n");
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
// TODO:...
|
// TODO:...
|
||||||
}
|
}
|
||||||
|
|
||||||
// check whether we know the complete location
|
// check whether we know the complete location
|
||||||
ValueLocation* location = fVariable->Location();
|
|
||||||
int32 count = location->CountPieces();
|
int32 count = location->CountPieces();
|
||||||
printf(" location: %p, %ld pieces\n", location, count);
|
|
||||||
if (count == 0)
|
TRACE_LOCALS(" location: %p, %ld pieces\n", location, count);
|
||||||
{
|
|
||||||
printf(" -> no location\n");
|
if (count == 0) {
|
||||||
|
TRACE_LOCALS(" -> no location\n");
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the source language implementation uses descriptors to point to
|
||||||
|
// objects, we need to resolve the object address to the data address.
|
||||||
|
if (count == 1) {
|
||||||
|
ValuePieceLocation piece = location->PieceAt(0);
|
||||||
|
if (piece.type == VALUE_PIECE_LOCATION_MEMORY) {
|
||||||
|
ValueLocation* dataLocation;
|
||||||
|
error = fStackFrame->DebugInfo()->ResolveObjectDataLocation(
|
||||||
|
fStackFrame, type, piece.address, dataLocation);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
location = dataLocation;
|
||||||
|
locationReference.SetTo(location, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
target_size_t totalSize = 0;
|
target_size_t totalSize = 0;
|
||||||
uint64 totalBitSize = 0;
|
uint64 totalBitSize = 0;
|
||||||
@@ -583,26 +617,26 @@ printf(" -> no location\n");
|
|||||||
totalSize += piece.size;
|
totalSize += piece.size;
|
||||||
totalBitSize += piece.bitSize;
|
totalBitSize += piece.bitSize;
|
||||||
}
|
}
|
||||||
printf(" -> totalSize: %llu, totalBitSize: %llu\n", totalSize, totalBitSize);
|
|
||||||
|
|
||||||
if (totalSize == 0 && totalBitSize == 0)
|
TRACE_LOCALS(" -> totalSize: %llu, totalBitSize: %llu\n", totalSize,
|
||||||
{
|
totalBitSize);
|
||||||
printf(" -> no size\n");
|
|
||||||
|
if (totalSize == 0 && totalBitSize == 0) {
|
||||||
|
TRACE_LOCALS(" -> no size\n");
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalSize > 8 || totalSize + (totalBitSize + 7) / 8 > 8)
|
if (totalSize > 8 || totalSize + (totalBitSize + 7) / 8 > 8) {
|
||||||
{
|
TRACE_LOCALS(" -> longer than 8 bytes: unsupported\n");
|
||||||
printf(" -> longer than 8 bytes: unsupported\n");
|
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalSize + (totalBitSize + 7) / 8 < BVariant::SizeOfType(valueType))
|
if (totalSize + (totalBitSize + 7) / 8 < BVariant::SizeOfType(valueType)) {
|
||||||
{
|
TRACE_LOCALS(" -> too short for value type (%llu vs. %lu)\n",
|
||||||
printf(" -> too short for value type (%llu vs. %lu)\n",
|
totalSize + (totalBitSize + 7) / 8,
|
||||||
totalSize + (totalBitSize + 7) / 8, BVariant::SizeOfType(valueType));
|
BVariant::SizeOfType(valueType));
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// load the data
|
// load the data
|
||||||
BitBuffer valueBuffer;
|
BitBuffer valueBuffer;
|
||||||
@@ -630,7 +664,10 @@ totalSize + (totalBitSize + 7) / 8, BVariant::SizeOfType(valueType));
|
|||||||
case VALUE_PIECE_LOCATION_MEMORY:
|
case VALUE_PIECE_LOCATION_MEMORY:
|
||||||
{
|
{
|
||||||
target_addr_t address = piece.address + bitOffset / 8;
|
target_addr_t address = piece.address + bitOffset / 8;
|
||||||
printf(" piece %ld: memory address: %#llx, bits: %lu\n", i, address, bitSize);
|
|
||||||
|
TRACE_LOCALS(" piece %ld: memory address: %#llx, bits: %lu\n",
|
||||||
|
i, address, bitSize);
|
||||||
|
|
||||||
bitOffset %= 8;
|
bitOffset %= 8;
|
||||||
uint8 pieceBuffer[8];
|
uint8 pieceBuffer[8];
|
||||||
ssize_t bytesRead = fDebuggerInterface->ReadMemory(address,
|
ssize_t bytesRead = fDebuggerInterface->ReadMemory(address,
|
||||||
@@ -639,17 +676,22 @@ printf(" piece %ld: memory address: %#llx, bits: %lu\n", i, address, bitSize);
|
|||||||
return bytesRead;
|
return bytesRead;
|
||||||
if ((uint32)bytesRead != bytesToRead)
|
if ((uint32)bytesRead != bytesToRead)
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
printf(" -> read: ");
|
|
||||||
for (ssize_t k = 0; k < bytesRead; k++)
|
TRACE_LOCALS_ONLY(
|
||||||
printf("%02x", pieceBuffer[k]);
|
TRACE_LOCALS(" -> read: ");
|
||||||
printf("\n");
|
for (ssize_t k = 0; k < bytesRead; k++)
|
||||||
|
TRACE_LOCALS("%02x", pieceBuffer[k]);
|
||||||
|
TRACE_LOCALS("\n");
|
||||||
|
)
|
||||||
|
|
||||||
valueBuffer.AddBits(pieceBuffer, bitSize, bitOffset);
|
valueBuffer.AddBits(pieceBuffer, bitSize, bitOffset);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VALUE_PIECE_LOCATION_REGISTER:
|
case VALUE_PIECE_LOCATION_REGISTER:
|
||||||
{
|
{
|
||||||
printf(" piece %ld: register: %lu, bits: %lu\n", i, piece.reg, bitSize);
|
TRACE_LOCALS(" piece %ld: register: %lu, bits: %lu\n", i,
|
||||||
|
piece.reg, bitSize);
|
||||||
|
|
||||||
BVariant registerValue;
|
BVariant registerValue;
|
||||||
if (!fStackFrame->GetCpuState()->GetRegisterValue(
|
if (!fStackFrame->GetCpuState()->GetRegisterValue(
|
||||||
registers + piece.reg, registerValue)) {
|
registers + piece.reg, registerValue)) {
|
||||||
@@ -675,28 +717,246 @@ printf(" piece %ld: register: %lu, bits: %lu\n", i, piece.reg, bitSize);
|
|||||||
|
|
||||||
// convert the bits into something we can work with
|
// convert the bits into something we can work with
|
||||||
BVariant value;
|
BVariant value;
|
||||||
status_t error = value.SetToTypedData(valueBuffer.Bytes(), valueType);
|
error = value.SetToTypedData(valueBuffer.Bytes(), valueType);
|
||||||
if (error != B_OK)
|
if (error != B_OK) {
|
||||||
{
|
TRACE_LOCALS(" -> failed to set typed data: %s\n", strerror(error));
|
||||||
printf(" -> failed to set typed data: %s\n", strerror(error));
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fArchitecture->IsHostEndian())
|
if (!fArchitecture->IsHostEndian())
|
||||||
value.SwapEndianess();
|
value.SwapEndianess();
|
||||||
|
|
||||||
|
return _SetValue(value, actualType, location);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
GetStackFrameValueJob::_SetValue(const BVariant& value, Type* type,
|
||||||
|
ValueLocation* location)
|
||||||
|
{
|
||||||
// set the value
|
// set the value
|
||||||
AutoLocker<Team> locker(fThread->GetTeam());
|
AutoLocker<Team> locker(fThread->GetTeam());
|
||||||
|
|
||||||
StackFrameValues* values = fStackFrame->Values();
|
status_t error = fStackFrame->Values()->SetValue(fVariable->ID(), fPath,
|
||||||
|
value);
|
||||||
error = values->SetValue(fVariable->ID(), fPath, value);
|
if (error != B_OK) {
|
||||||
if (error != B_OK)
|
TRACE_LOCALS(" -> failed to set value: %s\n", strerror(error));
|
||||||
{
|
|
||||||
printf(" -> failed to set value: %s\n", strerror(error));
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fStackFrame->ValueInfos()->SetInfo(fVariable->ID(), fPath, type, location);
|
||||||
|
|
||||||
fStackFrame->NotifyValueRetrieved(fVariable, fPath);
|
fStackFrame->NotifyValueRetrieved(fVariable, fPath);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
GetStackFrameValueJob::_ResolveTypeAndLocation(Type*& _type,
|
||||||
|
ValueLocation*& _location, bool& _valueResolved)
|
||||||
|
{
|
||||||
|
if (fPath->CountComponents() == 0) {
|
||||||
|
fVariable->GetType()->AcquireReference();
|
||||||
|
fVariable->Location()->AcquireReference();
|
||||||
|
_type = fVariable->GetType();
|
||||||
|
_location = fVariable->Location();
|
||||||
|
_valueResolved = false;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the parent value
|
||||||
|
int32 componentCount = fPath->CountComponents();
|
||||||
|
TypeComponentPath* parentPath = fPath->CreateSubPath(componentCount - 1);
|
||||||
|
if (parentPath == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
Reference<TypeComponentPath> parentPathReference(parentPath, true);
|
||||||
|
|
||||||
|
Type* parentType;
|
||||||
|
ValueLocation* parentLocation;
|
||||||
|
BVariant parentValue;
|
||||||
|
status_t error = _GetTypeLocationAndValue(parentPath, parentType,
|
||||||
|
parentLocation, parentValue);
|
||||||
|
if (error != B_OK) {
|
||||||
|
TRACE_LOCALS("GetStackFrameValueJob::_ResolveTypeAndLocation(): "
|
||||||
|
"_GetTypeLocationAndValue() failed: %s\n", strerror(error));
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
Reference<Type> parentTypeReference(parentType, true);
|
||||||
|
Reference<ValueLocation> parentLocationReference(parentLocation, true);
|
||||||
|
|
||||||
|
// resolve the last component
|
||||||
|
TypeComponent component = fPath->ComponentAt(componentCount - 1);
|
||||||
|
switch (component.typeKind) {
|
||||||
|
case TYPE_PRIMITIVE:
|
||||||
|
// cannot happen
|
||||||
|
TRACE_LOCALS("GetStackFrameValueJob::_ResolveTypeAndLocation(): "
|
||||||
|
"TYPE_PRIMITIVE subcomponent!\n");
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
case TYPE_COMPOUND:
|
||||||
|
{
|
||||||
|
CompoundType* compoundType
|
||||||
|
= dynamic_cast<CompoundType*>(parentType);
|
||||||
|
|
||||||
|
// base type
|
||||||
|
if (component.componentKind == TYPE_COMPONENT_BASE_TYPE) {
|
||||||
|
BaseType* baseType = compoundType->BaseTypeAt(
|
||||||
|
component.index);
|
||||||
|
if (baseType == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// The parent's location refers to the location of the complete
|
||||||
|
// object. We want to extract the location of a member.
|
||||||
|
ValueLocation* location;
|
||||||
|
error = fStackFrame->DebugInfo()->ResolveBaseTypeLocation(
|
||||||
|
fStackFrame, parentType, baseType, *parentLocation,
|
||||||
|
location);
|
||||||
|
if (error != B_OK) {
|
||||||
|
TRACE_LOCALS("GetStackFrameValueJob::"
|
||||||
|
"_ResolveTypeAndLocation(): TYPE_COMPOUND: "
|
||||||
|
"ResolveBaseTypeLocation() failed: %s\n",
|
||||||
|
strerror(error));
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
baseType->GetType()->AcquireReference();
|
||||||
|
_type = baseType->GetType();
|
||||||
|
_location = location;
|
||||||
|
_valueResolved = false;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// data member
|
||||||
|
if (component.componentKind == TYPE_COMPONENT_DATA_MEMBER) {
|
||||||
|
DataMember* dataMember = compoundType->DataMemberAt(
|
||||||
|
component.index);
|
||||||
|
if (dataMember == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// The parent's location refers to the location of the complete
|
||||||
|
// object. We want to extract the location of a member.
|
||||||
|
ValueLocation* location;
|
||||||
|
error = fStackFrame->DebugInfo()->ResolveDataMemberLocation(
|
||||||
|
fStackFrame, parentType, dataMember, *parentLocation,
|
||||||
|
location);
|
||||||
|
if (error != B_OK) {
|
||||||
|
TRACE_LOCALS("GetStackFrameValueJob::"
|
||||||
|
"_ResolveTypeAndLocation(): TYPE_COMPOUND: "
|
||||||
|
"ResolveDataMemberLocation() failed: %s\n",
|
||||||
|
strerror(error));
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataMember->GetType()->AcquireReference();
|
||||||
|
_type = dataMember->GetType();
|
||||||
|
_location = location;
|
||||||
|
_valueResolved = false;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
case TYPE_MODIFIED:
|
||||||
|
case TYPE_TYPEDEF:
|
||||||
|
{
|
||||||
|
Type* type = component.typeKind == TYPE_MODIFIED
|
||||||
|
? dynamic_cast<ModifiedType*>(parentType)->BaseType()
|
||||||
|
: dynamic_cast<TypedefType*>(parentType)->BaseType();
|
||||||
|
_valueResolved = true;
|
||||||
|
return _SetValue(parentValue, type, parentLocation);
|
||||||
|
}
|
||||||
|
case TYPE_ADDRESS:
|
||||||
|
{
|
||||||
|
// The parent's value is an address pointing to this component.
|
||||||
|
// resolve the location
|
||||||
|
Type* type = dynamic_cast<AddressType*>(parentType)->BaseType();
|
||||||
|
ValueLocation* location;
|
||||||
|
error = fStackFrame->DebugInfo()->ResolveObjectDataLocation(
|
||||||
|
fStackFrame, type, parentValue.ToUInt64(), location);
|
||||||
|
if (error != B_OK) {
|
||||||
|
TRACE_LOCALS("GetStackFrameValueJob::"
|
||||||
|
"_ResolveTypeAndLocation(): TYPE_ADDRESS: "
|
||||||
|
"ResolveObjectDataLocation() failed: %s\n",
|
||||||
|
strerror(error));
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
type->AcquireReference();
|
||||||
|
_type = type;
|
||||||
|
_location = location;
|
||||||
|
_valueResolved = false;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
case TYPE_ARRAY:
|
||||||
|
// TODO:...
|
||||||
|
default:
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
GetStackFrameValueJob::_GetTypeLocationAndValue(TypeComponentPath* parentPath,
|
||||||
|
Type*& _parentType, ValueLocation*& _parentLocation, BVariant& _parentValue)
|
||||||
|
{
|
||||||
|
AutoLocker<Team> teamLocker(fThread->GetTeam());
|
||||||
|
|
||||||
|
// If there's already a value for the parent path, we're done.
|
||||||
|
StackFrameValues* values = fStackFrame->Values();
|
||||||
|
StackFrameValueInfos* valueInfos = fStackFrame->ValueInfos();
|
||||||
|
if (values->HasValue(fVariable->ID(), parentPath)) {
|
||||||
|
if (!values->GetValue(fVariable->ID(), parentPath, _parentValue)
|
||||||
|
|| !valueInfos->GetInfo(fVariable->ID(), parentPath, &_parentType,
|
||||||
|
&_parentLocation)) {
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check whether a job is already in progress
|
||||||
|
AutoLocker<Worker> workerLocker(GetWorker());
|
||||||
|
GetStackFrameValueJobKey jobKey(fStackFrame, fVariable, parentPath);
|
||||||
|
if (GetWorker()->GetJob(jobKey) == NULL) {
|
||||||
|
workerLocker.Unlock();
|
||||||
|
|
||||||
|
// schedule the job
|
||||||
|
status_t error = GetWorker()->ScheduleJob(
|
||||||
|
new(std::nothrow) GetStackFrameValueJob(fDebuggerInterface,
|
||||||
|
fArchitecture, fThread, fStackFrame, fVariable, parentPath));
|
||||||
|
if (error != B_OK) {
|
||||||
|
// scheduling failed -- set the value to invalid
|
||||||
|
values->SetValue(fVariable->ID(), parentPath, BVariant());
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for the job to finish
|
||||||
|
workerLocker.Unlock();
|
||||||
|
teamLocker.Unlock();
|
||||||
|
|
||||||
|
switch (WaitFor(jobKey)) {
|
||||||
|
case JOB_DEPENDENCY_SUCCEEDED:
|
||||||
|
case JOB_DEPENDENCY_NOT_FOUND:
|
||||||
|
// "Not found" can happen due to a race condition between
|
||||||
|
// unlocking the worker and starting to wait.
|
||||||
|
break;
|
||||||
|
case JOB_DEPENDENCY_FAILED:
|
||||||
|
case JOB_DEPENDENCY_ABORTED:
|
||||||
|
default:
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
teamLocker.Lock();
|
||||||
|
|
||||||
|
// now there should be a value for the path
|
||||||
|
if (!values->GetValue(fVariable->ID(), parentPath, _parentValue)
|
||||||
|
|| !valueInfos->GetInfo(fVariable->ID(), parentPath, &_parentType,
|
||||||
|
&_parentLocation)) {
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
|
|
||||||
class Architecture;
|
class Architecture;
|
||||||
|
class BVariant;
|
||||||
class CpuState;
|
class CpuState;
|
||||||
class DebuggerInterface;
|
class DebuggerInterface;
|
||||||
class Function;
|
class Function;
|
||||||
@@ -20,7 +21,9 @@ class StackFrame;
|
|||||||
class StackFrameValues;
|
class StackFrameValues;
|
||||||
class Team;
|
class Team;
|
||||||
class Thread;
|
class Thread;
|
||||||
|
class Type;
|
||||||
class TypeComponentPath;
|
class TypeComponentPath;
|
||||||
|
class ValueLocation;
|
||||||
class Variable;
|
class Variable;
|
||||||
|
|
||||||
|
|
||||||
@@ -176,6 +179,18 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _GetValue();
|
status_t _GetValue();
|
||||||
|
status_t _SetValue(const BVariant& value, Type* type,
|
||||||
|
ValueLocation* location);
|
||||||
|
status_t _ResolveTypeAndLocation(Type*& _type,
|
||||||
|
ValueLocation*& _location,
|
||||||
|
bool& _valueResolved);
|
||||||
|
// returns references
|
||||||
|
status_t _GetTypeLocationAndValue(
|
||||||
|
TypeComponentPath* parentPath,
|
||||||
|
Type*& _parentType,
|
||||||
|
ValueLocation*& _parentLocation,
|
||||||
|
BVariant& _parentValue);
|
||||||
|
// returns references
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GetStackFrameValueJobKey fKey;
|
GetStackFrameValueJobKey fKey;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
#include "SymbolInfo.h"
|
#include "SymbolInfo.h"
|
||||||
#include "TeamDebugInfo.h"
|
#include "TeamDebugInfo.h"
|
||||||
#include "TeamSettings.h"
|
#include "TeamSettings.h"
|
||||||
|
#include "Tracing.h"
|
||||||
#include "Variable.h"
|
#include "Variable.h"
|
||||||
|
|
||||||
// #pragma mark - ImageHandler
|
// #pragma mark - ImageHandler
|
||||||
@@ -360,7 +361,7 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
|
|||||||
fTeamWindow = TeamWindow::Create(fTeam, this);
|
fTeamWindow = TeamWindow::Create(fTeam, this);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// TODO: Notify the user!
|
// TODO: Notify the user!
|
||||||
fprintf(stderr, "Error: Failed to create team window!\n");
|
ERROR("Error: Failed to create team window!\n");
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -645,21 +646,21 @@ TeamDebugger::TeamWindowQuitRequested()
|
|||||||
void
|
void
|
||||||
TeamDebugger::JobDone(Job* job)
|
TeamDebugger::JobDone(Job* job)
|
||||||
{
|
{
|
||||||
printf("TeamDebugger::JobDone(%p)\n", job);
|
TRACE_JOBS("TeamDebugger::JobDone(%p)\n", job);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TeamDebugger::JobFailed(Job* job)
|
TeamDebugger::JobFailed(Job* job)
|
||||||
{
|
{
|
||||||
printf("TeamDebugger::JobFailed(%p)\n", job);
|
TRACE_JOBS("TeamDebugger::JobFailed(%p)\n", job);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TeamDebugger::JobAborted(Job* job)
|
TeamDebugger::JobAborted(Job* job)
|
||||||
{
|
{
|
||||||
printf("TeamDebugger::JobAborted(%p)\n", job);
|
TRACE_JOBS("TeamDebugger::JobAborted(%p)\n", job);
|
||||||
// TODO: For a stack frame source loader thread we should reset the
|
// TODO: For a stack frame source loader thread we should reset the
|
||||||
// loading state! Asynchronously due to locking order.
|
// loading state! Asynchronously due to locking order.
|
||||||
}
|
}
|
||||||
@@ -721,8 +722,8 @@ TeamDebugger::_DebugEventListener()
|
|||||||
|
|
||||||
|
|
||||||
if (event->Team() != fTeamID) {
|
if (event->Team() != fTeamID) {
|
||||||
printf("TeamDebugger for team %ld: received event from team %ld!\n", fTeamID,
|
TRACE_EVENTS("TeamDebugger for team %ld: received event from team "
|
||||||
event->Team());
|
"%ld!\n", fTeamID, event->Team());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -741,7 +742,9 @@ event->Team());
|
|||||||
void
|
void
|
||||||
TeamDebugger::_HandleDebuggerMessage(DebugEvent* event)
|
TeamDebugger::_HandleDebuggerMessage(DebugEvent* event)
|
||||||
{
|
{
|
||||||
printf("TeamDebugger::_HandleDebuggerMessage(): %d\n", event->EventType());
|
TRACE_EVENTS("TeamDebugger::_HandleDebuggerMessage(): %d\n",
|
||||||
|
event->EventType());
|
||||||
|
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
|
|
||||||
ThreadHandler* handler = _GetThreadHandler(event->Thread());
|
ThreadHandler* handler = _GetThreadHandler(event->Thread());
|
||||||
@@ -749,42 +752,54 @@ printf("TeamDebugger::_HandleDebuggerMessage(): %d\n", event->EventType());
|
|||||||
|
|
||||||
switch (event->EventType()) {
|
switch (event->EventType()) {
|
||||||
case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED:
|
case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED:
|
||||||
printf("B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: thread: %ld\n", event->Thread());
|
TRACE_EVENTS("B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: thread: %ld\n",
|
||||||
|
event->Thread());
|
||||||
|
|
||||||
if (handler != NULL) {
|
if (handler != NULL) {
|
||||||
handled = handler->HandleThreadDebugged(
|
handled = handler->HandleThreadDebugged(
|
||||||
dynamic_cast<ThreadDebuggedEvent*>(event));
|
dynamic_cast<ThreadDebuggedEvent*>(event));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case B_DEBUGGER_MESSAGE_DEBUGGER_CALL:
|
case B_DEBUGGER_MESSAGE_DEBUGGER_CALL:
|
||||||
printf("B_DEBUGGER_MESSAGE_DEBUGGER_CALL: thread: %ld\n", event->Thread());
|
TRACE_EVENTS("B_DEBUGGER_MESSAGE_DEBUGGER_CALL: thread: %ld\n",
|
||||||
|
event->Thread());
|
||||||
|
|
||||||
if (handler != NULL) {
|
if (handler != NULL) {
|
||||||
handled = handler->HandleDebuggerCall(
|
handled = handler->HandleDebuggerCall(
|
||||||
dynamic_cast<DebuggerCallEvent*>(event));
|
dynamic_cast<DebuggerCallEvent*>(event));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT:
|
case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT:
|
||||||
printf("B_DEBUGGER_MESSAGE_BREAKPOINT_HIT: thread: %ld\n", event->Thread());
|
TRACE_EVENTS("B_DEBUGGER_MESSAGE_BREAKPOINT_HIT: thread: %ld\n",
|
||||||
|
event->Thread());
|
||||||
|
|
||||||
if (handler != NULL) {
|
if (handler != NULL) {
|
||||||
handled = handler->HandleBreakpointHit(
|
handled = handler->HandleBreakpointHit(
|
||||||
dynamic_cast<BreakpointHitEvent*>(event));
|
dynamic_cast<BreakpointHitEvent*>(event));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT:
|
case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT:
|
||||||
printf("B_DEBUGGER_MESSAGE_WATCHPOINT_HIT: thread: %ld\n", event->Thread());
|
TRACE_EVENTS("B_DEBUGGER_MESSAGE_WATCHPOINT_HIT: thread: %ld\n",
|
||||||
|
event->Thread());
|
||||||
|
|
||||||
if (handler != NULL) {
|
if (handler != NULL) {
|
||||||
handled = handler->HandleWatchpointHit(
|
handled = handler->HandleWatchpointHit(
|
||||||
dynamic_cast<WatchpointHitEvent*>(event));
|
dynamic_cast<WatchpointHitEvent*>(event));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case B_DEBUGGER_MESSAGE_SINGLE_STEP:
|
case B_DEBUGGER_MESSAGE_SINGLE_STEP:
|
||||||
printf("B_DEBUGGER_MESSAGE_SINGLE_STEP: thread: %ld\n", event->Thread());
|
TRACE_EVENTS("B_DEBUGGER_MESSAGE_SINGLE_STEP: thread: %ld\n",
|
||||||
|
event->Thread());
|
||||||
|
|
||||||
if (handler != NULL) {
|
if (handler != NULL) {
|
||||||
handled = handler->HandleSingleStep(
|
handled = handler->HandleSingleStep(
|
||||||
dynamic_cast<SingleStepEvent*>(event));
|
dynamic_cast<SingleStepEvent*>(event));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED:
|
case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED:
|
||||||
printf("B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: thread: %ld\n", event->Thread());
|
TRACE_EVENTS("B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: thread: %ld\n",
|
||||||
|
event->Thread());
|
||||||
|
|
||||||
if (handler != NULL) {
|
if (handler != NULL) {
|
||||||
handled = handler->HandleExceptionOccurred(
|
handled = handler->HandleExceptionOccurred(
|
||||||
dynamic_cast<ExceptionOccurredEvent*>(event));
|
dynamic_cast<ExceptionOccurredEvent*>(event));
|
||||||
@@ -795,10 +810,12 @@ printf("B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: thread: %ld\n", event->Thread());
|
|||||||
// break;
|
// break;
|
||||||
case B_DEBUGGER_MESSAGE_TEAM_DELETED:
|
case B_DEBUGGER_MESSAGE_TEAM_DELETED:
|
||||||
// TODO: Handle!
|
// TODO: Handle!
|
||||||
printf("B_DEBUGGER_MESSAGE_TEAM_DELETED: team: %ld\n", event->Team());
|
TRACE_EVENTS("B_DEBUGGER_MESSAGE_TEAM_DELETED: team: %ld\n",
|
||||||
|
event->Team());
|
||||||
break;
|
break;
|
||||||
case B_DEBUGGER_MESSAGE_TEAM_EXEC:
|
case B_DEBUGGER_MESSAGE_TEAM_EXEC:
|
||||||
printf("B_DEBUGGER_MESSAGE_TEAM_EXEC: team: %ld\n", event->Team());
|
TRACE_EVENTS("B_DEBUGGER_MESSAGE_TEAM_EXEC: team: %ld\n",
|
||||||
|
event->Team());
|
||||||
// TODO: Handle!
|
// TODO: Handle!
|
||||||
break;
|
break;
|
||||||
case B_DEBUGGER_MESSAGE_THREAD_CREATED:
|
case B_DEBUGGER_MESSAGE_THREAD_CREATED:
|
||||||
@@ -825,7 +842,7 @@ printf("B_DEBUGGER_MESSAGE_TEAM_EXEC: team: %ld\n", event->Team());
|
|||||||
// not interested
|
// not interested
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("TeamDebugger for team %ld: unknown event type: "
|
WARNING("TeamDebugger for team %ld: unknown event type: "
|
||||||
"%d\n", fTeamID, event->EventType());
|
"%d\n", fTeamID, event->EventType());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -926,7 +943,7 @@ TeamDebugger::_HandleImageDebugInfoChanged(image_id imageID)
|
|||||||
void
|
void
|
||||||
TeamDebugger::_HandleImageFileChanged(image_id imageID)
|
TeamDebugger::_HandleImageFileChanged(image_id imageID)
|
||||||
{
|
{
|
||||||
printf("TeamDebugger::_HandleImageFileChanged(%ld)\n", imageID);
|
TRACE_IMAGES("TeamDebugger::_HandleImageFileChanged(%ld)\n", imageID);
|
||||||
// TODO: Reload the debug info!
|
// TODO: Reload the debug info!
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -934,7 +951,9 @@ printf("TeamDebugger::_HandleImageFileChanged(%ld)\n", imageID);
|
|||||||
void
|
void
|
||||||
TeamDebugger::_HandleSetUserBreakpoint(target_addr_t address, bool enabled)
|
TeamDebugger::_HandleSetUserBreakpoint(target_addr_t address, bool enabled)
|
||||||
{
|
{
|
||||||
printf("TeamDebugger::_HandleSetUserBreakpoint(%#llx, %d)\n", address, enabled);
|
TRACE_CONTROL("TeamDebugger::_HandleSetUserBreakpoint(%#llx, %d)\n",
|
||||||
|
address, enabled);
|
||||||
|
|
||||||
// check whether there already is a breakpoint
|
// check whether there already is a breakpoint
|
||||||
AutoLocker< ::Team> locker(fTeam);
|
AutoLocker< ::Team> locker(fTeam);
|
||||||
|
|
||||||
@@ -945,24 +964,32 @@ printf("TeamDebugger::_HandleSetUserBreakpoint(%#llx, %d)\n", address, enabled);
|
|||||||
Reference<UserBreakpoint> userBreakpointReference(userBreakpoint);
|
Reference<UserBreakpoint> userBreakpointReference(userBreakpoint);
|
||||||
|
|
||||||
if (userBreakpoint == NULL) {
|
if (userBreakpoint == NULL) {
|
||||||
printf(" no breakpoint yet\n");
|
TRACE_CONTROL(" no breakpoint yet\n");
|
||||||
|
|
||||||
// get the function at the address
|
// get the function at the address
|
||||||
Image* image = fTeam->ImageByAddress(address);
|
Image* image = fTeam->ImageByAddress(address);
|
||||||
printf(" image: %p\n", image);
|
|
||||||
|
TRACE_CONTROL(" image: %p\n", image);
|
||||||
|
|
||||||
if (image == NULL)
|
if (image == NULL)
|
||||||
return;
|
return;
|
||||||
ImageDebugInfo* imageDebugInfo = image->GetImageDebugInfo();
|
ImageDebugInfo* imageDebugInfo = image->GetImageDebugInfo();
|
||||||
printf(" image debug info: %p\n", imageDebugInfo);
|
|
||||||
|
TRACE_CONTROL(" image debug info: %p\n", imageDebugInfo);
|
||||||
|
|
||||||
if (imageDebugInfo == NULL)
|
if (imageDebugInfo == NULL)
|
||||||
return;
|
return;
|
||||||
// TODO: Handle this case by loading the debug info, if possible!
|
// TODO: Handle this case by loading the debug info, if possible!
|
||||||
FunctionInstance* functionInstance
|
FunctionInstance* functionInstance
|
||||||
= imageDebugInfo->FunctionAtAddress(address);
|
= imageDebugInfo->FunctionAtAddress(address);
|
||||||
printf(" function instance: %p\n", functionInstance);
|
|
||||||
|
TRACE_CONTROL(" function instance: %p\n", functionInstance);
|
||||||
|
|
||||||
if (functionInstance == NULL)
|
if (functionInstance == NULL)
|
||||||
return;
|
return;
|
||||||
Function* function = functionInstance->GetFunction();
|
Function* function = functionInstance->GetFunction();
|
||||||
printf(" function: %p\n", function);
|
|
||||||
|
TRACE_CONTROL(" function: %p\n", function);
|
||||||
|
|
||||||
// get the source location for the address
|
// get the source location for the address
|
||||||
FunctionDebugInfo* functionDebugInfo
|
FunctionDebugInfo* functionDebugInfo
|
||||||
@@ -978,7 +1005,10 @@ printf(" function: %p\n", function);
|
|||||||
breakpointStatement->ReleaseReference();
|
breakpointStatement->ReleaseReference();
|
||||||
|
|
||||||
target_addr_t relativeAddress = address - functionInstance->Address();
|
target_addr_t relativeAddress = address - functionInstance->Address();
|
||||||
printf(" relative address: %#llx, source location: (%ld, %ld)\n", relativeAddress, sourceLocation.Line(), sourceLocation.Column());
|
|
||||||
|
TRACE_CONTROL(" relative address: %#llx, source location: "
|
||||||
|
"(%ld, %ld)\n", relativeAddress, sourceLocation.Line(),
|
||||||
|
sourceLocation.Column());
|
||||||
|
|
||||||
// get function id
|
// get function id
|
||||||
FunctionID* functionID = functionInstance->GetFunctionID();
|
FunctionID* functionID = functionInstance->GetFunctionID();
|
||||||
@@ -993,14 +1023,18 @@ printf(" relative address: %#llx, source location: (%ld, %ld)\n", relativeAddre
|
|||||||
if (userBreakpoint == NULL)
|
if (userBreakpoint == NULL)
|
||||||
return;
|
return;
|
||||||
userBreakpointReference.SetTo(userBreakpoint, true);
|
userBreakpointReference.SetTo(userBreakpoint, true);
|
||||||
printf(" created user breakpoint: %p\n", userBreakpoint);
|
|
||||||
|
TRACE_CONTROL(" created user breakpoint: %p\n", userBreakpoint);
|
||||||
|
|
||||||
// iterate through all function instances and create
|
// iterate through all function instances and create
|
||||||
// UserBreakpointInstances
|
// UserBreakpointInstances
|
||||||
for (FunctionInstanceList::ConstIterator it
|
for (FunctionInstanceList::ConstIterator it
|
||||||
= function->Instances().GetIterator();
|
= function->Instances().GetIterator();
|
||||||
FunctionInstance* instance = it.Next();) {
|
FunctionInstance* instance = it.Next();) {
|
||||||
printf(" function instance %p: range: %#llx - %#llx\n", instance, instance->Address(), instance->Address() + instance->Size());
|
TRACE_CONTROL(" function instance %p: range: %#llx - %#llx\n",
|
||||||
|
instance, instance->Address(),
|
||||||
|
instance->Address() + instance->Size());
|
||||||
|
|
||||||
// get the breakpoint address for the instance
|
// get the breakpoint address for the instance
|
||||||
target_addr_t instanceAddress = 0;
|
target_addr_t instanceAddress = 0;
|
||||||
if (instance == functionInstance) {
|
if (instance == functionInstance) {
|
||||||
@@ -1019,7 +1053,9 @@ printf(" function instance %p: range: %#llx - %#llx\n", instance, instance->Add
|
|||||||
statement->ReleaseReference();
|
statement->ReleaseReference();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf(" breakpoint address using source info: %llx\n", instanceAddress);
|
|
||||||
|
TRACE_CONTROL(" breakpoint address using source info: %llx\n",
|
||||||
|
instanceAddress);
|
||||||
|
|
||||||
if (instanceAddress == 0) {
|
if (instanceAddress == 0) {
|
||||||
// No source file (or we failed getting the statement), so try
|
// No source file (or we failed getting the statement), so try
|
||||||
@@ -1028,7 +1064,9 @@ printf(" breakpoint address using source info: %llx\n", instanceAddress);
|
|||||||
continue;
|
continue;
|
||||||
instanceAddress = instance->Address() + relativeAddress;
|
instanceAddress = instance->Address() + relativeAddress;
|
||||||
}
|
}
|
||||||
printf(" final breakpoint address: %llx\n", instanceAddress);
|
|
||||||
|
TRACE_CONTROL(" final breakpoint address: %llx\n",
|
||||||
|
instanceAddress);
|
||||||
|
|
||||||
UserBreakpointInstance* breakpointInstance = new(std::nothrow)
|
UserBreakpointInstance* breakpointInstance = new(std::nothrow)
|
||||||
UserBreakpointInstance(userBreakpoint, instanceAddress);
|
UserBreakpointInstance(userBreakpoint, instanceAddress);
|
||||||
@@ -1037,7 +1075,8 @@ printf(" final breakpoint address: %llx\n", instanceAddress);
|
|||||||
delete breakpointInstance;
|
delete breakpointInstance;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
printf(" breakpoint instance: %p\n", breakpointInstance);
|
|
||||||
|
TRACE_CONTROL(" breakpoint instance: %p\n", breakpointInstance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1055,7 +1094,7 @@ printf(" breakpoint instance: %p\n", breakpointInstance);
|
|||||||
void
|
void
|
||||||
TeamDebugger::_HandleClearUserBreakpoint(target_addr_t address)
|
TeamDebugger::_HandleClearUserBreakpoint(target_addr_t address)
|
||||||
{
|
{
|
||||||
printf("TeamDebugger::_HandleClearUserBreakpoint(%#llx)\n", address);
|
TRACE_CONTROL("TeamDebugger::_HandleClearUserBreakpoint(%#llx)\n", address);
|
||||||
|
|
||||||
AutoLocker< ::Team> locker(fTeam);
|
AutoLocker< ::Team> locker(fTeam);
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "StackTrace.h"
|
#include "StackTrace.h"
|
||||||
#include "Statement.h"
|
#include "Statement.h"
|
||||||
#include "Team.h"
|
#include "Team.h"
|
||||||
|
#include "Tracing.h"
|
||||||
#include "Worker.h"
|
#include "Worker.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -108,7 +109,9 @@ ThreadHandler::HandleBreakpointHit(BreakpointHitEvent* event)
|
|||||||
{
|
{
|
||||||
CpuState* cpuState = event->GetCpuState();
|
CpuState* cpuState = event->GetCpuState();
|
||||||
target_addr_t instructionPointer = cpuState->InstructionPointer();
|
target_addr_t instructionPointer = cpuState->InstructionPointer();
|
||||||
printf("ThreadHandler::HandleBreakpointHit(): ip: %llx\n", instructionPointer);
|
|
||||||
|
TRACE_EVENTS("ThreadHandler::HandleBreakpointHit(): ip: %llx\n",
|
||||||
|
instructionPointer);
|
||||||
|
|
||||||
// check whether this is a temporary breakpoint we're waiting for
|
// check whether this is a temporary breakpoint we're waiting for
|
||||||
if (fBreakpointAddress != 0 && instructionPointer == fBreakpointAddress
|
if (fBreakpointAddress != 0 && instructionPointer == fBreakpointAddress
|
||||||
@@ -225,7 +228,8 @@ ThreadHandler::HandleThreadAction(uint32 action)
|
|||||||
case MSG_THREAD_STEP_OUT:
|
case MSG_THREAD_STEP_OUT:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf("ThreadHandler::HandleThreadAction(MSG_THREAD_STEP_*)\n");
|
|
||||||
|
TRACE_CONTROL("ThreadHandler::HandleThreadAction(MSG_THREAD_STEP_*)\n");
|
||||||
|
|
||||||
// We want to step. We need a stack trace for that purpose. If we don't
|
// We want to step. We need a stack trace for that purpose. If we don't
|
||||||
// have one yet, get it. Start with the CPU state.
|
// have one yet, get it. Start with the CPU state.
|
||||||
@@ -247,7 +251,8 @@ printf("ThreadHandler::HandleThreadAction(MSG_THREAD_STEP_*)\n");
|
|||||||
}
|
}
|
||||||
|
|
||||||
StackFrame* frame = stackTrace->FrameAt(0);
|
StackFrame* frame = stackTrace->FrameAt(0);
|
||||||
printf(" ip: %#llx\n", frame->InstructionPointer());
|
|
||||||
|
TRACE_CONTROL(" ip: %#llx\n", frame->InstructionPointer());
|
||||||
|
|
||||||
// When the thread is in a syscall, do the same for all step kinds: Stop it
|
// When the thread is in a syscall, do the same for all step kinds: Stop it
|
||||||
// when it return by means of a breakpoint.
|
// when it return by means of a breakpoint.
|
||||||
@@ -290,8 +295,10 @@ printf(" ip: %#llx\n", frame->InstructionPointer());
|
|||||||
_StepFallback();
|
_StepFallback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
printf(" statement: %#llx - %#llx\n", fStepStatement->CoveringAddressRange().Start(),
|
|
||||||
fStepStatement->CoveringAddressRange().End());
|
TRACE_CONTROL(" statement: %#llx - %#llx\n",
|
||||||
|
fStepStatement->CoveringAddressRange().Start(),
|
||||||
|
fStepStatement->CoveringAddressRange().End());
|
||||||
|
|
||||||
if (action == MSG_THREAD_STEP_INTO) {
|
if (action == MSG_THREAD_STEP_INTO) {
|
||||||
// step into
|
// step into
|
||||||
@@ -430,7 +437,8 @@ ThreadHandler::_StepFallback()
|
|||||||
bool
|
bool
|
||||||
ThreadHandler::_DoStepOver(CpuState* cpuState)
|
ThreadHandler::_DoStepOver(CpuState* cpuState)
|
||||||
{
|
{
|
||||||
printf("ThreadHandler::_DoStepOver()\n");
|
TRACE_CONTROL("ThreadHandler::_DoStepOver()\n");
|
||||||
|
|
||||||
// The basic strategy is to single-step out of the statement like for
|
// The basic strategy is to single-step out of the statement like for
|
||||||
// "step into", only we have to avoid stepping into subroutines. Hence we
|
// "step into", only we have to avoid stepping into subroutines. Hence we
|
||||||
// check whether the current instruction is a subroutine call. If not, we
|
// check whether the current instruction is a subroutine call. If not, we
|
||||||
@@ -438,18 +446,20 @@ printf("ThreadHandler::_DoStepOver()\n");
|
|||||||
InstructionInfo info;
|
InstructionInfo info;
|
||||||
if (fDebuggerInterface->GetArchitecture()->GetInstructionInfo(
|
if (fDebuggerInterface->GetArchitecture()->GetInstructionInfo(
|
||||||
cpuState->InstructionPointer(), info) != B_OK) {
|
cpuState->InstructionPointer(), info) != B_OK) {
|
||||||
printf(" failed to get instruction info\n");
|
TRACE_CONTROL(" failed to get instruction info\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.Type() != INSTRUCTION_TYPE_SUBROUTINE_CALL) {
|
if (info.Type() != INSTRUCTION_TYPE_SUBROUTINE_CALL) {
|
||||||
_SingleStepThread(cpuState->InstructionPointer());
|
_SingleStepThread(cpuState->InstructionPointer());
|
||||||
printf(" not a subroutine call\n");
|
|
||||||
|
TRACE_CONTROL(" not a subroutine call\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" subroutine call -- installing breakpoint at address %#llx\n",
|
TRACE_CONTROL(" subroutine call -- installing breakpoint at address "
|
||||||
info.Address() + info.Size());
|
"%#llx\n", info.Address() + info.Size());
|
||||||
|
|
||||||
if (_InstallTemporaryBreakpoint(info.Address() + info.Size()) != B_OK)
|
if (_InstallTemporaryBreakpoint(info.Address() + info.Size()) != B_OK)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -548,7 +558,9 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState)
|
|||||||
bool
|
bool
|
||||||
ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
|
ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
|
||||||
{
|
{
|
||||||
printf("ThreadHandler::_HandleSingleStepStep(): ip: %llx\n", cpuState->InstructionPointer());
|
TRACE_CONTROL("ThreadHandler::_HandleSingleStepStep(): ip: %llx\n",
|
||||||
|
cpuState->InstructionPointer());
|
||||||
|
|
||||||
switch (fStepMode) {
|
switch (fStepMode) {
|
||||||
case STEP_INTO:
|
case STEP_INTO:
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef TRACING_H
|
||||||
|
#define TRACING_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "apps_debugger_config.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define WARNING(x...) fprintf(stderr, x)
|
||||||
|
#define ERROR(x...) fprintf(stderr, x)
|
||||||
|
|
||||||
|
|
||||||
|
#if APPS_DEBUGGER_TRACE_DWARF_DIE
|
||||||
|
# define TRACE_DIE(x...) printf(x)
|
||||||
|
# define TRACE_DIE_ONLY(x) x
|
||||||
|
#else
|
||||||
|
# define TRACE_DIE(x...) (void)0
|
||||||
|
# define TRACE_DIE_ONLY(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if APPS_DEBUGGER_TRACE_DWARF_LINE_INFO
|
||||||
|
# define TRACE_LINES(x...) printf(x)
|
||||||
|
# define TRACE_LINES_ONLY(x) x
|
||||||
|
#else
|
||||||
|
# define TRACE_LINES(x...) (void)0
|
||||||
|
# define TRACE_LINES_ONLY(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if APPS_DEBUGGER_TRACE_DWARF_LINE_INFO >= 2
|
||||||
|
# define TRACE_LINES2(x...) printf(x)
|
||||||
|
# define TRACE_LINES2_ONLY(x) x
|
||||||
|
#else
|
||||||
|
# define TRACE_LINES2(x...) (void)0
|
||||||
|
# define TRACE_LINES2_ONLY(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if APPS_DEBUGGER_TRACE_DWARF_EXPRESSIONS
|
||||||
|
# define TRACE_EXPR(x...) printf(x)
|
||||||
|
# define TRACE_EXPR_ONLY(x) x
|
||||||
|
#else
|
||||||
|
# define TRACE_EXPR(x...) (void)0
|
||||||
|
# define TRACE_EXPR_ONLY(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if APPS_DEBUGGER_TRACE_DWARF_PUBLIC_TYPES
|
||||||
|
# define TRACE_PUBTYPES(x...) printf(x)
|
||||||
|
# define TRACE_PUBTYPES_ONLY(x) x
|
||||||
|
#else
|
||||||
|
# define TRACE_PUBTYPES(x...) (void)0
|
||||||
|
# define TRACE_PUBTYPES_ONLY(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if APPS_DEBUGGER_TRACE_CFI
|
||||||
|
# define TRACE_CFI(x...) printf(x)
|
||||||
|
# define TRACE_CFI_ONLY(x) x
|
||||||
|
#else
|
||||||
|
# define TRACE_CFI(x...) (void)0
|
||||||
|
# define TRACE_CFI_ONLY(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if APPS_DEBUGGER_TRACE_STACK_FRAME_LOCALS
|
||||||
|
# define TRACE_LOCALS(x...) printf(x)
|
||||||
|
# define TRACE_LOCALS_ONLY(x) x
|
||||||
|
#else
|
||||||
|
# define TRACE_LOCALS(x...) (void)0
|
||||||
|
# define TRACE_LOCALS_ONLY(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if APPS_DEBUGGER_TRACE_IMAGES
|
||||||
|
# define TRACE_IMAGES(x...) printf(x)
|
||||||
|
# define TRACE_IMAGES_ONLY(x) x
|
||||||
|
#else
|
||||||
|
# define TRACE_IMAGES(x...) (void)0
|
||||||
|
# define TRACE_IMAGES_ONLY(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if APPS_DEBUGGER_TRACE_CODE
|
||||||
|
# define TRACE_CODE(x...) printf(x)
|
||||||
|
# define TRACE_CODE_ONLY(x) x
|
||||||
|
#else
|
||||||
|
# define TRACE_CODE(x...) (void)0
|
||||||
|
# define TRACE_CODE_ONLY(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if APPS_DEBUGGER_TRACE_JOBS
|
||||||
|
# define TRACE_JOBS(x...) printf(x)
|
||||||
|
# define TRACE_JOBS_ONLY(x) x
|
||||||
|
#else
|
||||||
|
# define TRACE_JOBS(x...) (void)0
|
||||||
|
# define TRACE_JOBS_ONLY(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if APPS_DEBUGGER_TRACE_DEBUG_EVENTS
|
||||||
|
# define TRACE_EVENTS(x...) printf(x)
|
||||||
|
# define TRACE_EVENTS_ONLY(x) x
|
||||||
|
#else
|
||||||
|
# define TRACE_EVENTS(x...) (void)0
|
||||||
|
# define TRACE_EVENTS_ONLY(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if APPS_DEBUGGER_TRACE_TEAM_CONTROL
|
||||||
|
# define TRACE_CONTROL(x...) printf(x)
|
||||||
|
# define TRACE_CONTROL_ONLY(x) x
|
||||||
|
#else
|
||||||
|
# define TRACE_CONTROL(x...) (void)0
|
||||||
|
# define TRACE_CONTROL_ONLY(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if APPS_DEBUGGER_TRACE_GUI
|
||||||
|
# define TRACE_GUI(x...) printf(x)
|
||||||
|
# define TRACE_GUI_ONLY(x) x
|
||||||
|
#else
|
||||||
|
# define TRACE_GUI(x...) (void)0
|
||||||
|
# define TRACE_GUI_ONLY(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif // TRACING_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "DisassembledCode.h"
|
#include "DisassembledCode.h"
|
||||||
#include "FunctionDebugInfo.h"
|
#include "FunctionDebugInfo.h"
|
||||||
#include "InstructionInfo.h"
|
#include "InstructionInfo.h"
|
||||||
|
#include "NoOpStackFrameDebugInfo.h"
|
||||||
#include "RegisterMap.h"
|
#include "RegisterMap.h"
|
||||||
#include "StackFrame.h"
|
#include "StackFrame.h"
|
||||||
#include "Statement.h"
|
#include "Statement.h"
|
||||||
@@ -320,8 +321,15 @@ ArchitectureX86::CreateStackFrame(Image* image, FunctionDebugInfo* function,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create the stack frame
|
// create the stack frame
|
||||||
|
StackFrameDebugInfo* stackFrameDebugInfo
|
||||||
|
= new(std::nothrow) NoOpStackFrameDebugInfo;
|
||||||
|
if (stackFrameDebugInfo == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
Reference<StackFrameDebugInfo> stackFrameDebugInfoReference(
|
||||||
|
stackFrameDebugInfo, true);
|
||||||
|
|
||||||
StackFrame* frame = new(std::nothrow) StackFrame(frameType, cpuState,
|
StackFrame* frame = new(std::nothrow) StackFrame(frameType, cpuState,
|
||||||
framePointer, eip);
|
framePointer, eip, stackFrameDebugInfo);
|
||||||
if (frame == NULL)
|
if (frame == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
Reference<StackFrame> frameReference(frame, true);
|
Reference<StackFrame> frameReference(frame, true);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#include "Dwarf.h"
|
#include "Dwarf.h"
|
||||||
#include "DwarfFile.h"
|
#include "DwarfFile.h"
|
||||||
#include "DwarfFunctionDebugInfo.h"
|
#include "DwarfFunctionDebugInfo.h"
|
||||||
#include "DwarfInterfaceFactory.h"
|
#include "DwarfStackFrameDebugInfo.h"
|
||||||
#include "DwarfTargetInterface.h"
|
#include "DwarfTargetInterface.h"
|
||||||
#include "DwarfUtils.h"
|
#include "DwarfUtils.h"
|
||||||
#include "ElfFile.h"
|
#include "ElfFile.h"
|
||||||
@@ -42,6 +42,7 @@
|
|||||||
#include "StringUtils.h"
|
#include "StringUtils.h"
|
||||||
#include "TargetAddressRangeList.h"
|
#include "TargetAddressRangeList.h"
|
||||||
#include "TeamMemory.h"
|
#include "TeamMemory.h"
|
||||||
|
#include "Tracing.h"
|
||||||
#include "UnsupportedLanguage.h"
|
#include "UnsupportedLanguage.h"
|
||||||
#include "ValueLocation.h"
|
#include "ValueLocation.h"
|
||||||
#include "Variable.h"
|
#include "Variable.h"
|
||||||
@@ -208,8 +209,8 @@ DwarfImageDebugInfo::Init()
|
|||||||
status_t
|
status_t
|
||||||
DwarfImageDebugInfo::GetFunctions(BObjectList<FunctionDebugInfo>& functions)
|
DwarfImageDebugInfo::GetFunctions(BObjectList<FunctionDebugInfo>& functions)
|
||||||
{
|
{
|
||||||
printf("DwarfImageDebugInfo::GetFunctions()\n");
|
TRACE_IMAGES("DwarfImageDebugInfo::GetFunctions()\n");
|
||||||
printf(" %ld compilation units\n", fFile->CountCompilationUnits());
|
TRACE_IMAGES(" %ld compilation units\n", fFile->CountCompilationUnits());
|
||||||
|
|
||||||
for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i);
|
for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i);
|
||||||
i++) {
|
i++) {
|
||||||
@@ -329,7 +330,9 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
|
|||||||
functionInstance->GetFunctionDebugInfo());
|
functionInstance->GetFunctionDebugInfo());
|
||||||
if (function == NULL)
|
if (function == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
printf("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p\n", function->SubprogramEntry());
|
|
||||||
|
TRACE_CFI("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p\n",
|
||||||
|
function->SubprogramEntry());
|
||||||
|
|
||||||
int32 registerCount = fArchitecture->CountRegisters();
|
int32 registerCount = fArchitecture->CountRegisters();
|
||||||
const Register* registers = fArchitecture->Registers();
|
const Register* registers = fArchitecture->Registers();
|
||||||
@@ -352,10 +355,22 @@ printf("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p\n", function->Sub
|
|||||||
Reference<CpuState> previousCpuStateReference(previousCpuState, true);
|
Reference<CpuState> previousCpuStateReference(previousCpuState, true);
|
||||||
|
|
||||||
// create the target interfaces
|
// create the target interfaces
|
||||||
UnwindTargetInterface inputInterface(registers, registerCount,
|
UnwindTargetInterface* inputInterface
|
||||||
fromDwarfMap, toDwarfMap, cpuState, fArchitecture, fTeamMemory);
|
= new(std::nothrow) UnwindTargetInterface(registers, registerCount,
|
||||||
UnwindTargetInterface outputInterface(registers, registerCount,
|
fromDwarfMap, toDwarfMap, cpuState, fArchitecture, fTeamMemory);
|
||||||
fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture, fTeamMemory);
|
if (inputInterface == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
Reference<UnwindTargetInterface> inputInterfaceReference(inputInterface,
|
||||||
|
true);
|
||||||
|
|
||||||
|
UnwindTargetInterface* outputInterface
|
||||||
|
= new(std::nothrow) UnwindTargetInterface(registers, registerCount,
|
||||||
|
fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture,
|
||||||
|
fTeamMemory);
|
||||||
|
if (outputInterface == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
Reference<UnwindTargetInterface> outputInterfaceReference(outputInterface,
|
||||||
|
true);
|
||||||
|
|
||||||
// do the unwinding
|
// do the unwinding
|
||||||
target_addr_t instructionPointer
|
target_addr_t instructionPointer
|
||||||
@@ -363,23 +378,41 @@ printf("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p\n", function->Sub
|
|||||||
target_addr_t framePointer;
|
target_addr_t framePointer;
|
||||||
CompilationUnit* unit = function->GetCompilationUnit();
|
CompilationUnit* unit = function->GetCompilationUnit();
|
||||||
error = fFile->UnwindCallFrame(unit, function->SubprogramEntry(),
|
error = fFile->UnwindCallFrame(unit, function->SubprogramEntry(),
|
||||||
instructionPointer, &inputInterface, &outputInterface, framePointer);
|
instructionPointer, inputInterface, outputInterface, framePointer);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
printf("unwound registers:\n");
|
TRACE_CFI_ONLY(
|
||||||
for (int32 i = 0; i < registerCount; i++) {
|
TRACE_CFI("unwound registers:\n");
|
||||||
const Register* reg = registers + i;
|
for (int32 i = 0; i < registerCount; i++) {
|
||||||
BVariant value;
|
const Register* reg = registers + i;
|
||||||
if (previousCpuState->GetRegisterValue(reg, value)) {
|
BVariant value;
|
||||||
printf(" %3s: %#lx\n", reg->Name(), value.ToUInt32());
|
if (previousCpuState->GetRegisterValue(reg, value))
|
||||||
} else
|
TRACE_CFI(" %3s: %#lx\n", reg->Name(), value.ToUInt32());
|
||||||
printf(" %3s: undefined\n", reg->Name());
|
else
|
||||||
}
|
TRACE_CFI(" %3s: undefined\n", reg->Name());
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// create the stack frame debug info
|
||||||
|
DIESubprogram* subprogramEntry = function->SubprogramEntry();
|
||||||
|
DwarfStackFrameDebugInfo* stackFrameDebugInfo
|
||||||
|
= new(std::nothrow) DwarfStackFrameDebugInfo(fFile, unit,
|
||||||
|
subprogramEntry, instructionPointer, framePointer, inputInterface,
|
||||||
|
fromDwarfMap);
|
||||||
|
if (stackFrameDebugInfo == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
Reference<DwarfStackFrameDebugInfo> stackFrameDebugInfoReference(
|
||||||
|
stackFrameDebugInfo, true);
|
||||||
|
|
||||||
|
error = stackFrameDebugInfo->Init();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
// create the stack frame
|
// create the stack frame
|
||||||
StackFrame* frame = new(std::nothrow) StackFrame(STACK_FRAME_TYPE_STANDARD,
|
StackFrame* frame = new(std::nothrow) StackFrame(STACK_FRAME_TYPE_STANDARD,
|
||||||
cpuState, framePointer, cpuState->InstructionPointer());
|
cpuState, framePointer, cpuState->InstructionPointer(),
|
||||||
|
stackFrameDebugInfo);
|
||||||
if (frame == NULL)
|
if (frame == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
Reference<StackFrame> frameReference(frame, true);
|
Reference<StackFrame> frameReference(frame, true);
|
||||||
@@ -398,13 +431,6 @@ if (previousCpuState->GetRegisterValue(reg, value)) {
|
|||||||
Reference<FunctionID> functionIDReference(functionID, true);
|
Reference<FunctionID> functionIDReference(functionID, true);
|
||||||
|
|
||||||
// create function parameter objects
|
// create function parameter objects
|
||||||
DIESubprogram* subprogramEntry = function->SubprogramEntry();
|
|
||||||
DwarfInterfaceFactory factory(fFile, unit, subprogramEntry,
|
|
||||||
instructionPointer, framePointer, &inputInterface, fromDwarfMap);
|
|
||||||
error = factory.Init();
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
for (DebugInfoEntryList::ConstIterator it = subprogramEntry->Parameters()
|
for (DebugInfoEntryList::ConstIterator it = subprogramEntry->Parameters()
|
||||||
.GetIterator(); DebugInfoEntry* entry = it.Next();) {
|
.GetIterator(); DebugInfoEntry* entry = it.Next();) {
|
||||||
BString parameterName;
|
BString parameterName;
|
||||||
@@ -415,8 +441,8 @@ if (previousCpuState->GetRegisterValue(reg, value)) {
|
|||||||
DIEFormalParameter* parameterEntry
|
DIEFormalParameter* parameterEntry
|
||||||
= dynamic_cast<DIEFormalParameter*>(entry);
|
= dynamic_cast<DIEFormalParameter*>(entry);
|
||||||
Variable* parameter;
|
Variable* parameter;
|
||||||
if (factory.CreateParameter(functionID, parameterEntry, parameter)
|
if (stackFrameDebugInfo->CreateParameter(functionID, parameterEntry,
|
||||||
!= B_OK) {
|
parameter) != B_OK) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Reference<Variable> parameterReference(parameter, true);
|
Reference<Variable> parameterReference(parameter, true);
|
||||||
@@ -426,8 +452,8 @@ if (previousCpuState->GetRegisterValue(reg, value)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create objects for the local variables
|
// create objects for the local variables
|
||||||
_CreateLocalVariables(unit, frame, functionID, factory, instructionPointer,
|
_CreateLocalVariables(unit, frame, functionID, *stackFrameDebugInfo,
|
||||||
functionInstance->Address() - fRelocationDelta,
|
instructionPointer, functionInstance->Address() - fRelocationDelta,
|
||||||
subprogramEntry->Variables(), subprogramEntry->Blocks());
|
subprogramEntry->Variables(), subprogramEntry->Blocks());
|
||||||
|
|
||||||
_previousFrame = frameReference.Detach();
|
_previousFrame = frameReference.Detach();
|
||||||
@@ -441,15 +467,15 @@ status_t
|
|||||||
DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function,
|
DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function,
|
||||||
target_addr_t address, Statement*& _statement)
|
target_addr_t address, Statement*& _statement)
|
||||||
{
|
{
|
||||||
printf("DwarfImageDebugInfo::GetStatement(function: %p, address: %#llx)\n",
|
TRACE_CODE("DwarfImageDebugInfo::GetStatement(function: %p, address: %#llx)\n",
|
||||||
_function, address);
|
_function, address);
|
||||||
|
|
||||||
DwarfFunctionDebugInfo* function
|
DwarfFunctionDebugInfo* function
|
||||||
= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
|
= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
|
||||||
if (function == NULL)
|
if (function == NULL) {
|
||||||
{
|
TRACE_LINES(" -> no dwarf function\n");
|
||||||
printf(" -> no dwarf function\n");
|
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoLocker<BLocker> locker(fLock);
|
AutoLocker<BLocker> locker(fLock);
|
||||||
|
|
||||||
@@ -457,7 +483,8 @@ printf(" -> no dwarf function\n");
|
|||||||
CompilationUnit* unit = function->GetCompilationUnit();
|
CompilationUnit* unit = function->GetCompilationUnit();
|
||||||
LocatableFile* file = function->SourceFile();
|
LocatableFile* file = function->SourceFile();
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
printf(" -> no source file\n");
|
TRACE_CODE(" -> no source file\n");
|
||||||
|
|
||||||
// no source code -- rather return the assembly statement
|
// no source code -- rather return the assembly statement
|
||||||
return fArchitecture->GetStatement(function, address, _statement);
|
return fArchitecture->GetStatement(function, address, _statement);
|
||||||
}
|
}
|
||||||
@@ -469,11 +496,10 @@ printf(" -> no source file\n");
|
|||||||
// Get the statement by executing the line number program for the
|
// Get the statement by executing the line number program for the
|
||||||
// compilation unit.
|
// compilation unit.
|
||||||
LineNumberProgram& program = unit->GetLineNumberProgram();
|
LineNumberProgram& program = unit->GetLineNumberProgram();
|
||||||
if (!program.IsValid())
|
if (!program.IsValid()) {
|
||||||
{
|
TRACE_CODE(" -> no line number program\n");
|
||||||
printf(" -> no line number program\n");
|
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
// adjust address
|
// adjust address
|
||||||
address -= fRelocationDelta;
|
address -= fRelocationDelta;
|
||||||
@@ -517,7 +543,7 @@ printf(" -> no line number program\n");
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" -> no line number program match\n");
|
TRACE_CODE(" -> no line number program match\n");
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,10 +556,14 @@ DwarfImageDebugInfo::GetStatementAtSourceLocation(FunctionDebugInfo* _function,
|
|||||||
= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
|
= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
|
||||||
if (function == NULL)
|
if (function == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
target_addr_t functionStartAddress = function->Address() - fRelocationDelta;
|
|
||||||
target_addr_t functionEndAddress = functionStartAddress + function->Size();
|
target_addr_t functionStartAddress = function->Address() - fRelocationDelta;
|
||||||
printf("DwarfImageDebugInfo::GetStatementAtSourceLocation(%p, (%ld, %ld)): function range: %#llx - %#llx\n",
|
target_addr_t functionEndAddress = functionStartAddress + function->Size();
|
||||||
function, sourceLocation.Line(), sourceLocation.Column(), functionStartAddress, functionEndAddress);
|
|
||||||
|
TRACE_LINES2("DwarfImageDebugInfo::GetStatementAtSourceLocation(%p, "
|
||||||
|
"(%ld, %ld)): function range: %#llx - %#llx\n", function,
|
||||||
|
sourceLocation.Line(), sourceLocation.Column(),
|
||||||
|
functionStartAddress, functionEndAddress);
|
||||||
|
|
||||||
AutoLocker<BLocker> locker(fLock);
|
AutoLocker<BLocker> locker(fLock);
|
||||||
|
|
||||||
@@ -548,9 +578,6 @@ function, sourceLocation.Line(), sourceLocation.Column(), functionStartAddress,
|
|||||||
// comparison below
|
// comparison below
|
||||||
int32 fileIndex = _GetSourceFileIndex(unit, file);
|
int32 fileIndex = _GetSourceFileIndex(unit, file);
|
||||||
|
|
||||||
// target_addr_t functionStartAddress = function->Address() - fRelocationDelta;
|
|
||||||
// target_addr_t functionEndAddress = functionStartAddress + function->Size();
|
|
||||||
|
|
||||||
// Get the statement by executing the line number program for the
|
// Get the statement by executing the line number program for the
|
||||||
// compilation unit.
|
// compilation unit.
|
||||||
LineNumberProgram& program = unit->GetLineNumberProgram();
|
LineNumberProgram& program = unit->GetLineNumberProgram();
|
||||||
@@ -569,15 +596,20 @@ function, sourceLocation.Line(), sourceLocation.Column(), functionStartAddress,
|
|||||||
if (statementAddress != 0
|
if (statementAddress != 0
|
||||||
&& (!isOurFile || state.isStatement || state.isSequenceEnd)) {
|
&& (!isOurFile || state.isStatement || state.isSequenceEnd)) {
|
||||||
target_addr_t endAddress = state.address;
|
target_addr_t endAddress = state.address;
|
||||||
if (statementAddress < endAddress) {
|
|
||||||
printf(" statement: %#llx - %#llx, location: (%ld, %ld)\n", statementAddress, endAddress, statementLine, statementColumn);
|
if (statementAddress < endAddress) {
|
||||||
}
|
TRACE_LINES2(" statement: %#llx - %#llx, location: "
|
||||||
|
"(%ld, %ld)\n", statementAddress, endAddress, statementLine,
|
||||||
|
statementColumn);
|
||||||
|
}
|
||||||
|
|
||||||
if (statementAddress < endAddress
|
if (statementAddress < endAddress
|
||||||
&& statementAddress >= functionStartAddress
|
&& statementAddress >= functionStartAddress
|
||||||
&& statementAddress < functionEndAddress
|
&& statementAddress < functionEndAddress
|
||||||
&& statementLine == (int32)sourceLocation.Line()
|
&& statementLine == (int32)sourceLocation.Line()
|
||||||
&& statementColumn == (int32)sourceLocation.Column()) {
|
&& statementColumn == (int32)sourceLocation.Column()) {
|
||||||
printf(" -> found statement!\n");
|
TRACE_LINES2(" -> found statement!\n");
|
||||||
|
|
||||||
ContiguousStatement* statement = new(std::nothrow)
|
ContiguousStatement* statement = new(std::nothrow)
|
||||||
ContiguousStatement(
|
ContiguousStatement(
|
||||||
SourceLocation(statementLine, statementColumn),
|
SourceLocation(statementLine, statementColumn),
|
||||||
@@ -690,7 +722,9 @@ DwarfImageDebugInfo::_AddSourceCodeInfo(CompilationUnit* unit,
|
|||||||
int32 statementLine = -1;
|
int32 statementLine = -1;
|
||||||
int32 statementColumn = -1;
|
int32 statementColumn = -1;
|
||||||
while (program.GetNextRow(state)) {
|
while (program.GetNextRow(state)) {
|
||||||
printf(" %#llx (%ld, %ld, %ld) %d\n", state.address, state.file, state.line, state.column, state.isStatement);
|
TRACE_LINES2(" %#llx (%ld, %ld, %ld) %d\n", state.address,
|
||||||
|
state.file, state.line, state.column, state.isStatement);
|
||||||
|
|
||||||
bool isOurFile = state.file == fileIndex;
|
bool isOurFile = state.file == fileIndex;
|
||||||
|
|
||||||
if (statementAddress != 0
|
if (statementAddress != 0
|
||||||
@@ -702,7 +736,10 @@ printf(" %#llx (%ld, %ld, %ld) %d\n", state.address, state.file, state.line,
|
|||||||
SourceLocation(statementLine, statementColumn));
|
SourceLocation(statementLine, statementColumn));
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
printf(" -> statement: %#llx - %#llx, source location: (%ld, %ld)\n", statementAddress, endAddress, statementLine, statementColumn);
|
|
||||||
|
TRACE_LINES2(" -> statement: %#llx - %#llx, source location: "
|
||||||
|
"(%ld, %ld)\n", statementAddress, endAddress, statementLine,
|
||||||
|
statementColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
statementAddress = 0;
|
statementAddress = 0;
|
||||||
@@ -747,18 +784,22 @@ DwarfImageDebugInfo::_GetSourceFileIndex(CompilationUnit* unit,
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit,
|
DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit,
|
||||||
StackFrame* frame, FunctionID* functionID, DwarfInterfaceFactory& factory,
|
StackFrame* frame, FunctionID* functionID,
|
||||||
target_addr_t instructionPointer, target_addr_t lowPC,
|
DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer,
|
||||||
const EntryListWrapper& variableEntries,
|
target_addr_t lowPC, const EntryListWrapper& variableEntries,
|
||||||
const EntryListWrapper& blockEntries)
|
const EntryListWrapper& blockEntries)
|
||||||
{
|
{
|
||||||
printf("DwarfImageDebugInfo::_CreateLocalVariables(): ip: %#llx, low PC: %#llx\n",
|
TRACE_LOCALS("DwarfImageDebugInfo::_CreateLocalVariables(): ip: %#llx, "
|
||||||
instructionPointer, lowPC);
|
"low PC: %#llx\n", instructionPointer, lowPC);
|
||||||
|
|
||||||
// iterate through the variables and add the ones in scope
|
// iterate through the variables and add the ones in scope
|
||||||
for (DebugInfoEntryList::ConstIterator it
|
for (DebugInfoEntryList::ConstIterator it
|
||||||
= variableEntries.list.GetIterator();
|
= variableEntries.list.GetIterator();
|
||||||
DIEVariable* variableEntry = dynamic_cast<DIEVariable*>(it.Next());) {
|
DIEVariable* variableEntry = dynamic_cast<DIEVariable*>(it.Next());) {
|
||||||
printf(" variableEntry %p, scope start: %llu\n", variableEntry, variableEntry->StartScope());
|
|
||||||
|
TRACE_LOCALS(" variableEntry %p, scope start: %llu\n", variableEntry,
|
||||||
|
variableEntry->StartScope());
|
||||||
|
|
||||||
// check the variable's scope
|
// check the variable's scope
|
||||||
if (instructionPointer < lowPC + variableEntry->StartScope())
|
if (instructionPointer < lowPC + variableEntry->StartScope())
|
||||||
continue;
|
continue;
|
||||||
@@ -778,34 +819,35 @@ printf(" variableEntry %p, scope start: %llu\n", variableEntry, variableEntry->
|
|||||||
// iterate through the blocks and find the one we're currently in (if any)
|
// iterate through the blocks and find the one we're currently in (if any)
|
||||||
for (DebugInfoEntryList::ConstIterator it = blockEntries.list.GetIterator();
|
for (DebugInfoEntryList::ConstIterator it = blockEntries.list.GetIterator();
|
||||||
DIELexicalBlock* block = dynamic_cast<DIELexicalBlock*>(it.Next());) {
|
DIELexicalBlock* block = dynamic_cast<DIELexicalBlock*>(it.Next());) {
|
||||||
printf(" lexical block: %p\n", block);
|
|
||||||
|
TRACE_LOCALS(" lexical block: %p\n", block);
|
||||||
|
|
||||||
// check whether the block has low/high PC attributes
|
// check whether the block has low/high PC attributes
|
||||||
if (block->LowPC() != 0) {
|
if (block->LowPC() != 0) {
|
||||||
printf(" has lowPC\n");
|
TRACE_LOCALS(" has lowPC\n");
|
||||||
|
|
||||||
// yep, compare with the instruction pointer
|
// yep, compare with the instruction pointer
|
||||||
if (instructionPointer < block->LowPC()
|
if (instructionPointer < block->LowPC()
|
||||||
|| instructionPointer >= block->HighPC()) {
|
|| instructionPointer >= block->HighPC()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf(" no lowPC\n");
|
TRACE_LOCALS(" no lowPC\n");
|
||||||
|
|
||||||
// check the address ranges instead
|
// check the address ranges instead
|
||||||
TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit,
|
TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit,
|
||||||
block->AddressRangesOffset());
|
block->AddressRangesOffset());
|
||||||
if (rangeList == NULL)
|
if (rangeList == NULL) {
|
||||||
{
|
TRACE_LOCALS(" failed to get ranges\n");
|
||||||
printf(" failed to get ranges\n");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Reference<TargetAddressRangeList> rangeListReference(rangeList,
|
Reference<TargetAddressRangeList> rangeListReference(rangeList,
|
||||||
true);
|
true);
|
||||||
|
|
||||||
if (!rangeList->Contains(instructionPointer))
|
if (!rangeList->Contains(instructionPointer)) {
|
||||||
{
|
TRACE_LOCALS(" ranges don't contain IP\n");
|
||||||
printf(" ranges don't contain IP\n");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// found a block -- recurse
|
// found a block -- recurse
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
class Architecture;
|
class Architecture;
|
||||||
class CompilationUnit;
|
class CompilationUnit;
|
||||||
class DwarfInterfaceFactory;
|
class DwarfStackFrameDebugInfo;
|
||||||
class DwarfFile;
|
class DwarfFile;
|
||||||
class ElfSegment;
|
class ElfSegment;
|
||||||
class FileManager;
|
class FileManager;
|
||||||
@@ -78,7 +78,7 @@ private:
|
|||||||
|
|
||||||
status_t _CreateLocalVariables(CompilationUnit* unit,
|
status_t _CreateLocalVariables(CompilationUnit* unit,
|
||||||
StackFrame* frame, FunctionID* functionID,
|
StackFrame* frame, FunctionID* functionID,
|
||||||
DwarfInterfaceFactory& factory,
|
DwarfStackFrameDebugInfo& factory,
|
||||||
target_addr_t instructionPointer,
|
target_addr_t instructionPointer,
|
||||||
target_addr_t lowPC,
|
target_addr_t lowPC,
|
||||||
const EntryListWrapper& variableEntries,
|
const EntryListWrapper& variableEntries,
|
||||||
|
|||||||
+400
-62
@@ -4,8 +4,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "DwarfInterfaceFactory.h"
|
#include "DwarfStackFrameDebugInfo.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
#include <Variant.h>
|
#include <Variant.h>
|
||||||
@@ -20,6 +21,7 @@
|
|||||||
#include "LocalVariableID.h"
|
#include "LocalVariableID.h"
|
||||||
#include "RegisterMap.h"
|
#include "RegisterMap.h"
|
||||||
#include "StringUtils.h"
|
#include "StringUtils.h"
|
||||||
|
#include "Tracing.h"
|
||||||
#include "ValueLocation.h"
|
#include "ValueLocation.h"
|
||||||
#include "Variable.h"
|
#include "Variable.h"
|
||||||
|
|
||||||
@@ -27,7 +29,7 @@
|
|||||||
// #pragma mark - DwarfFunctionParameterID
|
// #pragma mark - DwarfFunctionParameterID
|
||||||
|
|
||||||
|
|
||||||
struct DwarfInterfaceFactory::DwarfFunctionParameterID
|
struct DwarfStackFrameDebugInfo::DwarfFunctionParameterID
|
||||||
: public FunctionParameterID {
|
: public FunctionParameterID {
|
||||||
|
|
||||||
DwarfFunctionParameterID(FunctionID* functionID, const BString& name)
|
DwarfFunctionParameterID(FunctionID* functionID, const BString& name)
|
||||||
@@ -67,7 +69,7 @@ private:
|
|||||||
// #pragma mark - DwarfLocalVariableID
|
// #pragma mark - DwarfLocalVariableID
|
||||||
|
|
||||||
|
|
||||||
struct DwarfInterfaceFactory::DwarfLocalVariableID : public LocalVariableID {
|
struct DwarfStackFrameDebugInfo::DwarfLocalVariableID : public LocalVariableID {
|
||||||
|
|
||||||
DwarfLocalVariableID(FunctionID* functionID, const BString& name,
|
DwarfLocalVariableID(FunctionID* functionID, const BString& name,
|
||||||
int32 line, int32 column)
|
int32 line, int32 column)
|
||||||
@@ -115,7 +117,7 @@ private:
|
|||||||
// #pragma mark - DwarfType
|
// #pragma mark - DwarfType
|
||||||
|
|
||||||
|
|
||||||
struct DwarfInterfaceFactory::DwarfType : virtual Type {
|
struct DwarfStackFrameDebugInfo::DwarfType : virtual Type {
|
||||||
public:
|
public:
|
||||||
DwarfType(const BString& name)
|
DwarfType(const BString& name)
|
||||||
:
|
:
|
||||||
@@ -129,12 +131,12 @@ public:
|
|||||||
return fName.Length() > 0 ? fName.String() : NULL;
|
return fName.Length() > 0 ? fName.String() : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 ByteSize() const
|
virtual target_size_t ByteSize() const
|
||||||
{
|
{
|
||||||
return fByteSize;
|
return fByteSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetByteSize(uint64 size)
|
void SetByteSize(target_size_t size)
|
||||||
{
|
{
|
||||||
fByteSize = size;
|
fByteSize = size;
|
||||||
}
|
}
|
||||||
@@ -142,18 +144,53 @@ public:
|
|||||||
virtual DIEType* GetDIEType() const = 0;
|
virtual DIEType* GetDIEType() const = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BString fName;
|
BString fName;
|
||||||
uint64 fByteSize;
|
target_size_t fByteSize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DwarfType* fNext;
|
DwarfType* fNext;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - DwarfInheritance
|
||||||
|
|
||||||
|
|
||||||
|
struct DwarfStackFrameDebugInfo::DwarfInheritance : BaseType {
|
||||||
|
public:
|
||||||
|
DwarfInheritance(DIEInheritance* entry, DwarfType* type)
|
||||||
|
:
|
||||||
|
fEntry(entry),
|
||||||
|
fType(type)
|
||||||
|
{
|
||||||
|
fType->AcquireReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
~DwarfInheritance()
|
||||||
|
{
|
||||||
|
fType->ReleaseReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Type* GetType() const
|
||||||
|
{
|
||||||
|
return fType;
|
||||||
|
}
|
||||||
|
|
||||||
|
DIEInheritance* Entry() const
|
||||||
|
{
|
||||||
|
return fEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DIEInheritance* fEntry;
|
||||||
|
DwarfType* fType;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DwarfDataMember
|
// #pragma mark - DwarfDataMember
|
||||||
|
|
||||||
|
|
||||||
struct DwarfInterfaceFactory::DwarfDataMember : DataMember {
|
struct DwarfStackFrameDebugInfo::DwarfDataMember : DataMember {
|
||||||
public:
|
public:
|
||||||
DwarfDataMember(DIEMember* entry, const BString& name, DwarfType* type)
|
DwarfDataMember(DIEMember* entry, const BString& name, DwarfType* type)
|
||||||
:
|
:
|
||||||
@@ -195,7 +232,7 @@ private:
|
|||||||
// #pragma mark - DwarfPrimitiveType
|
// #pragma mark - DwarfPrimitiveType
|
||||||
|
|
||||||
|
|
||||||
struct DwarfInterfaceFactory::DwarfPrimitiveType : PrimitiveType, DwarfType {
|
struct DwarfStackFrameDebugInfo::DwarfPrimitiveType : PrimitiveType, DwarfType {
|
||||||
public:
|
public:
|
||||||
DwarfPrimitiveType(const BString& name, DIEBaseType* entry,
|
DwarfPrimitiveType(const BString& name, DIEBaseType* entry,
|
||||||
uint32 typeConstant)
|
uint32 typeConstant)
|
||||||
@@ -230,7 +267,7 @@ private:
|
|||||||
// #pragma mark - DwarfCompoundType
|
// #pragma mark - DwarfCompoundType
|
||||||
|
|
||||||
|
|
||||||
struct DwarfInterfaceFactory::DwarfCompoundType : CompoundType, DwarfType {
|
struct DwarfStackFrameDebugInfo::DwarfCompoundType : CompoundType, DwarfType {
|
||||||
public:
|
public:
|
||||||
DwarfCompoundType(const BString& name, DIECompoundType* entry)
|
DwarfCompoundType(const BString& name, DIECompoundType* entry)
|
||||||
:
|
:
|
||||||
@@ -241,10 +278,24 @@ public:
|
|||||||
|
|
||||||
~DwarfCompoundType()
|
~DwarfCompoundType()
|
||||||
{
|
{
|
||||||
|
for (int32 i = 0;
|
||||||
|
DwarfInheritance* inheritance = fInheritances.ItemAt(i); i++) {
|
||||||
|
inheritance->ReleaseReference();
|
||||||
|
}
|
||||||
for (int32 i = 0; DwarfDataMember* member = fDataMembers.ItemAt(i); i++)
|
for (int32 i = 0; DwarfDataMember* member = fDataMembers.ItemAt(i); i++)
|
||||||
member->ReleaseReference();
|
member->ReleaseReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual int32 CountBaseTypes() const
|
||||||
|
{
|
||||||
|
return fInheritances.CountItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual BaseType* BaseTypeAt(int32 index) const
|
||||||
|
{
|
||||||
|
return fInheritances.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
virtual int32 CountDataMembers() const
|
virtual int32 CountDataMembers() const
|
||||||
{
|
{
|
||||||
return fDataMembers.CountItems();
|
return fDataMembers.CountItems();
|
||||||
@@ -265,6 +316,15 @@ public:
|
|||||||
return fEntry;
|
return fEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AddInheritance(DwarfInheritance* inheritance)
|
||||||
|
{
|
||||||
|
if (!fInheritances.AddItem(inheritance))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
inheritance->AcquireReference();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool AddDataMember(DwarfDataMember* member)
|
bool AddDataMember(DwarfDataMember* member)
|
||||||
{
|
{
|
||||||
if (!fDataMembers.AddItem(member))
|
if (!fDataMembers.AddItem(member))
|
||||||
@@ -276,17 +336,19 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
typedef BObjectList<DwarfDataMember> DataMemberList;
|
typedef BObjectList<DwarfDataMember> DataMemberList;
|
||||||
|
typedef BObjectList<DwarfInheritance> InheritanceList;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DIECompoundType* fEntry;
|
DIECompoundType* fEntry;
|
||||||
DataMemberList fDataMembers;
|
InheritanceList fInheritances;
|
||||||
|
DataMemberList fDataMembers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DwarfModifiedType
|
// #pragma mark - DwarfModifiedType
|
||||||
|
|
||||||
|
|
||||||
struct DwarfInterfaceFactory::DwarfModifiedType : ModifiedType, DwarfType {
|
struct DwarfStackFrameDebugInfo::DwarfModifiedType : ModifiedType, DwarfType {
|
||||||
public:
|
public:
|
||||||
DwarfModifiedType(const BString& name, DIEModifiedType* entry,
|
DwarfModifiedType(const BString& name, DIEModifiedType* entry,
|
||||||
uint32 modifiers, DwarfType* baseType)
|
uint32 modifiers, DwarfType* baseType)
|
||||||
@@ -334,7 +396,7 @@ private:
|
|||||||
// #pragma mark - DwarfTypedefType
|
// #pragma mark - DwarfTypedefType
|
||||||
|
|
||||||
|
|
||||||
struct DwarfInterfaceFactory::DwarfTypedefType : TypedefType, DwarfType {
|
struct DwarfStackFrameDebugInfo::DwarfTypedefType : TypedefType, DwarfType {
|
||||||
public:
|
public:
|
||||||
DwarfTypedefType(const BString& name, DIETypedef* entry,
|
DwarfTypedefType(const BString& name, DIETypedef* entry,
|
||||||
DwarfType* baseType)
|
DwarfType* baseType)
|
||||||
@@ -375,7 +437,7 @@ private:
|
|||||||
// #pragma mark - DwarfAddressType
|
// #pragma mark - DwarfAddressType
|
||||||
|
|
||||||
|
|
||||||
struct DwarfInterfaceFactory::DwarfAddressType : AddressType, DwarfType {
|
struct DwarfStackFrameDebugInfo::DwarfAddressType : AddressType, DwarfType {
|
||||||
public:
|
public:
|
||||||
DwarfAddressType(const BString& name, DIEAddressingType* entry,
|
DwarfAddressType(const BString& name, DIEAddressingType* entry,
|
||||||
address_type_kind addressKind, DwarfType* baseType)
|
address_type_kind addressKind, DwarfType* baseType)
|
||||||
@@ -423,7 +485,7 @@ private:
|
|||||||
// #pragma mark - DwarfArrayType
|
// #pragma mark - DwarfArrayType
|
||||||
|
|
||||||
|
|
||||||
struct DwarfInterfaceFactory::DwarfArrayType : ArrayType, DwarfType {
|
struct DwarfStackFrameDebugInfo::DwarfArrayType : ArrayType, DwarfType {
|
||||||
DwarfArrayType(const BString& name, DIEArrayType* entry,
|
DwarfArrayType(const BString& name, DIEArrayType* entry,
|
||||||
DwarfType* baseType, target_size_t elementCount)
|
DwarfType* baseType, target_size_t elementCount)
|
||||||
:
|
:
|
||||||
@@ -470,7 +532,7 @@ private:
|
|||||||
// #pragma mark - DwarfTypeHashDefinition
|
// #pragma mark - DwarfTypeHashDefinition
|
||||||
|
|
||||||
|
|
||||||
struct DwarfInterfaceFactory::DwarfTypeHashDefinition {
|
struct DwarfStackFrameDebugInfo::DwarfTypeHashDefinition {
|
||||||
typedef const DIEType* KeyType;
|
typedef const DIEType* KeyType;
|
||||||
typedef DwarfType ValueType;
|
typedef DwarfType ValueType;
|
||||||
|
|
||||||
@@ -496,10 +558,10 @@ struct DwarfInterfaceFactory::DwarfTypeHashDefinition {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DwarfInterfaceFactory
|
// #pragma mark - DwarfStackFrameDebugInfo
|
||||||
|
|
||||||
|
|
||||||
DwarfInterfaceFactory::DwarfInterfaceFactory(DwarfFile* file,
|
DwarfStackFrameDebugInfo::DwarfStackFrameDebugInfo(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, RegisterMap* fromDwarfRegisterMap)
|
DwarfTargetInterface* targetInterface, RegisterMap* fromDwarfRegisterMap)
|
||||||
@@ -516,7 +578,7 @@ DwarfInterfaceFactory::DwarfInterfaceFactory(DwarfFile* file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DwarfInterfaceFactory::~DwarfInterfaceFactory()
|
DwarfStackFrameDebugInfo::~DwarfStackFrameDebugInfo()
|
||||||
{
|
{
|
||||||
if (fTypes != NULL) {
|
if (fTypes != NULL) {
|
||||||
DwarfType* type = fTypes->Clear(true);
|
DwarfType* type = fTypes->Clear(true);
|
||||||
@@ -532,7 +594,7 @@ DwarfInterfaceFactory::~DwarfInterfaceFactory()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfInterfaceFactory::Init()
|
DwarfStackFrameDebugInfo::Init()
|
||||||
{
|
{
|
||||||
fTypes = new(std::nothrow) TypeTable;
|
fTypes = new(std::nothrow) TypeTable;
|
||||||
if (fTypes == NULL)
|
if (fTypes == NULL)
|
||||||
@@ -543,7 +605,128 @@ DwarfInterfaceFactory::Init()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfInterfaceFactory::CreateType(DIEType* typeEntry, Type*& _type)
|
DwarfStackFrameDebugInfo::ResolveObjectDataLocation(StackFrame* stackFrame,
|
||||||
|
Type* type, target_addr_t objectAddress, ValueLocation*& _location)
|
||||||
|
{
|
||||||
|
// TODO: In some source languages the object address might be a pointer to
|
||||||
|
// a descriptor, not the actual object data.
|
||||||
|
|
||||||
|
ValuePieceLocation piece;
|
||||||
|
piece.SetToMemory(objectAddress);
|
||||||
|
piece.SetSize(type->ByteSize());
|
||||||
|
// TODO: Use bit size and bit offset, if specified!
|
||||||
|
|
||||||
|
ValueLocation* location = new(std::nothrow) ValueLocation;
|
||||||
|
if (location == NULL || !location->AddPiece(piece)) {
|
||||||
|
delete location;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
_location = location;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfStackFrameDebugInfo::ResolveBaseTypeLocation(StackFrame* stackFrame,
|
||||||
|
Type* _type, BaseType* _baseType, const ValueLocation& parentLocation,
|
||||||
|
ValueLocation*& _location)
|
||||||
|
{
|
||||||
|
DwarfCompoundType* type = dynamic_cast<DwarfCompoundType*>(_type);
|
||||||
|
DwarfInheritance* baseType = dynamic_cast<DwarfInheritance*>(_baseType);
|
||||||
|
if (type == NULL || baseType == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
return _ResolveDataMemberLocation(stackFrame, type, baseType->GetType(),
|
||||||
|
baseType->Entry()->Location(), parentLocation, _location);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfStackFrameDebugInfo::ResolveDataMemberLocation(StackFrame* stackFrame,
|
||||||
|
Type* _type, DataMember* _member, const ValueLocation& parentLocation,
|
||||||
|
ValueLocation*& _location)
|
||||||
|
{
|
||||||
|
DwarfCompoundType* type = dynamic_cast<DwarfCompoundType*>(_type);
|
||||||
|
DwarfDataMember* member = dynamic_cast<DwarfDataMember*>(_member);
|
||||||
|
if (type == NULL || member == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
ValueLocation* location;
|
||||||
|
status_t error = _ResolveDataMemberLocation(stackFrame, type,
|
||||||
|
member->GetType(), member->Entry()->Location(), parentLocation,
|
||||||
|
location);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// If the member isn't a bit field, we're done.
|
||||||
|
DIEMember* memberEntry = member->Entry();
|
||||||
|
if (!memberEntry->ByteSize()->IsValid()
|
||||||
|
&& !memberEntry->BitOffset()->IsValid()
|
||||||
|
&& !memberEntry->BitSize()->IsValid()) {
|
||||||
|
_location = location;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Reference<ValueLocation> locationReference(location);
|
||||||
|
|
||||||
|
// get the byte size
|
||||||
|
target_addr_t byteSize;
|
||||||
|
if (memberEntry->ByteSize()->IsValid()) {
|
||||||
|
BVariant value;
|
||||||
|
error = fFile->EvaluateDynamicValue(fCompilationUnit, fSubprogramEntry,
|
||||||
|
memberEntry->ByteSize(), fTargetInterface, fInstructionPointer,
|
||||||
|
fFramePointer, value);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
byteSize = value.ToUInt64();
|
||||||
|
} else
|
||||||
|
byteSize = type->ByteSize();
|
||||||
|
|
||||||
|
// get the bit offset
|
||||||
|
uint64 bitOffset;
|
||||||
|
if (memberEntry->BitOffset()->IsValid()) {
|
||||||
|
BVariant value;
|
||||||
|
error = fFile->EvaluateDynamicValue(fCompilationUnit, fSubprogramEntry,
|
||||||
|
memberEntry->BitOffset(), fTargetInterface, fInstructionPointer,
|
||||||
|
fFramePointer, value);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
bitOffset = value.ToUInt64();
|
||||||
|
} else
|
||||||
|
bitOffset = 0;
|
||||||
|
|
||||||
|
// get the bit size
|
||||||
|
uint64 bitSize = byteSize * 8;
|
||||||
|
if (memberEntry->BitSize()->IsValid()) {
|
||||||
|
BVariant value;
|
||||||
|
error = fFile->EvaluateDynamicValue(fCompilationUnit, fSubprogramEntry,
|
||||||
|
memberEntry->BitSize(), fTargetInterface, fInstructionPointer,
|
||||||
|
fFramePointer, value);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
bitSize = std::min(bitSize, value.ToUInt64());
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE_LOCALS("bit field: byte size: %llu, bit offset/size: %llu/%llu\n",
|
||||||
|
byteSize, bitOffset, bitSize);
|
||||||
|
|
||||||
|
// create the bit field value location
|
||||||
|
ValueLocation* bitFieldLocation = new(std::nothrow) ValueLocation;
|
||||||
|
if (bitFieldLocation == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
Reference<ValueLocation> bitFieldLocationReference(bitFieldLocation, true);
|
||||||
|
|
||||||
|
if (!bitFieldLocation->SetTo(*location, bitOffset, bitSize))
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
_location = bitFieldLocationReference.Detach();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfStackFrameDebugInfo::CreateType(DIEType* typeEntry, Type*& _type)
|
||||||
{
|
{
|
||||||
DwarfType* type;
|
DwarfType* type;
|
||||||
status_t error = _CreateType(typeEntry, type);
|
status_t error = _CreateType(typeEntry, type);
|
||||||
@@ -556,14 +739,15 @@ DwarfInterfaceFactory::CreateType(DIEType* typeEntry, Type*& _type)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfInterfaceFactory::CreateParameter(FunctionID* functionID,
|
DwarfStackFrameDebugInfo::CreateParameter(FunctionID* functionID,
|
||||||
DIEFormalParameter* parameterEntry, Variable*& _parameter)
|
DIEFormalParameter* parameterEntry, Variable*& _parameter)
|
||||||
{
|
{
|
||||||
// get the name
|
// get the name
|
||||||
BString name;
|
BString name;
|
||||||
DwarfUtils::GetDIEName(parameterEntry, name);
|
DwarfUtils::GetDIEName(parameterEntry, name);
|
||||||
printf("DwarfInterfaceFactory::CreateParameter(DIE: %p): name: \"%s\"\n",
|
|
||||||
parameterEntry, name.String());
|
TRACE_LOCALS("DwarfStackFrameDebugInfo::CreateParameter(DIE: %p): name: "
|
||||||
|
"\"%s\"\n", parameterEntry, name.String());
|
||||||
|
|
||||||
// create the ID
|
// create the ID
|
||||||
DwarfFunctionParameterID* id = new(std::nothrow) DwarfFunctionParameterID(
|
DwarfFunctionParameterID* id = new(std::nothrow) DwarfFunctionParameterID(
|
||||||
@@ -579,14 +763,15 @@ parameterEntry, name.String());
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfInterfaceFactory::CreateLocalVariable(FunctionID* functionID,
|
DwarfStackFrameDebugInfo::CreateLocalVariable(FunctionID* functionID,
|
||||||
DIEVariable* variableEntry, Variable*& _variable)
|
DIEVariable* variableEntry, Variable*& _variable)
|
||||||
{
|
{
|
||||||
// get the name
|
// get the name
|
||||||
BString name;
|
BString name;
|
||||||
DwarfUtils::GetDIEName(variableEntry, name);
|
DwarfUtils::GetDIEName(variableEntry, name);
|
||||||
printf("DwarfInterfaceFactory::CreateLocalVariable(DIE: %p): name: \"%s\"\n",
|
|
||||||
variableEntry, name.String());
|
TRACE_LOCALS("DwarfStackFrameDebugInfo::CreateLocalVariable(DIE: %p): "
|
||||||
|
"name: \"%s\"\n", variableEntry, name.String());
|
||||||
|
|
||||||
// get the declaration location
|
// get the declaration location
|
||||||
int32 line = -1;
|
int32 line = -1;
|
||||||
@@ -613,7 +798,90 @@ variableEntry, name.String());
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfInterfaceFactory::_CreateType(DIEType* typeEntry, DwarfType*& _type)
|
DwarfStackFrameDebugInfo::_ResolveDataMemberLocation(StackFrame* stackFrame,
|
||||||
|
DwarfCompoundType* type, Type* memberType,
|
||||||
|
const MemberLocation* memberLocation, const ValueLocation& parentLocation,
|
||||||
|
ValueLocation*& _location)
|
||||||
|
{
|
||||||
|
// create the value location object for the member
|
||||||
|
ValueLocation* location = new(std::nothrow) ValueLocation;
|
||||||
|
if (location == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
Reference<ValueLocation> locationReference(location, true);
|
||||||
|
|
||||||
|
switch (memberLocation->attributeClass) {
|
||||||
|
case ATTRIBUTE_CLASS_CONSTANT:
|
||||||
|
{
|
||||||
|
if (!location->SetTo(parentLocation, memberLocation->constant * 8,
|
||||||
|
memberType->ByteSize() * 8)) {
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ATTRIBUTE_CLASS_BLOCK:
|
||||||
|
case ATTRIBUTE_CLASS_LOCLISTPTR:
|
||||||
|
{
|
||||||
|
// The attribute is a location description. Since we need to push
|
||||||
|
// the parent object value onto the stack, we require the parent
|
||||||
|
// location to be a memory location.
|
||||||
|
if (parentLocation.CountPieces() != 1)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
ValuePieceLocation piece = parentLocation.PieceAt(0);
|
||||||
|
if (piece.type != VALUE_PIECE_LOCATION_MEMORY)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// convert member location to location description
|
||||||
|
LocationDescription locationDescription;
|
||||||
|
if (memberLocation->attributeClass == ATTRIBUTE_CLASS_BLOCK) {
|
||||||
|
locationDescription.SetToExpression(
|
||||||
|
memberLocation->expression.data,
|
||||||
|
memberLocation->expression.length);
|
||||||
|
} else {
|
||||||
|
locationDescription.SetToLocationList(
|
||||||
|
memberLocation->listOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// evaluate the location description
|
||||||
|
status_t error = fFile->ResolveLocation(fCompilationUnit,
|
||||||
|
fSubprogramEntry, &locationDescription, fTargetInterface,
|
||||||
|
fInstructionPointer, piece.address, fFramePointer, *location);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// If we only have a location but no size, use the size from the
|
||||||
|
// type.
|
||||||
|
if (location->CountPieces() == 1) {
|
||||||
|
piece = location->PieceAt(0);
|
||||||
|
if (piece.size == 0 && piece.bitSize == 0) {
|
||||||
|
piece.size = memberType->ByteSize();
|
||||||
|
location->SetPieceAt(0, piece);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// for unions the member location can be omitted -- all members
|
||||||
|
// start at the beginning of the parent object
|
||||||
|
if (type->GetDIEType()->Tag() != DW_TAG_union_type)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (!location->SetTo(parentLocation, 0, memberType->ByteSize() * 8))
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_location = locationReference.Detach();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfStackFrameDebugInfo::_CreateType(DIEType* typeEntry, DwarfType*& _type)
|
||||||
{
|
{
|
||||||
// Try the type cache first. If we don't know the type yet, create it.
|
// Try the type cache first. If we don't know the type yet, create it.
|
||||||
DwarfType* type = fTypes->Lookup(typeEntry);
|
DwarfType* type = fTypes->Lookup(typeEntry);
|
||||||
@@ -641,7 +909,7 @@ DwarfInterfaceFactory::_CreateType(DIEType* typeEntry, DwarfType*& _type)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfInterfaceFactory::_CreateTypeInternal(DIEType* typeEntry,
|
DwarfStackFrameDebugInfo::_CreateTypeInternal(DIEType* typeEntry,
|
||||||
DwarfType*& _type)
|
DwarfType*& _type)
|
||||||
{
|
{
|
||||||
BString name;
|
BString name;
|
||||||
@@ -718,9 +986,12 @@ DwarfInterfaceFactory::_CreateTypeInternal(DIEType* typeEntry,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfInterfaceFactory::_CreateCompoundType(const BString& name,
|
DwarfStackFrameDebugInfo::_CreateCompoundType(const BString& name,
|
||||||
DIECompoundType* typeEntry, DwarfType*& _type)
|
DIECompoundType* typeEntry, DwarfType*& _type)
|
||||||
{
|
{
|
||||||
|
TRACE_LOCALS("DwarfStackFrameDebugInfo::_CreateCompoundType(\"%s\", %p)\n",
|
||||||
|
name.String(), typeEntry);
|
||||||
|
|
||||||
// create the type
|
// create the type
|
||||||
DwarfCompoundType* type = new(std::nothrow) DwarfCompoundType(name,
|
DwarfCompoundType* type = new(std::nothrow) DwarfCompoundType(name,
|
||||||
typeEntry);
|
typeEntry);
|
||||||
@@ -734,7 +1005,10 @@ DwarfInterfaceFactory::_CreateCompoundType(const BString& name,
|
|||||||
fTypes->Insert(type);
|
fTypes->Insert(type);
|
||||||
|
|
||||||
// find the abstract origin or specification that defines the data members
|
// find the abstract origin or specification that defines the data members
|
||||||
|
DIECompoundType* originalTypeEntry = typeEntry;
|
||||||
if (typeEntry->DataMembers().IsEmpty()) {
|
if (typeEntry->DataMembers().IsEmpty()) {
|
||||||
|
TRACE_LOCALS(" no data members yet, trying abstract origin...\n");
|
||||||
|
|
||||||
if (DIECompoundType* abstractOrigin = dynamic_cast<DIECompoundType*>(
|
if (DIECompoundType* abstractOrigin = dynamic_cast<DIECompoundType*>(
|
||||||
typeEntry->AbstractOrigin())) {
|
typeEntry->AbstractOrigin())) {
|
||||||
typeEntry = abstractOrigin;
|
typeEntry = abstractOrigin;
|
||||||
@@ -742,6 +1016,8 @@ DwarfInterfaceFactory::_CreateCompoundType(const BString& name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeEntry->DataMembers().IsEmpty()) {
|
if (typeEntry->DataMembers().IsEmpty()) {
|
||||||
|
TRACE_LOCALS(" no data members yet, trying specification...\n");
|
||||||
|
|
||||||
if (DIECompoundType* specification = dynamic_cast<DIECompoundType*>(
|
if (DIECompoundType* specification = dynamic_cast<DIECompoundType*>(
|
||||||
typeEntry->Specification())) {
|
typeEntry->Specification())) {
|
||||||
typeEntry = specification;
|
typeEntry = specification;
|
||||||
@@ -754,6 +1030,8 @@ DwarfInterfaceFactory::_CreateCompoundType(const BString& name,
|
|||||||
DebugInfoEntry* _memberEntry = it.Next();) {
|
DebugInfoEntry* _memberEntry = it.Next();) {
|
||||||
DIEMember* memberEntry = dynamic_cast<DIEMember*>(_memberEntry);
|
DIEMember* memberEntry = dynamic_cast<DIEMember*>(_memberEntry);
|
||||||
|
|
||||||
|
TRACE_LOCALS(" member %p\n", memberEntry);
|
||||||
|
|
||||||
// get the type
|
// get the type
|
||||||
DwarfType* memberType;
|
DwarfType* memberType;
|
||||||
if (_CreateType(memberEntry->GetType(), memberType) != B_OK)
|
if (_CreateType(memberEntry->GetType(), memberType) != B_OK)
|
||||||
@@ -774,13 +1052,58 @@ DwarfInterfaceFactory::_CreateCompoundType(const BString& name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the type is a class/struct/interface type, we also need to add its
|
||||||
|
// base types.
|
||||||
|
if (DIEClassBaseType* classTypeEntry
|
||||||
|
= dynamic_cast<DIEClassBaseType*>(originalTypeEntry)) {
|
||||||
|
// find the abstract origin or specification that defines the base types
|
||||||
|
if (classTypeEntry->DataMembers().IsEmpty()) {
|
||||||
|
if (DIEClassBaseType* abstractOrigin
|
||||||
|
= dynamic_cast<DIEClassBaseType*>(
|
||||||
|
classTypeEntry->AbstractOrigin())) {
|
||||||
|
classTypeEntry = abstractOrigin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classTypeEntry->DataMembers().IsEmpty()) {
|
||||||
|
if (DIEClassBaseType* specification
|
||||||
|
= dynamic_cast<DIEClassBaseType*>(
|
||||||
|
classTypeEntry->Specification())) {
|
||||||
|
classTypeEntry = specification;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the inheritance objects for the base types
|
||||||
|
for (DebugInfoEntryList::ConstIterator it
|
||||||
|
= classTypeEntry->BaseTypes().GetIterator();
|
||||||
|
DebugInfoEntry* _inheritanceEntry = it.Next();) {
|
||||||
|
DIEInheritance* inheritanceEntry = dynamic_cast<DIEInheritance*>(
|
||||||
|
_inheritanceEntry);
|
||||||
|
|
||||||
|
// get the type
|
||||||
|
DwarfType* baseType;
|
||||||
|
if (_CreateType(inheritanceEntry->GetType(), baseType) != B_OK)
|
||||||
|
continue;
|
||||||
|
Reference<DwarfType> baseTypeReference(baseType, true);
|
||||||
|
|
||||||
|
// create and add the inheritance object
|
||||||
|
DwarfInheritance* inheritance = new(std::nothrow) DwarfInheritance(
|
||||||
|
inheritanceEntry, baseType);
|
||||||
|
Reference<DwarfInheritance> inheritanceReference(inheritance, true);
|
||||||
|
if (inheritance == NULL || !type->AddInheritance(inheritance)) {
|
||||||
|
fTypes->Remove(type);
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_type = typeReference.Detach();
|
_type = typeReference.Detach();
|
||||||
return B_OK;;
|
return B_OK;;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfInterfaceFactory::_CreatePrimitiveType(const BString& name,
|
DwarfStackFrameDebugInfo::_CreatePrimitiveType(const BString& name,
|
||||||
DIEBaseType* typeEntry, DwarfType*& _type)
|
DIEBaseType* typeEntry, DwarfType*& _type)
|
||||||
{
|
{
|
||||||
const DynamicAttributeValue* byteSizeValue = typeEntry->ByteSize();
|
const DynamicAttributeValue* byteSizeValue = typeEntry->ByteSize();
|
||||||
@@ -883,7 +1206,7 @@ DwarfInterfaceFactory::_CreatePrimitiveType(const BString& name,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfInterfaceFactory::_CreateAddressType(const BString& name,
|
DwarfStackFrameDebugInfo::_CreateAddressType(const BString& name,
|
||||||
DIEAddressingType* typeEntry, address_type_kind addressKind,
|
DIEAddressingType* typeEntry, address_type_kind addressKind,
|
||||||
DwarfType*& _type)
|
DwarfType*& _type)
|
||||||
{
|
{
|
||||||
@@ -928,7 +1251,7 @@ DwarfInterfaceFactory::_CreateAddressType(const BString& name,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfInterfaceFactory::_CreateModifiedType(const BString& name,
|
DwarfStackFrameDebugInfo::_CreateModifiedType(const BString& name,
|
||||||
DIEModifiedType* typeEntry, uint32 modifiers, DwarfType*& _type)
|
DIEModifiedType* typeEntry, uint32 modifiers, DwarfType*& _type)
|
||||||
{
|
{
|
||||||
// Get the base type entry. If it is a modified type too or a typedef,
|
// Get the base type entry. If it is a modified type too or a typedef,
|
||||||
@@ -1019,7 +1342,7 @@ DwarfInterfaceFactory::_CreateModifiedType(const BString& name,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfInterfaceFactory::_CreateTypedefType(const BString& name,
|
DwarfStackFrameDebugInfo::_CreateTypedefType(const BString& name,
|
||||||
DIETypedef* typeEntry, DwarfType*& _type)
|
DIETypedef* typeEntry, DwarfType*& _type)
|
||||||
{
|
{
|
||||||
// resolve the base type
|
// resolve the base type
|
||||||
@@ -1046,7 +1369,7 @@ DwarfInterfaceFactory::_CreateTypedefType(const BString& name,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfInterfaceFactory::_CreateArrayType(const BString& name,
|
DwarfStackFrameDebugInfo::_CreateArrayType(const BString& name,
|
||||||
DIEArrayType* typeEntry, DwarfType*& _type)
|
DIEArrayType* typeEntry, DwarfType*& _type)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
@@ -1094,7 +1417,7 @@ DwarfInterfaceFactory::_CreateArrayType(const BString& name,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfInterfaceFactory::_CreateVariable(ObjectID* id, const BString& name,
|
DwarfStackFrameDebugInfo::_CreateVariable(ObjectID* id, const BString& name,
|
||||||
DIEType* typeEntry, LocationDescription* locationDescription,
|
DIEType* typeEntry, LocationDescription* locationDescription,
|
||||||
Variable*& _variable)
|
Variable*& _variable)
|
||||||
{
|
{
|
||||||
@@ -1111,7 +1434,8 @@ DwarfInterfaceFactory::_CreateVariable(ObjectID* id, const BString& name,
|
|||||||
fFile->ResolveLocation(fCompilationUnit,
|
fFile->ResolveLocation(fCompilationUnit,
|
||||||
fSubprogramEntry, locationDescription, fTargetInterface,
|
fSubprogramEntry, locationDescription, fTargetInterface,
|
||||||
fInstructionPointer, 0, fFramePointer, *location);
|
fInstructionPointer, 0, fFramePointer, *location);
|
||||||
location->Dump();
|
|
||||||
|
TRACE_LOCALS_ONLY(location->Dump());
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the type
|
// create the type
|
||||||
@@ -1134,7 +1458,7 @@ location->Dump();
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfInterfaceFactory::_ResolveTypedef(DIETypedef* entry,
|
DwarfStackFrameDebugInfo::_ResolveTypedef(DIETypedef* entry,
|
||||||
DIEType*& _baseTypeEntry)
|
DIEType*& _baseTypeEntry)
|
||||||
{
|
{
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -1172,16 +1496,20 @@ DwarfInterfaceFactory::_ResolveTypedef(DIETypedef* entry,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfInterfaceFactory::_ResolveTypeByteSize(DIEType* typeEntry, uint64& _size)
|
DwarfStackFrameDebugInfo::_ResolveTypeByteSize(DIEType* typeEntry,
|
||||||
|
uint64& _size)
|
||||||
{
|
{
|
||||||
printf("DwarfInterfaceFactory::_ResolveTypeByteSize(%p)\n", typeEntry);
|
TRACE_LOCALS("DwarfStackFrameDebugInfo::_ResolveTypeByteSize(%p)\n",
|
||||||
|
typeEntry);
|
||||||
|
|
||||||
// get the size attribute
|
// get the size attribute
|
||||||
const DynamicAttributeValue* sizeValue;
|
const DynamicAttributeValue* sizeValue;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
// resolve a typedef
|
// resolve a typedef
|
||||||
if (typeEntry->Tag() == DW_TAG_typedef) {
|
if (typeEntry->Tag() == DW_TAG_typedef) {
|
||||||
printf(" resolving typedef...\n");
|
TRACE_LOCALS(" resolving typedef...\n");
|
||||||
|
|
||||||
status_t error = _ResolveTypedef(
|
status_t error = _ResolveTypedef(
|
||||||
dynamic_cast<DIETypedef*>(typeEntry), typeEntry);
|
dynamic_cast<DIETypedef*>(typeEntry), typeEntry);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
@@ -1195,7 +1523,9 @@ printf(" resolving typedef...\n");
|
|||||||
// resolve abstract origin
|
// resolve abstract origin
|
||||||
if (DIEType* abstractOrigin = dynamic_cast<DIEType*>(
|
if (DIEType* abstractOrigin = dynamic_cast<DIEType*>(
|
||||||
typeEntry->AbstractOrigin())) {
|
typeEntry->AbstractOrigin())) {
|
||||||
printf(" resolving abstract origin (%p)...\n", abstractOrigin);
|
TRACE_LOCALS(" resolving abstract origin (%p)...\n",
|
||||||
|
abstractOrigin);
|
||||||
|
|
||||||
typeEntry = abstractOrigin;
|
typeEntry = abstractOrigin;
|
||||||
sizeValue = typeEntry->ByteSize();
|
sizeValue = typeEntry->ByteSize();
|
||||||
if (sizeValue != NULL && sizeValue->IsValid())
|
if (sizeValue != NULL && sizeValue->IsValid())
|
||||||
@@ -1205,7 +1535,8 @@ printf(" resolving abstract origin (%p)...\n", abstractOrigin);
|
|||||||
// resolve specification
|
// resolve specification
|
||||||
if (DIEType* specification = dynamic_cast<DIEType*>(
|
if (DIEType* specification = dynamic_cast<DIEType*>(
|
||||||
typeEntry->Specification())) {
|
typeEntry->Specification())) {
|
||||||
printf(" resolving specification (%p)...\n", specification);
|
TRACE_LOCALS(" resolving specification (%p)...\n", specification);
|
||||||
|
|
||||||
typeEntry = specification;
|
typeEntry = specification;
|
||||||
sizeValue = typeEntry->ByteSize();
|
sizeValue = typeEntry->ByteSize();
|
||||||
if (sizeValue != NULL && sizeValue->IsValid())
|
if (sizeValue != NULL && sizeValue->IsValid())
|
||||||
@@ -1214,7 +1545,8 @@ printf(" resolving specification (%p)...\n", specification);
|
|||||||
|
|
||||||
// For some types we have a special handling. For modified types we
|
// For some types we have a special handling. For modified types we
|
||||||
// follow the base type, for address types we know the size anyway.
|
// follow the base type, for address types we know the size anyway.
|
||||||
printf(" nothing yet, special type handling\n");
|
TRACE_LOCALS(" nothing yet, special type handling\n");
|
||||||
|
|
||||||
switch (typeEntry->Tag()) {
|
switch (typeEntry->Tag()) {
|
||||||
case DW_TAG_const_type:
|
case DW_TAG_const_type:
|
||||||
case DW_TAG_packed_type:
|
case DW_TAG_packed_type:
|
||||||
@@ -1223,44 +1555,50 @@ printf(" nothing yet, special type handling\n");
|
|||||||
case DW_TAG_shared_type:
|
case DW_TAG_shared_type:
|
||||||
typeEntry = dynamic_cast<DIEModifiedType*>(typeEntry)
|
typeEntry = dynamic_cast<DIEModifiedType*>(typeEntry)
|
||||||
->GetType();
|
->GetType();
|
||||||
printf(" following modified type -> %p\n", typeEntry);
|
|
||||||
|
TRACE_LOCALS(" following modified type -> %p\n", typeEntry);
|
||||||
|
|
||||||
if (typeEntry == NULL)
|
if (typeEntry == NULL)
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
break;
|
break;
|
||||||
case DW_TAG_pointer_type:
|
case DW_TAG_pointer_type:
|
||||||
case DW_TAG_reference_type:
|
case DW_TAG_reference_type:
|
||||||
_size = fCompilationUnit->AddressSize();
|
_size = fCompilationUnit->AddressSize();
|
||||||
printf(" pointer/reference type: size: %llu\n", _size);
|
|
||||||
|
TRACE_LOCALS(" pointer/reference type: size: %llu\n", _size);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
default:
|
default:
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" found attribute\n");
|
TRACE_LOCALS(" found attribute\n");
|
||||||
|
|
||||||
// get the actual value
|
// get the actual value
|
||||||
BVariant size;
|
BVariant size;
|
||||||
status_t error = fFile->EvaluateDynamicValue(fCompilationUnit,
|
status_t error = fFile->EvaluateDynamicValue(fCompilationUnit,
|
||||||
fSubprogramEntry, sizeValue, fTargetInterface, fInstructionPointer,
|
fSubprogramEntry, sizeValue, fTargetInterface, fInstructionPointer,
|
||||||
fFramePointer, size);
|
fFramePointer, size);
|
||||||
if (error != B_OK)
|
if (error != B_OK) {
|
||||||
{
|
TRACE_LOCALS(" failed to resolve attribute: %s\n", strerror(error));
|
||||||
printf(" failed to resolve attribute: %s\n", strerror(error));
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
_size = size.ToUInt64();
|
_size = size.ToUInt64();
|
||||||
printf(" -> size: %llu\n", _size);
|
|
||||||
|
TRACE_LOCALS(" -> size: %llu\n", _size);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
DwarfInterfaceFactory::_FixLocation(ValueLocation* location, DwarfType* type)
|
DwarfStackFrameDebugInfo::_FixLocation(ValueLocation* location, DwarfType* type)
|
||||||
{
|
{
|
||||||
printf("DwarfInterfaceFactory::_FixLocation(%p, %p), type entry: %p\n",
|
TRACE_LOCALS("DwarfStackFrameDebugInfo::_FixLocation(%p, %p), type entry: "
|
||||||
location, type, type->GetDIEType());
|
"%p\n", location, type, type->GetDIEType());
|
||||||
|
|
||||||
// translate the DWARF register indices
|
// translate the DWARF register indices
|
||||||
int32 count = location->CountPieces();
|
int32 count = location->CountPieces();
|
||||||
for (int32 i = 0; i < count; i++) {
|
for (int32 i = 0; i < count; i++) {
|
||||||
@@ -1280,19 +1618,19 @@ location, type, type->GetDIEType());
|
|||||||
// the size of the type.
|
// the size of the type.
|
||||||
if (count == 1) {
|
if (count == 1) {
|
||||||
ValuePieceLocation piece = location->PieceAt(0);
|
ValuePieceLocation piece = location->PieceAt(0);
|
||||||
if (piece.IsValid() && piece.size == 0 && piece.bitSize == 0)
|
if (piece.IsValid() && piece.size == 0 && piece.bitSize == 0) {
|
||||||
{
|
|
||||||
piece.SetSize(type->ByteSize());
|
piece.SetSize(type->ByteSize());
|
||||||
location->SetPieceAt(0, piece);
|
location->SetPieceAt(0, piece);
|
||||||
printf(" set single piece size to %llu\n", type->ByteSize());
|
|
||||||
}
|
TRACE_LOCALS(" set single piece size to %llu\n", type->ByteSize());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename EntryType>
|
template<typename EntryType>
|
||||||
/*static*/ DIEType*
|
/*static*/ DIEType*
|
||||||
DwarfInterfaceFactory::_GetDIEType(EntryType* entry)
|
DwarfStackFrameDebugInfo::_GetDIEType(EntryType* entry)
|
||||||
{
|
{
|
||||||
if (DIEType* typeEntry = entry->GetType())
|
if (DIEType* typeEntry = entry->GetType())
|
||||||
return typeEntry;
|
return typeEntry;
|
||||||
+30
-5
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <util/OpenHashTable.h>
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
|
#include "StackFrameDebugInfo.h"
|
||||||
#include "Type.h"
|
#include "Type.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -28,26 +29,40 @@ class DwarfFile;
|
|||||||
class DwarfTargetInterface;
|
class DwarfTargetInterface;
|
||||||
class FunctionID;
|
class FunctionID;
|
||||||
class LocationDescription;
|
class LocationDescription;
|
||||||
|
class MemberLocation;
|
||||||
class ObjectID;
|
class ObjectID;
|
||||||
class RegisterMap;
|
class RegisterMap;
|
||||||
class Type;
|
|
||||||
class ValueLocation;
|
|
||||||
class Variable;
|
class Variable;
|
||||||
|
|
||||||
|
|
||||||
class DwarfInterfaceFactory {
|
class DwarfStackFrameDebugInfo : public StackFrameDebugInfo {
|
||||||
public:
|
public:
|
||||||
DwarfInterfaceFactory(DwarfFile* file,
|
DwarfStackFrameDebugInfo(DwarfFile* file,
|
||||||
CompilationUnit* compilationUnit,
|
CompilationUnit* compilationUnit,
|
||||||
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);
|
RegisterMap* fromDwarfRegisterMap);
|
||||||
~DwarfInterfaceFactory();
|
~DwarfStackFrameDebugInfo();
|
||||||
|
|
||||||
status_t Init();
|
status_t Init();
|
||||||
|
|
||||||
|
virtual status_t ResolveObjectDataLocation(
|
||||||
|
StackFrame* stackFrame, Type* type,
|
||||||
|
target_addr_t objectAddress,
|
||||||
|
ValueLocation*& _location);
|
||||||
|
virtual status_t ResolveBaseTypeLocation(
|
||||||
|
StackFrame* stackFrame, Type* type,
|
||||||
|
BaseType* baseType,
|
||||||
|
const ValueLocation& parentLocation,
|
||||||
|
ValueLocation*& _location);
|
||||||
|
virtual status_t ResolveDataMemberLocation(
|
||||||
|
StackFrame* stackFrame, Type* type,
|
||||||
|
DataMember* member,
|
||||||
|
const ValueLocation& parentLocation,
|
||||||
|
ValueLocation*& _location);
|
||||||
|
|
||||||
status_t CreateType(DIEType* typeEntry, Type*& _type);
|
status_t CreateType(DIEType* typeEntry, Type*& _type);
|
||||||
// returns reference
|
// returns reference
|
||||||
status_t CreateParameter(FunctionID* functionID,
|
status_t CreateParameter(FunctionID* functionID,
|
||||||
@@ -63,6 +78,7 @@ private:
|
|||||||
struct DwarfFunctionParameterID;
|
struct DwarfFunctionParameterID;
|
||||||
struct DwarfLocalVariableID;
|
struct DwarfLocalVariableID;
|
||||||
struct DwarfType;
|
struct DwarfType;
|
||||||
|
struct DwarfInheritance;
|
||||||
struct DwarfDataMember;
|
struct DwarfDataMember;
|
||||||
struct DwarfPrimitiveType;
|
struct DwarfPrimitiveType;
|
||||||
struct DwarfCompoundType;
|
struct DwarfCompoundType;
|
||||||
@@ -75,6 +91,15 @@ private:
|
|||||||
typedef BOpenHashTable<DwarfTypeHashDefinition> TypeTable;
|
typedef BOpenHashTable<DwarfTypeHashDefinition> TypeTable;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
status_t _ResolveDataMemberLocation(
|
||||||
|
StackFrame* stackFrame,
|
||||||
|
DwarfCompoundType* type,
|
||||||
|
Type* memberType,
|
||||||
|
const MemberLocation* memberLocation,
|
||||||
|
const ValueLocation& parentLocation,
|
||||||
|
ValueLocation*& _location);
|
||||||
|
// returns a new location
|
||||||
|
|
||||||
status_t _CreateType(DIEType* typeEntry,
|
status_t _CreateType(DIEType* typeEntry,
|
||||||
DwarfType*& _type);
|
DwarfType*& _type);
|
||||||
status_t _CreateTypeInternal(DIEType* typeEntry,
|
status_t _CreateTypeInternal(DIEType* typeEntry,
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "NoOpStackFrameDebugInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
NoOpStackFrameDebugInfo::NoOpStackFrameDebugInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NoOpStackFrameDebugInfo::~NoOpStackFrameDebugInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
NoOpStackFrameDebugInfo::ResolveObjectDataLocation(StackFrame* stackFrame,
|
||||||
|
Type* type, target_addr_t objectAddress, ValueLocation*& _location)
|
||||||
|
{
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
NoOpStackFrameDebugInfo::ResolveBaseTypeLocation(StackFrame* stackFrame,
|
||||||
|
Type* type, BaseType* baseType, const ValueLocation& parentLocation,
|
||||||
|
ValueLocation*& _location)
|
||||||
|
{
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
NoOpStackFrameDebugInfo::ResolveDataMemberLocation(StackFrame* stackFrame,
|
||||||
|
Type* type, DataMember* member, const ValueLocation& parentLocation,
|
||||||
|
ValueLocation*& _location)
|
||||||
|
{
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef NO_OP_STACK_FRAME_DEBUG_INFO_H
|
||||||
|
#define NO_OP_STACK_FRAME_DEBUG_INFO_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "StackFrameDebugInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
class NoOpStackFrameDebugInfo : public StackFrameDebugInfo {
|
||||||
|
public:
|
||||||
|
NoOpStackFrameDebugInfo();
|
||||||
|
virtual ~NoOpStackFrameDebugInfo();
|
||||||
|
|
||||||
|
virtual status_t ResolveObjectDataLocation(
|
||||||
|
StackFrame* stackFrame, Type* type,
|
||||||
|
target_addr_t objectAddress,
|
||||||
|
ValueLocation*& _location);
|
||||||
|
virtual status_t ResolveBaseTypeLocation(
|
||||||
|
StackFrame* stackFrame, Type* type,
|
||||||
|
BaseType* baseType,
|
||||||
|
const ValueLocation& parentLocation,
|
||||||
|
ValueLocation*& _location);
|
||||||
|
virtual status_t ResolveDataMemberLocation(
|
||||||
|
StackFrame* stackFrame, Type* type,
|
||||||
|
DataMember* member,
|
||||||
|
const ValueLocation& parentLocation,
|
||||||
|
ValueLocation*& _location);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // NO_OP_STACK_FRAME_DEBUG_INFO_H
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
class Architecture;
|
class Architecture;
|
||||||
class CpuState;
|
class CpuState;
|
||||||
|
class DataMember;
|
||||||
class DebuggerInterface;
|
class DebuggerInterface;
|
||||||
class FileSourceCode;
|
class FileSourceCode;
|
||||||
class FunctionDebugInfo;
|
class FunctionDebugInfo;
|
||||||
@@ -23,6 +24,8 @@ class SourceLanguage;
|
|||||||
class SourceLocation;
|
class SourceLocation;
|
||||||
class StackFrame;
|
class StackFrame;
|
||||||
class Statement;
|
class Statement;
|
||||||
|
class Type;
|
||||||
|
class ValueLocation;
|
||||||
|
|
||||||
|
|
||||||
class SpecificImageDebugInfo : public Referenceable {
|
class SpecificImageDebugInfo : public Referenceable {
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "StackFrameDebugInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
StackFrameDebugInfo::StackFrameDebugInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
StackFrameDebugInfo::~StackFrameDebugInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef STACK_FRAME_DEBUG_INFO_H
|
||||||
|
#define STACK_FRAME_DEBUG_INFO_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Referenceable.h>
|
||||||
|
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
|
|
||||||
|
class BaseType;
|
||||||
|
class DataMember;
|
||||||
|
class StackFrame;
|
||||||
|
class Type;
|
||||||
|
class ValueLocation;
|
||||||
|
|
||||||
|
|
||||||
|
class StackFrameDebugInfo : public Referenceable {
|
||||||
|
public:
|
||||||
|
StackFrameDebugInfo();
|
||||||
|
virtual ~StackFrameDebugInfo();
|
||||||
|
|
||||||
|
virtual status_t ResolveObjectDataLocation(
|
||||||
|
StackFrame* stackFrame, Type* type,
|
||||||
|
target_addr_t objectAddress,
|
||||||
|
ValueLocation*& _location) = 0;
|
||||||
|
// returns a reference
|
||||||
|
virtual status_t ResolveBaseTypeLocation(
|
||||||
|
StackFrame* stackFrame, Type* type,
|
||||||
|
BaseType* baseType,
|
||||||
|
const ValueLocation& parentLocation,
|
||||||
|
ValueLocation*& _location) = 0;
|
||||||
|
// returns a reference
|
||||||
|
virtual status_t ResolveDataMemberLocation(
|
||||||
|
StackFrame* stackFrame, Type* type,
|
||||||
|
DataMember* member,
|
||||||
|
const ValueLocation& parentLocation,
|
||||||
|
ValueLocation*& _location) = 0;
|
||||||
|
// returns a reference
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // STACK_FRAME_DEBUG_INFO_H
|
||||||
@@ -481,7 +481,6 @@ TeamDebugInfo::DisassembleFunction(FunctionInstance* functionInstance,
|
|||||||
status_t
|
status_t
|
||||||
TeamDebugInfo::AddImageDebugInfo(ImageDebugInfo* imageDebugInfo)
|
TeamDebugInfo::AddImageDebugInfo(ImageDebugInfo* imageDebugInfo)
|
||||||
{
|
{
|
||||||
printf("TeamDebugInfo::AddImageDebugInfo(%p)\n", imageDebugInfo);
|
|
||||||
AutoLocker<BLocker> locker(fLock);
|
AutoLocker<BLocker> locker(fLock);
|
||||||
// We have both locks now, so that for read-only access either lock
|
// We have both locks now, so that for read-only access either lock
|
||||||
// suffices.
|
// suffices.
|
||||||
@@ -497,7 +496,6 @@ printf("TeamDebugInfo::AddImageDebugInfo(%p)\n", imageDebugInfo);
|
|||||||
Function* function = fFunctions->Lookup(instance);
|
Function* function = fFunctions->Lookup(instance);
|
||||||
if (function != NULL) {
|
if (function != NULL) {
|
||||||
// TODO: Also update possible user breakpoints in this function!
|
// TODO: Also update possible user breakpoints in this function!
|
||||||
printf(" adding instance %p to existing function %p\n", instance, function);
|
|
||||||
function->AddInstance(instance);
|
function->AddInstance(instance);
|
||||||
instance->SetFunction(function);
|
instance->SetFunction(function);
|
||||||
|
|
||||||
@@ -515,7 +513,6 @@ printf(" adding instance %p to existing function %p\n", instance, function);
|
|||||||
RemoveImageDebugInfo(imageDebugInfo);
|
RemoveImageDebugInfo(imageDebugInfo);
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
printf(" adding instance %p to new function %p\n", instance, function);
|
|
||||||
function->AddInstance(instance);
|
function->AddInstance(instance);
|
||||||
instance->SetFunction(function);
|
instance->SetFunction(function);
|
||||||
|
|
||||||
|
|||||||
@@ -209,6 +209,65 @@ struct ConstantAttributeValue {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct MemberLocation {
|
||||||
|
union {
|
||||||
|
uint64 constant;
|
||||||
|
off_t listOffset;
|
||||||
|
struct {
|
||||||
|
const void* data;
|
||||||
|
off_t length;
|
||||||
|
} expression;
|
||||||
|
};
|
||||||
|
uint8 attributeClass;
|
||||||
|
|
||||||
|
MemberLocation()
|
||||||
|
:
|
||||||
|
attributeClass(ATTRIBUTE_CLASS_UNKNOWN)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValid() const
|
||||||
|
{
|
||||||
|
return attributeClass != ATTRIBUTE_CLASS_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsConstant() const
|
||||||
|
{
|
||||||
|
return attributeClass == ATTRIBUTE_CLASS_CONSTANT;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsExpression() const
|
||||||
|
{
|
||||||
|
return attributeClass == ATTRIBUTE_CLASS_BLOCK
|
||||||
|
&& expression.data != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsLocationList() const
|
||||||
|
{
|
||||||
|
return attributeClass == ATTRIBUTE_CLASS_LOCLISTPTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetToConstant(uint64 constant)
|
||||||
|
{
|
||||||
|
this->constant = constant;
|
||||||
|
attributeClass = ATTRIBUTE_CLASS_CONSTANT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetToExpression(const void* data, off_t length)
|
||||||
|
{
|
||||||
|
expression.data = data;
|
||||||
|
expression.length = length;
|
||||||
|
attributeClass = ATTRIBUTE_CLASS_BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetToLocationList(off_t listOffset)
|
||||||
|
{
|
||||||
|
this->listOffset = listOffset;
|
||||||
|
attributeClass = ATTRIBUTE_CLASS_LOCLISTPTR;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct LocationDescription {
|
struct LocationDescription {
|
||||||
union {
|
union {
|
||||||
off_t listOffset; // location list
|
off_t listOffset; // location list
|
||||||
|
|||||||
@@ -215,6 +215,13 @@ DIEType::Name() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
DIEType::IsDeclaration() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const DynamicAttributeValue*
|
const DynamicAttributeValue*
|
||||||
DIEType::ByteSize() const
|
DIEType::ByteSize() const
|
||||||
{
|
{
|
||||||
@@ -313,6 +320,13 @@ DIEDeclaredType::AbstractOrigin() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
DIEDeclaredType::IsDeclaration() const
|
||||||
|
{
|
||||||
|
return fDeclaration;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DIEDeclaredType::AddAttribute_accessibility(uint16 attributeName,
|
DIEDeclaredType::AddAttribute_accessibility(uint16 attributeName,
|
||||||
const AttributeValue& value)
|
const AttributeValue& value)
|
||||||
@@ -563,6 +577,13 @@ DIEDeclaredNamedBase::Description() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
DIEDeclaredNamedBase::IsDeclaration() const
|
||||||
|
{
|
||||||
|
return fDeclaration;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DIEDeclaredNamedBase::AddAttribute_name(uint16 attributeName,
|
DIEDeclaredNamedBase::AddAttribute_name(uint16 attributeName,
|
||||||
const AttributeValue& value)
|
const AttributeValue& value)
|
||||||
@@ -994,6 +1015,38 @@ DIEMember::AddAttribute_type(uint16 attributeName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIEMember::AddAttribute_byte_size(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
return SetDynamicAttributeValue(fByteSize, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIEMember::AddAttribute_bit_size(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
return SetDynamicAttributeValue(fBitSize, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIEMember::AddAttribute_data_member_location(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
return SetMemberLocation(fLocation, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIEMember::AddAttribute_bit_offset(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
return SetDynamicAttributeValue(fBitOffset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DIEPointerType
|
// #pragma mark - DIEPointerType
|
||||||
|
|
||||||
|
|
||||||
@@ -1286,6 +1339,14 @@ DIEInheritance::AddAttribute_type(uint16 attributeName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIEInheritance::AddAttribute_data_member_location(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
return SetMemberLocation(fLocation, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DIEInlinedSubroutine
|
// #pragma mark - DIEInlinedSubroutine
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -219,6 +219,7 @@ public:
|
|||||||
|
|
||||||
virtual const char* Name() const;
|
virtual const char* Name() const;
|
||||||
|
|
||||||
|
virtual bool IsDeclaration() const;
|
||||||
virtual const DynamicAttributeValue* ByteSize() const;
|
virtual const DynamicAttributeValue* ByteSize() const;
|
||||||
|
|
||||||
virtual status_t AddAttribute_name(uint16 attributeName,
|
virtual status_t AddAttribute_name(uint16 attributeName,
|
||||||
@@ -272,6 +273,8 @@ public:
|
|||||||
virtual const char* Description() const;
|
virtual const char* Description() const;
|
||||||
virtual DebugInfoEntry* AbstractOrigin() const;
|
virtual DebugInfoEntry* AbstractOrigin() const;
|
||||||
|
|
||||||
|
virtual bool IsDeclaration() const;
|
||||||
|
|
||||||
virtual status_t AddAttribute_accessibility(uint16 attributeName,
|
virtual status_t AddAttribute_accessibility(uint16 attributeName,
|
||||||
const AttributeValue& value);
|
const AttributeValue& value);
|
||||||
// TODO: !file, !pointer to member
|
// TODO: !file, !pointer to member
|
||||||
@@ -348,6 +351,9 @@ class DIEClassBaseType : public DIECompoundType {
|
|||||||
public:
|
public:
|
||||||
DIEClassBaseType();
|
DIEClassBaseType();
|
||||||
|
|
||||||
|
const DebugInfoEntryList& BaseTypes() const
|
||||||
|
{ return fBaseTypes; }
|
||||||
|
|
||||||
virtual status_t AddChild(DebugInfoEntry* child);
|
virtual status_t AddChild(DebugInfoEntry* child);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -398,7 +404,7 @@ public:
|
|||||||
|
|
||||||
uint8 Accessibility() const { return fAccessibility; }
|
uint8 Accessibility() const { return fAccessibility; }
|
||||||
uint8 Visibility() const { return fVisibility; }
|
uint8 Visibility() const { return fVisibility; }
|
||||||
bool IsDeclaration() const { return fDeclaration; }
|
virtual bool IsDeclaration() const;
|
||||||
|
|
||||||
virtual status_t AddAttribute_name(uint16 attributeName,
|
virtual status_t AddAttribute_name(uint16 attributeName,
|
||||||
const AttributeValue& value);
|
const AttributeValue& value);
|
||||||
@@ -628,19 +634,36 @@ public:
|
|||||||
virtual uint16 Tag() const;
|
virtual uint16 Tag() const;
|
||||||
|
|
||||||
DIEType* GetType() const { return fType; }
|
DIEType* GetType() const { return fType; }
|
||||||
|
const DynamicAttributeValue* ByteSize() const
|
||||||
|
{ return &fByteSize; }
|
||||||
|
const DynamicAttributeValue* BitOffset() const
|
||||||
|
{ return &fBitOffset; }
|
||||||
|
const DynamicAttributeValue* BitSize() const
|
||||||
|
{ return &fBitSize; }
|
||||||
|
const MemberLocation* Location() const
|
||||||
|
{ return &fLocation; }
|
||||||
|
|
||||||
virtual status_t AddAttribute_type(uint16 attributeName,
|
virtual status_t AddAttribute_type(uint16 attributeName,
|
||||||
const AttributeValue& value);
|
const AttributeValue& value);
|
||||||
|
virtual status_t AddAttribute_byte_size(uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
virtual status_t AddAttribute_bit_size(uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
virtual status_t AddAttribute_bit_offset(uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
virtual status_t AddAttribute_data_member_location(
|
||||||
|
uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// DW_AT_bit_offset
|
|
||||||
// DW_AT_bit_size
|
|
||||||
// DW_AT_byte_size
|
|
||||||
// DW_AT_data_member_location
|
|
||||||
// DW_AT_mutable
|
// DW_AT_mutable
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DIEType* fType;
|
DIEType* fType;
|
||||||
|
DynamicAttributeValue fByteSize;
|
||||||
|
DynamicAttributeValue fBitOffset;
|
||||||
|
DynamicAttributeValue fBitSize;
|
||||||
|
MemberLocation fLocation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -805,17 +828,22 @@ public:
|
|||||||
virtual uint16 Tag() const;
|
virtual uint16 Tag() const;
|
||||||
|
|
||||||
DIEType* GetType() const { return fType; }
|
DIEType* GetType() const { return fType; }
|
||||||
|
const MemberLocation* Location() const
|
||||||
|
{ return &fLocation; }
|
||||||
|
|
||||||
virtual status_t AddAttribute_type(uint16 attributeName,
|
virtual status_t AddAttribute_type(uint16 attributeName,
|
||||||
const AttributeValue& value);
|
const AttributeValue& value);
|
||||||
|
virtual status_t AddAttribute_data_member_location(
|
||||||
|
uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// DW_AT_accessibility
|
// DW_AT_accessibility
|
||||||
// DW_AT_data_member_location
|
|
||||||
// DW_AT_virtuality
|
// DW_AT_virtuality
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DIEType* fType;
|
DIEType* fType;
|
||||||
|
MemberLocation fLocation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -346,3 +346,23 @@ DebugInfoEntry::SetConstantAttributeValue(ConstantAttributeValue& toSet,
|
|||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DebugInfoEntry::SetMemberLocation(MemberLocation& toSet,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
switch (value.attributeClass) {
|
||||||
|
case ATTRIBUTE_CLASS_CONSTANT:
|
||||||
|
toSet.SetToConstant(value.constant);
|
||||||
|
return B_OK;
|
||||||
|
case ATTRIBUTE_CLASS_BLOCK:
|
||||||
|
toSet.SetToExpression(value.block.data, value.block.length);
|
||||||
|
return B_OK;
|
||||||
|
case ATTRIBUTE_CLASS_LOCLISTPTR:
|
||||||
|
toSet.SetToLocationList(value.pointer);
|
||||||
|
return B_OK;
|
||||||
|
default:
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ struct ConstantAttributeValue;
|
|||||||
struct DeclarationLocation;
|
struct DeclarationLocation;
|
||||||
struct DynamicAttributeValue;
|
struct DynamicAttributeValue;
|
||||||
struct LocationDescription;
|
struct LocationDescription;
|
||||||
|
struct MemberLocation;
|
||||||
struct SourceLanguageInfo;
|
struct SourceLanguageInfo;
|
||||||
|
|
||||||
|
|
||||||
@@ -171,6 +172,8 @@ protected:
|
|||||||
status_t SetConstantAttributeValue(
|
status_t SetConstantAttributeValue(
|
||||||
ConstantAttributeValue& toSet,
|
ConstantAttributeValue& toSet,
|
||||||
const AttributeValue& value);
|
const AttributeValue& value);
|
||||||
|
status_t SetMemberLocation(MemberLocation& toSet,
|
||||||
|
const AttributeValue& value);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DebugInfoEntry* fParent;
|
DebugInfoEntry* fParent;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "DataReader.h"
|
#include "DataReader.h"
|
||||||
#include "Dwarf.h"
|
#include "Dwarf.h"
|
||||||
#include "DwarfTargetInterface.h"
|
#include "DwarfTargetInterface.h"
|
||||||
|
#include "Tracing.h"
|
||||||
#include "ValueLocation.h"
|
#include "ValueLocation.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -147,7 +148,8 @@ DwarfExpressionEvaluator::Evaluate(const void* expression, size_t size,
|
|||||||
_result = _Pop();
|
_result = _Pop();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
} catch (const EvaluationException& exception) {
|
} catch (const EvaluationException& exception) {
|
||||||
printf("DwarfExpressionEvaluator::Evaluate(): %s\n", exception.message);
|
WARNING("DwarfExpressionEvaluator::Evaluate(): %s\n",
|
||||||
|
exception.message);
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
} catch (const std::bad_alloc& exception) {
|
} catch (const std::bad_alloc& exception) {
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
@@ -173,6 +175,11 @@ DwarfExpressionEvaluator::EvaluateLocation(const void* expression, size_t size,
|
|||||||
|
|
||||||
// parse the first (and maybe only) expression
|
// parse the first (and maybe only) expression
|
||||||
try {
|
try {
|
||||||
|
// push the object address, if any
|
||||||
|
target_addr_t objectAddress;
|
||||||
|
if (fContext->GetObjectAddress(objectAddress))
|
||||||
|
_Push(objectAddress);
|
||||||
|
|
||||||
ValuePieceLocation piece;
|
ValuePieceLocation piece;
|
||||||
status_t error = _Evaluate(&piece);
|
status_t error = _Evaluate(&piece);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
@@ -201,7 +208,8 @@ DwarfExpressionEvaluator::EvaluateLocation(const void* expression, size_t size,
|
|||||||
if (fDataReader.BytesRemaining() == 0)
|
if (fDataReader.BytesRemaining() == 0)
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
} catch (const EvaluationException& exception) {
|
} catch (const EvaluationException& exception) {
|
||||||
printf("DwarfExpressionEvaluator::EvaluateLocation(): %s\n", exception.message);
|
WARNING("DwarfExpressionEvaluator::EvaluateLocation(): %s\n",
|
||||||
|
exception.message);
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
} catch (const std::bad_alloc& exception) {
|
} catch (const std::bad_alloc& exception) {
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
@@ -215,6 +223,11 @@ printf("DwarfExpressionEvaluator::EvaluateLocation(): %s\n", exception.message);
|
|||||||
fDataReader.AddressSize());
|
fDataReader.AddressSize());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// push the object address, if any
|
||||||
|
target_addr_t objectAddress;
|
||||||
|
if (fContext->GetObjectAddress(objectAddress))
|
||||||
|
_Push(objectAddress);
|
||||||
|
|
||||||
ValuePieceLocation piece;
|
ValuePieceLocation piece;
|
||||||
status_t error = _Evaluate(&piece);
|
status_t error = _Evaluate(&piece);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
@@ -236,7 +249,8 @@ printf("DwarfExpressionEvaluator::EvaluateLocation(): %s\n", exception.message);
|
|||||||
} else
|
} else
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
} catch (const EvaluationException& exception) {
|
} catch (const EvaluationException& exception) {
|
||||||
printf("DwarfExpressionEvaluator::EvaluateLocation(): %s\n", exception.message);
|
WARNING("DwarfExpressionEvaluator::EvaluateLocation(): %s\n",
|
||||||
|
exception.message);
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
} catch (const std::bad_alloc& exception) {
|
} catch (const std::bad_alloc& exception) {
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
@@ -250,15 +264,16 @@ printf("DwarfExpressionEvaluator::EvaluateLocation(): %s\n", exception.message);
|
|||||||
status_t
|
status_t
|
||||||
DwarfExpressionEvaluator::_Evaluate(ValuePieceLocation* _piece)
|
DwarfExpressionEvaluator::_Evaluate(ValuePieceLocation* _piece)
|
||||||
{
|
{
|
||||||
{
|
TRACE_EXPR_ONLY({
|
||||||
printf("DwarfExpressionEvaluator::_Evaluate(%p, %lld)\n", fDataReader.Data(),
|
TRACE_EXPR("DwarfExpressionEvaluator::_Evaluate(%p, %lld)\n",
|
||||||
fDataReader.BytesRemaining());
|
fDataReader.Data(), fDataReader.BytesRemaining());
|
||||||
const uint8* data = (const uint8*)fDataReader.Data();
|
const uint8* data = (const uint8*)fDataReader.Data();
|
||||||
int32 count = fDataReader.BytesRemaining();
|
int32 count = fDataReader.BytesRemaining();
|
||||||
for (int32 i = 0; i < count; i++)
|
for (int32 i = 0; i < count; i++)
|
||||||
printf(" %02x", data[i]);
|
TRACE_EXPR(" %02x", data[i]);
|
||||||
printf("\n");
|
TRACE_EXPR("\n");
|
||||||
}
|
})
|
||||||
|
|
||||||
uint32 operationsExecuted = 0;
|
uint32 operationsExecuted = 0;
|
||||||
|
|
||||||
while (fDataReader.BytesRemaining() > 0) {
|
while (fDataReader.BytesRemaining() > 0) {
|
||||||
@@ -266,66 +281,66 @@ printf("\n");
|
|||||||
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case DW_OP_addr:
|
case DW_OP_addr:
|
||||||
printf(" DW_OP_addr\n");
|
TRACE_EXPR(" DW_OP_addr\n");
|
||||||
_Push(fDataReader.ReadAddress(0));
|
_Push(fDataReader.ReadAddress(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_const1u:
|
case DW_OP_const1u:
|
||||||
printf(" DW_OP_const1u\n");
|
TRACE_EXPR(" DW_OP_const1u\n");
|
||||||
_Push(fDataReader.Read<uint8>(0));
|
_Push(fDataReader.Read<uint8>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_const1s:
|
case DW_OP_const1s:
|
||||||
printf(" DW_OP_const1s\n");
|
TRACE_EXPR(" DW_OP_const1s\n");
|
||||||
_Push(fDataReader.Read<int8>(0));
|
_Push(fDataReader.Read<int8>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_const2u:
|
case DW_OP_const2u:
|
||||||
printf(" DW_OP_const2u\n");
|
TRACE_EXPR(" DW_OP_const2u\n");
|
||||||
_Push(fDataReader.Read<uint16>(0));
|
_Push(fDataReader.Read<uint16>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_const2s:
|
case DW_OP_const2s:
|
||||||
printf(" DW_OP_const2s\n");
|
TRACE_EXPR(" DW_OP_const2s\n");
|
||||||
_Push(fDataReader.Read<int16>(0));
|
_Push(fDataReader.Read<int16>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_const4u:
|
case DW_OP_const4u:
|
||||||
printf(" DW_OP_const4u\n");
|
TRACE_EXPR(" DW_OP_const4u\n");
|
||||||
_Push(fDataReader.Read<uint32>(0));
|
_Push(fDataReader.Read<uint32>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_const4s:
|
case DW_OP_const4s:
|
||||||
printf(" DW_OP_const4s\n");
|
TRACE_EXPR(" DW_OP_const4s\n");
|
||||||
_Push(fDataReader.Read<int32>(0));
|
_Push(fDataReader.Read<int32>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_const8u:
|
case DW_OP_const8u:
|
||||||
printf(" DW_OP_const8u\n");
|
TRACE_EXPR(" DW_OP_const8u\n");
|
||||||
_Push(fDataReader.Read<uint64>(0));
|
_Push(fDataReader.Read<uint64>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_const8s:
|
case DW_OP_const8s:
|
||||||
printf(" DW_OP_const8s\n");
|
TRACE_EXPR(" DW_OP_const8s\n");
|
||||||
_Push(fDataReader.Read<int64>(0));
|
_Push(fDataReader.Read<int64>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_constu:
|
case DW_OP_constu:
|
||||||
printf(" DW_OP_constu\n");
|
TRACE_EXPR(" DW_OP_constu\n");
|
||||||
_Push(fDataReader.ReadUnsignedLEB128(0));
|
_Push(fDataReader.ReadUnsignedLEB128(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_consts:
|
case DW_OP_consts:
|
||||||
printf(" DW_OP_consts\n");
|
TRACE_EXPR(" DW_OP_consts\n");
|
||||||
_Push(fDataReader.ReadSignedLEB128(0));
|
_Push(fDataReader.ReadSignedLEB128(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_dup:
|
case DW_OP_dup:
|
||||||
printf(" DW_OP_dup\n");
|
TRACE_EXPR(" DW_OP_dup\n");
|
||||||
_AssertMinStackSize(1);
|
_AssertMinStackSize(1);
|
||||||
_Push(fStack[fStackSize - 1]);
|
_Push(fStack[fStackSize - 1]);
|
||||||
break;
|
break;
|
||||||
case DW_OP_drop:
|
case DW_OP_drop:
|
||||||
printf(" DW_OP_drop\n");
|
TRACE_EXPR(" DW_OP_drop\n");
|
||||||
_Pop();
|
_Pop();
|
||||||
break;
|
break;
|
||||||
case DW_OP_over:
|
case DW_OP_over:
|
||||||
printf(" DW_OP_over\n");
|
TRACE_EXPR(" DW_OP_over\n");
|
||||||
_AssertMinStackSize(1);
|
_AssertMinStackSize(1);
|
||||||
_Push(fStack[fStackSize - 2]);
|
_Push(fStack[fStackSize - 2]);
|
||||||
break;
|
break;
|
||||||
case DW_OP_pick:
|
case DW_OP_pick:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_pick\n");
|
TRACE_EXPR(" DW_OP_pick\n");
|
||||||
uint8 index = fDataReader.Read<uint8>(0);
|
uint8 index = fDataReader.Read<uint8>(0);
|
||||||
_AssertMinStackSize(index + 1);
|
_AssertMinStackSize(index + 1);
|
||||||
_Push(fStack[fStackSize - index - 1]);
|
_Push(fStack[fStackSize - index - 1]);
|
||||||
@@ -333,14 +348,14 @@ printf(" DW_OP_pick\n");
|
|||||||
}
|
}
|
||||||
case DW_OP_swap:
|
case DW_OP_swap:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_swap\n");
|
TRACE_EXPR(" DW_OP_swap\n");
|
||||||
_AssertMinStackSize(2);
|
_AssertMinStackSize(2);
|
||||||
std::swap(fStack[fStackSize - 1], fStack[fStackSize - 2]);
|
std::swap(fStack[fStackSize - 1], fStack[fStackSize - 2]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_rot:
|
case DW_OP_rot:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_rot\n");
|
TRACE_EXPR(" DW_OP_rot\n");
|
||||||
_AssertMinStackSize(3);
|
_AssertMinStackSize(3);
|
||||||
target_addr_t tmp = fStack[fStackSize - 1];
|
target_addr_t tmp = fStack[fStackSize - 1];
|
||||||
fStack[fStackSize - 1] = fStack[fStackSize - 2];
|
fStack[fStackSize - 1] = fStack[fStackSize - 2];
|
||||||
@@ -350,25 +365,25 @@ printf(" DW_OP_rot\n");
|
|||||||
}
|
}
|
||||||
|
|
||||||
case DW_OP_deref:
|
case DW_OP_deref:
|
||||||
printf(" DW_OP_deref\n");
|
TRACE_EXPR(" DW_OP_deref\n");
|
||||||
_DereferenceAddress(fContext->AddressSize());
|
_DereferenceAddress(fContext->AddressSize());
|
||||||
break;
|
break;
|
||||||
case DW_OP_deref_size:
|
case DW_OP_deref_size:
|
||||||
printf(" DW_OP_deref_size\n");
|
TRACE_EXPR(" DW_OP_deref_size\n");
|
||||||
_DereferenceAddress(fDataReader.Read<uint8>(0));
|
_DereferenceAddress(fDataReader.Read<uint8>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_xderef:
|
case DW_OP_xderef:
|
||||||
printf(" DW_OP_xderef\n");
|
TRACE_EXPR(" DW_OP_xderef\n");
|
||||||
_DereferenceAddressSpaceAddress(fContext->AddressSize());
|
_DereferenceAddressSpaceAddress(fContext->AddressSize());
|
||||||
break;
|
break;
|
||||||
case DW_OP_xderef_size:
|
case DW_OP_xderef_size:
|
||||||
printf(" DW_OP_xderef_size\n");
|
TRACE_EXPR(" DW_OP_xderef_size\n");
|
||||||
_DereferenceAddressSpaceAddress(fDataReader.Read<uint8>(0));
|
_DereferenceAddressSpaceAddress(fDataReader.Read<uint8>(0));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_OP_abs:
|
case DW_OP_abs:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_abs\n");
|
TRACE_EXPR(" DW_OP_abs\n");
|
||||||
target_addr_t value = _Pop();
|
target_addr_t value = _Pop();
|
||||||
if (fContext->AddressSize() == 4) {
|
if (fContext->AddressSize() == 4) {
|
||||||
int32 signedValue = (int32)value;
|
int32 signedValue = (int32)value;
|
||||||
@@ -380,12 +395,12 @@ printf(" DW_OP_abs\n");
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_and:
|
case DW_OP_and:
|
||||||
printf(" DW_OP_and\n");
|
TRACE_EXPR(" DW_OP_and\n");
|
||||||
_Push(_Pop() & _Pop());
|
_Push(_Pop() & _Pop());
|
||||||
break;
|
break;
|
||||||
case DW_OP_div:
|
case DW_OP_div:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_div\n");
|
TRACE_EXPR(" DW_OP_div\n");
|
||||||
int64 top = (int64)_Pop();
|
int64 top = (int64)_Pop();
|
||||||
int64 second = (int64)_Pop();
|
int64 second = (int64)_Pop();
|
||||||
_Push(top != 0 ? second / top : 0);
|
_Push(top != 0 ? second / top : 0);
|
||||||
@@ -393,14 +408,14 @@ printf(" DW_OP_div\n");
|
|||||||
}
|
}
|
||||||
case DW_OP_minus:
|
case DW_OP_minus:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_minus\n");
|
TRACE_EXPR(" DW_OP_minus\n");
|
||||||
target_addr_t top = _Pop();
|
target_addr_t top = _Pop();
|
||||||
_Push(_Pop() - top);
|
_Push(_Pop() - top);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_mod:
|
case DW_OP_mod:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_mod\n");
|
TRACE_EXPR(" DW_OP_mod\n");
|
||||||
// While the specs explicitly speak of signed integer division
|
// While the specs explicitly speak of signed integer division
|
||||||
// for "div", nothing is mentioned for "mod".
|
// for "div", nothing is mentioned for "mod".
|
||||||
target_addr_t top = _Pop();
|
target_addr_t top = _Pop();
|
||||||
@@ -409,12 +424,12 @@ printf(" DW_OP_mod\n");
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_mul:
|
case DW_OP_mul:
|
||||||
printf(" DW_OP_mul\n");
|
TRACE_EXPR(" DW_OP_mul\n");
|
||||||
_Push(_Pop() * _Pop());
|
_Push(_Pop() * _Pop());
|
||||||
break;
|
break;
|
||||||
case DW_OP_neg:
|
case DW_OP_neg:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_neg\n");
|
TRACE_EXPR(" DW_OP_neg\n");
|
||||||
if (fContext->AddressSize() == 4)
|
if (fContext->AddressSize() == 4)
|
||||||
_Push(-(int32)_Pop());
|
_Push(-(int32)_Pop());
|
||||||
else
|
else
|
||||||
@@ -422,38 +437,38 @@ printf(" DW_OP_neg\n");
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_not:
|
case DW_OP_not:
|
||||||
printf(" DW_OP_not\n");
|
TRACE_EXPR(" DW_OP_not\n");
|
||||||
_Push(~_Pop());
|
_Push(~_Pop());
|
||||||
break;
|
break;
|
||||||
case DW_OP_or:
|
case DW_OP_or:
|
||||||
printf(" DW_OP_or\n");
|
TRACE_EXPR(" DW_OP_or\n");
|
||||||
_Push(_Pop() | _Pop());
|
_Push(_Pop() | _Pop());
|
||||||
break;
|
break;
|
||||||
case DW_OP_plus:
|
case DW_OP_plus:
|
||||||
printf(" DW_OP_plus\n");
|
TRACE_EXPR(" DW_OP_plus\n");
|
||||||
_Push(_Pop() + _Pop());
|
_Push(_Pop() + _Pop());
|
||||||
break;
|
break;
|
||||||
case DW_OP_plus_uconst:
|
case DW_OP_plus_uconst:
|
||||||
printf(" DW_OP_plus_uconst\n");
|
TRACE_EXPR(" DW_OP_plus_uconst\n");
|
||||||
_Push(_Pop() + fDataReader.ReadUnsignedLEB128(0));
|
_Push(_Pop() + fDataReader.ReadUnsignedLEB128(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_shl:
|
case DW_OP_shl:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_shl\n");
|
TRACE_EXPR(" DW_OP_shl\n");
|
||||||
target_addr_t top = _Pop();
|
target_addr_t top = _Pop();
|
||||||
_Push(_Pop() << top);
|
_Push(_Pop() << top);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_shr:
|
case DW_OP_shr:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_shr\n");
|
TRACE_EXPR(" DW_OP_shr\n");
|
||||||
target_addr_t top = _Pop();
|
target_addr_t top = _Pop();
|
||||||
_Push(_Pop() >> top);
|
_Push(_Pop() >> top);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_shra:
|
case DW_OP_shra:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_shra\n");
|
TRACE_EXPR(" DW_OP_shra\n");
|
||||||
target_addr_t top = _Pop();
|
target_addr_t top = _Pop();
|
||||||
int64 second = (int64)_Pop();
|
int64 second = (int64)_Pop();
|
||||||
_Push(second >= 0 ? second >> top : -(-second >> top));
|
_Push(second >= 0 ? second >> top : -(-second >> top));
|
||||||
@@ -461,18 +476,18 @@ printf(" DW_OP_shra\n");
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_xor:
|
case DW_OP_xor:
|
||||||
printf(" DW_OP_xor\n");
|
TRACE_EXPR(" DW_OP_xor\n");
|
||||||
_Push(_Pop() ^ _Pop());
|
_Push(_Pop() ^ _Pop());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_OP_bra:
|
case DW_OP_bra:
|
||||||
printf(" DW_OP_bra\n");
|
TRACE_EXPR(" DW_OP_bra\n");
|
||||||
if (_Pop() == 0)
|
if (_Pop() == 0)
|
||||||
break;
|
break;
|
||||||
// fall through
|
// fall through
|
||||||
case DW_OP_skip:
|
case DW_OP_skip:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_skip\n");
|
TRACE_EXPR(" DW_OP_skip\n");
|
||||||
int16 offset = fDataReader.Read<int16>(0);
|
int16 offset = fDataReader.Read<int16>(0);
|
||||||
if (offset >= 0 ? offset > fDataReader.BytesRemaining()
|
if (offset >= 0 ? offset > fDataReader.BytesRemaining()
|
||||||
: -offset > fDataReader.Offset()) {
|
: -offset > fDataReader.Offset()) {
|
||||||
@@ -483,45 +498,45 @@ printf(" DW_OP_skip\n");
|
|||||||
}
|
}
|
||||||
|
|
||||||
case DW_OP_eq:
|
case DW_OP_eq:
|
||||||
printf(" DW_OP_eq\n");
|
TRACE_EXPR(" DW_OP_eq\n");
|
||||||
_Push(_Pop() == _Pop() ? 1 : 0);
|
_Push(_Pop() == _Pop() ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
case DW_OP_ge:
|
case DW_OP_ge:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_ge\n");
|
TRACE_EXPR(" DW_OP_ge\n");
|
||||||
int64 top = (int64)_Pop();
|
int64 top = (int64)_Pop();
|
||||||
_Push((int64)_Pop() >= top ? 1 : 0);
|
_Push((int64)_Pop() >= top ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_gt:
|
case DW_OP_gt:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_gt\n");
|
TRACE_EXPR(" DW_OP_gt\n");
|
||||||
int64 top = (int64)_Pop();
|
int64 top = (int64)_Pop();
|
||||||
_Push((int64)_Pop() > top ? 1 : 0);
|
_Push((int64)_Pop() > top ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_le:
|
case DW_OP_le:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_le\n");
|
TRACE_EXPR(" DW_OP_le\n");
|
||||||
int64 top = (int64)_Pop();
|
int64 top = (int64)_Pop();
|
||||||
_Push((int64)_Pop() <= top ? 1 : 0);
|
_Push((int64)_Pop() <= top ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_lt:
|
case DW_OP_lt:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_lt\n");
|
TRACE_EXPR(" DW_OP_lt\n");
|
||||||
int64 top = (int64)_Pop();
|
int64 top = (int64)_Pop();
|
||||||
_Push((int64)_Pop() < top ? 1 : 0);
|
_Push((int64)_Pop() < top ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_ne:
|
case DW_OP_ne:
|
||||||
printf(" DW_OP_ne\n");
|
TRACE_EXPR(" DW_OP_ne\n");
|
||||||
_Push(_Pop() == _Pop() ? 1 : 0);
|
_Push(_Pop() == _Pop() ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_OP_push_object_address:
|
case DW_OP_push_object_address:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_push_object_address\n");
|
TRACE_EXPR(" DW_OP_push_object_address\n");
|
||||||
target_addr_t address;
|
target_addr_t address;
|
||||||
if (!fContext->GetObjectAddress(address))
|
if (!fContext->GetObjectAddress(address))
|
||||||
throw EvaluationException("failed to get object address");
|
throw EvaluationException("failed to get object address");
|
||||||
@@ -530,7 +545,7 @@ printf(" DW_OP_push_object_address\n");
|
|||||||
}
|
}
|
||||||
case DW_OP_call_frame_cfa:
|
case DW_OP_call_frame_cfa:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_call_frame_cfa\n");
|
TRACE_EXPR(" DW_OP_call_frame_cfa\n");
|
||||||
target_addr_t address;
|
target_addr_t address;
|
||||||
if (!fContext->GetFrameAddress(address))
|
if (!fContext->GetFrameAddress(address))
|
||||||
throw EvaluationException("failed to get frame address");
|
throw EvaluationException("failed to get frame address");
|
||||||
@@ -540,7 +555,7 @@ printf(" DW_OP_call_frame_cfa\n");
|
|||||||
case DW_OP_fbreg:
|
case DW_OP_fbreg:
|
||||||
{
|
{
|
||||||
int64 offset = fDataReader.ReadSignedLEB128(0);
|
int64 offset = fDataReader.ReadSignedLEB128(0);
|
||||||
printf(" DW_OP_fbreg(%lld)\n", offset);
|
TRACE_EXPR(" DW_OP_fbreg(%lld)\n", offset);
|
||||||
target_addr_t address;
|
target_addr_t address;
|
||||||
if (!fContext->GetFrameBaseAddress(address)) {
|
if (!fContext->GetFrameBaseAddress(address)) {
|
||||||
throw EvaluationException(
|
throw EvaluationException(
|
||||||
@@ -551,7 +566,7 @@ printf(" DW_OP_fbreg(%lld)\n", offset);
|
|||||||
}
|
}
|
||||||
case DW_OP_form_tls_address:
|
case DW_OP_form_tls_address:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_form_tls_address\n");
|
TRACE_EXPR(" DW_OP_form_tls_address\n");
|
||||||
target_addr_t address;
|
target_addr_t address;
|
||||||
if (!fContext->GetTLSAddress(_Pop(), address))
|
if (!fContext->GetTLSAddress(_Pop(), address))
|
||||||
throw EvaluationException("failed to get tls address");
|
throw EvaluationException("failed to get tls address");
|
||||||
@@ -561,7 +576,7 @@ printf(" DW_OP_form_tls_address\n");
|
|||||||
|
|
||||||
case DW_OP_regx:
|
case DW_OP_regx:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_regx\n");
|
TRACE_EXPR(" DW_OP_regx\n");
|
||||||
if (_piece == NULL) {
|
if (_piece == NULL) {
|
||||||
throw EvaluationException(
|
throw EvaluationException(
|
||||||
"DW_OP_regx in non-location expression");
|
"DW_OP_regx in non-location expression");
|
||||||
@@ -575,22 +590,22 @@ printf(" DW_OP_regx\n");
|
|||||||
|
|
||||||
case DW_OP_bregx:
|
case DW_OP_bregx:
|
||||||
{
|
{
|
||||||
printf(" DW_OP_bregx\n");
|
TRACE_EXPR(" DW_OP_bregx\n");
|
||||||
uint32 reg = fDataReader.ReadUnsignedLEB128(0);
|
uint32 reg = fDataReader.ReadUnsignedLEB128(0);
|
||||||
_PushRegister(reg, fDataReader.ReadSignedLEB128(0));
|
_PushRegister(reg, fDataReader.ReadSignedLEB128(0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case DW_OP_call2:
|
case DW_OP_call2:
|
||||||
printf(" DW_OP_call2\n");
|
TRACE_EXPR(" DW_OP_call2\n");
|
||||||
_Call(fDataReader.Read<uint16>(0), true);
|
_Call(fDataReader.Read<uint16>(0), true);
|
||||||
break;
|
break;
|
||||||
case DW_OP_call4:
|
case DW_OP_call4:
|
||||||
printf(" DW_OP_call4\n");
|
TRACE_EXPR(" DW_OP_call4\n");
|
||||||
_Call(fDataReader.Read<uint32>(0), true);
|
_Call(fDataReader.Read<uint32>(0), true);
|
||||||
break;
|
break;
|
||||||
case DW_OP_call_ref:
|
case DW_OP_call_ref:
|
||||||
printf(" DW_OP_call_ref\n");
|
TRACE_EXPR(" DW_OP_call_ref\n");
|
||||||
if (fContext->AddressSize() == 4)
|
if (fContext->AddressSize() == 4)
|
||||||
_Call(fDataReader.Read<uint32>(0), false);
|
_Call(fDataReader.Read<uint32>(0), false);
|
||||||
else
|
else
|
||||||
@@ -608,15 +623,15 @@ printf(" DW_OP_call_ref\n");
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
case DW_OP_nop:
|
case DW_OP_nop:
|
||||||
printf(" DW_OP_nop\n");
|
TRACE_EXPR(" DW_OP_nop\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (opcode >= DW_OP_lit0 && opcode <= DW_OP_lit31) {
|
if (opcode >= DW_OP_lit0 && opcode <= DW_OP_lit31) {
|
||||||
printf(" DW_OP_lit%u\n", opcode - DW_OP_lit0);
|
TRACE_EXPR(" DW_OP_lit%u\n", opcode - DW_OP_lit0);
|
||||||
_Push(opcode - DW_OP_lit0);
|
_Push(opcode - DW_OP_lit0);
|
||||||
} else if (opcode >= DW_OP_reg0 && opcode <= DW_OP_reg31) {
|
} else if (opcode >= DW_OP_reg0 && opcode <= DW_OP_reg31) {
|
||||||
printf(" DW_OP_reg%u\n", opcode - DW_OP_reg0);
|
TRACE_EXPR(" DW_OP_reg%u\n", opcode - DW_OP_reg0);
|
||||||
if (_piece == NULL) {
|
if (_piece == NULL) {
|
||||||
throw EvaluationException(
|
throw EvaluationException(
|
||||||
"DW_OP_reg* in non-location expression");
|
"DW_OP_reg* in non-location expression");
|
||||||
@@ -625,11 +640,12 @@ printf(" DW_OP_reg%u\n", opcode - DW_OP_reg0);
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
} else if (opcode >= DW_OP_breg0 && opcode <= DW_OP_breg31) {
|
} else if (opcode >= DW_OP_breg0 && opcode <= DW_OP_breg31) {
|
||||||
int64 offset = fDataReader.ReadSignedLEB128(0);
|
int64 offset = fDataReader.ReadSignedLEB128(0);
|
||||||
printf(" DW_OP_breg%u(%lld)\n", opcode - DW_OP_breg0, offset);
|
TRACE_EXPR(" DW_OP_breg%u(%lld)\n", opcode - DW_OP_breg0,
|
||||||
|
offset);
|
||||||
_PushRegister(opcode - DW_OP_breg0, offset);
|
_PushRegister(opcode - DW_OP_breg0, offset);
|
||||||
} else {
|
} else {
|
||||||
printf("DwarfExpressionEvaluator::_Evaluate(): unsupported "
|
WARNING("DwarfExpressionEvaluator::_Evaluate(): "
|
||||||
"opcode: %u\n", opcode);
|
"unsupported opcode: %u\n", opcode);
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "ElfFile.h"
|
#include "ElfFile.h"
|
||||||
#include "TagNames.h"
|
#include "TagNames.h"
|
||||||
#include "TargetAddressRangeList.h"
|
#include "TargetAddressRangeList.h"
|
||||||
|
#include "Tracing.h"
|
||||||
#include "Variant.h"
|
#include "Variant.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -96,7 +97,9 @@ public:
|
|||||||
fFrameBasePointer);
|
fFrameBasePointer);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return false;
|
return false;
|
||||||
printf(" -> frame base: %llx\n", fFrameBasePointer);
|
|
||||||
|
TRACE_EXPR(" -> frame base: %llx\n", fFrameBasePointer);
|
||||||
|
|
||||||
_address = fFrameBasePointer;
|
_address = fFrameBasePointer;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -155,6 +158,7 @@ DwarfFile::DwarfFile()
|
|||||||
fDebugLineSection(NULL),
|
fDebugLineSection(NULL),
|
||||||
fDebugFrameSection(NULL),
|
fDebugFrameSection(NULL),
|
||||||
fDebugLocationSection(NULL),
|
fDebugLocationSection(NULL),
|
||||||
|
fDebugPublicTypesSection(NULL),
|
||||||
fCompilationUnits(20, true),
|
fCompilationUnits(20, true),
|
||||||
fCurrentCompilationUnit(NULL),
|
fCurrentCompilationUnit(NULL),
|
||||||
fFinished(false),
|
fFinished(false),
|
||||||
@@ -176,6 +180,7 @@ DwarfFile::~DwarfFile()
|
|||||||
fElfFile->PutSection(fDebugLineSection);
|
fElfFile->PutSection(fDebugLineSection);
|
||||||
fElfFile->PutSection(fDebugFrameSection);
|
fElfFile->PutSection(fDebugFrameSection);
|
||||||
fElfFile->PutSection(fDebugLocationSection);
|
fElfFile->PutSection(fDebugLocationSection);
|
||||||
|
fElfFile->PutSection(fDebugPublicTypesSection);
|
||||||
delete fElfFile;
|
delete fElfFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,9 +208,8 @@ DwarfFile::Load(const char* fileName)
|
|||||||
fDebugInfoSection = fElfFile->GetSection(".debug_info");
|
fDebugInfoSection = fElfFile->GetSection(".debug_info");
|
||||||
fDebugAbbrevSection = fElfFile->GetSection(".debug_abbrev");
|
fDebugAbbrevSection = fElfFile->GetSection(".debug_abbrev");
|
||||||
if (fDebugInfoSection == NULL || fDebugAbbrevSection == NULL) {
|
if (fDebugInfoSection == NULL || fDebugAbbrevSection == NULL) {
|
||||||
fprintf(stderr, "DwarfManager::File::Load(\"%s\"): no "
|
WARNING("DwarfManager::File::Load(\"%s\"): no "
|
||||||
".debug_info, .debug_abbrev, or .debug_str section.\n",
|
".debug_info or .debug_abbrev.\n", fileName);
|
||||||
fileName);
|
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,6 +219,8 @@ DwarfFile::Load(const char* fileName)
|
|||||||
fDebugLineSection = fElfFile->GetSection(".debug_line");
|
fDebugLineSection = fElfFile->GetSection(".debug_line");
|
||||||
fDebugFrameSection = fElfFile->GetSection(".debug_frame");
|
fDebugFrameSection = fElfFile->GetSection(".debug_frame");
|
||||||
fDebugLocationSection = fElfFile->GetSection(".debug_loc");
|
fDebugLocationSection = fElfFile->GetSection(".debug_loc");
|
||||||
|
// fDebugPublicTypesSection = fElfFile->GetSection(".debug_pubtypes");
|
||||||
|
fDebugPublicTypesSection = fElfFile->GetSection(".debug_pubnames");
|
||||||
|
|
||||||
// iterate through the debug info section
|
// iterate through the debug info section
|
||||||
DataReader dataReader(fDebugInfoSection->Data(),
|
DataReader dataReader(fDebugInfoSection->Data(),
|
||||||
@@ -230,7 +236,7 @@ DwarfFile::Load(const char* fileName)
|
|||||||
|
|
||||||
if (unitLengthOffset + unitLength
|
if (unitLengthOffset + unitLength
|
||||||
> (uint64)fDebugInfoSection->Size()) {
|
> (uint64)fDebugInfoSection->Size()) {
|
||||||
printf("\"%s\": Invalid compilation unit length.\n", fileName);
|
WARNING("\"%s\": Invalid compilation unit length.\n", fileName);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,23 +247,23 @@ DwarfFile::Load(const char* fileName)
|
|||||||
uint8 addressSize = dataReader.Read<uint8>(0);
|
uint8 addressSize = dataReader.Read<uint8>(0);
|
||||||
|
|
||||||
if (dataReader.HasOverflow()) {
|
if (dataReader.HasOverflow()) {
|
||||||
printf("\"%s\": Unexpected end of data in compilation unit "
|
WARNING("\"%s\": Unexpected end of data in compilation unit "
|
||||||
"header.\n", fileName);
|
"header.\n", fileName);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("DWARF%d compilation unit: version %d, length: %lld, "
|
TRACE_DIE("DWARF%d compilation unit: version %d, length: %lld, "
|
||||||
"abbrevOffset: %lld, address size: %d\n", dwarf64 ? 64 : 32,
|
"abbrevOffset: %lld, address size: %d\n", dwarf64 ? 64 : 32,
|
||||||
version, unitLength, abbrevOffset, addressSize);
|
version, unitLength, abbrevOffset, addressSize);
|
||||||
|
|
||||||
if (version != 2 && version != 3) {
|
if (version != 2 && version != 3) {
|
||||||
printf("\"%s\": Unsupported compilation unit version: %d\n",
|
WARNING("\"%s\": Unsupported compilation unit version: %d\n",
|
||||||
fileName, version);
|
fileName, version);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addressSize != 4 && addressSize != 8) {
|
if (addressSize != 4 && addressSize != 8) {
|
||||||
printf("\"%s\": Unsupported address size: %d\n", fileName,
|
WARNING("\"%s\": Unsupported address size: %d\n", fileName,
|
||||||
addressSize);
|
addressSize);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -304,6 +310,8 @@ DwarfFile::FinishLoading()
|
|||||||
return fFinishError = error;
|
return fFinishError = error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ParsePublicTypesInfo();
|
||||||
|
|
||||||
fFinished = true;
|
fFinished = true;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -358,7 +366,7 @@ DwarfFile::ResolveRangeList(CompilationUnit* unit, uint64 offset) const
|
|||||||
|
|
||||||
TargetAddressRangeList* ranges = new(std::nothrow) TargetAddressRangeList;
|
TargetAddressRangeList* ranges = new(std::nothrow) TargetAddressRangeList;
|
||||||
if (ranges == NULL) {
|
if (ranges == NULL) {
|
||||||
fprintf(stderr, "Out of memory.\n");
|
ERROR("Out of memory.\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
Reference<TargetAddressRangeList> rangesReference(ranges, true);
|
Reference<TargetAddressRangeList> rangesReference(ranges, true);
|
||||||
@@ -384,7 +392,7 @@ DwarfFile::ResolveRangeList(CompilationUnit* unit, uint64 offset) const
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!ranges->AddRange(baseAddress + start, end - start)) {
|
if (!ranges->AddRange(baseAddress + start, end - start)) {
|
||||||
fprintf(stderr, "Out of memory.\n");
|
ERROR("Out of memory.\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -402,7 +410,7 @@ DwarfFile::UnwindCallFrame(CompilationUnit* unit,
|
|||||||
if (fDebugFrameSection == NULL)
|
if (fDebugFrameSection == NULL)
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
printf("DwarfFile::UnwindCallFrame(%#llx)\n", location);
|
TRACE_CFI("DwarfFile::UnwindCallFrame(%#llx)\n", location);
|
||||||
|
|
||||||
DataReader dataReader((uint8*)fDebugFrameSection->Data(),
|
DataReader dataReader((uint8*)fDebugFrameSection->Data(),
|
||||||
fDebugFrameSection->Size(), unit->AddressSize());
|
fDebugFrameSection->Size(), unit->AddressSize());
|
||||||
@@ -435,8 +443,10 @@ printf("DwarfFile::UnwindCallFrame(%#llx)\n", location);
|
|||||||
- (dataReader.Offset() - lengthOffset);
|
- (dataReader.Offset() - lengthOffset);
|
||||||
if (remaining < 0)
|
if (remaining < 0)
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
printf(" found fde: length: %llu (%lld), CIE offset: %llu, location: %#llx, range: %#llx\n", length, remaining, cieID,
|
|
||||||
initialLocation, addressRange);
|
TRACE_CFI(" found fde: length: %llu (%lld), CIE offset: %llu, "
|
||||||
|
"location: %#llx, range: %#llx\n", length, remaining, cieID,
|
||||||
|
initialLocation, addressRange);
|
||||||
|
|
||||||
CfaContext context(location, initialLocation);
|
CfaContext context(location, initialLocation);
|
||||||
uint32 registerCount = outputInterface->CountRegisters();
|
uint32 registerCount = outputInterface->CountRegisters();
|
||||||
@@ -471,7 +481,7 @@ initialLocation, addressRange);
|
|||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
printf(" found row!\n");
|
TRACE_CFI(" found row!\n");
|
||||||
|
|
||||||
// apply the rules of the final row
|
// apply the rules of the final row
|
||||||
// get the frameAddress first
|
// get the frameAddress first
|
||||||
@@ -504,11 +514,13 @@ printf(" found row!\n");
|
|||||||
default:
|
default:
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
printf(" frame address: %#llx\n", frameAddress);
|
|
||||||
|
TRACE_CFI(" frame address: %#llx\n", frameAddress);
|
||||||
|
|
||||||
// apply the register rules
|
// apply the register rules
|
||||||
for (uint32 i = 0; i < registerCount; i++) {
|
for (uint32 i = 0; i < registerCount; i++) {
|
||||||
printf(" reg %lu\n", i);
|
TRACE_CFI(" reg %lu\n", i);
|
||||||
|
|
||||||
uint32 valueType = outputInterface->RegisterValueType(i);
|
uint32 valueType = outputInterface->RegisterValueType(i);
|
||||||
if (valueType == 0)
|
if (valueType == 0)
|
||||||
continue;
|
continue;
|
||||||
@@ -521,7 +533,8 @@ printf(" reg %lu\n", i);
|
|||||||
switch (rule->Type()) {
|
switch (rule->Type()) {
|
||||||
case CFA_RULE_SAME_VALUE:
|
case CFA_RULE_SAME_VALUE:
|
||||||
{
|
{
|
||||||
printf(" -> CFA_RULE_SAME_VALUE\n");
|
TRACE_CFI(" -> CFA_RULE_SAME_VALUE\n");
|
||||||
|
|
||||||
BVariant value;
|
BVariant value;
|
||||||
if (inputInterface->GetRegisterValue(i, value))
|
if (inputInterface->GetRegisterValue(i, value))
|
||||||
outputInterface->SetRegisterValue(i, value);
|
outputInterface->SetRegisterValue(i, value);
|
||||||
@@ -529,7 +542,9 @@ printf(" -> CFA_RULE_SAME_VALUE\n");
|
|||||||
}
|
}
|
||||||
case CFA_RULE_LOCATION_OFFSET:
|
case CFA_RULE_LOCATION_OFFSET:
|
||||||
{
|
{
|
||||||
printf(" -> CFA_RULE_LOCATION_OFFSET: %lld\n", rule->Offset());
|
TRACE_CFI(" -> CFA_RULE_LOCATION_OFFSET: %lld\n",
|
||||||
|
rule->Offset());
|
||||||
|
|
||||||
BVariant value;
|
BVariant value;
|
||||||
if (inputInterface->ReadValueFromMemory(
|
if (inputInterface->ReadValueFromMemory(
|
||||||
frameAddress + rule->Offset(), valueType,
|
frameAddress + rule->Offset(), valueType,
|
||||||
@@ -539,13 +554,15 @@ printf(" -> CFA_RULE_LOCATION_OFFSET: %lld\n", rule->Offset());
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CFA_RULE_VALUE_OFFSET:
|
case CFA_RULE_VALUE_OFFSET:
|
||||||
printf(" -> CFA_RULE_VALUE_OFFSET\n");
|
TRACE_CFI(" -> CFA_RULE_VALUE_OFFSET\n");
|
||||||
|
|
||||||
outputInterface->SetRegisterValue(i,
|
outputInterface->SetRegisterValue(i,
|
||||||
frameAddress + rule->Offset());
|
frameAddress + rule->Offset());
|
||||||
break;
|
break;
|
||||||
case CFA_RULE_REGISTER:
|
case CFA_RULE_REGISTER:
|
||||||
{
|
{
|
||||||
printf(" -> CFA_RULE_REGISTER\n");
|
TRACE_CFI(" -> CFA_RULE_REGISTER\n");
|
||||||
|
|
||||||
BVariant value;
|
BVariant value;
|
||||||
if (inputInterface->GetRegisterValue(
|
if (inputInterface->GetRegisterValue(
|
||||||
rule->Register(), value)) {
|
rule->Register(), value)) {
|
||||||
@@ -555,7 +572,8 @@ printf(" -> CFA_RULE_REGISTER\n");
|
|||||||
}
|
}
|
||||||
case CFA_RULE_LOCATION_EXPRESSION:
|
case CFA_RULE_LOCATION_EXPRESSION:
|
||||||
{
|
{
|
||||||
printf(" -> CFA_RULE_LOCATION_EXPRESSION\n");
|
TRACE_CFI(" -> CFA_RULE_LOCATION_EXPRESSION\n");
|
||||||
|
|
||||||
target_addr_t address;
|
target_addr_t address;
|
||||||
error = EvaluateExpression(unit, subprogramEntry,
|
error = EvaluateExpression(unit, subprogramEntry,
|
||||||
rule->Expression().block,
|
rule->Expression().block,
|
||||||
@@ -572,7 +590,8 @@ printf(" -> CFA_RULE_LOCATION_EXPRESSION\n");
|
|||||||
}
|
}
|
||||||
case CFA_RULE_VALUE_EXPRESSION:
|
case CFA_RULE_VALUE_EXPRESSION:
|
||||||
{
|
{
|
||||||
printf(" -> CFA_RULE_VALUE_EXPRESSION\n");
|
TRACE_CFI(" -> CFA_RULE_VALUE_EXPRESSION\n");
|
||||||
|
|
||||||
target_addr_t value;
|
target_addr_t value;
|
||||||
error = EvaluateExpression(unit, subprogramEntry,
|
error = EvaluateExpression(unit, subprogramEntry,
|
||||||
rule->Expression().block,
|
rule->Expression().block,
|
||||||
@@ -584,7 +603,7 @@ printf(" -> CFA_RULE_VALUE_EXPRESSION\n");
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CFA_RULE_UNDEFINED:
|
case CFA_RULE_UNDEFINED:
|
||||||
printf(" -> CFA_RULE_UNDEFINED\n");
|
TRACE_CFI(" -> CFA_RULE_UNDEFINED\n");
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -782,21 +801,22 @@ DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
|
|||||||
|
|
||||||
DIECompileUnitBase* unitEntry = dynamic_cast<DIECompileUnitBase*>(entry);
|
DIECompileUnitBase* unitEntry = dynamic_cast<DIECompileUnitBase*>(entry);
|
||||||
if (unitEntry == NULL) {
|
if (unitEntry == NULL) {
|
||||||
fprintf(stderr, "No compilation unit entry in .debug_info "
|
WARNING("No compilation unit entry in .debug_info section.\n");
|
||||||
"section.\n");
|
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
unit->SetUnitEntry(unitEntry);
|
unit->SetUnitEntry(unitEntry);
|
||||||
|
|
||||||
printf("remaining bytes in unit: %lld\n", dataReader.BytesRemaining());
|
TRACE_DIE_ONLY(
|
||||||
if (dataReader.HasData()) {
|
TRACE_DIE("remaining bytes in unit: %lld\n",
|
||||||
printf(" ");
|
dataReader.BytesRemaining());
|
||||||
while (dataReader.HasData()) {
|
if (dataReader.HasData()) {
|
||||||
printf("%02x", dataReader.Read<uint8>(0));
|
TRACE_DIE(" ");
|
||||||
}
|
while (dataReader.HasData())
|
||||||
printf("\n");
|
TRACE_DIE("%02x", dataReader.Read<uint8>(0));
|
||||||
}
|
TRACE_DIE("\n");
|
||||||
|
}
|
||||||
|
)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -812,7 +832,7 @@ DwarfFile::_ParseDebugInfoEntry(DataReader& dataReader,
|
|||||||
uint32 code = dataReader.ReadUnsignedLEB128(0);
|
uint32 code = dataReader.ReadUnsignedLEB128(0);
|
||||||
if (code == 0) {
|
if (code == 0) {
|
||||||
if (dataReader.HasOverflow()) {
|
if (dataReader.HasOverflow()) {
|
||||||
fprintf(stderr, "Unexpected end of .debug_info section.\n");
|
WARNING("Unexpected end of .debug_info section.\n");
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
_entry = NULL;
|
_entry = NULL;
|
||||||
@@ -823,12 +843,9 @@ DwarfFile::_ParseDebugInfoEntry(DataReader& dataReader,
|
|||||||
// get the corresponding abbreviation entry
|
// get the corresponding abbreviation entry
|
||||||
AbbreviationEntry abbreviationEntry;
|
AbbreviationEntry abbreviationEntry;
|
||||||
if (!abbreviationTable->GetAbbreviationEntry(code, abbreviationEntry)) {
|
if (!abbreviationTable->GetAbbreviationEntry(code, abbreviationEntry)) {
|
||||||
fprintf(stderr, "No abbreviation entry for code %lu\n", code);
|
WARNING("No abbreviation entry for code %lu\n", code);
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
printf("%*sentry at %lld: %lu, tag: %s (%lu), children: %d\n", level * 2, "",
|
|
||||||
entryOffset, abbreviationEntry.Code(), get_entry_tag_name(abbreviationEntry.Tag()),
|
|
||||||
abbreviationEntry.Tag(), abbreviationEntry.HasChildren());
|
|
||||||
|
|
||||||
DebugInfoEntry* entry;
|
DebugInfoEntry* entry;
|
||||||
status_t error = fDebugInfoFactory.CreateDebugInfoEntry(
|
status_t error = fDebugInfoFactory.CreateDebugInfoEntry(
|
||||||
@@ -837,6 +854,11 @@ abbreviationEntry.Tag(), abbreviationEntry.HasChildren());
|
|||||||
return error;
|
return error;
|
||||||
ObjectDeleter<DebugInfoEntry> entryDeleter(entry);
|
ObjectDeleter<DebugInfoEntry> entryDeleter(entry);
|
||||||
|
|
||||||
|
TRACE_DIE("%*sentry %p at %lld: %lu, tag: %s (%lu), children: %d\n",
|
||||||
|
level * 2, "", entry, entryOffset, abbreviationEntry.Code(),
|
||||||
|
get_entry_tag_name(abbreviationEntry.Tag()), abbreviationEntry.Tag(),
|
||||||
|
abbreviationEntry.HasChildren());
|
||||||
|
|
||||||
error = fCurrentCompilationUnit->AddDebugInfoEntry(entry, entryOffset);
|
error = fCurrentCompilationUnit->AddDebugInfoEntry(entry, entryOffset);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
@@ -864,7 +886,7 @@ abbreviationEntry.Tag(), abbreviationEntry.HasChildren());
|
|||||||
childEntry->SetParent(entry);
|
childEntry->SetParent(entry);
|
||||||
} else if (error == ENTRY_NOT_HANDLED) {
|
} else if (error == ENTRY_NOT_HANDLED) {
|
||||||
error = B_OK;
|
error = B_OK;
|
||||||
printf("%*s -> child unhandled\n", level * 2, "");
|
TRACE_DIE("%*s -> child unhandled\n", level * 2, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
@@ -890,7 +912,8 @@ printf("%*s -> child unhandled\n", level * 2, "");
|
|||||||
status_t
|
status_t
|
||||||
DwarfFile::_FinishCompilationUnit(CompilationUnit* unit)
|
DwarfFile::_FinishCompilationUnit(CompilationUnit* unit)
|
||||||
{
|
{
|
||||||
printf("\nfinishing compilation unit %p\n", unit);
|
TRACE_DIE("\nfinishing compilation unit %p\n", unit);
|
||||||
|
|
||||||
AbbreviationTable* abbreviationTable = unit->GetAbbreviationTable();
|
AbbreviationTable* abbreviationTable = unit->GetAbbreviationTable();
|
||||||
|
|
||||||
DataReader dataReader(
|
DataReader dataReader(
|
||||||
@@ -905,7 +928,8 @@ printf("\nfinishing compilation unit %p\n", unit);
|
|||||||
DebugInfoEntry* entry;
|
DebugInfoEntry* entry;
|
||||||
off_t offset;
|
off_t offset;
|
||||||
unit->GetEntryAt(i, entry, offset);
|
unit->GetEntryAt(i, entry, offset);
|
||||||
printf("entry %p at %lld\n", entry, offset);
|
|
||||||
|
TRACE_DIE("entry %p at %lld\n", entry, offset);
|
||||||
|
|
||||||
// seek the reader to the entry
|
// seek the reader to the entry
|
||||||
dataReader.SeekAbsolute(offset);
|
dataReader.SeekAbsolute(offset);
|
||||||
@@ -920,7 +944,7 @@ printf("entry %p at %lld\n", entry, offset);
|
|||||||
// initialization before setting the attributes
|
// initialization before setting the attributes
|
||||||
status_t error = entry->InitAfterHierarchy(entryInitInfo);
|
status_t error = entry->InitAfterHierarchy(entryInitInfo);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
fprintf(stderr, "Init after hierarchy failed!\n");
|
WARNING("Init after hierarchy failed!\n");
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -933,7 +957,7 @@ printf("entry %p at %lld\n", entry, offset);
|
|||||||
// initialization after setting the attributes
|
// initialization after setting the attributes
|
||||||
error = entry->InitAfterAttributes(entryInitInfo);
|
error = entry->InitAfterAttributes(entryInitInfo);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
fprintf(stderr, "Init after attributes failed!\n");
|
WARNING("Init after attributes failed!\n");
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1028,15 +1052,13 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||||||
? (off_t)dataReader.Read<uint64>(0)
|
? (off_t)dataReader.Read<uint64>(0)
|
||||||
: (off_t)dataReader.Read<uint32>(0);
|
: (off_t)dataReader.Read<uint32>(0);
|
||||||
if (offset >= fDebugStringSection->Size()) {
|
if (offset >= fDebugStringSection->Size()) {
|
||||||
fprintf(stderr, "Invalid DW_FORM_strp offset: %lld\n",
|
WARNING("Invalid DW_FORM_strp offset: %lld\n", offset);
|
||||||
offset);
|
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
attributeValue.SetToString(
|
attributeValue.SetToString(
|
||||||
(const char*)fDebugStringSection->Data() + offset);
|
(const char*)fDebugStringSection->Data() + offset);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Invalid DW_FORM_strp: no string "
|
WARNING("Invalid DW_FORM_strp: no string section!\n");
|
||||||
"section!\n");
|
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1067,8 +1089,7 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||||||
break;
|
break;
|
||||||
case DW_FORM_indirect:
|
case DW_FORM_indirect:
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Unsupported attribute form: %lu\n",
|
WARNING("Unsupported attribute form: %lu\n", attributeForm);
|
||||||
attributeForm);
|
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1077,7 +1098,7 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||||||
uint8 attributeClass = get_attribute_class(attributeName,
|
uint8 attributeClass = get_attribute_class(attributeName,
|
||||||
attributeForm);
|
attributeForm);
|
||||||
if (attributeClass == ATTRIBUTE_CLASS_UNKNOWN) {
|
if (attributeClass == ATTRIBUTE_CLASS_UNKNOWN) {
|
||||||
printf("skipping attribute with unrecognized class: %s (%#lx) "
|
TRACE_DIE("skipping attribute with unrecognized class: %s (%#lx) "
|
||||||
"%s (%#lx)\n", get_attribute_name_name(attributeName),
|
"%s (%#lx)\n", get_attribute_name_name(attributeName),
|
||||||
attributeName, get_attribute_form_name(attributeForm),
|
attributeName, get_attribute_form_name(attributeForm),
|
||||||
attributeForm);
|
attributeForm);
|
||||||
@@ -1120,12 +1141,12 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||||||
if (attributeName == DW_AT_sibling)
|
if (attributeName == DW_AT_sibling)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
fprintf(stderr, "Failed to resolve reference: "
|
WARNING("Failed to resolve reference: %s (%#lx) "
|
||||||
"%s (%#lx) %s (%#lx): value: %llu\n",
|
"%s (%#lx): value: %llu\n",
|
||||||
get_attribute_name_name(attributeName),
|
get_attribute_name_name(attributeName),
|
||||||
attributeName,
|
attributeName,
|
||||||
get_attribute_form_name(attributeForm),
|
get_attribute_form_name(attributeForm),
|
||||||
attributeForm, value);
|
attributeForm, value);
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1137,15 +1158,19 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dataReader.HasOverflow()) {
|
if (dataReader.HasOverflow()) {
|
||||||
fprintf(stderr, "Unexpected end of .debug_info section.\n");
|
WARNING("Unexpected end of .debug_info section.\n");
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the attribute
|
// add the attribute
|
||||||
if (entry != NULL) {
|
if (entry != NULL) {
|
||||||
char buffer[1024];
|
TRACE_DIE_ONLY(
|
||||||
printf(" attr %s %s (%d): %s\n", get_attribute_name_name(attributeName),
|
char buffer[1024];
|
||||||
get_attribute_form_name(attributeForm), attributeClass, attributeValue.ToString(buffer, sizeof(buffer)));
|
TRACE_DIE(" attr %s %s (%d): %s\n",
|
||||||
|
get_attribute_name_name(attributeName),
|
||||||
|
get_attribute_form_name(attributeForm), attributeClass,
|
||||||
|
attributeValue.ToString(buffer, sizeof(buffer)));
|
||||||
|
)
|
||||||
|
|
||||||
DebugInfoEntrySetter attributeSetter
|
DebugInfoEntrySetter attributeSetter
|
||||||
= get_attribute_name_setter(attributeName);
|
= get_attribute_name_setter(attributeName);
|
||||||
@@ -1155,19 +1180,17 @@ get_attribute_form_name(attributeForm), attributeClass, attributeValue.ToString(
|
|||||||
|
|
||||||
if (error == ATTRIBUTE_NOT_HANDLED) {
|
if (error == ATTRIBUTE_NOT_HANDLED) {
|
||||||
error = B_OK;
|
error = B_OK;
|
||||||
printf(" -> unhandled\n");
|
TRACE_DIE(" -> unhandled\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
fprintf(stderr, "Failed to set attribute: name: %s, "
|
WARNING("Failed to set attribute: name: %s, form: %s: %s\n",
|
||||||
"form: %s: %s\n",
|
|
||||||
get_attribute_name_name(attributeName),
|
get_attribute_name_name(attributeName),
|
||||||
get_attribute_form_name(attributeForm),
|
get_attribute_form_name(attributeForm),
|
||||||
strerror(error));
|
strerror(error));
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else
|
TRACE_DIE(" -> no attribute setter!\n");
|
||||||
printf(" -> no attribute setter!\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1179,7 +1202,8 @@ status_t
|
|||||||
DwarfFile::_ParseLineInfo(CompilationUnit* unit)
|
DwarfFile::_ParseLineInfo(CompilationUnit* unit)
|
||||||
{
|
{
|
||||||
off_t offset = unit->UnitEntry()->StatementListOffset();
|
off_t offset = unit->UnitEntry()->StatementListOffset();
|
||||||
printf("DwarfFile::_ParseLineInfo(%p), offset: %lld\n", unit, offset);
|
|
||||||
|
TRACE_LINES("DwarfFile::_ParseLineInfo(%p), offset: %lld\n", unit, offset);
|
||||||
|
|
||||||
DataReader dataReader((uint8*)fDebugLineSection->Data() + offset,
|
DataReader dataReader((uint8*)fDebugLineSection->Data() + offset,
|
||||||
fDebugLineSection->Size() - offset, unit->AddressSize());
|
fDebugLineSection->Size() - offset, unit->AddressSize());
|
||||||
@@ -1227,40 +1251,42 @@ printf("DwarfFile::_ParseLineInfo(%p), offset: %lld\n", unit, offset);
|
|||||||
if (version != 2 && version != 3)
|
if (version != 2 && version != 3)
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
printf(" unitLength: %llu\n", unitLength);
|
TRACE_LINES(" unitLength: %llu\n", unitLength);
|
||||||
printf(" version: %u\n", version);
|
TRACE_LINES(" version: %u\n", version);
|
||||||
printf(" headerLength: %llu\n", headerLength);
|
TRACE_LINES(" headerLength: %llu\n", headerLength);
|
||||||
printf(" minInstructionLength: %u\n", minInstructionLength);
|
TRACE_LINES(" minInstructionLength: %u\n", minInstructionLength);
|
||||||
printf(" defaultIsStatement: %d\n", defaultIsStatement);
|
TRACE_LINES(" defaultIsStatement: %d\n", defaultIsStatement);
|
||||||
printf(" lineBase: %d\n", lineBase);
|
TRACE_LINES(" lineBase: %d\n", lineBase);
|
||||||
printf(" lineRange: %u\n", lineRange);
|
TRACE_LINES(" lineRange: %u\n", lineRange);
|
||||||
printf(" opcodeBase: %u\n", opcodeBase);
|
TRACE_LINES(" opcodeBase: %u\n", opcodeBase);
|
||||||
|
|
||||||
// include directories
|
// include directories
|
||||||
printf(" include directories:\n");
|
TRACE_LINES(" include directories:\n");
|
||||||
while (const char* directory = dataReader.ReadString()) {
|
while (const char* directory = dataReader.ReadString()) {
|
||||||
if (*directory == '\0')
|
if (*directory == '\0')
|
||||||
break;
|
break;
|
||||||
printf(" \"%s\"\n", directory);
|
TRACE_LINES(" \"%s\"\n", directory);
|
||||||
|
|
||||||
if (!unit->AddDirectory(directory))
|
if (!unit->AddDirectory(directory))
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// file names
|
// file names
|
||||||
printf(" files:\n");
|
TRACE_LINES(" files:\n");
|
||||||
while (const char* file = dataReader.ReadString()) {
|
while (const char* file = dataReader.ReadString()) {
|
||||||
if (*file == '\0')
|
if (*file == '\0')
|
||||||
break;
|
break;
|
||||||
uint64 dirIndex = dataReader.ReadUnsignedLEB128(0);
|
uint64 dirIndex = dataReader.ReadUnsignedLEB128(0);
|
||||||
uint64 modificationTime = dataReader.ReadUnsignedLEB128(0);
|
TRACE_LINES_ONLY(uint64 modificationTime =)
|
||||||
uint64 fileLength = dataReader.ReadUnsignedLEB128(0);
|
dataReader.ReadUnsignedLEB128(0);
|
||||||
|
TRACE_LINES_ONLY(uint64 fileLength =)
|
||||||
|
dataReader.ReadUnsignedLEB128(0);
|
||||||
|
|
||||||
if (dataReader.HasOverflow())
|
if (dataReader.HasOverflow())
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
|
|
||||||
printf(" \"%s\", dir index: %llu, mtime: %llu, length: %llu\n", file,
|
TRACE_LINES(" \"%s\", dir index: %llu, mtime: %llu, length: %llu\n",
|
||||||
dirIndex, modificationTime, fileLength);
|
file, dirIndex, modificationTime, fileLength);
|
||||||
|
|
||||||
if (!unit->AddFile(file, dirIndex))
|
if (!unit->AddFile(file, dirIndex))
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
@@ -1311,10 +1337,11 @@ DwarfFile::_ParseCIE(CompilationUnit* unit, CfaContext& context,
|
|||||||
context.SetCodeAlignment(dataReader.ReadUnsignedLEB128(0));
|
context.SetCodeAlignment(dataReader.ReadUnsignedLEB128(0));
|
||||||
context.SetDataAlignment(dataReader.ReadSignedLEB128(0));
|
context.SetDataAlignment(dataReader.ReadSignedLEB128(0));
|
||||||
context.SetReturnAddressRegister(dataReader.ReadUnsignedLEB128(0));
|
context.SetReturnAddressRegister(dataReader.ReadUnsignedLEB128(0));
|
||||||
printf(" cie: length: %llu, version: %u, augmentation: \"%s\", "
|
|
||||||
"aligment: code: %lu, data: %ld, return address reg: %lu\n",
|
TRACE_CFI(" cie: length: %llu, version: %u, augmentation: \"%s\", "
|
||||||
length, version, augmentation, context.CodeAlignment(), context.DataAlignment(),
|
"aligment: code: %lu, data: %ld, return address reg: %lu\n", length,
|
||||||
context.ReturnAddressRegister());
|
version, augmentation, context.CodeAlignment(), context.DataAlignment(),
|
||||||
|
context.ReturnAddressRegister());
|
||||||
|
|
||||||
if (dataReader.HasOverflow())
|
if (dataReader.HasOverflow())
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
@@ -1340,7 +1367,8 @@ DwarfFile::_ParseFrameInfoInstructions(CompilationUnit* unit,
|
|||||||
instructionSize, unit->AddressSize());
|
instructionSize, unit->AddressSize());
|
||||||
|
|
||||||
while (dataReader.BytesRemaining() > 0) {
|
while (dataReader.BytesRemaining() > 0) {
|
||||||
printf(" [%2lld]", dataReader.BytesRemaining());
|
TRACE_CFI(" [%2lld]", dataReader.BytesRemaining());
|
||||||
|
|
||||||
uint8 opcode = dataReader.Read<uint8>(0);
|
uint8 opcode = dataReader.Read<uint8>(0);
|
||||||
if ((opcode >> 6) != 0) {
|
if ((opcode >> 6) != 0) {
|
||||||
uint32 operand = opcode & 0x3f;
|
uint32 operand = opcode & 0x3f;
|
||||||
@@ -1348,7 +1376,8 @@ printf(" [%2lld]", dataReader.BytesRemaining());
|
|||||||
switch (opcode >> 6) {
|
switch (opcode >> 6) {
|
||||||
case DW_CFA_advance_loc:
|
case DW_CFA_advance_loc:
|
||||||
{
|
{
|
||||||
printf(" DW_CFA_advance_loc: %#lx\n", operand);
|
TRACE_CFI(" DW_CFA_advance_loc: %#lx\n", operand);
|
||||||
|
|
||||||
target_addr_t location = context.Location()
|
target_addr_t location = context.Location()
|
||||||
+ operand * context.CodeAlignment();
|
+ operand * context.CodeAlignment();
|
||||||
if (location > context.TargetLocation())
|
if (location > context.TargetLocation())
|
||||||
@@ -1359,7 +1388,9 @@ printf(" DW_CFA_advance_loc: %#lx\n", operand);
|
|||||||
case DW_CFA_offset:
|
case DW_CFA_offset:
|
||||||
{
|
{
|
||||||
uint64 offset = dataReader.ReadUnsignedLEB128(0);
|
uint64 offset = dataReader.ReadUnsignedLEB128(0);
|
||||||
printf(" DW_CFA_offset: reg: %lu, offset: %llu\n", operand, offset);
|
TRACE_CFI(" DW_CFA_offset: reg: %lu, offset: %llu\n",
|
||||||
|
operand, offset);
|
||||||
|
|
||||||
if (CfaRule* rule = context.RegisterRule(operand)) {
|
if (CfaRule* rule = context.RegisterRule(operand)) {
|
||||||
rule->SetToLocationOffset(
|
rule->SetToLocationOffset(
|
||||||
offset * context.DataAlignment());
|
offset * context.DataAlignment());
|
||||||
@@ -1368,7 +1399,8 @@ printf(" DW_CFA_offset: reg: %lu, offset: %llu\n", operand, offset);
|
|||||||
}
|
}
|
||||||
case DW_CFA_restore:
|
case DW_CFA_restore:
|
||||||
{
|
{
|
||||||
printf(" DW_CFA_restore: %#lx\n", operand);
|
TRACE_CFI(" DW_CFA_restore: %#lx\n", operand);
|
||||||
|
|
||||||
context.RestoreRegisterRule(operand);
|
context.RestoreRegisterRule(operand);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1377,13 +1409,15 @@ printf(" DW_CFA_restore: %#lx\n", operand);
|
|||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case DW_CFA_nop:
|
case DW_CFA_nop:
|
||||||
{
|
{
|
||||||
printf(" DW_CFA_nop\n");
|
TRACE_CFI(" DW_CFA_nop\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_CFA_set_loc:
|
case DW_CFA_set_loc:
|
||||||
{
|
{
|
||||||
target_addr_t location = dataReader.ReadAddress(0);
|
target_addr_t location = dataReader.ReadAddress(0);
|
||||||
printf(" DW_CFA_set_loc: %#llx\n", location);
|
|
||||||
|
TRACE_CFI(" DW_CFA_set_loc: %#llx\n", location);
|
||||||
|
|
||||||
if (location < context.Location())
|
if (location < context.Location())
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
if (location > context.TargetLocation())
|
if (location > context.TargetLocation())
|
||||||
@@ -1394,7 +1428,9 @@ printf(" DW_CFA_set_loc: %#llx\n", location);
|
|||||||
case DW_CFA_advance_loc1:
|
case DW_CFA_advance_loc1:
|
||||||
{
|
{
|
||||||
uint32 delta = dataReader.Read<uint8>(0);
|
uint32 delta = dataReader.Read<uint8>(0);
|
||||||
printf(" DW_CFA_advance_loc1: %#lx\n", delta);
|
|
||||||
|
TRACE_CFI(" DW_CFA_advance_loc1: %#lx\n", delta);
|
||||||
|
|
||||||
target_addr_t location = context.Location()
|
target_addr_t location = context.Location()
|
||||||
+ delta * context.CodeAlignment();
|
+ delta * context.CodeAlignment();
|
||||||
if (location > context.TargetLocation())
|
if (location > context.TargetLocation())
|
||||||
@@ -1405,7 +1441,9 @@ printf(" DW_CFA_advance_loc1: %#lx\n", delta);
|
|||||||
case DW_CFA_advance_loc2:
|
case DW_CFA_advance_loc2:
|
||||||
{
|
{
|
||||||
uint32 delta = dataReader.Read<uint16>(0);
|
uint32 delta = dataReader.Read<uint16>(0);
|
||||||
printf(" DW_CFA_advance_loc2: %#lx\n", delta);
|
|
||||||
|
TRACE_CFI(" DW_CFA_advance_loc2: %#lx\n", delta);
|
||||||
|
|
||||||
target_addr_t location = context.Location()
|
target_addr_t location = context.Location()
|
||||||
+ delta * context.CodeAlignment();
|
+ delta * context.CodeAlignment();
|
||||||
if (location > context.TargetLocation())
|
if (location > context.TargetLocation())
|
||||||
@@ -1416,7 +1454,9 @@ printf(" DW_CFA_advance_loc2: %#lx\n", delta);
|
|||||||
case DW_CFA_advance_loc4:
|
case DW_CFA_advance_loc4:
|
||||||
{
|
{
|
||||||
uint32 delta = dataReader.Read<uint32>(0);
|
uint32 delta = dataReader.Read<uint32>(0);
|
||||||
printf(" DW_CFA_advance_loc4: %#lx\n", delta);
|
|
||||||
|
TRACE_CFI(" DW_CFA_advance_loc4: %#lx\n", delta);
|
||||||
|
|
||||||
target_addr_t location = context.Location()
|
target_addr_t location = context.Location()
|
||||||
+ delta * context.CodeAlignment();
|
+ delta * context.CodeAlignment();
|
||||||
if (location > context.TargetLocation())
|
if (location > context.TargetLocation())
|
||||||
@@ -1428,7 +1468,10 @@ printf(" DW_CFA_advance_loc4: %#lx\n", delta);
|
|||||||
{
|
{
|
||||||
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
uint64 offset = dataReader.ReadUnsignedLEB128(0);
|
uint64 offset = dataReader.ReadUnsignedLEB128(0);
|
||||||
printf(" DW_CFA_offset_extended: reg: %lu, offset: %llu\n", reg, offset);
|
|
||||||
|
TRACE_CFI(" DW_CFA_offset_extended: reg: %lu, "
|
||||||
|
"offset: %llu\n", reg, offset);
|
||||||
|
|
||||||
if (CfaRule* rule = context.RegisterRule(reg)) {
|
if (CfaRule* rule = context.RegisterRule(reg)) {
|
||||||
rule->SetToLocationOffset(
|
rule->SetToLocationOffset(
|
||||||
offset * context.DataAlignment());
|
offset * context.DataAlignment());
|
||||||
@@ -1438,14 +1481,18 @@ printf(" DW_CFA_offset_extended: reg: %lu, offset: %llu\n", reg, offset);
|
|||||||
case DW_CFA_restore_extended:
|
case DW_CFA_restore_extended:
|
||||||
{
|
{
|
||||||
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
printf(" DW_CFA_restore_extended: %#lx\n", reg);
|
|
||||||
|
TRACE_CFI(" DW_CFA_restore_extended: %#lx\n", reg);
|
||||||
|
|
||||||
context.RestoreRegisterRule(reg);
|
context.RestoreRegisterRule(reg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_CFA_undefined:
|
case DW_CFA_undefined:
|
||||||
{
|
{
|
||||||
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
printf(" DW_CFA_undefined: %lu\n", reg);
|
|
||||||
|
TRACE_CFI(" DW_CFA_undefined: %lu\n", reg);
|
||||||
|
|
||||||
if (CfaRule* rule = context.RegisterRule(reg))
|
if (CfaRule* rule = context.RegisterRule(reg))
|
||||||
rule->SetToUndefined();
|
rule->SetToUndefined();
|
||||||
break;
|
break;
|
||||||
@@ -1453,7 +1500,9 @@ printf(" DW_CFA_undefined: %lu\n", reg);
|
|||||||
case DW_CFA_same_value:
|
case DW_CFA_same_value:
|
||||||
{
|
{
|
||||||
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
printf(" DW_CFA_same_value: %lu\n", reg);
|
|
||||||
|
TRACE_CFI(" DW_CFA_same_value: %lu\n", reg);
|
||||||
|
|
||||||
if (CfaRule* rule = context.RegisterRule(reg))
|
if (CfaRule* rule = context.RegisterRule(reg))
|
||||||
rule->SetToSameValue();
|
rule->SetToSameValue();
|
||||||
break;
|
break;
|
||||||
@@ -1462,14 +1511,17 @@ printf(" DW_CFA_same_value: %lu\n", reg);
|
|||||||
{
|
{
|
||||||
uint32 reg1 = dataReader.ReadUnsignedLEB128(0);
|
uint32 reg1 = dataReader.ReadUnsignedLEB128(0);
|
||||||
uint32 reg2 = dataReader.ReadUnsignedLEB128(0);
|
uint32 reg2 = dataReader.ReadUnsignedLEB128(0);
|
||||||
printf(" DW_CFA_register: reg1: %lu, reg2: %lu\n", reg1, reg2);
|
|
||||||
|
TRACE_CFI(" DW_CFA_register: reg1: %lu, reg2: %lu\n", reg1, reg2);
|
||||||
|
|
||||||
if (CfaRule* rule = context.RegisterRule(reg1))
|
if (CfaRule* rule = context.RegisterRule(reg1))
|
||||||
rule->SetToValueOffset(reg2);
|
rule->SetToValueOffset(reg2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_CFA_remember_state:
|
case DW_CFA_remember_state:
|
||||||
{
|
{
|
||||||
printf(" DW_CFA_remember_state\n");
|
TRACE_CFI(" DW_CFA_remember_state\n");
|
||||||
|
|
||||||
status_t error = context.PushRuleSet();
|
status_t error = context.PushRuleSet();
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
@@ -1477,7 +1529,8 @@ printf(" DW_CFA_remember_state\n");
|
|||||||
}
|
}
|
||||||
case DW_CFA_restore_state:
|
case DW_CFA_restore_state:
|
||||||
{
|
{
|
||||||
printf(" DW_CFA_restore_state\n");
|
TRACE_CFI(" DW_CFA_restore_state\n");
|
||||||
|
|
||||||
status_t error = context.PopRuleSet();
|
status_t error = context.PopRuleSet();
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
@@ -1487,14 +1540,19 @@ printf(" DW_CFA_restore_state\n");
|
|||||||
{
|
{
|
||||||
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
uint64 offset = dataReader.ReadUnsignedLEB128(0);
|
uint64 offset = dataReader.ReadUnsignedLEB128(0);
|
||||||
printf(" DW_CFA_def_cfa: reg: %lu, offset: %llu\n", reg, offset);
|
|
||||||
|
TRACE_CFI(" DW_CFA_def_cfa: reg: %lu, offset: %llu\n",
|
||||||
|
reg, offset);
|
||||||
|
|
||||||
context.GetCfaCfaRule()->SetToRegisterOffset(reg, offset);
|
context.GetCfaCfaRule()->SetToRegisterOffset(reg, offset);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_CFA_def_cfa_register:
|
case DW_CFA_def_cfa_register:
|
||||||
{
|
{
|
||||||
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
printf(" DW_CFA_def_cfa_register: %lu\n", reg);
|
|
||||||
|
TRACE_CFI(" DW_CFA_def_cfa_register: %lu\n", reg);
|
||||||
|
|
||||||
if (context.GetCfaCfaRule()->Type()
|
if (context.GetCfaCfaRule()->Type()
|
||||||
!= CFA_CFA_RULE_REGISTER_OFFSET) {
|
!= CFA_CFA_RULE_REGISTER_OFFSET) {
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
@@ -1505,7 +1563,9 @@ printf(" DW_CFA_def_cfa_register: %lu\n", reg);
|
|||||||
case DW_CFA_def_cfa_offset:
|
case DW_CFA_def_cfa_offset:
|
||||||
{
|
{
|
||||||
uint64 offset = dataReader.ReadUnsignedLEB128(0);
|
uint64 offset = dataReader.ReadUnsignedLEB128(0);
|
||||||
printf(" DW_CFA_def_cfa_offset: %llu\n", offset);
|
|
||||||
|
TRACE_CFI(" DW_CFA_def_cfa_offset: %llu\n", offset);
|
||||||
|
|
||||||
if (context.GetCfaCfaRule()->Type()
|
if (context.GetCfaCfaRule()->Type()
|
||||||
!= CFA_CFA_RULE_REGISTER_OFFSET) {
|
!= CFA_CFA_RULE_REGISTER_OFFSET) {
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
@@ -1518,7 +1578,10 @@ printf(" DW_CFA_def_cfa_offset: %llu\n", offset);
|
|||||||
uint8* block = (uint8*)dataReader.Data();
|
uint8* block = (uint8*)dataReader.Data();
|
||||||
uint64 blockLength = dataReader.ReadUnsignedLEB128(0);
|
uint64 blockLength = dataReader.ReadUnsignedLEB128(0);
|
||||||
dataReader.Skip(blockLength);
|
dataReader.Skip(blockLength);
|
||||||
printf(" DW_CFA_def_cfa_expression: %p, %llu\n", block, blockLength);
|
|
||||||
|
TRACE_CFI(" DW_CFA_def_cfa_expression: %p, %llu\n",
|
||||||
|
block, blockLength);
|
||||||
|
|
||||||
context.GetCfaCfaRule()->SetToExpression(block,
|
context.GetCfaCfaRule()->SetToExpression(block,
|
||||||
blockLength);
|
blockLength);
|
||||||
break;
|
break;
|
||||||
@@ -1529,7 +1592,10 @@ printf(" DW_CFA_def_cfa_expression: %p, %llu\n", block, blockLength);
|
|||||||
uint8* block = (uint8*)dataReader.Data();
|
uint8* block = (uint8*)dataReader.Data();
|
||||||
uint64 blockLength = dataReader.ReadUnsignedLEB128(0);
|
uint64 blockLength = dataReader.ReadUnsignedLEB128(0);
|
||||||
dataReader.Skip(blockLength);
|
dataReader.Skip(blockLength);
|
||||||
printf(" DW_CFA_expression: reg: %lu, block: %p, %llu\n", reg, block, blockLength);
|
|
||||||
|
TRACE_CFI(" DW_CFA_expression: reg: %lu, block: %p, "
|
||||||
|
"%llu\n", reg, block, blockLength);
|
||||||
|
|
||||||
if (CfaRule* rule = context.RegisterRule(reg))
|
if (CfaRule* rule = context.RegisterRule(reg))
|
||||||
rule->SetToLocationExpression(block, blockLength);
|
rule->SetToLocationExpression(block, blockLength);
|
||||||
break;
|
break;
|
||||||
@@ -1538,7 +1604,10 @@ printf(" DW_CFA_expression: reg: %lu, block: %p, %llu\n", reg, block, blockLe
|
|||||||
{
|
{
|
||||||
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
int64 offset = dataReader.ReadSignedLEB128(0);
|
int64 offset = dataReader.ReadSignedLEB128(0);
|
||||||
printf(" DW_CFA_offset_extended: reg: %lu, offset: %lld\n", reg, offset);
|
|
||||||
|
TRACE_CFI(" DW_CFA_offset_extended: reg: %lu, "
|
||||||
|
"offset: %lld\n", reg, offset);
|
||||||
|
|
||||||
if (CfaRule* rule = context.RegisterRule(reg)) {
|
if (CfaRule* rule = context.RegisterRule(reg)) {
|
||||||
rule->SetToLocationOffset(
|
rule->SetToLocationOffset(
|
||||||
offset * (int32)context.DataAlignment());
|
offset * (int32)context.DataAlignment());
|
||||||
@@ -1549,7 +1618,10 @@ printf(" DW_CFA_offset_extended: reg: %lu, offset: %lld\n", reg, offset);
|
|||||||
{
|
{
|
||||||
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
int64 offset = dataReader.ReadSignedLEB128(0);
|
int64 offset = dataReader.ReadSignedLEB128(0);
|
||||||
printf(" DW_CFA_def_cfa_sf: reg: %lu, offset: %lld\n", reg, offset);
|
|
||||||
|
TRACE_CFI(" DW_CFA_def_cfa_sf: reg: %lu, offset: %lld\n",
|
||||||
|
reg, offset);
|
||||||
|
|
||||||
context.GetCfaCfaRule()->SetToRegisterOffset(reg,
|
context.GetCfaCfaRule()->SetToRegisterOffset(reg,
|
||||||
offset * (int32)context.DataAlignment());
|
offset * (int32)context.DataAlignment());
|
||||||
break;
|
break;
|
||||||
@@ -1557,7 +1629,9 @@ printf(" DW_CFA_def_cfa_sf: reg: %lu, offset: %lld\n", reg, offset);
|
|||||||
case DW_CFA_def_cfa_offset_sf:
|
case DW_CFA_def_cfa_offset_sf:
|
||||||
{
|
{
|
||||||
int64 offset = dataReader.ReadSignedLEB128(0);
|
int64 offset = dataReader.ReadSignedLEB128(0);
|
||||||
printf(" DW_CFA_def_cfa_offset: %lld\n", offset);
|
|
||||||
|
TRACE_CFI(" DW_CFA_def_cfa_offset: %lld\n", offset);
|
||||||
|
|
||||||
if (context.GetCfaCfaRule()->Type()
|
if (context.GetCfaCfaRule()->Type()
|
||||||
!= CFA_CFA_RULE_REGISTER_OFFSET) {
|
!= CFA_CFA_RULE_REGISTER_OFFSET) {
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
@@ -1570,7 +1644,10 @@ printf(" DW_CFA_def_cfa_offset: %lld\n", offset);
|
|||||||
{
|
{
|
||||||
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
uint64 offset = dataReader.ReadUnsignedLEB128(0);
|
uint64 offset = dataReader.ReadUnsignedLEB128(0);
|
||||||
printf(" DW_CFA_val_offset: reg: %lu, offset: %llu\n", reg, offset);
|
|
||||||
|
TRACE_CFI(" DW_CFA_val_offset: reg: %lu, offset: %llu\n",
|
||||||
|
reg, offset);
|
||||||
|
|
||||||
if (CfaRule* rule = context.RegisterRule(reg)) {
|
if (CfaRule* rule = context.RegisterRule(reg)) {
|
||||||
rule->SetToValueOffset(
|
rule->SetToValueOffset(
|
||||||
offset * context.DataAlignment());
|
offset * context.DataAlignment());
|
||||||
@@ -1581,7 +1658,10 @@ printf(" DW_CFA_val_offset: reg: %lu, offset: %llu\n", reg, offset);
|
|||||||
{
|
{
|
||||||
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
int64 offset = dataReader.ReadSignedLEB128(0);
|
int64 offset = dataReader.ReadSignedLEB128(0);
|
||||||
printf(" DW_CFA_val_offset_sf: reg: %lu, offset: %lld\n", reg, offset);
|
|
||||||
|
TRACE_CFI(" DW_CFA_val_offset_sf: reg: %lu, "
|
||||||
|
"offset: %lld\n", reg, offset);
|
||||||
|
|
||||||
if (CfaRule* rule = context.RegisterRule(reg)) {
|
if (CfaRule* rule = context.RegisterRule(reg)) {
|
||||||
rule->SetToValueOffset(
|
rule->SetToValueOffset(
|
||||||
offset * (int32)context.DataAlignment());
|
offset * (int32)context.DataAlignment());
|
||||||
@@ -1594,7 +1674,10 @@ printf(" DW_CFA_val_offset_sf: reg: %lu, offset: %lld\n", reg, offset);
|
|||||||
uint8* block = (uint8*)dataReader.Data();
|
uint8* block = (uint8*)dataReader.Data();
|
||||||
uint64 blockLength = dataReader.ReadUnsignedLEB128(0);
|
uint64 blockLength = dataReader.ReadUnsignedLEB128(0);
|
||||||
dataReader.Skip(blockLength);
|
dataReader.Skip(blockLength);
|
||||||
printf(" DW_CFA_val_expression: reg: %lu, block: %p, %llu\n", reg, block, blockLength);
|
|
||||||
|
TRACE_CFI(" DW_CFA_val_expression: reg: %lu, block: %p, "
|
||||||
|
"%llu\n", reg, block, blockLength);
|
||||||
|
|
||||||
if (CfaRule* rule = context.RegisterRule(reg))
|
if (CfaRule* rule = context.RegisterRule(reg))
|
||||||
rule->SetToValueExpression(block, blockLength);
|
rule->SetToValueExpression(block, blockLength);
|
||||||
break;
|
break;
|
||||||
@@ -1604,7 +1687,9 @@ printf(" DW_CFA_val_expression: reg: %lu, block: %p, %llu\n", reg, block, blo
|
|||||||
case DW_CFA_MIPS_advance_loc8:
|
case DW_CFA_MIPS_advance_loc8:
|
||||||
{
|
{
|
||||||
uint64 delta = dataReader.Read<uint64>(0);
|
uint64 delta = dataReader.Read<uint64>(0);
|
||||||
printf(" DW_CFA_MIPS_advance_loc8: %#llx\n", delta);
|
|
||||||
|
TRACE_CFI(" DW_CFA_MIPS_advance_loc8: %#llx\n", delta);
|
||||||
|
|
||||||
target_addr_t location = context.Location()
|
target_addr_t location = context.Location()
|
||||||
+ delta * context.CodeAlignment();
|
+ delta * context.CodeAlignment();
|
||||||
if (location > context.TargetLocation())
|
if (location > context.TargetLocation())
|
||||||
@@ -1615,15 +1700,18 @@ printf(" DW_CFA_MIPS_advance_loc8: %#llx\n", delta);
|
|||||||
case DW_CFA_GNU_window_save:
|
case DW_CFA_GNU_window_save:
|
||||||
{
|
{
|
||||||
// SPARC specific, no args
|
// SPARC specific, no args
|
||||||
printf(" DW_CFA_GNU_window_save\n");
|
TRACE_CFI(" DW_CFA_GNU_window_save\n");
|
||||||
|
|
||||||
// TODO: Implement once we have SPARC support!
|
// TODO: Implement once we have SPARC support!
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_CFA_GNU_args_size:
|
case DW_CFA_GNU_args_size:
|
||||||
{
|
{
|
||||||
// Updates the total size of arguments on the stack.
|
// Updates the total size of arguments on the stack.
|
||||||
uint64 size = dataReader.ReadUnsignedLEB128(0);
|
TRACE_CFI_ONLY(uint64 size =)
|
||||||
printf(" DW_CFA_GNU_args_size: %llu\n", size);
|
dataReader.ReadUnsignedLEB128(0);
|
||||||
|
|
||||||
|
TRACE_CFI(" DW_CFA_GNU_args_size: %llu\n", size);
|
||||||
// TODO: Implement!
|
// TODO: Implement!
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1632,7 +1720,10 @@ printf(" DW_CFA_MIPS_advance_loc8: %#llx\n", delta);
|
|||||||
// obsolete
|
// obsolete
|
||||||
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
int64 offset = dataReader.ReadSignedLEB128(0);
|
int64 offset = dataReader.ReadSignedLEB128(0);
|
||||||
printf(" DW_CFA_GNU_negative_offset_extended: reg: %lu, offset: %lld\n", reg, offset);
|
|
||||||
|
TRACE_CFI(" DW_CFA_GNU_negative_offset_extended: "
|
||||||
|
"reg: %lu, offset: %lld\n", reg, offset);
|
||||||
|
|
||||||
if (CfaRule* rule = context.RegisterRule(reg)) {
|
if (CfaRule* rule = context.RegisterRule(reg)) {
|
||||||
rule->SetToLocationOffset(
|
rule->SetToLocationOffset(
|
||||||
offset * (int32)context.DataAlignment());
|
offset * (int32)context.DataAlignment());
|
||||||
@@ -1641,7 +1732,7 @@ printf(" DW_CFA_GNU_negative_offset_extended: reg: %lu, offset: %lld\n", reg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf(" unknown opcode %u!\n", opcode);
|
WARNING(" unknown opcode %u!\n", opcode);
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1651,6 +1742,84 @@ printf(" DW_CFA_GNU_negative_offset_extended: reg: %lu, offset: %lld\n", reg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::_ParsePublicTypesInfo()
|
||||||
|
{
|
||||||
|
TRACE_PUBTYPES("DwarfFile::_ParsePublicTypesInfo()\n");
|
||||||
|
if (fDebugPublicTypesSection == NULL) {
|
||||||
|
TRACE_PUBTYPES(" -> no public types section\n");
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataReader dataReader((uint8*)fDebugPublicTypesSection->Data(),
|
||||||
|
fDebugPublicTypesSection->Size(), 4);
|
||||||
|
// address size doesn't matter at this point
|
||||||
|
|
||||||
|
while (dataReader.BytesRemaining() > 0) {
|
||||||
|
bool dwarf64;
|
||||||
|
uint64 unitLength = dataReader.ReadInitialLength(dwarf64);
|
||||||
|
|
||||||
|
off_t unitLengthOffset = dataReader.Offset();
|
||||||
|
// the unitLength starts here
|
||||||
|
|
||||||
|
if (dataReader.HasOverflow())
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
if (unitLengthOffset + unitLength
|
||||||
|
> (uint64)fDebugPublicTypesSection->Size()) {
|
||||||
|
WARNING("Invalid public types set unit length.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataReader unitDataReader(dataReader.Data(), unitLength, 4);
|
||||||
|
// address size doesn't matter
|
||||||
|
_ParsePublicTypesInfo(unitDataReader, dwarf64);
|
||||||
|
|
||||||
|
dataReader.SeekAbsolute(unitLengthOffset + unitLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::_ParsePublicTypesInfo(DataReader& dataReader, bool dwarf64)
|
||||||
|
{
|
||||||
|
int version = dataReader.Read<uint16>(0);
|
||||||
|
if (version != 2) {
|
||||||
|
TRACE_PUBTYPES(" pubtypes version %d unsupported\n", version);
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE_CFI_ONLY(off_t debugInfoOffset =) dwarf64
|
||||||
|
? dataReader.Read<uint64>(0)
|
||||||
|
: (uint64)dataReader.Read<uint32>(0);
|
||||||
|
TRACE_CFI_ONLY(off_t debugInfoSize =) dwarf64
|
||||||
|
? dataReader.Read<uint64>(0)
|
||||||
|
: (uint64)dataReader.Read<uint32>(0);
|
||||||
|
|
||||||
|
if (dataReader.HasOverflow())
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
TRACE_PUBTYPES("DwarfFile::_ParsePublicTypesInfo(): compilation unit debug "
|
||||||
|
"info: (%lld, %lld)\n", debugInfoOffset, debugInfoSize);
|
||||||
|
|
||||||
|
while (dataReader.BytesRemaining() > 0) {
|
||||||
|
off_t entryOffset = dwarf64
|
||||||
|
? dataReader.Read<uint64>(0)
|
||||||
|
: (uint64)dataReader.Read<uint32>(0);
|
||||||
|
if (entryOffset == 0)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
TRACE_PUBTYPES_ONLY(const char* name =) dataReader.ReadString();
|
||||||
|
|
||||||
|
TRACE_PUBTYPES(" \"%s\" -> %lld\n", name, entryOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfFile::_GetAbbreviationTable(off_t offset, AbbreviationTable*& _table)
|
DwarfFile::_GetAbbreviationTable(off_t offset, AbbreviationTable*& _table)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -110,6 +110,10 @@ private:
|
|||||||
off_t instructionOffset,
|
off_t instructionOffset,
|
||||||
off_t instructionSize);
|
off_t instructionSize);
|
||||||
|
|
||||||
|
status_t _ParsePublicTypesInfo();
|
||||||
|
status_t _ParsePublicTypesInfo(DataReader& dataReader,
|
||||||
|
bool dwarf64);
|
||||||
|
|
||||||
status_t _GetAbbreviationTable(off_t offset,
|
status_t _GetAbbreviationTable(off_t offset,
|
||||||
AbbreviationTable*& _table);
|
AbbreviationTable*& _table);
|
||||||
|
|
||||||
@@ -139,6 +143,7 @@ private:
|
|||||||
ElfSection* fDebugLineSection;
|
ElfSection* fDebugLineSection;
|
||||||
ElfSection* fDebugFrameSection;
|
ElfSection* fDebugFrameSection;
|
||||||
ElfSection* fDebugLocationSection;
|
ElfSection* fDebugLocationSection;
|
||||||
|
ElfSection* fDebugPublicTypesSection;
|
||||||
AbbreviationTableList fAbbreviationTables;
|
AbbreviationTableList fAbbreviationTables;
|
||||||
DebugInfoEntryFactory fDebugInfoFactory;
|
DebugInfoEntryFactory fDebugInfoFactory;
|
||||||
CompilationUnitList fCompilationUnits;
|
CompilationUnitList fCompilationUnits;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#define DWARF_TARGET_INTERFACE_H
|
#define DWARF_TARGET_INTERFACE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Referenceable.h>
|
||||||
#include <Variant.h>
|
#include <Variant.h>
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
@@ -14,7 +15,7 @@
|
|||||||
class Register;
|
class Register;
|
||||||
|
|
||||||
|
|
||||||
class DwarfTargetInterface {
|
class DwarfTargetInterface : public Referenceable {
|
||||||
public:
|
public:
|
||||||
virtual ~DwarfTargetInterface();
|
virtual ~DwarfTargetInterface();
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "Dwarf.h"
|
#include "Dwarf.h"
|
||||||
|
#include "Tracing.h"
|
||||||
|
|
||||||
|
|
||||||
static const uint8 kLineNumberStandardOpcodeOperands[]
|
static const uint8 kLineNumberStandardOpcodeOperands[]
|
||||||
@@ -48,7 +49,8 @@ LineNumberProgram::Init(const void* program, size_t programSize,
|
|||||||
kLineNumberStandardOpcodeCount);
|
kLineNumberStandardOpcodeCount);
|
||||||
for (uint8 i = 0; i < standardOpcodeCount; i++) {
|
for (uint8 i = 0; i < standardOpcodeCount; i++) {
|
||||||
if (standardOpcodeLengths[i] != kLineNumberStandardOpcodeOperands[i]) {
|
if (standardOpcodeLengths[i] != kLineNumberStandardOpcodeOperands[i]) {
|
||||||
printf("operand count for standard opcode %u does not what we expect\n", i + 1);
|
WARNING("operand count for standard opcode %u does not what we "
|
||||||
|
"expect\n", i + 1);
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,7 +145,7 @@ LineNumberProgram::GetNextRow(State& state) const
|
|||||||
state.instructionSet = dataReader.ReadUnsignedLEB128(0);
|
state.instructionSet = dataReader.ReadUnsignedLEB128(0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("unsupported standard opcode %u\n", opcode);
|
WARNING("unsupported standard opcode %u\n", opcode);
|
||||||
for (int32 i = 0; i < fStandardOpcodeLengths[opcode - 1];
|
for (int32 i = 0; i < fStandardOpcodeLengths[opcode - 1];
|
||||||
i++) {
|
i++) {
|
||||||
dataReader.ReadUnsignedLEB128(0);
|
dataReader.ReadUnsignedLEB128(0);
|
||||||
@@ -174,7 +176,8 @@ printf("unsupported standard opcode %u\n", opcode);
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
printf("unsupported extended opcode: %u\n", extendedOpcode);
|
WARNING("unsupported extended opcode: %u\n",
|
||||||
|
extendedOpcode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
#include "Tracing.h"
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - ElfSection
|
// #pragma mark - ElfSection
|
||||||
|
|
||||||
@@ -129,20 +131,17 @@ ElfFile::Init(const char* fileName)
|
|||||||
// open file
|
// open file
|
||||||
fFD = open(fileName, O_RDONLY);
|
fFD = open(fileName, O_RDONLY);
|
||||||
if (fFD < 0) {
|
if (fFD < 0) {
|
||||||
fprintf(stderr, "Failed to open \"%s\": %s\n", fileName,
|
WARNING("Failed to open \"%s\": %s\n", fileName, strerror(errno));
|
||||||
strerror(errno));
|
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
// stat() file to get its size
|
// stat() file to get its size
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (fstat(fFD, &st) < 0) {
|
if (fstat(fFD, &st) < 0) {
|
||||||
fprintf(stderr, "Failed to stat \"%s\": %s\n", fileName,
|
WARNING("Failed to stat \"%s\": %s\n", fileName, strerror(errno));
|
||||||
strerror(errno));
|
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
fFileSize = st.st_size;
|
fFileSize = st.st_size;
|
||||||
printf("fFileSize: %lld\n", fFileSize);
|
|
||||||
|
|
||||||
// read the elf header
|
// read the elf header
|
||||||
fElfHeader = (Elf32_Ehdr*)malloc(sizeof(Elf32_Ehdr));
|
fElfHeader = (Elf32_Ehdr*)malloc(sizeof(Elf32_Ehdr));
|
||||||
@@ -155,7 +154,7 @@ printf("fFileSize: %lld\n", fFileSize);
|
|||||||
|
|
||||||
// check the ELF header
|
// check the ELF header
|
||||||
if (!_CheckRange(0, sizeof(Elf32_Ehdr)) || !_CheckElfHeader()) {
|
if (!_CheckRange(0, sizeof(Elf32_Ehdr)) || !_CheckElfHeader()) {
|
||||||
fprintf(stderr, "\"%s\": Not an ELF file\n", fileName);
|
WARNING("\"%s\": Not an ELF file\n", fileName);
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,10 +164,9 @@ printf("fFileSize: %lld\n", fFileSize);
|
|||||||
int sectionCount = fElfHeader->e_shnum;
|
int sectionCount = fElfHeader->e_shnum;
|
||||||
size_t sectionHeaderTableSize = sectionHeaderSize * sectionCount;
|
size_t sectionHeaderTableSize = sectionHeaderSize * sectionCount;
|
||||||
if (!_CheckRange(sectionHeadersOffset, sectionHeaderTableSize)) {
|
if (!_CheckRange(sectionHeadersOffset, sectionHeaderTableSize)) {
|
||||||
fprintf(stderr, "\"%s\": Invalid ELF header\n", fileName);
|
WARNING("\"%s\": Invalid ELF header\n", fileName);
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
printf("sectionHeaderTable: %lld\n", sectionHeadersOffset);
|
|
||||||
|
|
||||||
// read the section header table
|
// read the section header table
|
||||||
uint8* sectionHeaderTable = (uint8*)malloc(sectionHeaderTableSize);
|
uint8* sectionHeaderTable = (uint8*)malloc(sectionHeaderTableSize);
|
||||||
@@ -186,11 +184,10 @@ printf("sectionHeaderTable: %lld\n", sectionHeadersOffset);
|
|||||||
+ fElfHeader->e_shstrndx * sectionHeaderSize);
|
+ fElfHeader->e_shstrndx * sectionHeaderSize);
|
||||||
if (!_CheckRange(stringSectionHeader->sh_offset,
|
if (!_CheckRange(stringSectionHeader->sh_offset,
|
||||||
stringSectionHeader->sh_size)) {
|
stringSectionHeader->sh_size)) {
|
||||||
fprintf(stderr, "\"%s\": Invalid string section header\n", fileName);
|
WARNING("\"%s\": Invalid string section header\n", fileName);
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
size_t sectionStringSize = stringSectionHeader->sh_size;
|
size_t sectionStringSize = stringSectionHeader->sh_size;
|
||||||
printf("sectionStrings: %ld\n", stringSectionHeader->sh_offset);
|
|
||||||
|
|
||||||
ElfSection* sectionStringSection = new(std::nothrow) ElfSection(".shstrtab",
|
ElfSection* sectionStringSection = new(std::nothrow) ElfSection(".shstrtab",
|
||||||
fFD, stringSectionHeader->sh_offset, sectionStringSize);
|
fFD, stringSectionHeader->sh_offset, sectionStringSize);
|
||||||
@@ -230,10 +227,9 @@ printf("sectionStrings: %ld\n", stringSectionHeader->sh_offset);
|
|||||||
int segmentCount = fElfHeader->e_phnum;
|
int segmentCount = fElfHeader->e_phnum;
|
||||||
size_t programHeaderTableSize = programHeaderSize * segmentCount;
|
size_t programHeaderTableSize = programHeaderSize * segmentCount;
|
||||||
if (!_CheckRange(programHeadersOffset, programHeaderTableSize)) {
|
if (!_CheckRange(programHeadersOffset, programHeaderTableSize)) {
|
||||||
fprintf(stderr, "\"%s\": Invalid ELF header\n", fileName);
|
WARNING("\"%s\": Invalid ELF header\n", fileName);
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
printf("programHeaderTable: %lld\n", programHeadersOffset);
|
|
||||||
|
|
||||||
// read the program header table
|
// read the program header table
|
||||||
uint8* programHeaderTable = (uint8*)malloc(programHeaderTableSize);
|
uint8* programHeaderTable = (uint8*)malloc(programHeaderTableSize);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "Image.h"
|
#include "Image.h"
|
||||||
#include "ImageDebugInfo.h"
|
#include "ImageDebugInfo.h"
|
||||||
#include "LocatableFile.h"
|
#include "LocatableFile.h"
|
||||||
|
#include "Tracing.h"
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - FunctionsTableModel
|
// #pragma mark - FunctionsTableModel
|
||||||
@@ -346,7 +347,8 @@ ImageFunctionsView::SetImageDebugInfo(ImageDebugInfo* imageDebugInfo)
|
|||||||
{
|
{
|
||||||
if (imageDebugInfo == fImageDebugInfo)
|
if (imageDebugInfo == fImageDebugInfo)
|
||||||
return;
|
return;
|
||||||
printf("ImageFunctionsView::SetImageDebugInfo(%p)\n", imageDebugInfo);
|
|
||||||
|
TRACE_GUI("ImageFunctionsView::SetImageDebugInfo(%p)\n", imageDebugInfo);
|
||||||
|
|
||||||
if (fImageDebugInfo != NULL)
|
if (fImageDebugInfo != NULL)
|
||||||
fImageDebugInfo->RemoveReference();
|
fImageDebugInfo->RemoveReference();
|
||||||
@@ -369,14 +371,16 @@ printf("ImageFunctionsView::SetImageDebugInfo(%p)\n", imageDebugInfo);
|
|||||||
if (fImageDebugInfo != NULL)
|
if (fImageDebugInfo != NULL)
|
||||||
fFunctionsTable->ResizeAllColumnsToPreferred();
|
fFunctionsTable->ResizeAllColumnsToPreferred();
|
||||||
|
|
||||||
printf("ImageFunctionsView::SetImageDebugInfo(%p) done\n", imageDebugInfo);
|
TRACE_GUI("ImageFunctionsView::SetImageDebugInfo(%p) done\n",
|
||||||
|
imageDebugInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ImageFunctionsView::SetFunction(FunctionInstance* function)
|
ImageFunctionsView::SetFunction(FunctionInstance* function)
|
||||||
{
|
{
|
||||||
printf("ImageFunctionsView::SetFunction(%p)\n", function);
|
TRACE_GUI("ImageFunctionsView::SetFunction(%p)\n", function);
|
||||||
|
|
||||||
TreeTablePath path;
|
TreeTablePath path;
|
||||||
if (fFunctionsTableModel->GetFunctionPath(function, path)) {
|
if (fFunctionsTableModel->GetFunctionPath(function, path)) {
|
||||||
fFunctionsTable->SetNodeExpanded(path, true, true);
|
fFunctionsTable->SetNodeExpanded(path, true, true);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <ObjectList.h>
|
#include <ObjectList.h>
|
||||||
|
|
||||||
#include "table/TableColumns.h"
|
#include "table/TableColumns.h"
|
||||||
|
#include "Tracing.h"
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -181,7 +182,8 @@ ImageListView::SetImage(Image* image)
|
|||||||
{
|
{
|
||||||
if (image == fImage)
|
if (image == fImage)
|
||||||
return;
|
return;
|
||||||
printf("ImageListView::SetImage(%p)\n", image);
|
|
||||||
|
TRACE_GUI("ImageListView::SetImage(%p)\n", image);
|
||||||
|
|
||||||
if (fImage != NULL)
|
if (fImage != NULL)
|
||||||
fImage->RemoveReference();
|
fImage->RemoveReference();
|
||||||
@@ -194,14 +196,16 @@ printf("ImageListView::SetImage(%p)\n", image);
|
|||||||
for (int32 i = 0; Image* other = fImagesTableModel->ImageAt(i); i++) {
|
for (int32 i = 0; Image* other = fImagesTableModel->ImageAt(i); i++) {
|
||||||
if (fImage == other) {
|
if (fImage == other) {
|
||||||
fImagesTable->SelectRow(i, false);
|
fImagesTable->SelectRow(i, false);
|
||||||
printf("ImageListView::SetImage() done\n");
|
|
||||||
|
TRACE_GUI("ImageListView::SetImage() done\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fImagesTable->DeselectAllRows();
|
fImagesTable->DeselectAllRows();
|
||||||
printf("ImageListView::SetImage() done\n");
|
|
||||||
|
TRACE_GUI("ImageListView::SetImage() done\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
#include "StackTrace.h"
|
#include "StackTrace.h"
|
||||||
#include "Statement.h"
|
#include "Statement.h"
|
||||||
#include "Team.h"
|
#include "Team.h"
|
||||||
|
#include "Tracing.h"
|
||||||
|
|
||||||
|
|
||||||
static const int32 kLeftTextMargin = 3;
|
static const int32 kLeftTextMargin = 3;
|
||||||
@@ -1670,7 +1671,8 @@ SourceView::UnsetListener()
|
|||||||
void
|
void
|
||||||
SourceView::SetStackTrace(StackTrace* stackTrace)
|
SourceView::SetStackTrace(StackTrace* stackTrace)
|
||||||
{
|
{
|
||||||
printf("SourceView::SetStackTrace(%p)\n", stackTrace);
|
TRACE_GUI("SourceView::SetStackTrace(%p)\n", stackTrace);
|
||||||
|
|
||||||
if (stackTrace == fStackTrace)
|
if (stackTrace == fStackTrace)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1758,7 +1760,8 @@ SourceView::UserBreakpointChanged(target_addr_t address)
|
|||||||
bool
|
bool
|
||||||
SourceView::ScrollToAddress(target_addr_t address)
|
SourceView::ScrollToAddress(target_addr_t address)
|
||||||
{
|
{
|
||||||
printf("SourceView::ScrollToAddress(%#llx)\n", address);
|
TRACE_GUI("SourceView::ScrollToAddress(%#llx)\n", address);
|
||||||
|
|
||||||
if (fSourceCode == NULL)
|
if (fSourceCode == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -1779,7 +1782,8 @@ printf("SourceView::ScrollToAddress(%#llx)\n", address);
|
|||||||
bool
|
bool
|
||||||
SourceView::ScrollToLine(uint32 line)
|
SourceView::ScrollToLine(uint32 line)
|
||||||
{
|
{
|
||||||
printf("SourceView::ScrollToLine(%lu)\n", line);
|
TRACE_GUI("SourceView::ScrollToLine(%lu)\n", line);
|
||||||
|
|
||||||
if (fSourceCode == NULL || line >= (uint32)fSourceCode->CountLines())
|
if (fSourceCode == NULL || line >= (uint32)fSourceCode->CountLines())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -1787,17 +1791,18 @@ printf("SourceView::ScrollToLine(%lu)\n", line);
|
|||||||
float bottom = top + fFontInfo.lineHeight - 1;
|
float bottom = top + fFontInfo.lineHeight - 1;
|
||||||
|
|
||||||
BRect visible = Bounds();
|
BRect visible = Bounds();
|
||||||
printf("SourceView::ScrollToLine(%ld)\n", line);
|
|
||||||
printf(" visible: (%f, %f) - (%f, %f), line: %f - %f\n", visible.left, visible.top, visible.right, visible.bottom, top, bottom);
|
TRACE_GUI("SourceView::ScrollToLine(%ld)\n", line);
|
||||||
|
TRACE_GUI(" visible: (%f, %f) - (%f, %f), line: %f - %f\n", visible.left,
|
||||||
|
visible.top, visible.right, visible.bottom, top, bottom);
|
||||||
|
|
||||||
// If not visible at all, scroll to the center, otherwise scroll so that at
|
// If not visible at all, scroll to the center, otherwise scroll so that at
|
||||||
// least one more line is visible.
|
// least one more line is visible.
|
||||||
if (top >= visible.bottom || bottom <= visible.top)
|
if (top >= visible.bottom || bottom <= visible.top) {
|
||||||
{
|
TRACE_GUI(" -> scrolling to (%f, %f)\n", visible.left,
|
||||||
printf(" -> scrolling to (%f, %f)\n", visible.left, top - (visible.Height() + 1) / 2);
|
top - (visible.Height() + 1) / 2);
|
||||||
ScrollTo(visible.left, top - (visible.Height() + 1) / 2);
|
ScrollTo(visible.left, top - (visible.Height() + 1) / 2);
|
||||||
}
|
} else if (top - fFontInfo.lineHeight < visible.top)
|
||||||
else if (top - fFontInfo.lineHeight < visible.top)
|
|
||||||
ScrollBy(0, top - fFontInfo.lineHeight - visible.top);
|
ScrollBy(0, top - fFontInfo.lineHeight - visible.top);
|
||||||
else if (bottom + fFontInfo.lineHeight > visible.bottom)
|
else if (bottom + fFontInfo.lineHeight > visible.bottom)
|
||||||
ScrollBy(0, bottom + fFontInfo.lineHeight - visible.bottom);
|
ScrollBy(0, bottom + fFontInfo.lineHeight - visible.bottom);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "RegistersView.h"
|
#include "RegistersView.h"
|
||||||
#include "StackTrace.h"
|
#include "StackTrace.h"
|
||||||
#include "StackTraceView.h"
|
#include "StackTraceView.h"
|
||||||
|
#include "Tracing.h"
|
||||||
#include "TypeComponentPath.h"
|
#include "TypeComponentPath.h"
|
||||||
#include "Variable.h"
|
#include "Variable.h"
|
||||||
|
|
||||||
@@ -361,8 +362,10 @@ TeamWindow::UserBreakpointChanged(const Team::BreakpointEvent& event)
|
|||||||
void
|
void
|
||||||
TeamWindow::FunctionSourceCodeChanged(Function* function)
|
TeamWindow::FunctionSourceCodeChanged(Function* function)
|
||||||
{
|
{
|
||||||
printf("TeamWindow::FunctionSourceCodeChanged(%p): source: %p, state: %d\n",
|
TRACE_GUI("TeamWindow::FunctionSourceCodeChanged(%p): source: %p, "
|
||||||
function, function->GetSourceCode(), function->SourceCodeState());
|
"state: %d\n", function, function->GetSourceCode(),
|
||||||
|
function->SourceCodeState());
|
||||||
|
|
||||||
PostMessage(MSG_FUNCTION_SOURCE_CODE_CHANGED);
|
PostMessage(MSG_FUNCTION_SOURCE_CODE_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -807,7 +810,8 @@ TeamWindow::_HandleStackFrameValueRetrieved(StackFrame* stackFrame,
|
|||||||
void
|
void
|
||||||
TeamWindow::_HandleImageDebugInfoChanged(image_id imageID)
|
TeamWindow::_HandleImageDebugInfoChanged(image_id imageID)
|
||||||
{
|
{
|
||||||
printf("TeamWindow::_HandleImageDebugInfoChanged(%ld)\n", imageID);
|
TRACE_GUI("TeamWindow::_HandleImageDebugInfoChanged(%ld)\n", imageID);
|
||||||
|
|
||||||
// We're only interested in the currently selected thread
|
// We're only interested in the currently selected thread
|
||||||
if (fActiveImage == NULL || imageID != fActiveImage->ID())
|
if (fActiveImage == NULL || imageID != fActiveImage->ID())
|
||||||
return;
|
return;
|
||||||
@@ -816,7 +820,9 @@ printf("TeamWindow::_HandleImageDebugInfoChanged(%ld)\n", imageID);
|
|||||||
|
|
||||||
ImageDebugInfo* imageDebugInfo = fActiveImage != NULL
|
ImageDebugInfo* imageDebugInfo = fActiveImage != NULL
|
||||||
? fActiveImage->GetImageDebugInfo() : NULL;
|
? fActiveImage->GetImageDebugInfo() : NULL;
|
||||||
printf(" image debug info: %p\n", imageDebugInfo);
|
|
||||||
|
TRACE_GUI(" image debug info: %p\n", imageDebugInfo);
|
||||||
|
|
||||||
Reference<ImageDebugInfo> imageDebugInfoReference(imageDebugInfo);
|
Reference<ImageDebugInfo> imageDebugInfoReference(imageDebugInfo);
|
||||||
// hold a reference until we've set it
|
// hold a reference until we've set it
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "StackFrameValues.h"
|
#include "StackFrameValues.h"
|
||||||
#include "Team.h"
|
#include "Team.h"
|
||||||
#include "Thread.h"
|
#include "Thread.h"
|
||||||
|
#include "Tracing.h"
|
||||||
#include "TypeComponentPath.h"
|
#include "TypeComponentPath.h"
|
||||||
#include "Variable.h"
|
#include "Variable.h"
|
||||||
|
|
||||||
@@ -32,7 +33,8 @@ public:
|
|||||||
fVariable(variable),
|
fVariable(variable),
|
||||||
fPath(path),
|
fPath(path),
|
||||||
fName(name),
|
fName(name),
|
||||||
fType(type)
|
fType(type),
|
||||||
|
fChildrenAdded(false)
|
||||||
{
|
{
|
||||||
fVariable->AcquireReference();
|
fVariable->AcquireReference();
|
||||||
fPath->AcquireReference();
|
fPath->AcquireReference();
|
||||||
@@ -108,6 +110,16 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ChildrenAdded() const
|
||||||
|
{
|
||||||
|
return fChildrenAdded;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetChildrenAdded(bool added)
|
||||||
|
{
|
||||||
|
fChildrenAdded = added;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef BObjectList<ValueNode> ChildList;
|
typedef BObjectList<ValueNode> ChildList;
|
||||||
|
|
||||||
@@ -119,6 +131,7 @@ private:
|
|||||||
Type* fType;
|
Type* fType;
|
||||||
BVariant fValue;
|
BVariant fValue;
|
||||||
ChildList fChildren;
|
ChildList fChildren;
|
||||||
|
bool fChildrenAdded;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -323,6 +336,13 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodeExpanded(ValueNode* node)
|
||||||
|
{
|
||||||
|
// add children of all children
|
||||||
|
for (int32 i = 0; ValueNode* child = node->ChildAt(i); i++)
|
||||||
|
_AddChildNodes(child);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef BObjectList<ValueNode> ValueList;
|
typedef BObjectList<ValueNode> ValueList;
|
||||||
|
|
||||||
@@ -340,6 +360,157 @@ private:
|
|||||||
delete node;
|
delete node;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// automatically add child nodes for the top level nodes
|
||||||
|
_AddChildNodes(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _AddChildNodes(ValueNode* node)
|
||||||
|
{
|
||||||
|
if (node == NULL || node->ChildrenAdded())
|
||||||
|
return;
|
||||||
|
|
||||||
|
_AddChildNodesInternal(node);
|
||||||
|
node->SetChildrenAdded(true);
|
||||||
|
|
||||||
|
// If the node is already known, notify the model listeners about the
|
||||||
|
// new child nodes. We assume that this holds true for the all but the
|
||||||
|
// top-level nodes.
|
||||||
|
TreeTablePath treePath;
|
||||||
|
if (node->Parent() != NULL && node->CountChildren() > 0
|
||||||
|
&& _GetTreePath(node, treePath)) {
|
||||||
|
NotifyNodesAdded(treePath, 0, node->CountChildren());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _AddChildNodesInternal(ValueNode* node)
|
||||||
|
{
|
||||||
|
TRACE_LOCALS("_AddChildNodesInternal(%p)\n", node);
|
||||||
|
|
||||||
|
Type* type = node->GetType();
|
||||||
|
TypeComponentPath* path
|
||||||
|
= new(std::nothrow) TypeComponentPath(*node->Path());
|
||||||
|
if (path == NULL
|
||||||
|
|| path->CountComponents() != node->Path()->CountComponents()) {
|
||||||
|
delete path;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Reference<TypeComponentPath> pathReference(path, true);
|
||||||
|
|
||||||
|
bool dereferencedType = false;
|
||||||
|
while (true) {
|
||||||
|
bool done = false;
|
||||||
|
TypeComponent component;
|
||||||
|
|
||||||
|
switch (type->Kind()) {
|
||||||
|
case TYPE_PRIMITIVE:
|
||||||
|
TRACE_LOCALS("TYPE_PRIMITIVE\n");
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
case TYPE_COMPOUND:
|
||||||
|
{
|
||||||
|
TRACE_LOCALS("TYPE_COMPOUND\n");
|
||||||
|
CompoundType* compoundType
|
||||||
|
= dynamic_cast<CompoundType*>(type);
|
||||||
|
|
||||||
|
// base types
|
||||||
|
for (int32 i = 0; BaseType* baseType
|
||||||
|
= compoundType->BaseTypeAt(i); i++) {
|
||||||
|
TRACE_LOCALS(" base %ld\n", i);
|
||||||
|
|
||||||
|
component.SetToBaseType(type->Kind(), i);
|
||||||
|
TypeComponentPath* baseTypePath
|
||||||
|
= new(std::nothrow) TypeComponentPath(*path);
|
||||||
|
if (baseTypePath == NULL
|
||||||
|
|| baseTypePath->CountComponents()
|
||||||
|
!= path->CountComponents()
|
||||||
|
|| !baseTypePath->AddComponent(component)) {
|
||||||
|
delete baseTypePath;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Reference<TypeComponentPath> baseTypePathReference(
|
||||||
|
baseTypePath, true);
|
||||||
|
_AddChildNode(node, node->GetVariable(), baseTypePath,
|
||||||
|
baseType->GetType()->Name(), baseType->GetType());
|
||||||
|
}
|
||||||
|
|
||||||
|
// members
|
||||||
|
for (int32 i = 0; DataMember* member
|
||||||
|
= compoundType->DataMemberAt(i); i++) {
|
||||||
|
BString name = member->Name();
|
||||||
|
|
||||||
|
TRACE_LOCALS(" member %ld: \"%s\"\n", i, name.String());
|
||||||
|
|
||||||
|
component.SetToDataMember(type->Kind(), i, name);
|
||||||
|
TypeComponentPath* memberPath
|
||||||
|
= new(std::nothrow) TypeComponentPath(*path);
|
||||||
|
if (memberPath == NULL
|
||||||
|
|| memberPath->CountComponents()
|
||||||
|
!= path->CountComponents()
|
||||||
|
|| !memberPath->AddComponent(component)) {
|
||||||
|
delete memberPath;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Reference<TypeComponentPath> memberPathReference(
|
||||||
|
memberPath, true);
|
||||||
|
_AddChildNode(node, node->GetVariable(), memberPath,
|
||||||
|
name, member->GetType());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case TYPE_MODIFIED:
|
||||||
|
TRACE_LOCALS("TYPE_MODIFIED\n");
|
||||||
|
component.SetToBaseType(type->Kind());
|
||||||
|
type = dynamic_cast<ModifiedType*>(type)->BaseType();
|
||||||
|
break;
|
||||||
|
case TYPE_TYPEDEF:
|
||||||
|
TRACE_LOCALS("TYPE_TYPEDEF\n");
|
||||||
|
component.SetToBaseType(type->Kind());
|
||||||
|
type = dynamic_cast<TypedefType*>(type)->BaseType();
|
||||||
|
break;
|
||||||
|
case TYPE_ADDRESS:
|
||||||
|
TRACE_LOCALS("TYPE_ADDRESS\n");
|
||||||
|
// don't dereference twice
|
||||||
|
if (dereferencedType) {
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
component.SetToBaseType(type->Kind());
|
||||||
|
type = dynamic_cast<AddressType*>(type)->BaseType();
|
||||||
|
dereferencedType = true;
|
||||||
|
break;
|
||||||
|
case TYPE_ARRAY:
|
||||||
|
TRACE_LOCALS("TYPE_ARRAY\n");
|
||||||
|
// TODO:...
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
TRACE_LOCALS("unknown\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done) {
|
||||||
|
if (dereferencedType) {
|
||||||
|
_AddChildNode(node, node->GetVariable(), path,
|
||||||
|
BString("*") << node->Name(), type);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!path->AddComponent(component))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _AddChildNode(ValueNode* parent, Variable* variable,
|
||||||
|
TypeComponentPath* path, const BString& name, Type* type)
|
||||||
|
{
|
||||||
|
ValueNode* node = new(std::nothrow) ValueNode(parent, variable, path,
|
||||||
|
name, type);
|
||||||
|
if (node == NULL || !parent->AddChild(node)) {
|
||||||
|
delete node;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueNode* _GetNode(Variable* variable, TypeComponentPath* path) const
|
ValueNode* _GetNode(Variable* variable, TypeComponentPath* path) const
|
||||||
@@ -353,15 +524,32 @@ private:
|
|||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// now walk along the path, finding the respective child node for each
|
// Now walk along the path, finding the respective child node for each
|
||||||
// component
|
// component (might be several components at once).
|
||||||
int32 componentCount = path->CountComponents();
|
int32 componentCount = path->CountComponents();
|
||||||
for (int32 i = 0; i < componentCount; i++) {
|
for (int32 i = 0; i < componentCount;) {
|
||||||
ValueNode* childNode = NULL;
|
ValueNode* childNode = NULL;
|
||||||
TypeComponent typeComponent = path->ComponentAt(i);
|
|
||||||
for (int32 k = 0; (childNode = node->ChildAt(k)) != NULL; k++) {
|
for (int32 k = 0; (childNode = node->ChildAt(k)) != NULL; k++) {
|
||||||
if (childNode->Path()->ComponentAt(i) == typeComponent)
|
TypeComponentPath* childPath = childNode->Path();
|
||||||
|
int32 childComponentCount = childPath->CountComponents();
|
||||||
|
if (childComponentCount > componentCount)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int32 componentIndex = i;
|
||||||
|
componentIndex < childComponentCount; componentIndex++) {
|
||||||
|
if (childPath->ComponentAt(componentIndex)
|
||||||
|
!= path->ComponentAt(componentIndex)) {
|
||||||
|
childNode = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childNode != NULL) {
|
||||||
|
// got a match -- skip the matched children components
|
||||||
|
i = childComponentCount;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (childNode == NULL)
|
if (childNode == NULL)
|
||||||
@@ -479,11 +667,37 @@ VariablesView::StackFrameValueRetrieved(StackFrame* stackFrame,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
VariablesView::TreeTableNodeExpandedChanged(TreeTable* table,
|
||||||
|
const TreeTablePath& path, bool expanded)
|
||||||
|
{
|
||||||
|
if (expanded) {
|
||||||
|
ValueNode* node = (ValueNode*)fVariableTableModel->NodeForPath(path);
|
||||||
|
if (node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fVariableTableModel->NodeExpanded(node);
|
||||||
|
|
||||||
|
// request the values of all children that don't have any yet
|
||||||
|
for (int32 i = 0; ValueNode* child = node->ChildAt(i); i++) {
|
||||||
|
Variable* variable = child->GetVariable();
|
||||||
|
TypeComponentPath* path = child->Path();
|
||||||
|
if (fStackFrame->Values()->HasValue(variable->ID(), *path))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fListener->StackFrameValueRequested(fThread, fStackFrame, variable,
|
||||||
|
path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
VariablesView::_Init()
|
VariablesView::_Init()
|
||||||
{
|
{
|
||||||
fVariableTable = new TreeTable("variable list", 0, B_FANCY_BORDER);
|
fVariableTable = new TreeTable("variable list", 0, B_FANCY_BORDER);
|
||||||
AddChild(fVariableTable->ToView());
|
AddChild(fVariableTable->ToView());
|
||||||
|
fVariableTable->SetSortingEnabled(false);
|
||||||
|
|
||||||
// columns
|
// columns
|
||||||
fVariableTable->AddColumn(new StringTableColumn(0, "Variable", 80, 40, 1000,
|
fVariableTable->AddColumn(new StringTableColumn(0, "Variable", 80, 40, 1000,
|
||||||
@@ -510,8 +724,7 @@ VariablesView::_RequestVariableValue(Variable* variable)
|
|||||||
return;
|
return;
|
||||||
Reference<TypeComponentPath> pathReference(path, true);
|
Reference<TypeComponentPath> pathReference(path, true);
|
||||||
|
|
||||||
fListener->StackFrameValueRequested(fThread, fStackFrame,
|
fListener->StackFrameValueRequested(fThread, fStackFrame, variable, path);
|
||||||
variable, path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,11 @@ public:
|
|||||||
Variable* variable,
|
Variable* variable,
|
||||||
TypeComponentPath* path);
|
TypeComponentPath* path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// TreeTableListener
|
||||||
|
virtual void TreeTableNodeExpandedChanged(TreeTable* table,
|
||||||
|
const TreeTablePath& path, bool expanded);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class ValueNode;
|
class ValueNode;
|
||||||
class VariableValueColumn;
|
class VariableValueColumn;
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include "CpuState.h"
|
#include "CpuState.h"
|
||||||
#include "FunctionInstance.h"
|
#include "FunctionInstance.h"
|
||||||
#include "Image.h"
|
#include "Image.h"
|
||||||
|
#include "StackFrameDebugInfo.h"
|
||||||
|
#include "StackFrameValueInfos.h"
|
||||||
#include "StackFrameValues.h"
|
#include "StackFrameValues.h"
|
||||||
#include "Variable.h"
|
#include "Variable.h"
|
||||||
|
|
||||||
@@ -18,18 +20,22 @@
|
|||||||
|
|
||||||
|
|
||||||
StackFrame::StackFrame(stack_frame_type type, CpuState* cpuState,
|
StackFrame::StackFrame(stack_frame_type type, CpuState* cpuState,
|
||||||
target_addr_t frameAddress, target_addr_t instructionPointer)
|
target_addr_t frameAddress, target_addr_t instructionPointer,
|
||||||
|
StackFrameDebugInfo* debugInfo)
|
||||||
:
|
:
|
||||||
fType(type),
|
fType(type),
|
||||||
fCpuState(cpuState),
|
fCpuState(cpuState),
|
||||||
fFrameAddress(frameAddress),
|
fFrameAddress(frameAddress),
|
||||||
fInstructionPointer(instructionPointer),
|
fInstructionPointer(instructionPointer),
|
||||||
fReturnAddress(0),
|
fReturnAddress(0),
|
||||||
|
fDebugInfo(debugInfo),
|
||||||
fImage(NULL),
|
fImage(NULL),
|
||||||
fFunction(NULL),
|
fFunction(NULL),
|
||||||
fValues(NULL)
|
fValues(NULL),
|
||||||
|
fValueInfos(NULL)
|
||||||
{
|
{
|
||||||
fCpuState->AcquireReference();
|
fCpuState->AcquireReference();
|
||||||
|
fDebugInfo->AcquireReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -43,6 +49,8 @@ StackFrame::~StackFrame()
|
|||||||
|
|
||||||
SetImage(NULL);
|
SetImage(NULL);
|
||||||
SetFunction(NULL);
|
SetFunction(NULL);
|
||||||
|
|
||||||
|
fDebugInfo->ReleaseReference();
|
||||||
fCpuState->ReleaseReference();
|
fCpuState->ReleaseReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,11 +58,25 @@ StackFrame::~StackFrame()
|
|||||||
status_t
|
status_t
|
||||||
StackFrame::Init()
|
StackFrame::Init()
|
||||||
{
|
{
|
||||||
|
// create values map
|
||||||
fValues = new(std::nothrow) StackFrameValues;
|
fValues = new(std::nothrow) StackFrameValues;
|
||||||
if (fValues == NULL)
|
if (fValues == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
return fValues->Init();
|
status_t error = fValues->Init();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// create value infos map
|
||||||
|
fValueInfos = new(std::nothrow) StackFrameValueInfos;
|
||||||
|
if (fValueInfos == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
error = fValueInfos->Init();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ enum stack_frame_type {
|
|||||||
class CpuState;
|
class CpuState;
|
||||||
class Image;
|
class Image;
|
||||||
class FunctionInstance;
|
class FunctionInstance;
|
||||||
|
class StackFrameDebugInfo;
|
||||||
|
class StackFrameValueInfos;
|
||||||
class StackFrameValues;
|
class StackFrameValues;
|
||||||
class TypeComponentPath;
|
class TypeComponentPath;
|
||||||
class Variable;
|
class Variable;
|
||||||
@@ -39,7 +41,8 @@ public:
|
|||||||
StackFrame(stack_frame_type type,
|
StackFrame(stack_frame_type type,
|
||||||
CpuState* cpuState,
|
CpuState* cpuState,
|
||||||
target_addr_t frameAddress,
|
target_addr_t frameAddress,
|
||||||
target_addr_t instructionPointer);
|
target_addr_t instructionPointer,
|
||||||
|
StackFrameDebugInfo* debugInfo);
|
||||||
~StackFrame();
|
~StackFrame();
|
||||||
|
|
||||||
status_t Init();
|
status_t Init();
|
||||||
@@ -47,6 +50,7 @@ public:
|
|||||||
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; }
|
||||||
|
StackFrameDebugInfo* DebugInfo() const { return fDebugInfo; }
|
||||||
|
|
||||||
target_addr_t InstructionPointer() const
|
target_addr_t InstructionPointer() const
|
||||||
{ return fInstructionPointer; }
|
{ return fInstructionPointer; }
|
||||||
@@ -68,7 +72,8 @@ public:
|
|||||||
Variable* LocalVariableAt(int32 index) const;
|
Variable* LocalVariableAt(int32 index) const;
|
||||||
bool AddLocalVariable(Variable* variable);
|
bool AddLocalVariable(Variable* variable);
|
||||||
|
|
||||||
StackFrameValues* Values() const { return fValues; }
|
StackFrameValues* Values() const { return fValues; }
|
||||||
|
StackFrameValueInfos* ValueInfos() const { return fValueInfos; }
|
||||||
|
|
||||||
// team lock must be held
|
// team lock must be held
|
||||||
void AddListener(Listener* listener);
|
void AddListener(Listener* listener);
|
||||||
@@ -87,11 +92,13 @@ private:
|
|||||||
target_addr_t fFrameAddress;
|
target_addr_t fFrameAddress;
|
||||||
target_addr_t fInstructionPointer;
|
target_addr_t fInstructionPointer;
|
||||||
target_addr_t fReturnAddress;
|
target_addr_t fReturnAddress;
|
||||||
|
StackFrameDebugInfo* fDebugInfo;
|
||||||
Image* fImage;
|
Image* fImage;
|
||||||
FunctionInstance* fFunction;
|
FunctionInstance* fFunction;
|
||||||
VariableList fParameters;
|
VariableList fParameters;
|
||||||
VariableList fLocalVariables;
|
VariableList fLocalVariables;
|
||||||
StackFrameValues* fValues;
|
StackFrameValues* fValues;
|
||||||
|
StackFrameValueInfos* fValueInfos;
|
||||||
ListenerList fListeners;
|
ListenerList fListeners;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,195 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "StackFrameValueInfos.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include "FunctionID.h"
|
||||||
|
#include "Type.h"
|
||||||
|
#include "TypeComponentPath.h"
|
||||||
|
#include "ValueLocation.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct StackFrameValueInfos::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 StackFrameValueInfos::InfoEntry : Key {
|
||||||
|
Type* type;
|
||||||
|
ValueLocation* location;
|
||||||
|
InfoEntry* next;
|
||||||
|
|
||||||
|
InfoEntry(ObjectID* variable, TypeComponentPath* path)
|
||||||
|
:
|
||||||
|
Key(variable, path),
|
||||||
|
type(NULL),
|
||||||
|
location(NULL)
|
||||||
|
{
|
||||||
|
variable->AcquireReference();
|
||||||
|
path->AcquireReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
~InfoEntry()
|
||||||
|
{
|
||||||
|
SetInfo(NULL, NULL);
|
||||||
|
variable->ReleaseReference();
|
||||||
|
path->ReleaseReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SetInfo(Type* type, ValueLocation* location)
|
||||||
|
{
|
||||||
|
if (type != NULL)
|
||||||
|
type->AcquireReference();
|
||||||
|
if (location != NULL)
|
||||||
|
location->AcquireReference();
|
||||||
|
|
||||||
|
if (this->type != NULL)
|
||||||
|
this->type->ReleaseReference();
|
||||||
|
if (this->location != NULL)
|
||||||
|
this->location->ReleaseReference();
|
||||||
|
|
||||||
|
this->type = type;
|
||||||
|
this->location = location;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct StackFrameValueInfos::InfoEntryHashDefinition {
|
||||||
|
typedef Key KeyType;
|
||||||
|
typedef InfoEntry ValueType;
|
||||||
|
|
||||||
|
size_t HashKey(const Key& key) const
|
||||||
|
{
|
||||||
|
return key.HashValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Hash(const InfoEntry* value) const
|
||||||
|
{
|
||||||
|
return value->HashValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Compare(const Key& key, const InfoEntry* value) const
|
||||||
|
{
|
||||||
|
return key == *value;
|
||||||
|
}
|
||||||
|
|
||||||
|
InfoEntry*& GetLink(InfoEntry* value) const
|
||||||
|
{
|
||||||
|
return value->next;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
StackFrameValueInfos::StackFrameValueInfos()
|
||||||
|
:
|
||||||
|
fValues(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
StackFrameValueInfos::~StackFrameValueInfos()
|
||||||
|
{
|
||||||
|
_Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
StackFrameValueInfos::Init()
|
||||||
|
{
|
||||||
|
fValues = new(std::nothrow) ValueTable;
|
||||||
|
if (fValues == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
return fValues->Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
StackFrameValueInfos::GetInfo(ObjectID* variable,
|
||||||
|
const TypeComponentPath* path, Type** _type,
|
||||||
|
ValueLocation** _location) const
|
||||||
|
{
|
||||||
|
InfoEntry* entry = fValues->Lookup(
|
||||||
|
Key(variable, (TypeComponentPath*)path));
|
||||||
|
if (entry == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (_type != NULL) {
|
||||||
|
entry->type->AcquireReference();
|
||||||
|
*_type = entry->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_location != NULL) {
|
||||||
|
entry->location->AcquireReference();
|
||||||
|
*_location = entry->location;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
StackFrameValueInfos::HasInfo(ObjectID* variable,
|
||||||
|
const TypeComponentPath* path) const
|
||||||
|
{
|
||||||
|
return fValues->Lookup(Key(variable, (TypeComponentPath*)path)) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
StackFrameValueInfos::SetInfo(ObjectID* variable, TypeComponentPath* path,
|
||||||
|
Type* type, ValueLocation* location)
|
||||||
|
{
|
||||||
|
InfoEntry* entry = fValues->Lookup(Key(variable, path));
|
||||||
|
if (entry == NULL) {
|
||||||
|
entry = new(std::nothrow) InfoEntry(variable, path);
|
||||||
|
if (entry == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
fValues->Insert(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->SetInfo(type, location);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
StackFrameValueInfos::_Cleanup()
|
||||||
|
{
|
||||||
|
if (fValues != NULL) {
|
||||||
|
InfoEntry* entry = fValues->Clear(true);
|
||||||
|
|
||||||
|
while (entry != NULL) {
|
||||||
|
InfoEntry* next = entry->next;
|
||||||
|
delete entry;
|
||||||
|
entry = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete fValues;
|
||||||
|
fValues = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef STACK_FRAME_VALUE_INFOS_H
|
||||||
|
#define STACK_FRAME_VALUE_INFOS_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Referenceable.h>
|
||||||
|
#include <util/OpenHashTable.h>
|
||||||
|
#include <Variant.h>
|
||||||
|
|
||||||
|
|
||||||
|
class ObjectID;
|
||||||
|
class Type;
|
||||||
|
class TypeComponentPath;
|
||||||
|
class ValueLocation;
|
||||||
|
|
||||||
|
|
||||||
|
class StackFrameValueInfos : public Referenceable {
|
||||||
|
public:
|
||||||
|
StackFrameValueInfos();
|
||||||
|
virtual ~StackFrameValueInfos();
|
||||||
|
|
||||||
|
status_t Init();
|
||||||
|
|
||||||
|
bool GetInfo(ObjectID* variable,
|
||||||
|
const TypeComponentPath* path,
|
||||||
|
Type** _type, ValueLocation** _location)
|
||||||
|
const;
|
||||||
|
// returns a references
|
||||||
|
inline bool GetInfo(ObjectID* variable,
|
||||||
|
const TypeComponentPath& path,
|
||||||
|
Type** _type, ValueLocation** _location)
|
||||||
|
const;
|
||||||
|
// returns a references
|
||||||
|
bool HasInfo(ObjectID* variable,
|
||||||
|
const TypeComponentPath* path) const;
|
||||||
|
inline bool HasInfo(ObjectID* variable,
|
||||||
|
const TypeComponentPath& path) const;
|
||||||
|
status_t SetInfo(ObjectID* variable,
|
||||||
|
TypeComponentPath* path,
|
||||||
|
Type* type, ValueLocation* location);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Key;
|
||||||
|
struct InfoEntry;
|
||||||
|
struct InfoEntryHashDefinition;
|
||||||
|
|
||||||
|
typedef BOpenHashTable<InfoEntryHashDefinition> ValueTable;
|
||||||
|
|
||||||
|
private:
|
||||||
|
StackFrameValueInfos& operator=(const StackFrameValueInfos& other);
|
||||||
|
|
||||||
|
void _Cleanup();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ValueTable* fValues;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
StackFrameValueInfos::GetInfo(ObjectID* variable, const TypeComponentPath& path,
|
||||||
|
Type** _type, ValueLocation** _location) const
|
||||||
|
{
|
||||||
|
return GetInfo(variable, &path, _type, _location);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
StackFrameValueInfos::HasInfo(ObjectID* variable, const TypeComponentPath& path)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return HasInfo(variable, &path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // STACK_FRAME_VALUE_INFOS_H
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "SpecificImageDebugInfo.h"
|
#include "SpecificImageDebugInfo.h"
|
||||||
#include "Statement.h"
|
#include "Statement.h"
|
||||||
#include "TeamDebugInfo.h"
|
#include "TeamDebugInfo.h"
|
||||||
|
#include "Tracing.h"
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - BreakpointByAddressPredicate
|
// #pragma mark - BreakpointByAddressPredicate
|
||||||
@@ -365,30 +366,28 @@ status_t
|
|||||||
Team::GetStatementAtAddress(target_addr_t address, FunctionInstance*& _function,
|
Team::GetStatementAtAddress(target_addr_t address, FunctionInstance*& _function,
|
||||||
Statement*& _statement)
|
Statement*& _statement)
|
||||||
{
|
{
|
||||||
printf("Team::GetStatementAtAddress(%#llx)\n", address);
|
TRACE_CODE("Team::GetStatementAtAddress(%#llx)\n", address);
|
||||||
|
|
||||||
// get the image at the address
|
// get the image at the address
|
||||||
Image* image = ImageByAddress(address);
|
Image* image = ImageByAddress(address);
|
||||||
if (image == NULL)
|
if (image == NULL) {
|
||||||
{
|
TRACE_CODE(" -> no image\n");
|
||||||
printf(" -> no image\n");
|
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageDebugInfo* imageDebugInfo = image->GetImageDebugInfo();
|
ImageDebugInfo* imageDebugInfo = image->GetImageDebugInfo();
|
||||||
if (imageDebugInfo == NULL)
|
if (imageDebugInfo == NULL) {
|
||||||
{
|
TRACE_CODE(" -> no image debug info\n");
|
||||||
printf(" -> no image debug info\n");
|
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the function
|
// get the function
|
||||||
FunctionInstance* functionInstance
|
FunctionInstance* functionInstance
|
||||||
= imageDebugInfo->FunctionAtAddress(address);
|
= imageDebugInfo->FunctionAtAddress(address);
|
||||||
if (functionInstance == NULL)
|
if (functionInstance == NULL) {
|
||||||
{
|
TRACE_CODE(" -> no function instance\n");
|
||||||
printf(" -> no function instance\n");
|
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the function instance has disassembled code attached, we can get the
|
// If the function instance has disassembled code attached, we can get the
|
||||||
// statement directly.
|
// statement directly.
|
||||||
@@ -408,11 +407,10 @@ printf(" -> no function instance\n");
|
|||||||
= functionInstance->GetFunctionDebugInfo();
|
= functionInstance->GetFunctionDebugInfo();
|
||||||
status_t error = functionDebugInfo->GetSpecificImageDebugInfo()
|
status_t error = functionDebugInfo->GetSpecificImageDebugInfo()
|
||||||
->GetStatement(functionDebugInfo, address, _statement);
|
->GetStatement(functionDebugInfo, address, _statement);
|
||||||
if (error != B_OK)
|
if (error != B_OK) {
|
||||||
{
|
TRACE_CODE(" -> no statement from the specific image debug info\n");
|
||||||
printf(" -> no statement from the specific image debug info\n");
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
_function = functionInstance;
|
_function = functionInstance;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -423,7 +421,9 @@ status_t
|
|||||||
Team::GetStatementAtSourceLocation(SourceCode* sourceCode,
|
Team::GetStatementAtSourceLocation(SourceCode* sourceCode,
|
||||||
const SourceLocation& location, Statement*& _statement)
|
const SourceLocation& location, Statement*& _statement)
|
||||||
{
|
{
|
||||||
printf("Team::GetStatementAtSourceLocation(%p, (%ld, %ld))\n", sourceCode, location.Line(), location.Column());
|
TRACE_CODE("Team::GetStatementAtSourceLocation(%p, (%ld, %ld))\n",
|
||||||
|
sourceCode, location.Line(), location.Column());
|
||||||
|
|
||||||
// If we're lucky the source code can provide us with a statement.
|
// If we're lucky the source code can provide us with a statement.
|
||||||
if (DisassembledCode* code = dynamic_cast<DisassembledCode*>(sourceCode)) {
|
if (DisassembledCode* code = dynamic_cast<DisassembledCode*>(sourceCode)) {
|
||||||
Statement* statement = code->StatementAtLocation(location);
|
Statement* statement = code->StatementAtLocation(location);
|
||||||
|
|||||||
@@ -7,6 +7,14 @@
|
|||||||
#include "Type.h"
|
#include "Type.h"
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - BaseType
|
||||||
|
|
||||||
|
|
||||||
|
BaseType::~BaseType()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DataMember
|
// #pragma mark - DataMember
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,14 @@ enum {
|
|||||||
class Type;
|
class Type;
|
||||||
|
|
||||||
|
|
||||||
|
class BaseType : public Referenceable {
|
||||||
|
public:
|
||||||
|
virtual ~BaseType();
|
||||||
|
|
||||||
|
virtual Type* GetType() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class DataMember : public Referenceable {
|
class DataMember : public Referenceable {
|
||||||
public:
|
public:
|
||||||
virtual ~DataMember();
|
virtual ~DataMember();
|
||||||
@@ -54,6 +62,7 @@ public:
|
|||||||
|
|
||||||
virtual const char* Name() const = 0;
|
virtual const char* Name() const = 0;
|
||||||
virtual type_kind Kind() const = 0;
|
virtual type_kind Kind() const = 0;
|
||||||
|
virtual target_size_t ByteSize() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -73,6 +82,9 @@ public:
|
|||||||
|
|
||||||
virtual type_kind Kind() const;
|
virtual type_kind Kind() const;
|
||||||
|
|
||||||
|
virtual int32 CountBaseTypes() const = 0;
|
||||||
|
virtual BaseType* BaseTypeAt(int32 index) const = 0;
|
||||||
|
|
||||||
virtual int32 CountDataMembers() const = 0;
|
virtual int32 CountDataMembers() const = 0;
|
||||||
virtual DataMember* DataMemberAt(int32 index) const = 0;
|
virtual DataMember* DataMemberAt(int32 index) const = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "TypeComponentPath.h"
|
#include "TypeComponentPath.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
#include "StringUtils.h"
|
#include "StringUtils.h"
|
||||||
@@ -22,6 +24,49 @@ TypeComponent::HashValue() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TypeComponent::Dump() const
|
||||||
|
{
|
||||||
|
switch (typeKind) {
|
||||||
|
case TYPE_PRIMITIVE:
|
||||||
|
printf("primitive");
|
||||||
|
break;
|
||||||
|
case TYPE_COMPOUND:
|
||||||
|
printf("compound");
|
||||||
|
break;
|
||||||
|
case TYPE_MODIFIED:
|
||||||
|
printf("modified");
|
||||||
|
break;
|
||||||
|
case TYPE_TYPEDEF:
|
||||||
|
printf("typedef");
|
||||||
|
break;
|
||||||
|
case TYPE_ADDRESS:
|
||||||
|
printf("address");
|
||||||
|
break;
|
||||||
|
case TYPE_ARRAY:
|
||||||
|
printf("array");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" ");
|
||||||
|
|
||||||
|
switch (componentKind) {
|
||||||
|
case TYPE_COMPONENT_UNDEFINED:
|
||||||
|
printf("undefined");
|
||||||
|
break;
|
||||||
|
case TYPE_COMPONENT_BASE_TYPE:
|
||||||
|
printf("base %llu \"%s\"", index, name.String());
|
||||||
|
break;
|
||||||
|
case TYPE_COMPONENT_DATA_MEMBER:
|
||||||
|
printf("member %llu \"%s\"", index, name.String());
|
||||||
|
break;
|
||||||
|
case TYPE_COMPONENT_ARRAY_ELEMENT:
|
||||||
|
printf("element %llu \"%s\"", index, name.String());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TypeComponent::operator==(const TypeComponent& other) const
|
TypeComponent::operator==(const TypeComponent& other) const
|
||||||
{
|
{
|
||||||
@@ -90,6 +135,26 @@ TypeComponentPath::Clear()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TypeComponentPath*
|
||||||
|
TypeComponentPath::CreateSubPath(int32 componentCount) const
|
||||||
|
{
|
||||||
|
if (componentCount < 0 || componentCount > fComponents.CountItems())
|
||||||
|
componentCount = fComponents.CountItems();
|
||||||
|
|
||||||
|
TypeComponentPath* path = new(std::nothrow) TypeComponentPath;
|
||||||
|
if (path == NULL)
|
||||||
|
return NULL;
|
||||||
|
Reference<TypeComponentPath> pathReference(path, true);
|
||||||
|
|
||||||
|
for (int32 i = 0; i < componentCount; i++) {
|
||||||
|
if (!path->AddComponent(*fComponents.ItemAt(i)))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pathReference.Detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32
|
uint32
|
||||||
TypeComponentPath::HashValue() const
|
TypeComponentPath::HashValue() const
|
||||||
{
|
{
|
||||||
@@ -106,6 +171,21 @@ TypeComponentPath::HashValue() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TypeComponentPath::Dump() const
|
||||||
|
{
|
||||||
|
int32 count = fComponents.CountItems();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
if (i == 0)
|
||||||
|
printf("[");
|
||||||
|
else
|
||||||
|
printf(" -> [");
|
||||||
|
fComponents.ItemAt(i)->Dump();
|
||||||
|
printf("]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TypeComponentPath&
|
TypeComponentPath&
|
||||||
TypeComponentPath::operator=(const TypeComponentPath& other)
|
TypeComponentPath::operator=(const TypeComponentPath& other)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ struct TypeComponent {
|
|||||||
|
|
||||||
uint32 HashValue() const;
|
uint32 HashValue() const;
|
||||||
|
|
||||||
|
void Dump() const;
|
||||||
|
|
||||||
TypeComponent& operator=(const TypeComponent& other)
|
TypeComponent& operator=(const TypeComponent& other)
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -110,8 +112,14 @@ public:
|
|||||||
bool AddComponent(const TypeComponent& component);
|
bool AddComponent(const TypeComponent& component);
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
TypeComponentPath* CreateSubPath(int32 componentCount) const;
|
||||||
|
// returns a new object (or NULL when out
|
||||||
|
// of memory)
|
||||||
|
|
||||||
uint32 HashValue() const;
|
uint32 HashValue() const;
|
||||||
|
|
||||||
|
void Dump() const;
|
||||||
|
|
||||||
TypeComponentPath& operator=(const TypeComponentPath& other);
|
TypeComponentPath& operator=(const TypeComponentPath& other);
|
||||||
|
|
||||||
bool operator==(const TypeComponentPath& other) const;
|
bool operator==(const TypeComponentPath& other) const;
|
||||||
|
|||||||
@@ -25,6 +25,72 @@ ValueLocation::ValueLocation(const ValueLocation& other)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
ValueLocation::SetTo(const ValueLocation& other, uint64 bitOffset,
|
||||||
|
uint64 bitSize)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
|
||||||
|
// skip pieces before the offset
|
||||||
|
int32 count = other.CountPieces();
|
||||||
|
int32 i;
|
||||||
|
ValuePieceLocation piece;
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
piece = other.PieceAt(i);
|
||||||
|
if (piece.size * 8 + piece.bitSize > bitOffset)
|
||||||
|
break;
|
||||||
|
bitOffset -= piece.size * 8 + piece.bitSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= count)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// handle partial piece
|
||||||
|
if (bitOffset > 0) {
|
||||||
|
uint64 remainingBits = piece.size * 8 + piece.bitSize - bitOffset;
|
||||||
|
piece.size = remainingBits / 8;
|
||||||
|
piece.bitSize = remainingBits % 8;
|
||||||
|
|
||||||
|
switch (piece.type) {
|
||||||
|
case VALUE_PIECE_LOCATION_MEMORY:
|
||||||
|
piece.address += (bitOffset + piece.bitOffset) / 8;
|
||||||
|
piece.bitOffset = (bitOffset + piece.bitOffset) % 8;
|
||||||
|
break;
|
||||||
|
case VALUE_PIECE_LOCATION_UNKNOWN:
|
||||||
|
piece.bitOffset = 0;
|
||||||
|
break;
|
||||||
|
case VALUE_PIECE_LOCATION_REGISTER:
|
||||||
|
piece.bitOffset += bitOffset;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle remaining pieces
|
||||||
|
while (bitSize > 0) {
|
||||||
|
target_addr_t pieceSize = piece.size * 8 + piece.bitSize;
|
||||||
|
if (pieceSize > bitSize) {
|
||||||
|
// the piece is bigger than the remaining size -- cut it
|
||||||
|
piece.size = bitSize / 8;
|
||||||
|
piece.bitSize = bitSize % 8;
|
||||||
|
bitSize = 0;
|
||||||
|
} else
|
||||||
|
bitSize -= pieceSize;
|
||||||
|
|
||||||
|
if (!AddPiece(piece))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (++i >= count)
|
||||||
|
break;
|
||||||
|
|
||||||
|
piece = other.PieceAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ValueLocation::Clear()
|
ValueLocation::Clear()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -80,6 +80,9 @@ public:
|
|||||||
ValueLocation(const ValuePieceLocation& piece);
|
ValueLocation(const ValuePieceLocation& piece);
|
||||||
ValueLocation(const ValueLocation& other);
|
ValueLocation(const ValueLocation& other);
|
||||||
|
|
||||||
|
bool SetTo(const ValueLocation& other,
|
||||||
|
uint64 bitOffset, uint64 bitSize);
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
bool AddPiece(const ValuePieceLocation& piece);
|
bool AddPiece(const ValuePieceLocation& piece);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user