* 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 "Statement.h"
|
||||
#include "Team.h"
|
||||
#include "Tracing.h"
|
||||
|
||||
|
||||
BreakpointManager::BreakpointManager(Team* team,
|
||||
@@ -44,36 +45,41 @@ status_t
|
||||
BreakpointManager::InstallUserBreakpoint(UserBreakpoint* userBreakpoint,
|
||||
bool enabled)
|
||||
{
|
||||
printf("BreakpointManager::InstallUserBreakpoint(%p, %d)\n", userBreakpoint, enabled);
|
||||
TRACE_CONTROL("BreakpointManager::InstallUserBreakpoint(%p, %d)\n",
|
||||
userBreakpoint, enabled);
|
||||
|
||||
AutoLocker<BLocker> installLocker(fLock);
|
||||
AutoLocker<Team> teamLocker(fTeam);
|
||||
|
||||
bool oldEnabled = userBreakpoint->IsEnabled();
|
||||
if (userBreakpoint->IsValid() && enabled == oldEnabled)
|
||||
{
|
||||
printf(" user breakpoint already valid and with same enabled state\n");
|
||||
if (userBreakpoint->IsValid() && enabled == oldEnabled) {
|
||||
TRACE_CONTROL(" user breakpoint already valid and with same enabled "
|
||||
"state\n");
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
for (int32 i = 0;
|
||||
UserBreakpointInstance* instance = userBreakpoint->InstanceAt(i); i++) {
|
||||
printf(" breakpoint instance %p\n", instance);
|
||||
if (instance->GetBreakpoint() != NULL)
|
||||
{
|
||||
printf(" -> already has breakpoint\n");
|
||||
|
||||
TRACE_CONTROL(" breakpoint instance %p\n", instance);
|
||||
|
||||
if (instance->GetBreakpoint() != NULL) {
|
||||
TRACE_CONTROL(" -> already has breakpoint\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
target_addr_t address = instance->Address();
|
||||
Breakpoint* breakpoint = fTeam->BreakpointAtAddress(address);
|
||||
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);
|
||||
if (image == NULL) {
|
||||
printf(" -> no image at that address\n");
|
||||
TRACE_CONTROL(" -> no image at that address\n");
|
||||
error = B_BAD_ADDRESS;
|
||||
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);
|
||||
instance->SetBreakpoint(breakpoint);
|
||||
}
|
||||
@@ -108,12 +115,14 @@ printf(" -> adding instance to breakpoint %p\n", breakpoint);
|
||||
teamLocker.Unlock();
|
||||
|
||||
// install/uninstall the breakpoints as needed
|
||||
printf(" updating breakpoints\n");
|
||||
TRACE_CONTROL(" updating breakpoints\n");
|
||||
|
||||
if (error == B_OK) {
|
||||
for (int32 i = 0;
|
||||
UserBreakpointInstance* instance = userBreakpoint->InstanceAt(i);
|
||||
i++) {
|
||||
printf(" breakpoint instance %p\n", instance);
|
||||
TRACE_CONTROL(" breakpoint instance %p\n", instance);
|
||||
|
||||
error = _UpdateBreakpointInstallation(instance->GetBreakpoint());
|
||||
if (error != B_OK)
|
||||
break;
|
||||
@@ -121,7 +130,8 @@ printf(" breakpoint instance %p\n", instance);
|
||||
}
|
||||
|
||||
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
|
||||
if (!userBreakpoint->IsValid()) {
|
||||
teamLocker.Lock();
|
||||
@@ -132,7 +142,8 @@ printf(" success, marking user breakpoint valid\n");
|
||||
}
|
||||
} else {
|
||||
// something went wrong -- revert the situation
|
||||
printf(" error, reverting\n");
|
||||
TRACE_CONTROL(" error, reverting\n");
|
||||
|
||||
teamLocker.Lock();
|
||||
userBreakpoint->SetEnabled(oldEnabled);
|
||||
teamLocker.Unlock();
|
||||
@@ -471,7 +482,11 @@ status_t
|
||||
BreakpointManager::_UpdateBreakpointInstallation(Breakpoint* breakpoint)
|
||||
{
|
||||
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())
|
||||
return B_OK;
|
||||
|
||||
@@ -481,12 +496,18 @@ printf("BreakpointManager::_UpdateBreakpointInstallation(%p): should be installe
|
||||
breakpoint->Address());
|
||||
if (error != B_OK)
|
||||
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);
|
||||
} else {
|
||||
// uninstall
|
||||
fDebuggerInterface->UninstallBreakpoint(breakpoint->Address());
|
||||
printf("BREAKPOINT at %#llx uninstalled\n", breakpoint->Address());
|
||||
|
||||
TRACE_CONTROL("BREAKPOINT at %#llx uninstalled\n",
|
||||
breakpoint->Address());
|
||||
|
||||
breakpoint->SetInstalled(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,8 @@ SubDirHdrs [ FDirName $(debugAnalyzerSources) gui ] ;
|
||||
SourceHdrs
|
||||
DwarfFunctionDebugInfo.cpp
|
||||
DwarfImageDebugInfo.cpp
|
||||
DwarfStackFrameDebugInfo.cpp
|
||||
DwarfTeamDebugInfo.cpp
|
||||
DwarfInterfaceFactory.cpp
|
||||
: [ FDirName $(SUBDIR) dwarf ]
|
||||
;
|
||||
|
||||
@@ -60,15 +60,17 @@ Application Debugger :
|
||||
DebuggerTeamDebugInfo.cpp
|
||||
DwarfFunctionDebugInfo.cpp
|
||||
DwarfImageDebugInfo.cpp
|
||||
DwarfStackFrameDebugInfo.cpp
|
||||
DwarfTeamDebugInfo.cpp
|
||||
DwarfInterfaceFactory.cpp
|
||||
Function.cpp
|
||||
FunctionDebugInfo.cpp
|
||||
FunctionInstance.cpp
|
||||
ImageDebugInfo.cpp
|
||||
ImageDebugInfoProvider.cpp
|
||||
NoOpStackFrameDebugInfo.cpp
|
||||
SpecificImageDebugInfo.cpp
|
||||
SpecificTeamDebugInfo.cpp
|
||||
StackFrameDebugInfo.cpp
|
||||
TeamDebugInfo.cpp
|
||||
|
||||
# debugger_interface
|
||||
@@ -110,6 +112,7 @@ Application Debugger :
|
||||
SourceCode.cpp
|
||||
StackFrame.cpp
|
||||
StackFrameValues.cpp
|
||||
StackFrameValueInfos.cpp
|
||||
StackTrace.cpp
|
||||
Statement.cpp
|
||||
SymbolInfo.cpp
|
||||
|
||||
+332
-72
@@ -5,8 +5,6 @@
|
||||
|
||||
#include "Jobs.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <AutoLocker.h>
|
||||
|
||||
#include "Architecture.h"
|
||||
@@ -21,11 +19,14 @@
|
||||
#include "Register.h"
|
||||
#include "SourceCode.h"
|
||||
#include "SpecificImageDebugInfo.h"
|
||||
#include "StackFrameDebugInfo.h"
|
||||
#include "StackFrameValueInfos.h"
|
||||
#include "StackFrameValues.h"
|
||||
#include "StackTrace.h"
|
||||
#include "Team.h"
|
||||
#include "TeamDebugInfo.h"
|
||||
#include "Thread.h"
|
||||
#include "Tracing.h"
|
||||
#include "Type.h"
|
||||
#include "TypeComponentPath.h"
|
||||
#include "ValueLocation.h"
|
||||
@@ -495,77 +496,110 @@ GetStackFrameValueJob::Do()
|
||||
status_t
|
||||
GetStackFrameValueJob::_GetValue()
|
||||
{
|
||||
printf("GetStackFrameValueJob::_GetValue()\n");
|
||||
if (fPath->CountComponents() > 0)
|
||||
{
|
||||
printf(" -> non-empty path\n");
|
||||
return B_UNSUPPORTED;
|
||||
// TODO: Implement!
|
||||
}
|
||||
TRACE_LOCALS_ONLY(
|
||||
TRACE_LOCALS("GetStackFrameValueJob::_GetValue(): %s ",
|
||||
fVariable->Name().String());
|
||||
fPath->Dump();
|
||||
TRACE_LOCALS("\n");
|
||||
)
|
||||
|
||||
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
|
||||
Type* type = fVariable->GetType();
|
||||
type_code valueType = 0;
|
||||
while (valueType == 0) {
|
||||
switch (type->Kind()) {
|
||||
case TYPE_PRIMITIVE:
|
||||
valueType = dynamic_cast<PrimitiveType*>(type)->TypeConstant();
|
||||
printf(" TYPE_PRIMITIVE: '%c%c%c%c'\n", int(valueType >> 24),
|
||||
int(valueType >> 16), int(valueType >> 8), int(valueType));
|
||||
if (valueType == 0)
|
||||
{
|
||||
printf(" -> unknown type constant\n");
|
||||
|
||||
TRACE_LOCALS(" TYPE_PRIMITIVE: '%c%c%c%c'\n",
|
||||
int(valueType >> 24), int(valueType >> 16),
|
||||
int(valueType >> 8), int(valueType));
|
||||
|
||||
if (valueType == 0) {
|
||||
TRACE_LOCALS(" -> unknown type constant\n");
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TYPE_MODIFIED:
|
||||
printf(" TYPE_MODIFIED\n");
|
||||
TRACE_LOCALS(" TYPE_MODIFIED\n");
|
||||
// ignore modifiers
|
||||
type = dynamic_cast<ModifiedType*>(type)->BaseType();
|
||||
break;
|
||||
case TYPE_TYPEDEF:
|
||||
printf(" TYPE_TYPEDEF\n");
|
||||
TRACE_LOCALS(" TYPE_TYPEDEF\n");
|
||||
type = dynamic_cast<TypedefType*>(type)->BaseType();
|
||||
break;
|
||||
case TYPE_ADDRESS:
|
||||
printf(" TYPE_ADDRESS\n");
|
||||
if (fArchitecture->AddressSize() == 4)
|
||||
{
|
||||
TRACE_LOCALS(" TYPE_ADDRESS\n");
|
||||
if (fArchitecture->AddressSize() == 4) {
|
||||
valueType = B_UINT32_TYPE;
|
||||
printf(" -> 32 bit\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE_LOCALS(" -> 32 bit\n");
|
||||
} else {
|
||||
valueType = B_UINT64_TYPE;
|
||||
printf(" -> 64 bit\n");
|
||||
}
|
||||
TRACE_LOCALS(" -> 64 bit\n");
|
||||
}
|
||||
break;
|
||||
case TYPE_COMPOUND:
|
||||
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:
|
||||
printf(" TYPE_COMPOUND/TYPE_ARRAY/default\n");
|
||||
// TODO:...
|
||||
printf(" -> unsupported\n");
|
||||
TRACE_LOCALS(" default -> unsupported\n");
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (valueType == B_STRING_TYPE)
|
||||
{
|
||||
printf(" -> B_STRING_TYPE: unsupported\n");
|
||||
// update the reference in case the type has changed
|
||||
typeReference.SetTo(type);
|
||||
|
||||
if (valueType == B_STRING_TYPE) {
|
||||
TRACE_LOCALS(" -> B_STRING_TYPE: unsupported\n");
|
||||
return B_UNSUPPORTED;
|
||||
// TODO:...
|
||||
}
|
||||
}
|
||||
|
||||
// check whether we know the complete location
|
||||
ValueLocation* location = fVariable->Location();
|
||||
int32 count = location->CountPieces();
|
||||
printf(" location: %p, %ld pieces\n", location, count);
|
||||
if (count == 0)
|
||||
{
|
||||
printf(" -> no location\n");
|
||||
|
||||
TRACE_LOCALS(" location: %p, %ld pieces\n", location, count);
|
||||
|
||||
if (count == 0) {
|
||||
TRACE_LOCALS(" -> no location\n");
|
||||
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;
|
||||
uint64 totalBitSize = 0;
|
||||
@@ -583,26 +617,26 @@ printf(" -> no location\n");
|
||||
totalSize += piece.size;
|
||||
totalBitSize += piece.bitSize;
|
||||
}
|
||||
printf(" -> totalSize: %llu, totalBitSize: %llu\n", totalSize, totalBitSize);
|
||||
|
||||
if (totalSize == 0 && totalBitSize == 0)
|
||||
{
|
||||
printf(" -> no size\n");
|
||||
TRACE_LOCALS(" -> totalSize: %llu, totalBitSize: %llu\n", totalSize,
|
||||
totalBitSize);
|
||||
|
||||
if (totalSize == 0 && totalBitSize == 0) {
|
||||
TRACE_LOCALS(" -> no size\n");
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
if (totalSize > 8 || totalSize + (totalBitSize + 7) / 8 > 8)
|
||||
{
|
||||
printf(" -> longer than 8 bytes: unsupported\n");
|
||||
if (totalSize > 8 || totalSize + (totalBitSize + 7) / 8 > 8) {
|
||||
TRACE_LOCALS(" -> longer than 8 bytes: unsupported\n");
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (totalSize + (totalBitSize + 7) / 8 < BVariant::SizeOfType(valueType))
|
||||
{
|
||||
printf(" -> too short for value type (%llu vs. %lu)\n",
|
||||
totalSize + (totalBitSize + 7) / 8, BVariant::SizeOfType(valueType));
|
||||
if (totalSize + (totalBitSize + 7) / 8 < BVariant::SizeOfType(valueType)) {
|
||||
TRACE_LOCALS(" -> too short for value type (%llu vs. %lu)\n",
|
||||
totalSize + (totalBitSize + 7) / 8,
|
||||
BVariant::SizeOfType(valueType));
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
// load the data
|
||||
BitBuffer valueBuffer;
|
||||
@@ -630,7 +664,10 @@ totalSize + (totalBitSize + 7) / 8, BVariant::SizeOfType(valueType));
|
||||
case VALUE_PIECE_LOCATION_MEMORY:
|
||||
{
|
||||
target_addr_t address = piece.address + bitOffset / 8;
|
||||
printf(" piece %ld: memory address: %#llx, bits: %lu\n", i, address, bitSize);
|
||||
|
||||
TRACE_LOCALS(" piece %ld: memory address: %#llx, bits: %lu\n",
|
||||
i, address, bitSize);
|
||||
|
||||
bitOffset %= 8;
|
||||
uint8 pieceBuffer[8];
|
||||
ssize_t bytesRead = fDebuggerInterface->ReadMemory(address,
|
||||
@@ -639,17 +676,22 @@ printf(" piece %ld: memory address: %#llx, bits: %lu\n", i, address, bitSize);
|
||||
return bytesRead;
|
||||
if ((uint32)bytesRead != bytesToRead)
|
||||
return B_BAD_ADDRESS;
|
||||
printf(" -> read: ");
|
||||
for (ssize_t k = 0; k < bytesRead; k++)
|
||||
printf("%02x", pieceBuffer[k]);
|
||||
printf("\n");
|
||||
|
||||
TRACE_LOCALS_ONLY(
|
||||
TRACE_LOCALS(" -> read: ");
|
||||
for (ssize_t k = 0; k < bytesRead; k++)
|
||||
TRACE_LOCALS("%02x", pieceBuffer[k]);
|
||||
TRACE_LOCALS("\n");
|
||||
)
|
||||
|
||||
valueBuffer.AddBits(pieceBuffer, bitSize, bitOffset);
|
||||
break;
|
||||
}
|
||||
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;
|
||||
if (!fStackFrame->GetCpuState()->GetRegisterValue(
|
||||
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
|
||||
BVariant value;
|
||||
status_t error = value.SetToTypedData(valueBuffer.Bytes(), valueType);
|
||||
if (error != B_OK)
|
||||
{
|
||||
printf(" -> failed to set typed data: %s\n", strerror(error));
|
||||
error = value.SetToTypedData(valueBuffer.Bytes(), valueType);
|
||||
if (error != B_OK) {
|
||||
TRACE_LOCALS(" -> failed to set typed data: %s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fArchitecture->IsHostEndian())
|
||||
value.SwapEndianess();
|
||||
|
||||
return _SetValue(value, actualType, location);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
GetStackFrameValueJob::_SetValue(const BVariant& value, Type* type,
|
||||
ValueLocation* location)
|
||||
{
|
||||
// set the value
|
||||
AutoLocker<Team> locker(fThread->GetTeam());
|
||||
|
||||
StackFrameValues* values = fStackFrame->Values();
|
||||
|
||||
error = values->SetValue(fVariable->ID(), fPath, value);
|
||||
if (error != B_OK)
|
||||
{
|
||||
printf(" -> failed to set value: %s\n", strerror(error));
|
||||
status_t error = fStackFrame->Values()->SetValue(fVariable->ID(), fPath,
|
||||
value);
|
||||
if (error != B_OK) {
|
||||
TRACE_LOCALS(" -> failed to set value: %s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
fStackFrame->ValueInfos()->SetInfo(fVariable->ID(), fPath, type, location);
|
||||
|
||||
fStackFrame->NotifyValueRetrieved(fVariable, fPath);
|
||||
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 BVariant;
|
||||
class CpuState;
|
||||
class DebuggerInterface;
|
||||
class Function;
|
||||
@@ -20,7 +21,9 @@ class StackFrame;
|
||||
class StackFrameValues;
|
||||
class Team;
|
||||
class Thread;
|
||||
class Type;
|
||||
class TypeComponentPath;
|
||||
class ValueLocation;
|
||||
class Variable;
|
||||
|
||||
|
||||
@@ -176,6 +179,18 @@ private:
|
||||
|
||||
private:
|
||||
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:
|
||||
GetStackFrameValueJobKey fKey;
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "SymbolInfo.h"
|
||||
#include "TeamDebugInfo.h"
|
||||
#include "TeamSettings.h"
|
||||
#include "Tracing.h"
|
||||
#include "Variable.h"
|
||||
|
||||
// #pragma mark - ImageHandler
|
||||
@@ -360,7 +361,7 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
|
||||
fTeamWindow = TeamWindow::Create(fTeam, this);
|
||||
} catch (...) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -645,21 +646,21 @@ TeamDebugger::TeamWindowQuitRequested()
|
||||
void
|
||||
TeamDebugger::JobDone(Job* job)
|
||||
{
|
||||
printf("TeamDebugger::JobDone(%p)\n", job);
|
||||
TRACE_JOBS("TeamDebugger::JobDone(%p)\n", job);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TeamDebugger::JobFailed(Job* job)
|
||||
{
|
||||
printf("TeamDebugger::JobFailed(%p)\n", job);
|
||||
TRACE_JOBS("TeamDebugger::JobFailed(%p)\n", job);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
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
|
||||
// loading state! Asynchronously due to locking order.
|
||||
}
|
||||
@@ -721,8 +722,8 @@ TeamDebugger::_DebugEventListener()
|
||||
|
||||
|
||||
if (event->Team() != fTeamID) {
|
||||
printf("TeamDebugger for team %ld: received event from team %ld!\n", fTeamID,
|
||||
event->Team());
|
||||
TRACE_EVENTS("TeamDebugger for team %ld: received event from team "
|
||||
"%ld!\n", fTeamID, event->Team());
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -741,7 +742,9 @@ event->Team());
|
||||
void
|
||||
TeamDebugger::_HandleDebuggerMessage(DebugEvent* event)
|
||||
{
|
||||
printf("TeamDebugger::_HandleDebuggerMessage(): %d\n", event->EventType());
|
||||
TRACE_EVENTS("TeamDebugger::_HandleDebuggerMessage(): %d\n",
|
||||
event->EventType());
|
||||
|
||||
bool handled = false;
|
||||
|
||||
ThreadHandler* handler = _GetThreadHandler(event->Thread());
|
||||
@@ -749,42 +752,54 @@ printf("TeamDebugger::_HandleDebuggerMessage(): %d\n", event->EventType());
|
||||
|
||||
switch (event->EventType()) {
|
||||
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) {
|
||||
handled = handler->HandleThreadDebugged(
|
||||
dynamic_cast<ThreadDebuggedEvent*>(event));
|
||||
}
|
||||
break;
|
||||
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) {
|
||||
handled = handler->HandleDebuggerCall(
|
||||
dynamic_cast<DebuggerCallEvent*>(event));
|
||||
}
|
||||
break;
|
||||
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) {
|
||||
handled = handler->HandleBreakpointHit(
|
||||
dynamic_cast<BreakpointHitEvent*>(event));
|
||||
}
|
||||
break;
|
||||
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) {
|
||||
handled = handler->HandleWatchpointHit(
|
||||
dynamic_cast<WatchpointHitEvent*>(event));
|
||||
}
|
||||
break;
|
||||
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) {
|
||||
handled = handler->HandleSingleStep(
|
||||
dynamic_cast<SingleStepEvent*>(event));
|
||||
}
|
||||
break;
|
||||
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) {
|
||||
handled = handler->HandleExceptionOccurred(
|
||||
dynamic_cast<ExceptionOccurredEvent*>(event));
|
||||
@@ -795,10 +810,12 @@ printf("B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: thread: %ld\n", event->Thread());
|
||||
// break;
|
||||
case B_DEBUGGER_MESSAGE_TEAM_DELETED:
|
||||
// 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;
|
||||
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!
|
||||
break;
|
||||
case B_DEBUGGER_MESSAGE_THREAD_CREATED:
|
||||
@@ -825,7 +842,7 @@ printf("B_DEBUGGER_MESSAGE_TEAM_EXEC: team: %ld\n", event->Team());
|
||||
// not interested
|
||||
break;
|
||||
default:
|
||||
printf("TeamDebugger for team %ld: unknown event type: "
|
||||
WARNING("TeamDebugger for team %ld: unknown event type: "
|
||||
"%d\n", fTeamID, event->EventType());
|
||||
break;
|
||||
}
|
||||
@@ -926,7 +943,7 @@ TeamDebugger::_HandleImageDebugInfoChanged(image_id imageID)
|
||||
void
|
||||
TeamDebugger::_HandleImageFileChanged(image_id imageID)
|
||||
{
|
||||
printf("TeamDebugger::_HandleImageFileChanged(%ld)\n", imageID);
|
||||
TRACE_IMAGES("TeamDebugger::_HandleImageFileChanged(%ld)\n", imageID);
|
||||
// TODO: Reload the debug info!
|
||||
}
|
||||
|
||||
@@ -934,7 +951,9 @@ printf("TeamDebugger::_HandleImageFileChanged(%ld)\n", imageID);
|
||||
void
|
||||
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
|
||||
AutoLocker< ::Team> locker(fTeam);
|
||||
|
||||
@@ -945,24 +964,32 @@ printf("TeamDebugger::_HandleSetUserBreakpoint(%#llx, %d)\n", address, enabled);
|
||||
Reference<UserBreakpoint> userBreakpointReference(userBreakpoint);
|
||||
|
||||
if (userBreakpoint == NULL) {
|
||||
printf(" no breakpoint yet\n");
|
||||
TRACE_CONTROL(" no breakpoint yet\n");
|
||||
|
||||
// get the function at the address
|
||||
Image* image = fTeam->ImageByAddress(address);
|
||||
printf(" image: %p\n", image);
|
||||
|
||||
TRACE_CONTROL(" image: %p\n", image);
|
||||
|
||||
if (image == NULL)
|
||||
return;
|
||||
ImageDebugInfo* imageDebugInfo = image->GetImageDebugInfo();
|
||||
printf(" image debug info: %p\n", imageDebugInfo);
|
||||
|
||||
TRACE_CONTROL(" image debug info: %p\n", imageDebugInfo);
|
||||
|
||||
if (imageDebugInfo == NULL)
|
||||
return;
|
||||
// TODO: Handle this case by loading the debug info, if possible!
|
||||
FunctionInstance* functionInstance
|
||||
= imageDebugInfo->FunctionAtAddress(address);
|
||||
printf(" function instance: %p\n", functionInstance);
|
||||
|
||||
TRACE_CONTROL(" function instance: %p\n", functionInstance);
|
||||
|
||||
if (functionInstance == NULL)
|
||||
return;
|
||||
Function* function = functionInstance->GetFunction();
|
||||
printf(" function: %p\n", function);
|
||||
|
||||
TRACE_CONTROL(" function: %p\n", function);
|
||||
|
||||
// get the source location for the address
|
||||
FunctionDebugInfo* functionDebugInfo
|
||||
@@ -978,7 +1005,10 @@ printf(" function: %p\n", function);
|
||||
breakpointStatement->ReleaseReference();
|
||||
|
||||
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
|
||||
FunctionID* functionID = functionInstance->GetFunctionID();
|
||||
@@ -993,14 +1023,18 @@ printf(" relative address: %#llx, source location: (%ld, %ld)\n", relativeAddre
|
||||
if (userBreakpoint == NULL)
|
||||
return;
|
||||
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
|
||||
// UserBreakpointInstances
|
||||
for (FunctionInstanceList::ConstIterator it
|
||||
= function->Instances().GetIterator();
|
||||
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
|
||||
target_addr_t instanceAddress = 0;
|
||||
if (instance == functionInstance) {
|
||||
@@ -1019,7 +1053,9 @@ printf(" function instance %p: range: %#llx - %#llx\n", instance, instance->Add
|
||||
statement->ReleaseReference();
|
||||
}
|
||||
}
|
||||
printf(" breakpoint address using source info: %llx\n", instanceAddress);
|
||||
|
||||
TRACE_CONTROL(" breakpoint address using source info: %llx\n",
|
||||
instanceAddress);
|
||||
|
||||
if (instanceAddress == 0) {
|
||||
// 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;
|
||||
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(userBreakpoint, instanceAddress);
|
||||
@@ -1037,7 +1075,8 @@ printf(" final breakpoint address: %llx\n", instanceAddress);
|
||||
delete breakpointInstance;
|
||||
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
|
||||
TeamDebugger::_HandleClearUserBreakpoint(target_addr_t address)
|
||||
{
|
||||
printf("TeamDebugger::_HandleClearUserBreakpoint(%#llx)\n", address);
|
||||
TRACE_CONTROL("TeamDebugger::_HandleClearUserBreakpoint(%#llx)\n", address);
|
||||
|
||||
AutoLocker< ::Team> locker(fTeam);
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "StackTrace.h"
|
||||
#include "Statement.h"
|
||||
#include "Team.h"
|
||||
#include "Tracing.h"
|
||||
#include "Worker.h"
|
||||
|
||||
|
||||
@@ -108,7 +109,9 @@ ThreadHandler::HandleBreakpointHit(BreakpointHitEvent* event)
|
||||
{
|
||||
CpuState* cpuState = event->GetCpuState();
|
||||
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
|
||||
if (fBreakpointAddress != 0 && instructionPointer == fBreakpointAddress
|
||||
@@ -225,7 +228,8 @@ ThreadHandler::HandleThreadAction(uint32 action)
|
||||
case MSG_THREAD_STEP_OUT:
|
||||
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
|
||||
// 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);
|
||||
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 it return by means of a breakpoint.
|
||||
@@ -290,8 +295,10 @@ printf(" ip: %#llx\n", frame->InstructionPointer());
|
||||
_StepFallback();
|
||||
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) {
|
||||
// step into
|
||||
@@ -430,7 +437,8 @@ ThreadHandler::_StepFallback()
|
||||
bool
|
||||
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
|
||||
// "step into", only we have to avoid stepping into subroutines. Hence we
|
||||
// check whether the current instruction is a subroutine call. If not, we
|
||||
@@ -438,18 +446,20 @@ printf("ThreadHandler::_DoStepOver()\n");
|
||||
InstructionInfo info;
|
||||
if (fDebuggerInterface->GetArchitecture()->GetInstructionInfo(
|
||||
cpuState->InstructionPointer(), info) != B_OK) {
|
||||
printf(" failed to get instruction info\n");
|
||||
TRACE_CONTROL(" failed to get instruction info\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (info.Type() != INSTRUCTION_TYPE_SUBROUTINE_CALL) {
|
||||
_SingleStepThread(cpuState->InstructionPointer());
|
||||
printf(" not a subroutine call\n");
|
||||
|
||||
TRACE_CONTROL(" not a subroutine call\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
printf(" subroutine call -- installing breakpoint at address %#llx\n",
|
||||
info.Address() + info.Size());
|
||||
TRACE_CONTROL(" subroutine call -- installing breakpoint at address "
|
||||
"%#llx\n", info.Address() + info.Size());
|
||||
|
||||
if (_InstallTemporaryBreakpoint(info.Address() + info.Size()) != B_OK)
|
||||
return false;
|
||||
|
||||
@@ -548,7 +558,9 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState)
|
||||
bool
|
||||
ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
|
||||
{
|
||||
printf("ThreadHandler::_HandleSingleStepStep(): ip: %llx\n", cpuState->InstructionPointer());
|
||||
TRACE_CONTROL("ThreadHandler::_HandleSingleStepStep(): ip: %llx\n",
|
||||
cpuState->InstructionPointer());
|
||||
|
||||
switch (fStepMode) {
|
||||
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 "FunctionDebugInfo.h"
|
||||
#include "InstructionInfo.h"
|
||||
#include "NoOpStackFrameDebugInfo.h"
|
||||
#include "RegisterMap.h"
|
||||
#include "StackFrame.h"
|
||||
#include "Statement.h"
|
||||
@@ -320,8 +321,15 @@ ArchitectureX86::CreateStackFrame(Image* image, FunctionDebugInfo* function,
|
||||
}
|
||||
|
||||
// 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,
|
||||
framePointer, eip);
|
||||
framePointer, eip, stackFrameDebugInfo);
|
||||
if (frame == NULL)
|
||||
return B_NO_MEMORY;
|
||||
Reference<StackFrame> frameReference(frame, true);
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "Dwarf.h"
|
||||
#include "DwarfFile.h"
|
||||
#include "DwarfFunctionDebugInfo.h"
|
||||
#include "DwarfInterfaceFactory.h"
|
||||
#include "DwarfStackFrameDebugInfo.h"
|
||||
#include "DwarfTargetInterface.h"
|
||||
#include "DwarfUtils.h"
|
||||
#include "ElfFile.h"
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "StringUtils.h"
|
||||
#include "TargetAddressRangeList.h"
|
||||
#include "TeamMemory.h"
|
||||
#include "Tracing.h"
|
||||
#include "UnsupportedLanguage.h"
|
||||
#include "ValueLocation.h"
|
||||
#include "Variable.h"
|
||||
@@ -208,8 +209,8 @@ DwarfImageDebugInfo::Init()
|
||||
status_t
|
||||
DwarfImageDebugInfo::GetFunctions(BObjectList<FunctionDebugInfo>& functions)
|
||||
{
|
||||
printf("DwarfImageDebugInfo::GetFunctions()\n");
|
||||
printf(" %ld compilation units\n", fFile->CountCompilationUnits());
|
||||
TRACE_IMAGES("DwarfImageDebugInfo::GetFunctions()\n");
|
||||
TRACE_IMAGES(" %ld compilation units\n", fFile->CountCompilationUnits());
|
||||
|
||||
for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i);
|
||||
i++) {
|
||||
@@ -329,7 +330,9 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
|
||||
functionInstance->GetFunctionDebugInfo());
|
||||
if (function == NULL)
|
||||
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();
|
||||
const Register* registers = fArchitecture->Registers();
|
||||
@@ -352,10 +355,22 @@ printf("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p\n", function->Sub
|
||||
Reference<CpuState> previousCpuStateReference(previousCpuState, true);
|
||||
|
||||
// create the target interfaces
|
||||
UnwindTargetInterface inputInterface(registers, registerCount,
|
||||
fromDwarfMap, toDwarfMap, cpuState, fArchitecture, fTeamMemory);
|
||||
UnwindTargetInterface outputInterface(registers, registerCount,
|
||||
fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture, fTeamMemory);
|
||||
UnwindTargetInterface* inputInterface
|
||||
= new(std::nothrow) UnwindTargetInterface(registers, registerCount,
|
||||
fromDwarfMap, toDwarfMap, cpuState, 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
|
||||
target_addr_t instructionPointer
|
||||
@@ -363,23 +378,41 @@ printf("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p\n", function->Sub
|
||||
target_addr_t framePointer;
|
||||
CompilationUnit* unit = function->GetCompilationUnit();
|
||||
error = fFile->UnwindCallFrame(unit, function->SubprogramEntry(),
|
||||
instructionPointer, &inputInterface, &outputInterface, framePointer);
|
||||
instructionPointer, inputInterface, outputInterface, framePointer);
|
||||
if (error != B_OK)
|
||||
return B_UNSUPPORTED;
|
||||
|
||||
printf("unwound registers:\n");
|
||||
for (int32 i = 0; i < registerCount; i++) {
|
||||
const Register* reg = registers + i;
|
||||
BVariant value;
|
||||
if (previousCpuState->GetRegisterValue(reg, value)) {
|
||||
printf(" %3s: %#lx\n", reg->Name(), value.ToUInt32());
|
||||
} else
|
||||
printf(" %3s: undefined\n", reg->Name());
|
||||
}
|
||||
TRACE_CFI_ONLY(
|
||||
TRACE_CFI("unwound registers:\n");
|
||||
for (int32 i = 0; i < registerCount; i++) {
|
||||
const Register* reg = registers + i;
|
||||
BVariant value;
|
||||
if (previousCpuState->GetRegisterValue(reg, value))
|
||||
TRACE_CFI(" %3s: %#lx\n", reg->Name(), value.ToUInt32());
|
||||
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
|
||||
StackFrame* frame = new(std::nothrow) StackFrame(STACK_FRAME_TYPE_STANDARD,
|
||||
cpuState, framePointer, cpuState->InstructionPointer());
|
||||
cpuState, framePointer, cpuState->InstructionPointer(),
|
||||
stackFrameDebugInfo);
|
||||
if (frame == NULL)
|
||||
return B_NO_MEMORY;
|
||||
Reference<StackFrame> frameReference(frame, true);
|
||||
@@ -398,13 +431,6 @@ if (previousCpuState->GetRegisterValue(reg, value)) {
|
||||
Reference<FunctionID> functionIDReference(functionID, true);
|
||||
|
||||
// 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()
|
||||
.GetIterator(); DebugInfoEntry* entry = it.Next();) {
|
||||
BString parameterName;
|
||||
@@ -415,8 +441,8 @@ if (previousCpuState->GetRegisterValue(reg, value)) {
|
||||
DIEFormalParameter* parameterEntry
|
||||
= dynamic_cast<DIEFormalParameter*>(entry);
|
||||
Variable* parameter;
|
||||
if (factory.CreateParameter(functionID, parameterEntry, parameter)
|
||||
!= B_OK) {
|
||||
if (stackFrameDebugInfo->CreateParameter(functionID, parameterEntry,
|
||||
parameter) != B_OK) {
|
||||
continue;
|
||||
}
|
||||
Reference<Variable> parameterReference(parameter, true);
|
||||
@@ -426,8 +452,8 @@ if (previousCpuState->GetRegisterValue(reg, value)) {
|
||||
}
|
||||
|
||||
// create objects for the local variables
|
||||
_CreateLocalVariables(unit, frame, functionID, factory, instructionPointer,
|
||||
functionInstance->Address() - fRelocationDelta,
|
||||
_CreateLocalVariables(unit, frame, functionID, *stackFrameDebugInfo,
|
||||
instructionPointer, functionInstance->Address() - fRelocationDelta,
|
||||
subprogramEntry->Variables(), subprogramEntry->Blocks());
|
||||
|
||||
_previousFrame = frameReference.Detach();
|
||||
@@ -441,15 +467,15 @@ status_t
|
||||
DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function,
|
||||
target_addr_t address, Statement*& _statement)
|
||||
{
|
||||
printf("DwarfImageDebugInfo::GetStatement(function: %p, address: %#llx)\n",
|
||||
_function, address);
|
||||
TRACE_CODE("DwarfImageDebugInfo::GetStatement(function: %p, address: %#llx)\n",
|
||||
_function, address);
|
||||
|
||||
DwarfFunctionDebugInfo* function
|
||||
= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
|
||||
if (function == NULL)
|
||||
{
|
||||
printf(" -> no dwarf function\n");
|
||||
if (function == NULL) {
|
||||
TRACE_LINES(" -> no dwarf function\n");
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
AutoLocker<BLocker> locker(fLock);
|
||||
|
||||
@@ -457,7 +483,8 @@ printf(" -> no dwarf function\n");
|
||||
CompilationUnit* unit = function->GetCompilationUnit();
|
||||
LocatableFile* file = function->SourceFile();
|
||||
if (file == NULL) {
|
||||
printf(" -> no source file\n");
|
||||
TRACE_CODE(" -> no source file\n");
|
||||
|
||||
// no source code -- rather return the assembly 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
|
||||
// compilation unit.
|
||||
LineNumberProgram& program = unit->GetLineNumberProgram();
|
||||
if (!program.IsValid())
|
||||
{
|
||||
printf(" -> no line number program\n");
|
||||
if (!program.IsValid()) {
|
||||
TRACE_CODE(" -> no line number program\n");
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
// adjust address
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -530,10 +556,14 @@ DwarfImageDebugInfo::GetStatementAtSourceLocation(FunctionDebugInfo* _function,
|
||||
= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
|
||||
if (function == NULL)
|
||||
return B_BAD_VALUE;
|
||||
target_addr_t functionStartAddress = function->Address() - fRelocationDelta;
|
||||
target_addr_t functionEndAddress = functionStartAddress + function->Size();
|
||||
printf("DwarfImageDebugInfo::GetStatementAtSourceLocation(%p, (%ld, %ld)): function range: %#llx - %#llx\n",
|
||||
function, sourceLocation.Line(), sourceLocation.Column(), functionStartAddress, functionEndAddress);
|
||||
|
||||
target_addr_t functionStartAddress = function->Address() - fRelocationDelta;
|
||||
target_addr_t functionEndAddress = functionStartAddress + function->Size();
|
||||
|
||||
TRACE_LINES2("DwarfImageDebugInfo::GetStatementAtSourceLocation(%p, "
|
||||
"(%ld, %ld)): function range: %#llx - %#llx\n", function,
|
||||
sourceLocation.Line(), sourceLocation.Column(),
|
||||
functionStartAddress, functionEndAddress);
|
||||
|
||||
AutoLocker<BLocker> locker(fLock);
|
||||
|
||||
@@ -548,9 +578,6 @@ function, sourceLocation.Line(), sourceLocation.Column(), functionStartAddress,
|
||||
// comparison below
|
||||
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
|
||||
// compilation unit.
|
||||
LineNumberProgram& program = unit->GetLineNumberProgram();
|
||||
@@ -569,15 +596,20 @@ function, sourceLocation.Line(), sourceLocation.Column(), functionStartAddress,
|
||||
if (statementAddress != 0
|
||||
&& (!isOurFile || state.isStatement || state.isSequenceEnd)) {
|
||||
target_addr_t endAddress = state.address;
|
||||
if (statementAddress < endAddress) {
|
||||
printf(" statement: %#llx - %#llx, location: (%ld, %ld)\n", statementAddress, endAddress, statementLine, statementColumn);
|
||||
}
|
||||
|
||||
if (statementAddress < endAddress) {
|
||||
TRACE_LINES2(" statement: %#llx - %#llx, location: "
|
||||
"(%ld, %ld)\n", statementAddress, endAddress, statementLine,
|
||||
statementColumn);
|
||||
}
|
||||
|
||||
if (statementAddress < endAddress
|
||||
&& statementAddress >= functionStartAddress
|
||||
&& statementAddress < functionEndAddress
|
||||
&& statementLine == (int32)sourceLocation.Line()
|
||||
&& statementColumn == (int32)sourceLocation.Column()) {
|
||||
printf(" -> found statement!\n");
|
||||
TRACE_LINES2(" -> found statement!\n");
|
||||
|
||||
ContiguousStatement* statement = new(std::nothrow)
|
||||
ContiguousStatement(
|
||||
SourceLocation(statementLine, statementColumn),
|
||||
@@ -690,7 +722,9 @@ DwarfImageDebugInfo::_AddSourceCodeInfo(CompilationUnit* unit,
|
||||
int32 statementLine = -1;
|
||||
int32 statementColumn = -1;
|
||||
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;
|
||||
|
||||
if (statementAddress != 0
|
||||
@@ -702,7 +736,10 @@ printf(" %#llx (%ld, %ld, %ld) %d\n", state.address, state.file, state.line,
|
||||
SourceLocation(statementLine, statementColumn));
|
||||
if (error != B_OK)
|
||||
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;
|
||||
@@ -747,18 +784,22 @@ DwarfImageDebugInfo::_GetSourceFileIndex(CompilationUnit* unit,
|
||||
|
||||
status_t
|
||||
DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit,
|
||||
StackFrame* frame, FunctionID* functionID, DwarfInterfaceFactory& factory,
|
||||
target_addr_t instructionPointer, target_addr_t lowPC,
|
||||
const EntryListWrapper& variableEntries,
|
||||
StackFrame* frame, FunctionID* functionID,
|
||||
DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer,
|
||||
target_addr_t lowPC, const EntryListWrapper& variableEntries,
|
||||
const EntryListWrapper& blockEntries)
|
||||
{
|
||||
printf("DwarfImageDebugInfo::_CreateLocalVariables(): ip: %#llx, low PC: %#llx\n",
|
||||
instructionPointer, lowPC);
|
||||
TRACE_LOCALS("DwarfImageDebugInfo::_CreateLocalVariables(): ip: %#llx, "
|
||||
"low PC: %#llx\n", instructionPointer, lowPC);
|
||||
|
||||
// iterate through the variables and add the ones in scope
|
||||
for (DebugInfoEntryList::ConstIterator it
|
||||
= variableEntries.list.GetIterator();
|
||||
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
|
||||
if (instructionPointer < lowPC + variableEntry->StartScope())
|
||||
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)
|
||||
for (DebugInfoEntryList::ConstIterator it = blockEntries.list.GetIterator();
|
||||
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
|
||||
if (block->LowPC() != 0) {
|
||||
printf(" has lowPC\n");
|
||||
TRACE_LOCALS(" has lowPC\n");
|
||||
|
||||
// yep, compare with the instruction pointer
|
||||
if (instructionPointer < block->LowPC()
|
||||
|| instructionPointer >= block->HighPC()) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
printf(" no lowPC\n");
|
||||
TRACE_LOCALS(" no lowPC\n");
|
||||
|
||||
// check the address ranges instead
|
||||
TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit,
|
||||
block->AddressRangesOffset());
|
||||
if (rangeList == NULL)
|
||||
{
|
||||
printf(" failed to get ranges\n");
|
||||
if (rangeList == NULL) {
|
||||
TRACE_LOCALS(" failed to get ranges\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Reference<TargetAddressRangeList> rangeListReference(rangeList,
|
||||
true);
|
||||
|
||||
if (!rangeList->Contains(instructionPointer))
|
||||
{
|
||||
printf(" ranges don't contain IP\n");
|
||||
if (!rangeList->Contains(instructionPointer)) {
|
||||
TRACE_LOCALS(" ranges don't contain IP\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// found a block -- recurse
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
class Architecture;
|
||||
class CompilationUnit;
|
||||
class DwarfInterfaceFactory;
|
||||
class DwarfStackFrameDebugInfo;
|
||||
class DwarfFile;
|
||||
class ElfSegment;
|
||||
class FileManager;
|
||||
@@ -78,7 +78,7 @@ private:
|
||||
|
||||
status_t _CreateLocalVariables(CompilationUnit* unit,
|
||||
StackFrame* frame, FunctionID* functionID,
|
||||
DwarfInterfaceFactory& factory,
|
||||
DwarfStackFrameDebugInfo& factory,
|
||||
target_addr_t instructionPointer,
|
||||
target_addr_t lowPC,
|
||||
const EntryListWrapper& variableEntries,
|
||||
|
||||
+400
-62
@@ -4,8 +4,9 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "DwarfInterfaceFactory.h"
|
||||
#include "DwarfStackFrameDebugInfo.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <new>
|
||||
|
||||
#include <Variant.h>
|
||||
@@ -20,6 +21,7 @@
|
||||
#include "LocalVariableID.h"
|
||||
#include "RegisterMap.h"
|
||||
#include "StringUtils.h"
|
||||
#include "Tracing.h"
|
||||
#include "ValueLocation.h"
|
||||
#include "Variable.h"
|
||||
|
||||
@@ -27,7 +29,7 @@
|
||||
// #pragma mark - DwarfFunctionParameterID
|
||||
|
||||
|
||||
struct DwarfInterfaceFactory::DwarfFunctionParameterID
|
||||
struct DwarfStackFrameDebugInfo::DwarfFunctionParameterID
|
||||
: public FunctionParameterID {
|
||||
|
||||
DwarfFunctionParameterID(FunctionID* functionID, const BString& name)
|
||||
@@ -67,7 +69,7 @@ private:
|
||||
// #pragma mark - DwarfLocalVariableID
|
||||
|
||||
|
||||
struct DwarfInterfaceFactory::DwarfLocalVariableID : public LocalVariableID {
|
||||
struct DwarfStackFrameDebugInfo::DwarfLocalVariableID : public LocalVariableID {
|
||||
|
||||
DwarfLocalVariableID(FunctionID* functionID, const BString& name,
|
||||
int32 line, int32 column)
|
||||
@@ -115,7 +117,7 @@ private:
|
||||
// #pragma mark - DwarfType
|
||||
|
||||
|
||||
struct DwarfInterfaceFactory::DwarfType : virtual Type {
|
||||
struct DwarfStackFrameDebugInfo::DwarfType : virtual Type {
|
||||
public:
|
||||
DwarfType(const BString& name)
|
||||
:
|
||||
@@ -129,12 +131,12 @@ public:
|
||||
return fName.Length() > 0 ? fName.String() : NULL;
|
||||
}
|
||||
|
||||
uint64 ByteSize() const
|
||||
virtual target_size_t ByteSize() const
|
||||
{
|
||||
return fByteSize;
|
||||
}
|
||||
|
||||
void SetByteSize(uint64 size)
|
||||
void SetByteSize(target_size_t size)
|
||||
{
|
||||
fByteSize = size;
|
||||
}
|
||||
@@ -142,18 +144,53 @@ public:
|
||||
virtual DIEType* GetDIEType() const = 0;
|
||||
|
||||
private:
|
||||
BString fName;
|
||||
uint64 fByteSize;
|
||||
BString fName;
|
||||
target_size_t fByteSize;
|
||||
|
||||
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
|
||||
|
||||
|
||||
struct DwarfInterfaceFactory::DwarfDataMember : DataMember {
|
||||
struct DwarfStackFrameDebugInfo::DwarfDataMember : DataMember {
|
||||
public:
|
||||
DwarfDataMember(DIEMember* entry, const BString& name, DwarfType* type)
|
||||
:
|
||||
@@ -195,7 +232,7 @@ private:
|
||||
// #pragma mark - DwarfPrimitiveType
|
||||
|
||||
|
||||
struct DwarfInterfaceFactory::DwarfPrimitiveType : PrimitiveType, DwarfType {
|
||||
struct DwarfStackFrameDebugInfo::DwarfPrimitiveType : PrimitiveType, DwarfType {
|
||||
public:
|
||||
DwarfPrimitiveType(const BString& name, DIEBaseType* entry,
|
||||
uint32 typeConstant)
|
||||
@@ -230,7 +267,7 @@ private:
|
||||
// #pragma mark - DwarfCompoundType
|
||||
|
||||
|
||||
struct DwarfInterfaceFactory::DwarfCompoundType : CompoundType, DwarfType {
|
||||
struct DwarfStackFrameDebugInfo::DwarfCompoundType : CompoundType, DwarfType {
|
||||
public:
|
||||
DwarfCompoundType(const BString& name, DIECompoundType* entry)
|
||||
:
|
||||
@@ -241,10 +278,24 @@ public:
|
||||
|
||||
~DwarfCompoundType()
|
||||
{
|
||||
for (int32 i = 0;
|
||||
DwarfInheritance* inheritance = fInheritances.ItemAt(i); i++) {
|
||||
inheritance->ReleaseReference();
|
||||
}
|
||||
for (int32 i = 0; DwarfDataMember* member = fDataMembers.ItemAt(i); i++)
|
||||
member->ReleaseReference();
|
||||
}
|
||||
|
||||
virtual int32 CountBaseTypes() const
|
||||
{
|
||||
return fInheritances.CountItems();
|
||||
}
|
||||
|
||||
virtual BaseType* BaseTypeAt(int32 index) const
|
||||
{
|
||||
return fInheritances.ItemAt(index);
|
||||
}
|
||||
|
||||
virtual int32 CountDataMembers() const
|
||||
{
|
||||
return fDataMembers.CountItems();
|
||||
@@ -265,6 +316,15 @@ public:
|
||||
return fEntry;
|
||||
}
|
||||
|
||||
bool AddInheritance(DwarfInheritance* inheritance)
|
||||
{
|
||||
if (!fInheritances.AddItem(inheritance))
|
||||
return false;
|
||||
|
||||
inheritance->AcquireReference();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AddDataMember(DwarfDataMember* member)
|
||||
{
|
||||
if (!fDataMembers.AddItem(member))
|
||||
@@ -276,17 +336,19 @@ public:
|
||||
|
||||
private:
|
||||
typedef BObjectList<DwarfDataMember> DataMemberList;
|
||||
typedef BObjectList<DwarfInheritance> InheritanceList;
|
||||
|
||||
private:
|
||||
DIECompoundType* fEntry;
|
||||
DataMemberList fDataMembers;
|
||||
InheritanceList fInheritances;
|
||||
DataMemberList fDataMembers;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - DwarfModifiedType
|
||||
|
||||
|
||||
struct DwarfInterfaceFactory::DwarfModifiedType : ModifiedType, DwarfType {
|
||||
struct DwarfStackFrameDebugInfo::DwarfModifiedType : ModifiedType, DwarfType {
|
||||
public:
|
||||
DwarfModifiedType(const BString& name, DIEModifiedType* entry,
|
||||
uint32 modifiers, DwarfType* baseType)
|
||||
@@ -334,7 +396,7 @@ private:
|
||||
// #pragma mark - DwarfTypedefType
|
||||
|
||||
|
||||
struct DwarfInterfaceFactory::DwarfTypedefType : TypedefType, DwarfType {
|
||||
struct DwarfStackFrameDebugInfo::DwarfTypedefType : TypedefType, DwarfType {
|
||||
public:
|
||||
DwarfTypedefType(const BString& name, DIETypedef* entry,
|
||||
DwarfType* baseType)
|
||||
@@ -375,7 +437,7 @@ private:
|
||||
// #pragma mark - DwarfAddressType
|
||||
|
||||
|
||||
struct DwarfInterfaceFactory::DwarfAddressType : AddressType, DwarfType {
|
||||
struct DwarfStackFrameDebugInfo::DwarfAddressType : AddressType, DwarfType {
|
||||
public:
|
||||
DwarfAddressType(const BString& name, DIEAddressingType* entry,
|
||||
address_type_kind addressKind, DwarfType* baseType)
|
||||
@@ -423,7 +485,7 @@ private:
|
||||
// #pragma mark - DwarfArrayType
|
||||
|
||||
|
||||
struct DwarfInterfaceFactory::DwarfArrayType : ArrayType, DwarfType {
|
||||
struct DwarfStackFrameDebugInfo::DwarfArrayType : ArrayType, DwarfType {
|
||||
DwarfArrayType(const BString& name, DIEArrayType* entry,
|
||||
DwarfType* baseType, target_size_t elementCount)
|
||||
:
|
||||
@@ -470,7 +532,7 @@ private:
|
||||
// #pragma mark - DwarfTypeHashDefinition
|
||||
|
||||
|
||||
struct DwarfInterfaceFactory::DwarfTypeHashDefinition {
|
||||
struct DwarfStackFrameDebugInfo::DwarfTypeHashDefinition {
|
||||
typedef const DIEType* KeyType;
|
||||
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,
|
||||
target_addr_t instructionPointer, target_addr_t framePointer,
|
||||
DwarfTargetInterface* targetInterface, RegisterMap* fromDwarfRegisterMap)
|
||||
@@ -516,7 +578,7 @@ DwarfInterfaceFactory::DwarfInterfaceFactory(DwarfFile* file,
|
||||
}
|
||||
|
||||
|
||||
DwarfInterfaceFactory::~DwarfInterfaceFactory()
|
||||
DwarfStackFrameDebugInfo::~DwarfStackFrameDebugInfo()
|
||||
{
|
||||
if (fTypes != NULL) {
|
||||
DwarfType* type = fTypes->Clear(true);
|
||||
@@ -532,7 +594,7 @@ DwarfInterfaceFactory::~DwarfInterfaceFactory()
|
||||
|
||||
|
||||
status_t
|
||||
DwarfInterfaceFactory::Init()
|
||||
DwarfStackFrameDebugInfo::Init()
|
||||
{
|
||||
fTypes = new(std::nothrow) TypeTable;
|
||||
if (fTypes == NULL)
|
||||
@@ -543,7 +605,128 @@ DwarfInterfaceFactory::Init()
|
||||
|
||||
|
||||
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;
|
||||
status_t error = _CreateType(typeEntry, type);
|
||||
@@ -556,14 +739,15 @@ DwarfInterfaceFactory::CreateType(DIEType* typeEntry, Type*& _type)
|
||||
|
||||
|
||||
status_t
|
||||
DwarfInterfaceFactory::CreateParameter(FunctionID* functionID,
|
||||
DwarfStackFrameDebugInfo::CreateParameter(FunctionID* functionID,
|
||||
DIEFormalParameter* parameterEntry, Variable*& _parameter)
|
||||
{
|
||||
// get the name
|
||||
BString 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
|
||||
DwarfFunctionParameterID* id = new(std::nothrow) DwarfFunctionParameterID(
|
||||
@@ -579,14 +763,15 @@ parameterEntry, name.String());
|
||||
|
||||
|
||||
status_t
|
||||
DwarfInterfaceFactory::CreateLocalVariable(FunctionID* functionID,
|
||||
DwarfStackFrameDebugInfo::CreateLocalVariable(FunctionID* functionID,
|
||||
DIEVariable* variableEntry, Variable*& _variable)
|
||||
{
|
||||
// get the name
|
||||
BString 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
|
||||
int32 line = -1;
|
||||
@@ -613,7 +798,90 @@ variableEntry, name.String());
|
||||
|
||||
|
||||
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.
|
||||
DwarfType* type = fTypes->Lookup(typeEntry);
|
||||
@@ -641,7 +909,7 @@ DwarfInterfaceFactory::_CreateType(DIEType* typeEntry, DwarfType*& _type)
|
||||
|
||||
|
||||
status_t
|
||||
DwarfInterfaceFactory::_CreateTypeInternal(DIEType* typeEntry,
|
||||
DwarfStackFrameDebugInfo::_CreateTypeInternal(DIEType* typeEntry,
|
||||
DwarfType*& _type)
|
||||
{
|
||||
BString name;
|
||||
@@ -718,9 +986,12 @@ DwarfInterfaceFactory::_CreateTypeInternal(DIEType* typeEntry,
|
||||
|
||||
|
||||
status_t
|
||||
DwarfInterfaceFactory::_CreateCompoundType(const BString& name,
|
||||
DwarfStackFrameDebugInfo::_CreateCompoundType(const BString& name,
|
||||
DIECompoundType* typeEntry, DwarfType*& _type)
|
||||
{
|
||||
TRACE_LOCALS("DwarfStackFrameDebugInfo::_CreateCompoundType(\"%s\", %p)\n",
|
||||
name.String(), typeEntry);
|
||||
|
||||
// create the type
|
||||
DwarfCompoundType* type = new(std::nothrow) DwarfCompoundType(name,
|
||||
typeEntry);
|
||||
@@ -734,7 +1005,10 @@ DwarfInterfaceFactory::_CreateCompoundType(const BString& name,
|
||||
fTypes->Insert(type);
|
||||
|
||||
// find the abstract origin or specification that defines the data members
|
||||
DIECompoundType* originalTypeEntry = typeEntry;
|
||||
if (typeEntry->DataMembers().IsEmpty()) {
|
||||
TRACE_LOCALS(" no data members yet, trying abstract origin...\n");
|
||||
|
||||
if (DIECompoundType* abstractOrigin = dynamic_cast<DIECompoundType*>(
|
||||
typeEntry->AbstractOrigin())) {
|
||||
typeEntry = abstractOrigin;
|
||||
@@ -742,6 +1016,8 @@ DwarfInterfaceFactory::_CreateCompoundType(const BString& name,
|
||||
}
|
||||
|
||||
if (typeEntry->DataMembers().IsEmpty()) {
|
||||
TRACE_LOCALS(" no data members yet, trying specification...\n");
|
||||
|
||||
if (DIECompoundType* specification = dynamic_cast<DIECompoundType*>(
|
||||
typeEntry->Specification())) {
|
||||
typeEntry = specification;
|
||||
@@ -754,6 +1030,8 @@ DwarfInterfaceFactory::_CreateCompoundType(const BString& name,
|
||||
DebugInfoEntry* _memberEntry = it.Next();) {
|
||||
DIEMember* memberEntry = dynamic_cast<DIEMember*>(_memberEntry);
|
||||
|
||||
TRACE_LOCALS(" member %p\n", memberEntry);
|
||||
|
||||
// get the type
|
||||
DwarfType* memberType;
|
||||
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();
|
||||
return B_OK;;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DwarfInterfaceFactory::_CreatePrimitiveType(const BString& name,
|
||||
DwarfStackFrameDebugInfo::_CreatePrimitiveType(const BString& name,
|
||||
DIEBaseType* typeEntry, DwarfType*& _type)
|
||||
{
|
||||
const DynamicAttributeValue* byteSizeValue = typeEntry->ByteSize();
|
||||
@@ -883,7 +1206,7 @@ DwarfInterfaceFactory::_CreatePrimitiveType(const BString& name,
|
||||
|
||||
|
||||
status_t
|
||||
DwarfInterfaceFactory::_CreateAddressType(const BString& name,
|
||||
DwarfStackFrameDebugInfo::_CreateAddressType(const BString& name,
|
||||
DIEAddressingType* typeEntry, address_type_kind addressKind,
|
||||
DwarfType*& _type)
|
||||
{
|
||||
@@ -928,7 +1251,7 @@ DwarfInterfaceFactory::_CreateAddressType(const BString& name,
|
||||
|
||||
|
||||
status_t
|
||||
DwarfInterfaceFactory::_CreateModifiedType(const BString& name,
|
||||
DwarfStackFrameDebugInfo::_CreateModifiedType(const BString& name,
|
||||
DIEModifiedType* typeEntry, uint32 modifiers, DwarfType*& _type)
|
||||
{
|
||||
// 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
|
||||
DwarfInterfaceFactory::_CreateTypedefType(const BString& name,
|
||||
DwarfStackFrameDebugInfo::_CreateTypedefType(const BString& name,
|
||||
DIETypedef* typeEntry, DwarfType*& _type)
|
||||
{
|
||||
// resolve the base type
|
||||
@@ -1046,7 +1369,7 @@ DwarfInterfaceFactory::_CreateTypedefType(const BString& name,
|
||||
|
||||
|
||||
status_t
|
||||
DwarfInterfaceFactory::_CreateArrayType(const BString& name,
|
||||
DwarfStackFrameDebugInfo::_CreateArrayType(const BString& name,
|
||||
DIEArrayType* typeEntry, DwarfType*& _type)
|
||||
{
|
||||
#if 0
|
||||
@@ -1094,7 +1417,7 @@ DwarfInterfaceFactory::_CreateArrayType(const BString& name,
|
||||
|
||||
|
||||
status_t
|
||||
DwarfInterfaceFactory::_CreateVariable(ObjectID* id, const BString& name,
|
||||
DwarfStackFrameDebugInfo::_CreateVariable(ObjectID* id, const BString& name,
|
||||
DIEType* typeEntry, LocationDescription* locationDescription,
|
||||
Variable*& _variable)
|
||||
{
|
||||
@@ -1111,7 +1434,8 @@ DwarfInterfaceFactory::_CreateVariable(ObjectID* id, const BString& name,
|
||||
fFile->ResolveLocation(fCompilationUnit,
|
||||
fSubprogramEntry, locationDescription, fTargetInterface,
|
||||
fInstructionPointer, 0, fFramePointer, *location);
|
||||
location->Dump();
|
||||
|
||||
TRACE_LOCALS_ONLY(location->Dump());
|
||||
}
|
||||
|
||||
// create the type
|
||||
@@ -1134,7 +1458,7 @@ location->Dump();
|
||||
|
||||
|
||||
status_t
|
||||
DwarfInterfaceFactory::_ResolveTypedef(DIETypedef* entry,
|
||||
DwarfStackFrameDebugInfo::_ResolveTypedef(DIETypedef* entry,
|
||||
DIEType*& _baseTypeEntry)
|
||||
{
|
||||
while (true) {
|
||||
@@ -1172,16 +1496,20 @@ DwarfInterfaceFactory::_ResolveTypedef(DIETypedef* entry,
|
||||
|
||||
|
||||
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
|
||||
const DynamicAttributeValue* sizeValue;
|
||||
|
||||
while (true) {
|
||||
// resolve a typedef
|
||||
if (typeEntry->Tag() == DW_TAG_typedef) {
|
||||
printf(" resolving typedef...\n");
|
||||
TRACE_LOCALS(" resolving typedef...\n");
|
||||
|
||||
status_t error = _ResolveTypedef(
|
||||
dynamic_cast<DIETypedef*>(typeEntry), typeEntry);
|
||||
if (error != B_OK)
|
||||
@@ -1195,7 +1523,9 @@ printf(" resolving typedef...\n");
|
||||
// resolve abstract origin
|
||||
if (DIEType* abstractOrigin = dynamic_cast<DIEType*>(
|
||||
typeEntry->AbstractOrigin())) {
|
||||
printf(" resolving abstract origin (%p)...\n", abstractOrigin);
|
||||
TRACE_LOCALS(" resolving abstract origin (%p)...\n",
|
||||
abstractOrigin);
|
||||
|
||||
typeEntry = abstractOrigin;
|
||||
sizeValue = typeEntry->ByteSize();
|
||||
if (sizeValue != NULL && sizeValue->IsValid())
|
||||
@@ -1205,7 +1535,8 @@ printf(" resolving abstract origin (%p)...\n", abstractOrigin);
|
||||
// resolve specification
|
||||
if (DIEType* specification = dynamic_cast<DIEType*>(
|
||||
typeEntry->Specification())) {
|
||||
printf(" resolving specification (%p)...\n", specification);
|
||||
TRACE_LOCALS(" resolving specification (%p)...\n", specification);
|
||||
|
||||
typeEntry = specification;
|
||||
sizeValue = typeEntry->ByteSize();
|
||||
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
|
||||
// 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()) {
|
||||
case DW_TAG_const_type:
|
||||
case DW_TAG_packed_type:
|
||||
@@ -1223,44 +1555,50 @@ printf(" nothing yet, special type handling\n");
|
||||
case DW_TAG_shared_type:
|
||||
typeEntry = dynamic_cast<DIEModifiedType*>(typeEntry)
|
||||
->GetType();
|
||||
printf(" following modified type -> %p\n", typeEntry);
|
||||
|
||||
TRACE_LOCALS(" following modified type -> %p\n", typeEntry);
|
||||
|
||||
if (typeEntry == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
break;
|
||||
case DW_TAG_pointer_type:
|
||||
case DW_TAG_reference_type:
|
||||
_size = fCompilationUnit->AddressSize();
|
||||
printf(" pointer/reference type: size: %llu\n", _size);
|
||||
|
||||
TRACE_LOCALS(" pointer/reference type: size: %llu\n", _size);
|
||||
|
||||
return B_OK;
|
||||
default:
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
printf(" found attribute\n");
|
||||
TRACE_LOCALS(" found attribute\n");
|
||||
|
||||
// get the actual value
|
||||
BVariant size;
|
||||
status_t error = fFile->EvaluateDynamicValue(fCompilationUnit,
|
||||
fSubprogramEntry, sizeValue, fTargetInterface, fInstructionPointer,
|
||||
fFramePointer, size);
|
||||
if (error != B_OK)
|
||||
{
|
||||
printf(" failed to resolve attribute: %s\n", strerror(error));
|
||||
if (error != B_OK) {
|
||||
TRACE_LOCALS(" failed to resolve attribute: %s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
_size = size.ToUInt64();
|
||||
printf(" -> size: %llu\n", _size);
|
||||
|
||||
TRACE_LOCALS(" -> size: %llu\n", _size);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DwarfInterfaceFactory::_FixLocation(ValueLocation* location, DwarfType* type)
|
||||
DwarfStackFrameDebugInfo::_FixLocation(ValueLocation* location, DwarfType* type)
|
||||
{
|
||||
printf("DwarfInterfaceFactory::_FixLocation(%p, %p), type entry: %p\n",
|
||||
location, type, type->GetDIEType());
|
||||
TRACE_LOCALS("DwarfStackFrameDebugInfo::_FixLocation(%p, %p), type entry: "
|
||||
"%p\n", location, type, type->GetDIEType());
|
||||
|
||||
// translate the DWARF register indices
|
||||
int32 count = location->CountPieces();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
@@ -1280,19 +1618,19 @@ location, type, type->GetDIEType());
|
||||
// the size of the type.
|
||||
if (count == 1) {
|
||||
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());
|
||||
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>
|
||||
/*static*/ DIEType*
|
||||
DwarfInterfaceFactory::_GetDIEType(EntryType* entry)
|
||||
DwarfStackFrameDebugInfo::_GetDIEType(EntryType* entry)
|
||||
{
|
||||
if (DIEType* typeEntry = entry->GetType())
|
||||
return typeEntry;
|
||||
+30
-5
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <util/OpenHashTable.h>
|
||||
|
||||
#include "StackFrameDebugInfo.h"
|
||||
#include "Type.h"
|
||||
|
||||
|
||||
@@ -28,26 +29,40 @@ class DwarfFile;
|
||||
class DwarfTargetInterface;
|
||||
class FunctionID;
|
||||
class LocationDescription;
|
||||
class MemberLocation;
|
||||
class ObjectID;
|
||||
class RegisterMap;
|
||||
class Type;
|
||||
class ValueLocation;
|
||||
class Variable;
|
||||
|
||||
|
||||
class DwarfInterfaceFactory {
|
||||
class DwarfStackFrameDebugInfo : public StackFrameDebugInfo {
|
||||
public:
|
||||
DwarfInterfaceFactory(DwarfFile* file,
|
||||
DwarfStackFrameDebugInfo(DwarfFile* file,
|
||||
CompilationUnit* compilationUnit,
|
||||
DIESubprogram* subprogramEntry,
|
||||
target_addr_t instructionPointer,
|
||||
target_addr_t framePointer,
|
||||
DwarfTargetInterface* targetInterface,
|
||||
RegisterMap* fromDwarfRegisterMap);
|
||||
~DwarfInterfaceFactory();
|
||||
~DwarfStackFrameDebugInfo();
|
||||
|
||||
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);
|
||||
// returns reference
|
||||
status_t CreateParameter(FunctionID* functionID,
|
||||
@@ -63,6 +78,7 @@ private:
|
||||
struct DwarfFunctionParameterID;
|
||||
struct DwarfLocalVariableID;
|
||||
struct DwarfType;
|
||||
struct DwarfInheritance;
|
||||
struct DwarfDataMember;
|
||||
struct DwarfPrimitiveType;
|
||||
struct DwarfCompoundType;
|
||||
@@ -75,6 +91,15 @@ private:
|
||||
typedef BOpenHashTable<DwarfTypeHashDefinition> TypeTable;
|
||||
|
||||
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,
|
||||
DwarfType*& _type);
|
||||
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 CpuState;
|
||||
class DataMember;
|
||||
class DebuggerInterface;
|
||||
class FileSourceCode;
|
||||
class FunctionDebugInfo;
|
||||
@@ -23,6 +24,8 @@ class SourceLanguage;
|
||||
class SourceLocation;
|
||||
class StackFrame;
|
||||
class Statement;
|
||||
class Type;
|
||||
class ValueLocation;
|
||||
|
||||
|
||||
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
|
||||
TeamDebugInfo::AddImageDebugInfo(ImageDebugInfo* imageDebugInfo)
|
||||
{
|
||||
printf("TeamDebugInfo::AddImageDebugInfo(%p)\n", imageDebugInfo);
|
||||
AutoLocker<BLocker> locker(fLock);
|
||||
// We have both locks now, so that for read-only access either lock
|
||||
// suffices.
|
||||
@@ -497,7 +496,6 @@ printf("TeamDebugInfo::AddImageDebugInfo(%p)\n", imageDebugInfo);
|
||||
Function* function = fFunctions->Lookup(instance);
|
||||
if (function != NULL) {
|
||||
// TODO: Also update possible user breakpoints in this function!
|
||||
printf(" adding instance %p to existing function %p\n", instance, function);
|
||||
function->AddInstance(instance);
|
||||
instance->SetFunction(function);
|
||||
|
||||
@@ -515,7 +513,6 @@ printf(" adding instance %p to existing function %p\n", instance, function);
|
||||
RemoveImageDebugInfo(imageDebugInfo);
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
printf(" adding instance %p to new function %p\n", instance, function);
|
||||
function->AddInstance(instance);
|
||||
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 {
|
||||
union {
|
||||
off_t listOffset; // location list
|
||||
|
||||
@@ -215,6 +215,13 @@ DIEType::Name() const
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DIEType::IsDeclaration() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const DynamicAttributeValue*
|
||||
DIEType::ByteSize() const
|
||||
{
|
||||
@@ -313,6 +320,13 @@ DIEDeclaredType::AbstractOrigin() const
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DIEDeclaredType::IsDeclaration() const
|
||||
{
|
||||
return fDeclaration;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DIEDeclaredType::AddAttribute_accessibility(uint16 attributeName,
|
||||
const AttributeValue& value)
|
||||
@@ -563,6 +577,13 @@ DIEDeclaredNamedBase::Description() const
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DIEDeclaredNamedBase::IsDeclaration() const
|
||||
{
|
||||
return fDeclaration;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DIEDeclaredNamedBase::AddAttribute_name(uint16 attributeName,
|
||||
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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -219,6 +219,7 @@ public:
|
||||
|
||||
virtual const char* Name() const;
|
||||
|
||||
virtual bool IsDeclaration() const;
|
||||
virtual const DynamicAttributeValue* ByteSize() const;
|
||||
|
||||
virtual status_t AddAttribute_name(uint16 attributeName,
|
||||
@@ -272,6 +273,8 @@ public:
|
||||
virtual const char* Description() const;
|
||||
virtual DebugInfoEntry* AbstractOrigin() const;
|
||||
|
||||
virtual bool IsDeclaration() const;
|
||||
|
||||
virtual status_t AddAttribute_accessibility(uint16 attributeName,
|
||||
const AttributeValue& value);
|
||||
// TODO: !file, !pointer to member
|
||||
@@ -348,6 +351,9 @@ class DIEClassBaseType : public DIECompoundType {
|
||||
public:
|
||||
DIEClassBaseType();
|
||||
|
||||
const DebugInfoEntryList& BaseTypes() const
|
||||
{ return fBaseTypes; }
|
||||
|
||||
virtual status_t AddChild(DebugInfoEntry* child);
|
||||
|
||||
protected:
|
||||
@@ -398,7 +404,7 @@ public:
|
||||
|
||||
uint8 Accessibility() const { return fAccessibility; }
|
||||
uint8 Visibility() const { return fVisibility; }
|
||||
bool IsDeclaration() const { return fDeclaration; }
|
||||
virtual bool IsDeclaration() const;
|
||||
|
||||
virtual status_t AddAttribute_name(uint16 attributeName,
|
||||
const AttributeValue& value);
|
||||
@@ -628,19 +634,36 @@ public:
|
||||
virtual uint16 Tag() const;
|
||||
|
||||
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,
|
||||
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:
|
||||
// DW_AT_bit_offset
|
||||
// DW_AT_bit_size
|
||||
// DW_AT_byte_size
|
||||
// DW_AT_data_member_location
|
||||
// DW_AT_mutable
|
||||
|
||||
private:
|
||||
DIEType* fType;
|
||||
DynamicAttributeValue fByteSize;
|
||||
DynamicAttributeValue fBitOffset;
|
||||
DynamicAttributeValue fBitSize;
|
||||
MemberLocation fLocation;
|
||||
};
|
||||
|
||||
|
||||
@@ -805,17 +828,22 @@ public:
|
||||
virtual uint16 Tag() const;
|
||||
|
||||
DIEType* GetType() const { return fType; }
|
||||
const MemberLocation* Location() const
|
||||
{ return &fLocation; }
|
||||
|
||||
virtual status_t AddAttribute_type(uint16 attributeName,
|
||||
const AttributeValue& value);
|
||||
virtual status_t AddAttribute_data_member_location(
|
||||
uint16 attributeName,
|
||||
const AttributeValue& value);
|
||||
|
||||
// TODO:
|
||||
// DW_AT_accessibility
|
||||
// DW_AT_data_member_location
|
||||
// DW_AT_virtuality
|
||||
|
||||
private:
|
||||
DIEType* fType;
|
||||
MemberLocation fLocation;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -346,3 +346,23 @@ DebugInfoEntry::SetConstantAttributeValue(ConstantAttributeValue& toSet,
|
||||
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 DynamicAttributeValue;
|
||||
struct LocationDescription;
|
||||
struct MemberLocation;
|
||||
struct SourceLanguageInfo;
|
||||
|
||||
|
||||
@@ -171,6 +172,8 @@ protected:
|
||||
status_t SetConstantAttributeValue(
|
||||
ConstantAttributeValue& toSet,
|
||||
const AttributeValue& value);
|
||||
status_t SetMemberLocation(MemberLocation& toSet,
|
||||
const AttributeValue& value);
|
||||
|
||||
protected:
|
||||
DebugInfoEntry* fParent;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "DataReader.h"
|
||||
#include "Dwarf.h"
|
||||
#include "DwarfTargetInterface.h"
|
||||
#include "Tracing.h"
|
||||
#include "ValueLocation.h"
|
||||
|
||||
|
||||
@@ -147,7 +148,8 @@ DwarfExpressionEvaluator::Evaluate(const void* expression, size_t size,
|
||||
_result = _Pop();
|
||||
return B_OK;
|
||||
} catch (const EvaluationException& exception) {
|
||||
printf("DwarfExpressionEvaluator::Evaluate(): %s\n", exception.message);
|
||||
WARNING("DwarfExpressionEvaluator::Evaluate(): %s\n",
|
||||
exception.message);
|
||||
return B_BAD_VALUE;
|
||||
} catch (const std::bad_alloc& exception) {
|
||||
return B_NO_MEMORY;
|
||||
@@ -173,6 +175,11 @@ DwarfExpressionEvaluator::EvaluateLocation(const void* expression, size_t size,
|
||||
|
||||
// parse the first (and maybe only) expression
|
||||
try {
|
||||
// push the object address, if any
|
||||
target_addr_t objectAddress;
|
||||
if (fContext->GetObjectAddress(objectAddress))
|
||||
_Push(objectAddress);
|
||||
|
||||
ValuePieceLocation piece;
|
||||
status_t error = _Evaluate(&piece);
|
||||
if (error != B_OK)
|
||||
@@ -201,7 +208,8 @@ DwarfExpressionEvaluator::EvaluateLocation(const void* expression, size_t size,
|
||||
if (fDataReader.BytesRemaining() == 0)
|
||||
return B_BAD_DATA;
|
||||
} catch (const EvaluationException& exception) {
|
||||
printf("DwarfExpressionEvaluator::EvaluateLocation(): %s\n", exception.message);
|
||||
WARNING("DwarfExpressionEvaluator::EvaluateLocation(): %s\n",
|
||||
exception.message);
|
||||
return B_BAD_VALUE;
|
||||
} catch (const std::bad_alloc& exception) {
|
||||
return B_NO_MEMORY;
|
||||
@@ -215,6 +223,11 @@ printf("DwarfExpressionEvaluator::EvaluateLocation(): %s\n", exception.message);
|
||||
fDataReader.AddressSize());
|
||||
|
||||
try {
|
||||
// push the object address, if any
|
||||
target_addr_t objectAddress;
|
||||
if (fContext->GetObjectAddress(objectAddress))
|
||||
_Push(objectAddress);
|
||||
|
||||
ValuePieceLocation piece;
|
||||
status_t error = _Evaluate(&piece);
|
||||
if (error != B_OK)
|
||||
@@ -236,7 +249,8 @@ printf("DwarfExpressionEvaluator::EvaluateLocation(): %s\n", exception.message);
|
||||
} else
|
||||
return B_BAD_DATA;
|
||||
} catch (const EvaluationException& exception) {
|
||||
printf("DwarfExpressionEvaluator::EvaluateLocation(): %s\n", exception.message);
|
||||
WARNING("DwarfExpressionEvaluator::EvaluateLocation(): %s\n",
|
||||
exception.message);
|
||||
return B_BAD_VALUE;
|
||||
} catch (const std::bad_alloc& exception) {
|
||||
return B_NO_MEMORY;
|
||||
@@ -250,15 +264,16 @@ printf("DwarfExpressionEvaluator::EvaluateLocation(): %s\n", exception.message);
|
||||
status_t
|
||||
DwarfExpressionEvaluator::_Evaluate(ValuePieceLocation* _piece)
|
||||
{
|
||||
{
|
||||
printf("DwarfExpressionEvaluator::_Evaluate(%p, %lld)\n", fDataReader.Data(),
|
||||
fDataReader.BytesRemaining());
|
||||
const uint8* data = (const uint8*)fDataReader.Data();
|
||||
int32 count = fDataReader.BytesRemaining();
|
||||
for (int32 i = 0; i < count; i++)
|
||||
printf(" %02x", data[i]);
|
||||
printf("\n");
|
||||
}
|
||||
TRACE_EXPR_ONLY({
|
||||
TRACE_EXPR("DwarfExpressionEvaluator::_Evaluate(%p, %lld)\n",
|
||||
fDataReader.Data(), fDataReader.BytesRemaining());
|
||||
const uint8* data = (const uint8*)fDataReader.Data();
|
||||
int32 count = fDataReader.BytesRemaining();
|
||||
for (int32 i = 0; i < count; i++)
|
||||
TRACE_EXPR(" %02x", data[i]);
|
||||
TRACE_EXPR("\n");
|
||||
})
|
||||
|
||||
uint32 operationsExecuted = 0;
|
||||
|
||||
while (fDataReader.BytesRemaining() > 0) {
|
||||
@@ -266,66 +281,66 @@ printf("\n");
|
||||
|
||||
switch (opcode) {
|
||||
case DW_OP_addr:
|
||||
printf(" DW_OP_addr\n");
|
||||
TRACE_EXPR(" DW_OP_addr\n");
|
||||
_Push(fDataReader.ReadAddress(0));
|
||||
break;
|
||||
case DW_OP_const1u:
|
||||
printf(" DW_OP_const1u\n");
|
||||
TRACE_EXPR(" DW_OP_const1u\n");
|
||||
_Push(fDataReader.Read<uint8>(0));
|
||||
break;
|
||||
case DW_OP_const1s:
|
||||
printf(" DW_OP_const1s\n");
|
||||
TRACE_EXPR(" DW_OP_const1s\n");
|
||||
_Push(fDataReader.Read<int8>(0));
|
||||
break;
|
||||
case DW_OP_const2u:
|
||||
printf(" DW_OP_const2u\n");
|
||||
TRACE_EXPR(" DW_OP_const2u\n");
|
||||
_Push(fDataReader.Read<uint16>(0));
|
||||
break;
|
||||
case DW_OP_const2s:
|
||||
printf(" DW_OP_const2s\n");
|
||||
TRACE_EXPR(" DW_OP_const2s\n");
|
||||
_Push(fDataReader.Read<int16>(0));
|
||||
break;
|
||||
case DW_OP_const4u:
|
||||
printf(" DW_OP_const4u\n");
|
||||
TRACE_EXPR(" DW_OP_const4u\n");
|
||||
_Push(fDataReader.Read<uint32>(0));
|
||||
break;
|
||||
case DW_OP_const4s:
|
||||
printf(" DW_OP_const4s\n");
|
||||
TRACE_EXPR(" DW_OP_const4s\n");
|
||||
_Push(fDataReader.Read<int32>(0));
|
||||
break;
|
||||
case DW_OP_const8u:
|
||||
printf(" DW_OP_const8u\n");
|
||||
TRACE_EXPR(" DW_OP_const8u\n");
|
||||
_Push(fDataReader.Read<uint64>(0));
|
||||
break;
|
||||
case DW_OP_const8s:
|
||||
printf(" DW_OP_const8s\n");
|
||||
TRACE_EXPR(" DW_OP_const8s\n");
|
||||
_Push(fDataReader.Read<int64>(0));
|
||||
break;
|
||||
case DW_OP_constu:
|
||||
printf(" DW_OP_constu\n");
|
||||
TRACE_EXPR(" DW_OP_constu\n");
|
||||
_Push(fDataReader.ReadUnsignedLEB128(0));
|
||||
break;
|
||||
case DW_OP_consts:
|
||||
printf(" DW_OP_consts\n");
|
||||
TRACE_EXPR(" DW_OP_consts\n");
|
||||
_Push(fDataReader.ReadSignedLEB128(0));
|
||||
break;
|
||||
case DW_OP_dup:
|
||||
printf(" DW_OP_dup\n");
|
||||
TRACE_EXPR(" DW_OP_dup\n");
|
||||
_AssertMinStackSize(1);
|
||||
_Push(fStack[fStackSize - 1]);
|
||||
break;
|
||||
case DW_OP_drop:
|
||||
printf(" DW_OP_drop\n");
|
||||
TRACE_EXPR(" DW_OP_drop\n");
|
||||
_Pop();
|
||||
break;
|
||||
case DW_OP_over:
|
||||
printf(" DW_OP_over\n");
|
||||
TRACE_EXPR(" DW_OP_over\n");
|
||||
_AssertMinStackSize(1);
|
||||
_Push(fStack[fStackSize - 2]);
|
||||
break;
|
||||
case DW_OP_pick:
|
||||
{
|
||||
printf(" DW_OP_pick\n");
|
||||
TRACE_EXPR(" DW_OP_pick\n");
|
||||
uint8 index = fDataReader.Read<uint8>(0);
|
||||
_AssertMinStackSize(index + 1);
|
||||
_Push(fStack[fStackSize - index - 1]);
|
||||
@@ -333,14 +348,14 @@ printf(" DW_OP_pick\n");
|
||||
}
|
||||
case DW_OP_swap:
|
||||
{
|
||||
printf(" DW_OP_swap\n");
|
||||
TRACE_EXPR(" DW_OP_swap\n");
|
||||
_AssertMinStackSize(2);
|
||||
std::swap(fStack[fStackSize - 1], fStack[fStackSize - 2]);
|
||||
break;
|
||||
}
|
||||
case DW_OP_rot:
|
||||
{
|
||||
printf(" DW_OP_rot\n");
|
||||
TRACE_EXPR(" DW_OP_rot\n");
|
||||
_AssertMinStackSize(3);
|
||||
target_addr_t tmp = fStack[fStackSize - 1];
|
||||
fStack[fStackSize - 1] = fStack[fStackSize - 2];
|
||||
@@ -350,25 +365,25 @@ printf(" DW_OP_rot\n");
|
||||
}
|
||||
|
||||
case DW_OP_deref:
|
||||
printf(" DW_OP_deref\n");
|
||||
TRACE_EXPR(" DW_OP_deref\n");
|
||||
_DereferenceAddress(fContext->AddressSize());
|
||||
break;
|
||||
case DW_OP_deref_size:
|
||||
printf(" DW_OP_deref_size\n");
|
||||
TRACE_EXPR(" DW_OP_deref_size\n");
|
||||
_DereferenceAddress(fDataReader.Read<uint8>(0));
|
||||
break;
|
||||
case DW_OP_xderef:
|
||||
printf(" DW_OP_xderef\n");
|
||||
TRACE_EXPR(" DW_OP_xderef\n");
|
||||
_DereferenceAddressSpaceAddress(fContext->AddressSize());
|
||||
break;
|
||||
case DW_OP_xderef_size:
|
||||
printf(" DW_OP_xderef_size\n");
|
||||
TRACE_EXPR(" DW_OP_xderef_size\n");
|
||||
_DereferenceAddressSpaceAddress(fDataReader.Read<uint8>(0));
|
||||
break;
|
||||
|
||||
case DW_OP_abs:
|
||||
{
|
||||
printf(" DW_OP_abs\n");
|
||||
TRACE_EXPR(" DW_OP_abs\n");
|
||||
target_addr_t value = _Pop();
|
||||
if (fContext->AddressSize() == 4) {
|
||||
int32 signedValue = (int32)value;
|
||||
@@ -380,12 +395,12 @@ printf(" DW_OP_abs\n");
|
||||
break;
|
||||
}
|
||||
case DW_OP_and:
|
||||
printf(" DW_OP_and\n");
|
||||
TRACE_EXPR(" DW_OP_and\n");
|
||||
_Push(_Pop() & _Pop());
|
||||
break;
|
||||
case DW_OP_div:
|
||||
{
|
||||
printf(" DW_OP_div\n");
|
||||
TRACE_EXPR(" DW_OP_div\n");
|
||||
int64 top = (int64)_Pop();
|
||||
int64 second = (int64)_Pop();
|
||||
_Push(top != 0 ? second / top : 0);
|
||||
@@ -393,14 +408,14 @@ printf(" DW_OP_div\n");
|
||||
}
|
||||
case DW_OP_minus:
|
||||
{
|
||||
printf(" DW_OP_minus\n");
|
||||
TRACE_EXPR(" DW_OP_minus\n");
|
||||
target_addr_t top = _Pop();
|
||||
_Push(_Pop() - top);
|
||||
break;
|
||||
}
|
||||
case DW_OP_mod:
|
||||
{
|
||||
printf(" DW_OP_mod\n");
|
||||
TRACE_EXPR(" DW_OP_mod\n");
|
||||
// While the specs explicitly speak of signed integer division
|
||||
// for "div", nothing is mentioned for "mod".
|
||||
target_addr_t top = _Pop();
|
||||
@@ -409,12 +424,12 @@ printf(" DW_OP_mod\n");
|
||||
break;
|
||||
}
|
||||
case DW_OP_mul:
|
||||
printf(" DW_OP_mul\n");
|
||||
TRACE_EXPR(" DW_OP_mul\n");
|
||||
_Push(_Pop() * _Pop());
|
||||
break;
|
||||
case DW_OP_neg:
|
||||
{
|
||||
printf(" DW_OP_neg\n");
|
||||
TRACE_EXPR(" DW_OP_neg\n");
|
||||
if (fContext->AddressSize() == 4)
|
||||
_Push(-(int32)_Pop());
|
||||
else
|
||||
@@ -422,38 +437,38 @@ printf(" DW_OP_neg\n");
|
||||
break;
|
||||
}
|
||||
case DW_OP_not:
|
||||
printf(" DW_OP_not\n");
|
||||
TRACE_EXPR(" DW_OP_not\n");
|
||||
_Push(~_Pop());
|
||||
break;
|
||||
case DW_OP_or:
|
||||
printf(" DW_OP_or\n");
|
||||
TRACE_EXPR(" DW_OP_or\n");
|
||||
_Push(_Pop() | _Pop());
|
||||
break;
|
||||
case DW_OP_plus:
|
||||
printf(" DW_OP_plus\n");
|
||||
TRACE_EXPR(" DW_OP_plus\n");
|
||||
_Push(_Pop() + _Pop());
|
||||
break;
|
||||
case DW_OP_plus_uconst:
|
||||
printf(" DW_OP_plus_uconst\n");
|
||||
TRACE_EXPR(" DW_OP_plus_uconst\n");
|
||||
_Push(_Pop() + fDataReader.ReadUnsignedLEB128(0));
|
||||
break;
|
||||
case DW_OP_shl:
|
||||
{
|
||||
printf(" DW_OP_shl\n");
|
||||
TRACE_EXPR(" DW_OP_shl\n");
|
||||
target_addr_t top = _Pop();
|
||||
_Push(_Pop() << top);
|
||||
break;
|
||||
}
|
||||
case DW_OP_shr:
|
||||
{
|
||||
printf(" DW_OP_shr\n");
|
||||
TRACE_EXPR(" DW_OP_shr\n");
|
||||
target_addr_t top = _Pop();
|
||||
_Push(_Pop() >> top);
|
||||
break;
|
||||
}
|
||||
case DW_OP_shra:
|
||||
{
|
||||
printf(" DW_OP_shra\n");
|
||||
TRACE_EXPR(" DW_OP_shra\n");
|
||||
target_addr_t top = _Pop();
|
||||
int64 second = (int64)_Pop();
|
||||
_Push(second >= 0 ? second >> top : -(-second >> top));
|
||||
@@ -461,18 +476,18 @@ printf(" DW_OP_shra\n");
|
||||
break;
|
||||
}
|
||||
case DW_OP_xor:
|
||||
printf(" DW_OP_xor\n");
|
||||
TRACE_EXPR(" DW_OP_xor\n");
|
||||
_Push(_Pop() ^ _Pop());
|
||||
break;
|
||||
|
||||
case DW_OP_bra:
|
||||
printf(" DW_OP_bra\n");
|
||||
TRACE_EXPR(" DW_OP_bra\n");
|
||||
if (_Pop() == 0)
|
||||
break;
|
||||
// fall through
|
||||
case DW_OP_skip:
|
||||
{
|
||||
printf(" DW_OP_skip\n");
|
||||
TRACE_EXPR(" DW_OP_skip\n");
|
||||
int16 offset = fDataReader.Read<int16>(0);
|
||||
if (offset >= 0 ? offset > fDataReader.BytesRemaining()
|
||||
: -offset > fDataReader.Offset()) {
|
||||
@@ -483,45 +498,45 @@ printf(" DW_OP_skip\n");
|
||||
}
|
||||
|
||||
case DW_OP_eq:
|
||||
printf(" DW_OP_eq\n");
|
||||
TRACE_EXPR(" DW_OP_eq\n");
|
||||
_Push(_Pop() == _Pop() ? 1 : 0);
|
||||
break;
|
||||
case DW_OP_ge:
|
||||
{
|
||||
printf(" DW_OP_ge\n");
|
||||
TRACE_EXPR(" DW_OP_ge\n");
|
||||
int64 top = (int64)_Pop();
|
||||
_Push((int64)_Pop() >= top ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
case DW_OP_gt:
|
||||
{
|
||||
printf(" DW_OP_gt\n");
|
||||
TRACE_EXPR(" DW_OP_gt\n");
|
||||
int64 top = (int64)_Pop();
|
||||
_Push((int64)_Pop() > top ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
case DW_OP_le:
|
||||
{
|
||||
printf(" DW_OP_le\n");
|
||||
TRACE_EXPR(" DW_OP_le\n");
|
||||
int64 top = (int64)_Pop();
|
||||
_Push((int64)_Pop() <= top ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
case DW_OP_lt:
|
||||
{
|
||||
printf(" DW_OP_lt\n");
|
||||
TRACE_EXPR(" DW_OP_lt\n");
|
||||
int64 top = (int64)_Pop();
|
||||
_Push((int64)_Pop() < top ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
case DW_OP_ne:
|
||||
printf(" DW_OP_ne\n");
|
||||
TRACE_EXPR(" DW_OP_ne\n");
|
||||
_Push(_Pop() == _Pop() ? 1 : 0);
|
||||
break;
|
||||
|
||||
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;
|
||||
if (!fContext->GetObjectAddress(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:
|
||||
{
|
||||
printf(" DW_OP_call_frame_cfa\n");
|
||||
TRACE_EXPR(" DW_OP_call_frame_cfa\n");
|
||||
target_addr_t address;
|
||||
if (!fContext->GetFrameAddress(address))
|
||||
throw EvaluationException("failed to get frame address");
|
||||
@@ -540,7 +555,7 @@ printf(" DW_OP_call_frame_cfa\n");
|
||||
case DW_OP_fbreg:
|
||||
{
|
||||
int64 offset = fDataReader.ReadSignedLEB128(0);
|
||||
printf(" DW_OP_fbreg(%lld)\n", offset);
|
||||
TRACE_EXPR(" DW_OP_fbreg(%lld)\n", offset);
|
||||
target_addr_t address;
|
||||
if (!fContext->GetFrameBaseAddress(address)) {
|
||||
throw EvaluationException(
|
||||
@@ -551,7 +566,7 @@ printf(" DW_OP_fbreg(%lld)\n", offset);
|
||||
}
|
||||
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;
|
||||
if (!fContext->GetTLSAddress(_Pop(), address))
|
||||
throw EvaluationException("failed to get tls address");
|
||||
@@ -561,7 +576,7 @@ printf(" DW_OP_form_tls_address\n");
|
||||
|
||||
case DW_OP_regx:
|
||||
{
|
||||
printf(" DW_OP_regx\n");
|
||||
TRACE_EXPR(" DW_OP_regx\n");
|
||||
if (_piece == NULL) {
|
||||
throw EvaluationException(
|
||||
"DW_OP_regx in non-location expression");
|
||||
@@ -575,22 +590,22 @@ printf(" DW_OP_regx\n");
|
||||
|
||||
case DW_OP_bregx:
|
||||
{
|
||||
printf(" DW_OP_bregx\n");
|
||||
TRACE_EXPR(" DW_OP_bregx\n");
|
||||
uint32 reg = fDataReader.ReadUnsignedLEB128(0);
|
||||
_PushRegister(reg, fDataReader.ReadSignedLEB128(0));
|
||||
break;
|
||||
}
|
||||
|
||||
case DW_OP_call2:
|
||||
printf(" DW_OP_call2\n");
|
||||
TRACE_EXPR(" DW_OP_call2\n");
|
||||
_Call(fDataReader.Read<uint16>(0), true);
|
||||
break;
|
||||
case DW_OP_call4:
|
||||
printf(" DW_OP_call4\n");
|
||||
TRACE_EXPR(" DW_OP_call4\n");
|
||||
_Call(fDataReader.Read<uint32>(0), true);
|
||||
break;
|
||||
case DW_OP_call_ref:
|
||||
printf(" DW_OP_call_ref\n");
|
||||
TRACE_EXPR(" DW_OP_call_ref\n");
|
||||
if (fContext->AddressSize() == 4)
|
||||
_Call(fDataReader.Read<uint32>(0), false);
|
||||
else
|
||||
@@ -608,15 +623,15 @@ printf(" DW_OP_call_ref\n");
|
||||
return B_OK;
|
||||
|
||||
case DW_OP_nop:
|
||||
printf(" DW_OP_nop\n");
|
||||
TRACE_EXPR(" DW_OP_nop\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
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);
|
||||
} 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) {
|
||||
throw EvaluationException(
|
||||
"DW_OP_reg* in non-location expression");
|
||||
@@ -625,11 +640,12 @@ printf(" DW_OP_reg%u\n", opcode - DW_OP_reg0);
|
||||
return B_OK;
|
||||
} else if (opcode >= DW_OP_breg0 && opcode <= DW_OP_breg31) {
|
||||
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);
|
||||
} else {
|
||||
printf("DwarfExpressionEvaluator::_Evaluate(): unsupported "
|
||||
"opcode: %u\n", opcode);
|
||||
WARNING("DwarfExpressionEvaluator::_Evaluate(): "
|
||||
"unsupported opcode: %u\n", opcode);
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "ElfFile.h"
|
||||
#include "TagNames.h"
|
||||
#include "TargetAddressRangeList.h"
|
||||
#include "Tracing.h"
|
||||
#include "Variant.h"
|
||||
|
||||
|
||||
@@ -96,7 +97,9 @@ public:
|
||||
fFrameBasePointer);
|
||||
if (error != B_OK)
|
||||
return false;
|
||||
printf(" -> frame base: %llx\n", fFrameBasePointer);
|
||||
|
||||
TRACE_EXPR(" -> frame base: %llx\n", fFrameBasePointer);
|
||||
|
||||
_address = fFrameBasePointer;
|
||||
return true;
|
||||
}
|
||||
@@ -155,6 +158,7 @@ DwarfFile::DwarfFile()
|
||||
fDebugLineSection(NULL),
|
||||
fDebugFrameSection(NULL),
|
||||
fDebugLocationSection(NULL),
|
||||
fDebugPublicTypesSection(NULL),
|
||||
fCompilationUnits(20, true),
|
||||
fCurrentCompilationUnit(NULL),
|
||||
fFinished(false),
|
||||
@@ -176,6 +180,7 @@ DwarfFile::~DwarfFile()
|
||||
fElfFile->PutSection(fDebugLineSection);
|
||||
fElfFile->PutSection(fDebugFrameSection);
|
||||
fElfFile->PutSection(fDebugLocationSection);
|
||||
fElfFile->PutSection(fDebugPublicTypesSection);
|
||||
delete fElfFile;
|
||||
}
|
||||
|
||||
@@ -203,9 +208,8 @@ DwarfFile::Load(const char* fileName)
|
||||
fDebugInfoSection = fElfFile->GetSection(".debug_info");
|
||||
fDebugAbbrevSection = fElfFile->GetSection(".debug_abbrev");
|
||||
if (fDebugInfoSection == NULL || fDebugAbbrevSection == NULL) {
|
||||
fprintf(stderr, "DwarfManager::File::Load(\"%s\"): no "
|
||||
".debug_info, .debug_abbrev, or .debug_str section.\n",
|
||||
fileName);
|
||||
WARNING("DwarfManager::File::Load(\"%s\"): no "
|
||||
".debug_info or .debug_abbrev.\n", fileName);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
@@ -215,6 +219,8 @@ DwarfFile::Load(const char* fileName)
|
||||
fDebugLineSection = fElfFile->GetSection(".debug_line");
|
||||
fDebugFrameSection = fElfFile->GetSection(".debug_frame");
|
||||
fDebugLocationSection = fElfFile->GetSection(".debug_loc");
|
||||
// fDebugPublicTypesSection = fElfFile->GetSection(".debug_pubtypes");
|
||||
fDebugPublicTypesSection = fElfFile->GetSection(".debug_pubnames");
|
||||
|
||||
// iterate through the debug info section
|
||||
DataReader dataReader(fDebugInfoSection->Data(),
|
||||
@@ -230,7 +236,7 @@ DwarfFile::Load(const char* fileName)
|
||||
|
||||
if (unitLengthOffset + unitLength
|
||||
> (uint64)fDebugInfoSection->Size()) {
|
||||
printf("\"%s\": Invalid compilation unit length.\n", fileName);
|
||||
WARNING("\"%s\": Invalid compilation unit length.\n", fileName);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -241,23 +247,23 @@ DwarfFile::Load(const char* fileName)
|
||||
uint8 addressSize = dataReader.Read<uint8>(0);
|
||||
|
||||
if (dataReader.HasOverflow()) {
|
||||
printf("\"%s\": Unexpected end of data in compilation unit "
|
||||
WARNING("\"%s\": Unexpected end of data in compilation unit "
|
||||
"header.\n", fileName);
|
||||
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,
|
||||
version, unitLength, abbrevOffset, addressSize);
|
||||
|
||||
if (version != 2 && version != 3) {
|
||||
printf("\"%s\": Unsupported compilation unit version: %d\n",
|
||||
WARNING("\"%s\": Unsupported compilation unit version: %d\n",
|
||||
fileName, version);
|
||||
break;
|
||||
}
|
||||
|
||||
if (addressSize != 4 && addressSize != 8) {
|
||||
printf("\"%s\": Unsupported address size: %d\n", fileName,
|
||||
WARNING("\"%s\": Unsupported address size: %d\n", fileName,
|
||||
addressSize);
|
||||
break;
|
||||
}
|
||||
@@ -304,6 +310,8 @@ DwarfFile::FinishLoading()
|
||||
return fFinishError = error;
|
||||
}
|
||||
|
||||
_ParsePublicTypesInfo();
|
||||
|
||||
fFinished = true;
|
||||
return B_OK;
|
||||
}
|
||||
@@ -358,7 +366,7 @@ DwarfFile::ResolveRangeList(CompilationUnit* unit, uint64 offset) const
|
||||
|
||||
TargetAddressRangeList* ranges = new(std::nothrow) TargetAddressRangeList;
|
||||
if (ranges == NULL) {
|
||||
fprintf(stderr, "Out of memory.\n");
|
||||
ERROR("Out of memory.\n");
|
||||
return NULL;
|
||||
}
|
||||
Reference<TargetAddressRangeList> rangesReference(ranges, true);
|
||||
@@ -384,7 +392,7 @@ DwarfFile::ResolveRangeList(CompilationUnit* unit, uint64 offset) const
|
||||
continue;
|
||||
|
||||
if (!ranges->AddRange(baseAddress + start, end - start)) {
|
||||
fprintf(stderr, "Out of memory.\n");
|
||||
ERROR("Out of memory.\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -402,7 +410,7 @@ DwarfFile::UnwindCallFrame(CompilationUnit* unit,
|
||||
if (fDebugFrameSection == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
printf("DwarfFile::UnwindCallFrame(%#llx)\n", location);
|
||||
TRACE_CFI("DwarfFile::UnwindCallFrame(%#llx)\n", location);
|
||||
|
||||
DataReader dataReader((uint8*)fDebugFrameSection->Data(),
|
||||
fDebugFrameSection->Size(), unit->AddressSize());
|
||||
@@ -435,8 +443,10 @@ printf("DwarfFile::UnwindCallFrame(%#llx)\n", location);
|
||||
- (dataReader.Offset() - lengthOffset);
|
||||
if (remaining < 0)
|
||||
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);
|
||||
uint32 registerCount = outputInterface->CountRegisters();
|
||||
@@ -471,7 +481,7 @@ initialLocation, addressRange);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
printf(" found row!\n");
|
||||
TRACE_CFI(" found row!\n");
|
||||
|
||||
// apply the rules of the final row
|
||||
// get the frameAddress first
|
||||
@@ -504,11 +514,13 @@ printf(" found row!\n");
|
||||
default:
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
printf(" frame address: %#llx\n", frameAddress);
|
||||
|
||||
TRACE_CFI(" frame address: %#llx\n", frameAddress);
|
||||
|
||||
// apply the register rules
|
||||
for (uint32 i = 0; i < registerCount; i++) {
|
||||
printf(" reg %lu\n", i);
|
||||
TRACE_CFI(" reg %lu\n", i);
|
||||
|
||||
uint32 valueType = outputInterface->RegisterValueType(i);
|
||||
if (valueType == 0)
|
||||
continue;
|
||||
@@ -521,7 +533,8 @@ printf(" reg %lu\n", i);
|
||||
switch (rule->Type()) {
|
||||
case CFA_RULE_SAME_VALUE:
|
||||
{
|
||||
printf(" -> CFA_RULE_SAME_VALUE\n");
|
||||
TRACE_CFI(" -> CFA_RULE_SAME_VALUE\n");
|
||||
|
||||
BVariant value;
|
||||
if (inputInterface->GetRegisterValue(i, value))
|
||||
outputInterface->SetRegisterValue(i, value);
|
||||
@@ -529,7 +542,9 @@ printf(" -> CFA_RULE_SAME_VALUE\n");
|
||||
}
|
||||
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;
|
||||
if (inputInterface->ReadValueFromMemory(
|
||||
frameAddress + rule->Offset(), valueType,
|
||||
@@ -539,13 +554,15 @@ printf(" -> CFA_RULE_LOCATION_OFFSET: %lld\n", rule->Offset());
|
||||
break;
|
||||
}
|
||||
case CFA_RULE_VALUE_OFFSET:
|
||||
printf(" -> CFA_RULE_VALUE_OFFSET\n");
|
||||
TRACE_CFI(" -> CFA_RULE_VALUE_OFFSET\n");
|
||||
|
||||
outputInterface->SetRegisterValue(i,
|
||||
frameAddress + rule->Offset());
|
||||
break;
|
||||
case CFA_RULE_REGISTER:
|
||||
{
|
||||
printf(" -> CFA_RULE_REGISTER\n");
|
||||
TRACE_CFI(" -> CFA_RULE_REGISTER\n");
|
||||
|
||||
BVariant value;
|
||||
if (inputInterface->GetRegisterValue(
|
||||
rule->Register(), value)) {
|
||||
@@ -555,7 +572,8 @@ printf(" -> CFA_RULE_REGISTER\n");
|
||||
}
|
||||
case CFA_RULE_LOCATION_EXPRESSION:
|
||||
{
|
||||
printf(" -> CFA_RULE_LOCATION_EXPRESSION\n");
|
||||
TRACE_CFI(" -> CFA_RULE_LOCATION_EXPRESSION\n");
|
||||
|
||||
target_addr_t address;
|
||||
error = EvaluateExpression(unit, subprogramEntry,
|
||||
rule->Expression().block,
|
||||
@@ -572,7 +590,8 @@ printf(" -> CFA_RULE_LOCATION_EXPRESSION\n");
|
||||
}
|
||||
case CFA_RULE_VALUE_EXPRESSION:
|
||||
{
|
||||
printf(" -> CFA_RULE_VALUE_EXPRESSION\n");
|
||||
TRACE_CFI(" -> CFA_RULE_VALUE_EXPRESSION\n");
|
||||
|
||||
target_addr_t value;
|
||||
error = EvaluateExpression(unit, subprogramEntry,
|
||||
rule->Expression().block,
|
||||
@@ -584,7 +603,7 @@ printf(" -> CFA_RULE_VALUE_EXPRESSION\n");
|
||||
break;
|
||||
}
|
||||
case CFA_RULE_UNDEFINED:
|
||||
printf(" -> CFA_RULE_UNDEFINED\n");
|
||||
TRACE_CFI(" -> CFA_RULE_UNDEFINED\n");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -782,21 +801,22 @@ DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
|
||||
|
||||
DIECompileUnitBase* unitEntry = dynamic_cast<DIECompileUnitBase*>(entry);
|
||||
if (unitEntry == NULL) {
|
||||
fprintf(stderr, "No compilation unit entry in .debug_info "
|
||||
"section.\n");
|
||||
WARNING("No compilation unit entry in .debug_info section.\n");
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
unit->SetUnitEntry(unitEntry);
|
||||
|
||||
printf("remaining bytes in unit: %lld\n", dataReader.BytesRemaining());
|
||||
if (dataReader.HasData()) {
|
||||
printf(" ");
|
||||
while (dataReader.HasData()) {
|
||||
printf("%02x", dataReader.Read<uint8>(0));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
TRACE_DIE_ONLY(
|
||||
TRACE_DIE("remaining bytes in unit: %lld\n",
|
||||
dataReader.BytesRemaining());
|
||||
if (dataReader.HasData()) {
|
||||
TRACE_DIE(" ");
|
||||
while (dataReader.HasData())
|
||||
TRACE_DIE("%02x", dataReader.Read<uint8>(0));
|
||||
TRACE_DIE("\n");
|
||||
}
|
||||
)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -812,7 +832,7 @@ DwarfFile::_ParseDebugInfoEntry(DataReader& dataReader,
|
||||
uint32 code = dataReader.ReadUnsignedLEB128(0);
|
||||
if (code == 0) {
|
||||
if (dataReader.HasOverflow()) {
|
||||
fprintf(stderr, "Unexpected end of .debug_info section.\n");
|
||||
WARNING("Unexpected end of .debug_info section.\n");
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
_entry = NULL;
|
||||
@@ -823,12 +843,9 @@ DwarfFile::_ParseDebugInfoEntry(DataReader& dataReader,
|
||||
// get the corresponding abbreviation entry
|
||||
AbbreviationEntry 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;
|
||||
}
|
||||
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;
|
||||
status_t error = fDebugInfoFactory.CreateDebugInfoEntry(
|
||||
@@ -837,6 +854,11 @@ abbreviationEntry.Tag(), abbreviationEntry.HasChildren());
|
||||
return error;
|
||||
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);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
@@ -864,7 +886,7 @@ abbreviationEntry.Tag(), abbreviationEntry.HasChildren());
|
||||
childEntry->SetParent(entry);
|
||||
} else if (error == ENTRY_NOT_HANDLED) {
|
||||
error = B_OK;
|
||||
printf("%*s -> child unhandled\n", level * 2, "");
|
||||
TRACE_DIE("%*s -> child unhandled\n", level * 2, "");
|
||||
}
|
||||
|
||||
if (error != B_OK) {
|
||||
@@ -890,7 +912,8 @@ printf("%*s -> child unhandled\n", level * 2, "");
|
||||
status_t
|
||||
DwarfFile::_FinishCompilationUnit(CompilationUnit* unit)
|
||||
{
|
||||
printf("\nfinishing compilation unit %p\n", unit);
|
||||
TRACE_DIE("\nfinishing compilation unit %p\n", unit);
|
||||
|
||||
AbbreviationTable* abbreviationTable = unit->GetAbbreviationTable();
|
||||
|
||||
DataReader dataReader(
|
||||
@@ -905,7 +928,8 @@ printf("\nfinishing compilation unit %p\n", unit);
|
||||
DebugInfoEntry* entry;
|
||||
off_t 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
|
||||
dataReader.SeekAbsolute(offset);
|
||||
@@ -920,7 +944,7 @@ printf("entry %p at %lld\n", entry, offset);
|
||||
// initialization before setting the attributes
|
||||
status_t error = entry->InitAfterHierarchy(entryInitInfo);
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "Init after hierarchy failed!\n");
|
||||
WARNING("Init after hierarchy failed!\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -933,7 +957,7 @@ printf("entry %p at %lld\n", entry, offset);
|
||||
// initialization after setting the attributes
|
||||
error = entry->InitAfterAttributes(entryInitInfo);
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "Init after attributes failed!\n");
|
||||
WARNING("Init after attributes failed!\n");
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@@ -1028,15 +1052,13 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
||||
? (off_t)dataReader.Read<uint64>(0)
|
||||
: (off_t)dataReader.Read<uint32>(0);
|
||||
if (offset >= fDebugStringSection->Size()) {
|
||||
fprintf(stderr, "Invalid DW_FORM_strp offset: %lld\n",
|
||||
offset);
|
||||
WARNING("Invalid DW_FORM_strp offset: %lld\n", offset);
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
attributeValue.SetToString(
|
||||
(const char*)fDebugStringSection->Data() + offset);
|
||||
} else {
|
||||
fprintf(stderr, "Invalid DW_FORM_strp: no string "
|
||||
"section!\n");
|
||||
WARNING("Invalid DW_FORM_strp: no string section!\n");
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
break;
|
||||
@@ -1067,8 +1089,7 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
||||
break;
|
||||
case DW_FORM_indirect:
|
||||
default:
|
||||
fprintf(stderr, "Unsupported attribute form: %lu\n",
|
||||
attributeForm);
|
||||
WARNING("Unsupported attribute form: %lu\n", attributeForm);
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
@@ -1077,7 +1098,7 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
||||
uint8 attributeClass = get_attribute_class(attributeName,
|
||||
attributeForm);
|
||||
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),
|
||||
attributeName, get_attribute_form_name(attributeForm),
|
||||
attributeForm);
|
||||
@@ -1120,12 +1141,12 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
||||
if (attributeName == DW_AT_sibling)
|
||||
continue;
|
||||
|
||||
fprintf(stderr, "Failed to resolve reference: "
|
||||
"%s (%#lx) %s (%#lx): value: %llu\n",
|
||||
get_attribute_name_name(attributeName),
|
||||
attributeName,
|
||||
get_attribute_form_name(attributeForm),
|
||||
attributeForm, value);
|
||||
WARNING("Failed to resolve reference: %s (%#lx) "
|
||||
"%s (%#lx): value: %llu\n",
|
||||
get_attribute_name_name(attributeName),
|
||||
attributeName,
|
||||
get_attribute_form_name(attributeForm),
|
||||
attributeForm, value);
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
@@ -1137,15 +1158,19 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
||||
}
|
||||
|
||||
if (dataReader.HasOverflow()) {
|
||||
fprintf(stderr, "Unexpected end of .debug_info section.\n");
|
||||
WARNING("Unexpected end of .debug_info section.\n");
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
// add the attribute
|
||||
if (entry != NULL) {
|
||||
char buffer[1024];
|
||||
printf(" attr %s %s (%d): %s\n", get_attribute_name_name(attributeName),
|
||||
get_attribute_form_name(attributeForm), attributeClass, attributeValue.ToString(buffer, sizeof(buffer)));
|
||||
TRACE_DIE_ONLY(
|
||||
char buffer[1024];
|
||||
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
|
||||
= get_attribute_name_setter(attributeName);
|
||||
@@ -1155,19 +1180,17 @@ get_attribute_form_name(attributeForm), attributeClass, attributeValue.ToString(
|
||||
|
||||
if (error == ATTRIBUTE_NOT_HANDLED) {
|
||||
error = B_OK;
|
||||
printf(" -> unhandled\n");
|
||||
TRACE_DIE(" -> unhandled\n");
|
||||
}
|
||||
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "Failed to set attribute: name: %s, "
|
||||
"form: %s: %s\n",
|
||||
WARNING("Failed to set attribute: name: %s, form: %s: %s\n",
|
||||
get_attribute_name_name(attributeName),
|
||||
get_attribute_form_name(attributeForm),
|
||||
strerror(error));
|
||||
}
|
||||
}
|
||||
else
|
||||
printf(" -> no attribute setter!\n");
|
||||
} else
|
||||
TRACE_DIE(" -> no attribute setter!\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1179,7 +1202,8 @@ status_t
|
||||
DwarfFile::_ParseLineInfo(CompilationUnit* unit)
|
||||
{
|
||||
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,
|
||||
fDebugLineSection->Size() - offset, unit->AddressSize());
|
||||
@@ -1227,40 +1251,42 @@ printf("DwarfFile::_ParseLineInfo(%p), offset: %lld\n", unit, offset);
|
||||
if (version != 2 && version != 3)
|
||||
return B_UNSUPPORTED;
|
||||
|
||||
printf(" unitLength: %llu\n", unitLength);
|
||||
printf(" version: %u\n", version);
|
||||
printf(" headerLength: %llu\n", headerLength);
|
||||
printf(" minInstructionLength: %u\n", minInstructionLength);
|
||||
printf(" defaultIsStatement: %d\n", defaultIsStatement);
|
||||
printf(" lineBase: %d\n", lineBase);
|
||||
printf(" lineRange: %u\n", lineRange);
|
||||
printf(" opcodeBase: %u\n", opcodeBase);
|
||||
TRACE_LINES(" unitLength: %llu\n", unitLength);
|
||||
TRACE_LINES(" version: %u\n", version);
|
||||
TRACE_LINES(" headerLength: %llu\n", headerLength);
|
||||
TRACE_LINES(" minInstructionLength: %u\n", minInstructionLength);
|
||||
TRACE_LINES(" defaultIsStatement: %d\n", defaultIsStatement);
|
||||
TRACE_LINES(" lineBase: %d\n", lineBase);
|
||||
TRACE_LINES(" lineRange: %u\n", lineRange);
|
||||
TRACE_LINES(" opcodeBase: %u\n", opcodeBase);
|
||||
|
||||
// include directories
|
||||
printf(" include directories:\n");
|
||||
TRACE_LINES(" include directories:\n");
|
||||
while (const char* directory = dataReader.ReadString()) {
|
||||
if (*directory == '\0')
|
||||
break;
|
||||
printf(" \"%s\"\n", directory);
|
||||
TRACE_LINES(" \"%s\"\n", directory);
|
||||
|
||||
if (!unit->AddDirectory(directory))
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
// file names
|
||||
printf(" files:\n");
|
||||
TRACE_LINES(" files:\n");
|
||||
while (const char* file = dataReader.ReadString()) {
|
||||
if (*file == '\0')
|
||||
break;
|
||||
uint64 dirIndex = dataReader.ReadUnsignedLEB128(0);
|
||||
uint64 modificationTime = dataReader.ReadUnsignedLEB128(0);
|
||||
uint64 fileLength = dataReader.ReadUnsignedLEB128(0);
|
||||
TRACE_LINES_ONLY(uint64 modificationTime =)
|
||||
dataReader.ReadUnsignedLEB128(0);
|
||||
TRACE_LINES_ONLY(uint64 fileLength =)
|
||||
dataReader.ReadUnsignedLEB128(0);
|
||||
|
||||
if (dataReader.HasOverflow())
|
||||
return B_BAD_DATA;
|
||||
|
||||
printf(" \"%s\", dir index: %llu, mtime: %llu, length: %llu\n", file,
|
||||
dirIndex, modificationTime, fileLength);
|
||||
TRACE_LINES(" \"%s\", dir index: %llu, mtime: %llu, length: %llu\n",
|
||||
file, dirIndex, modificationTime, fileLength);
|
||||
|
||||
if (!unit->AddFile(file, dirIndex))
|
||||
return B_NO_MEMORY;
|
||||
@@ -1311,10 +1337,11 @@ DwarfFile::_ParseCIE(CompilationUnit* unit, CfaContext& context,
|
||||
context.SetCodeAlignment(dataReader.ReadUnsignedLEB128(0));
|
||||
context.SetDataAlignment(dataReader.ReadSignedLEB128(0));
|
||||
context.SetReturnAddressRegister(dataReader.ReadUnsignedLEB128(0));
|
||||
printf(" cie: length: %llu, version: %u, augmentation: \"%s\", "
|
||||
"aligment: code: %lu, data: %ld, return address reg: %lu\n",
|
||||
length, version, augmentation, context.CodeAlignment(), context.DataAlignment(),
|
||||
context.ReturnAddressRegister());
|
||||
|
||||
TRACE_CFI(" cie: length: %llu, version: %u, augmentation: \"%s\", "
|
||||
"aligment: code: %lu, data: %ld, return address reg: %lu\n", length,
|
||||
version, augmentation, context.CodeAlignment(), context.DataAlignment(),
|
||||
context.ReturnAddressRegister());
|
||||
|
||||
if (dataReader.HasOverflow())
|
||||
return B_BAD_DATA;
|
||||
@@ -1340,7 +1367,8 @@ DwarfFile::_ParseFrameInfoInstructions(CompilationUnit* unit,
|
||||
instructionSize, unit->AddressSize());
|
||||
|
||||
while (dataReader.BytesRemaining() > 0) {
|
||||
printf(" [%2lld]", dataReader.BytesRemaining());
|
||||
TRACE_CFI(" [%2lld]", dataReader.BytesRemaining());
|
||||
|
||||
uint8 opcode = dataReader.Read<uint8>(0);
|
||||
if ((opcode >> 6) != 0) {
|
||||
uint32 operand = opcode & 0x3f;
|
||||
@@ -1348,7 +1376,8 @@ printf(" [%2lld]", dataReader.BytesRemaining());
|
||||
switch (opcode >> 6) {
|
||||
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()
|
||||
+ operand * context.CodeAlignment();
|
||||
if (location > context.TargetLocation())
|
||||
@@ -1359,7 +1388,9 @@ printf(" DW_CFA_advance_loc: %#lx\n", operand);
|
||||
case DW_CFA_offset:
|
||||
{
|
||||
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)) {
|
||||
rule->SetToLocationOffset(
|
||||
offset * context.DataAlignment());
|
||||
@@ -1368,7 +1399,8 @@ printf(" DW_CFA_offset: reg: %lu, offset: %llu\n", operand, offset);
|
||||
}
|
||||
case DW_CFA_restore:
|
||||
{
|
||||
printf(" DW_CFA_restore: %#lx\n", operand);
|
||||
TRACE_CFI(" DW_CFA_restore: %#lx\n", operand);
|
||||
|
||||
context.RestoreRegisterRule(operand);
|
||||
break;
|
||||
}
|
||||
@@ -1377,13 +1409,15 @@ printf(" DW_CFA_restore: %#lx\n", operand);
|
||||
switch (opcode) {
|
||||
case DW_CFA_nop:
|
||||
{
|
||||
printf(" DW_CFA_nop\n");
|
||||
TRACE_CFI(" DW_CFA_nop\n");
|
||||
break;
|
||||
}
|
||||
case DW_CFA_set_loc:
|
||||
{
|
||||
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())
|
||||
return B_BAD_VALUE;
|
||||
if (location > context.TargetLocation())
|
||||
@@ -1394,7 +1428,9 @@ printf(" DW_CFA_set_loc: %#llx\n", location);
|
||||
case DW_CFA_advance_loc1:
|
||||
{
|
||||
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()
|
||||
+ delta * context.CodeAlignment();
|
||||
if (location > context.TargetLocation())
|
||||
@@ -1405,7 +1441,9 @@ printf(" DW_CFA_advance_loc1: %#lx\n", delta);
|
||||
case DW_CFA_advance_loc2:
|
||||
{
|
||||
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()
|
||||
+ delta * context.CodeAlignment();
|
||||
if (location > context.TargetLocation())
|
||||
@@ -1416,7 +1454,9 @@ printf(" DW_CFA_advance_loc2: %#lx\n", delta);
|
||||
case DW_CFA_advance_loc4:
|
||||
{
|
||||
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()
|
||||
+ delta * context.CodeAlignment();
|
||||
if (location > context.TargetLocation())
|
||||
@@ -1428,7 +1468,10 @@ printf(" DW_CFA_advance_loc4: %#lx\n", delta);
|
||||
{
|
||||
uint32 reg = 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)) {
|
||||
rule->SetToLocationOffset(
|
||||
offset * context.DataAlignment());
|
||||
@@ -1438,14 +1481,18 @@ printf(" DW_CFA_offset_extended: reg: %lu, offset: %llu\n", reg, offset);
|
||||
case DW_CFA_restore_extended:
|
||||
{
|
||||
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);
|
||||
break;
|
||||
}
|
||||
case DW_CFA_undefined:
|
||||
{
|
||||
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))
|
||||
rule->SetToUndefined();
|
||||
break;
|
||||
@@ -1453,7 +1500,9 @@ printf(" DW_CFA_undefined: %lu\n", reg);
|
||||
case DW_CFA_same_value:
|
||||
{
|
||||
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))
|
||||
rule->SetToSameValue();
|
||||
break;
|
||||
@@ -1462,14 +1511,17 @@ printf(" DW_CFA_same_value: %lu\n", reg);
|
||||
{
|
||||
uint32 reg1 = 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))
|
||||
rule->SetToValueOffset(reg2);
|
||||
break;
|
||||
}
|
||||
case DW_CFA_remember_state:
|
||||
{
|
||||
printf(" DW_CFA_remember_state\n");
|
||||
TRACE_CFI(" DW_CFA_remember_state\n");
|
||||
|
||||
status_t error = context.PushRuleSet();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
@@ -1477,7 +1529,8 @@ printf(" DW_CFA_remember_state\n");
|
||||
}
|
||||
case DW_CFA_restore_state:
|
||||
{
|
||||
printf(" DW_CFA_restore_state\n");
|
||||
TRACE_CFI(" DW_CFA_restore_state\n");
|
||||
|
||||
status_t error = context.PopRuleSet();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
@@ -1487,14 +1540,19 @@ printf(" DW_CFA_restore_state\n");
|
||||
{
|
||||
uint32 reg = 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);
|
||||
break;
|
||||
}
|
||||
case DW_CFA_def_cfa_register:
|
||||
{
|
||||
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()
|
||||
!= CFA_CFA_RULE_REGISTER_OFFSET) {
|
||||
return B_BAD_DATA;
|
||||
@@ -1505,7 +1563,9 @@ printf(" DW_CFA_def_cfa_register: %lu\n", reg);
|
||||
case DW_CFA_def_cfa_offset:
|
||||
{
|
||||
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()
|
||||
!= CFA_CFA_RULE_REGISTER_OFFSET) {
|
||||
return B_BAD_DATA;
|
||||
@@ -1518,7 +1578,10 @@ printf(" DW_CFA_def_cfa_offset: %llu\n", offset);
|
||||
uint8* block = (uint8*)dataReader.Data();
|
||||
uint64 blockLength = dataReader.ReadUnsignedLEB128(0);
|
||||
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,
|
||||
blockLength);
|
||||
break;
|
||||
@@ -1529,7 +1592,10 @@ printf(" DW_CFA_def_cfa_expression: %p, %llu\n", block, blockLength);
|
||||
uint8* block = (uint8*)dataReader.Data();
|
||||
uint64 blockLength = dataReader.ReadUnsignedLEB128(0);
|
||||
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))
|
||||
rule->SetToLocationExpression(block, blockLength);
|
||||
break;
|
||||
@@ -1538,7 +1604,10 @@ printf(" DW_CFA_expression: reg: %lu, block: %p, %llu\n", reg, block, blockLe
|
||||
{
|
||||
uint32 reg = dataReader.ReadUnsignedLEB128(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)) {
|
||||
rule->SetToLocationOffset(
|
||||
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);
|
||||
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,
|
||||
offset * (int32)context.DataAlignment());
|
||||
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:
|
||||
{
|
||||
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()
|
||||
!= CFA_CFA_RULE_REGISTER_OFFSET) {
|
||||
return B_BAD_DATA;
|
||||
@@ -1570,7 +1644,10 @@ printf(" DW_CFA_def_cfa_offset: %lld\n", offset);
|
||||
{
|
||||
uint32 reg = 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)) {
|
||||
rule->SetToValueOffset(
|
||||
offset * context.DataAlignment());
|
||||
@@ -1581,7 +1658,10 @@ printf(" DW_CFA_val_offset: reg: %lu, offset: %llu\n", reg, offset);
|
||||
{
|
||||
uint32 reg = dataReader.ReadUnsignedLEB128(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)) {
|
||||
rule->SetToValueOffset(
|
||||
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();
|
||||
uint64 blockLength = dataReader.ReadUnsignedLEB128(0);
|
||||
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))
|
||||
rule->SetToValueExpression(block, blockLength);
|
||||
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:
|
||||
{
|
||||
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()
|
||||
+ delta * context.CodeAlignment();
|
||||
if (location > context.TargetLocation())
|
||||
@@ -1615,15 +1700,18 @@ printf(" DW_CFA_MIPS_advance_loc8: %#llx\n", delta);
|
||||
case DW_CFA_GNU_window_save:
|
||||
{
|
||||
// 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!
|
||||
break;
|
||||
}
|
||||
case DW_CFA_GNU_args_size:
|
||||
{
|
||||
// Updates the total size of arguments on the stack.
|
||||
uint64 size = dataReader.ReadUnsignedLEB128(0);
|
||||
printf(" DW_CFA_GNU_args_size: %llu\n", size);
|
||||
TRACE_CFI_ONLY(uint64 size =)
|
||||
dataReader.ReadUnsignedLEB128(0);
|
||||
|
||||
TRACE_CFI(" DW_CFA_GNU_args_size: %llu\n", size);
|
||||
// TODO: Implement!
|
||||
break;
|
||||
}
|
||||
@@ -1632,7 +1720,10 @@ printf(" DW_CFA_MIPS_advance_loc8: %#llx\n", delta);
|
||||
// obsolete
|
||||
uint32 reg = dataReader.ReadUnsignedLEB128(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)) {
|
||||
rule->SetToLocationOffset(
|
||||
offset * (int32)context.DataAlignment());
|
||||
@@ -1641,7 +1732,7 @@ printf(" DW_CFA_GNU_negative_offset_extended: reg: %lu, offset: %lld\n", reg,
|
||||
}
|
||||
|
||||
default:
|
||||
printf(" unknown opcode %u!\n", opcode);
|
||||
WARNING(" unknown opcode %u!\n", opcode);
|
||||
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
|
||||
DwarfFile::_GetAbbreviationTable(off_t offset, AbbreviationTable*& _table)
|
||||
{
|
||||
|
||||
@@ -110,6 +110,10 @@ private:
|
||||
off_t instructionOffset,
|
||||
off_t instructionSize);
|
||||
|
||||
status_t _ParsePublicTypesInfo();
|
||||
status_t _ParsePublicTypesInfo(DataReader& dataReader,
|
||||
bool dwarf64);
|
||||
|
||||
status_t _GetAbbreviationTable(off_t offset,
|
||||
AbbreviationTable*& _table);
|
||||
|
||||
@@ -139,6 +143,7 @@ private:
|
||||
ElfSection* fDebugLineSection;
|
||||
ElfSection* fDebugFrameSection;
|
||||
ElfSection* fDebugLocationSection;
|
||||
ElfSection* fDebugPublicTypesSection;
|
||||
AbbreviationTableList fAbbreviationTables;
|
||||
DebugInfoEntryFactory fDebugInfoFactory;
|
||||
CompilationUnitList fCompilationUnits;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#define DWARF_TARGET_INTERFACE_H
|
||||
|
||||
|
||||
#include <Referenceable.h>
|
||||
#include <Variant.h>
|
||||
|
||||
#include "Types.h"
|
||||
@@ -14,7 +15,7 @@
|
||||
class Register;
|
||||
|
||||
|
||||
class DwarfTargetInterface {
|
||||
class DwarfTargetInterface : public Referenceable {
|
||||
public:
|
||||
virtual ~DwarfTargetInterface();
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "Dwarf.h"
|
||||
#include "Tracing.h"
|
||||
|
||||
|
||||
static const uint8 kLineNumberStandardOpcodeOperands[]
|
||||
@@ -48,7 +49,8 @@ LineNumberProgram::Init(const void* program, size_t programSize,
|
||||
kLineNumberStandardOpcodeCount);
|
||||
for (uint8 i = 0; i < standardOpcodeCount; 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;
|
||||
}
|
||||
}
|
||||
@@ -143,7 +145,7 @@ LineNumberProgram::GetNextRow(State& state) const
|
||||
state.instructionSet = dataReader.ReadUnsignedLEB128(0);
|
||||
break;
|
||||
default:
|
||||
printf("unsupported standard opcode %u\n", opcode);
|
||||
WARNING("unsupported standard opcode %u\n", opcode);
|
||||
for (int32 i = 0; i < fStandardOpcodeLengths[opcode - 1];
|
||||
i++) {
|
||||
dataReader.ReadUnsignedLEB128(0);
|
||||
@@ -174,7 +176,8 @@ printf("unsupported standard opcode %u\n", opcode);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("unsupported extended opcode: %u\n", extendedOpcode);
|
||||
WARNING("unsupported extended opcode: %u\n",
|
||||
extendedOpcode);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
|
||||
#include "Tracing.h"
|
||||
|
||||
|
||||
// #pragma mark - ElfSection
|
||||
|
||||
@@ -129,20 +131,17 @@ ElfFile::Init(const char* fileName)
|
||||
// open file
|
||||
fFD = open(fileName, O_RDONLY);
|
||||
if (fFD < 0) {
|
||||
fprintf(stderr, "Failed to open \"%s\": %s\n", fileName,
|
||||
strerror(errno));
|
||||
WARNING("Failed to open \"%s\": %s\n", fileName, strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
|
||||
// stat() file to get its size
|
||||
struct stat st;
|
||||
if (fstat(fFD, &st) < 0) {
|
||||
fprintf(stderr, "Failed to stat \"%s\": %s\n", fileName,
|
||||
strerror(errno));
|
||||
WARNING("Failed to stat \"%s\": %s\n", fileName, strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
fFileSize = st.st_size;
|
||||
printf("fFileSize: %lld\n", fFileSize);
|
||||
|
||||
// read the elf header
|
||||
fElfHeader = (Elf32_Ehdr*)malloc(sizeof(Elf32_Ehdr));
|
||||
@@ -155,7 +154,7 @@ printf("fFileSize: %lld\n", fFileSize);
|
||||
|
||||
// check the ELF header
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -165,10 +164,9 @@ printf("fFileSize: %lld\n", fFileSize);
|
||||
int sectionCount = fElfHeader->e_shnum;
|
||||
size_t sectionHeaderTableSize = sectionHeaderSize * sectionCount;
|
||||
if (!_CheckRange(sectionHeadersOffset, sectionHeaderTableSize)) {
|
||||
fprintf(stderr, "\"%s\": Invalid ELF header\n", fileName);
|
||||
WARNING("\"%s\": Invalid ELF header\n", fileName);
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
printf("sectionHeaderTable: %lld\n", sectionHeadersOffset);
|
||||
|
||||
// read the section header table
|
||||
uint8* sectionHeaderTable = (uint8*)malloc(sectionHeaderTableSize);
|
||||
@@ -186,11 +184,10 @@ printf("sectionHeaderTable: %lld\n", sectionHeadersOffset);
|
||||
+ fElfHeader->e_shstrndx * sectionHeaderSize);
|
||||
if (!_CheckRange(stringSectionHeader->sh_offset,
|
||||
stringSectionHeader->sh_size)) {
|
||||
fprintf(stderr, "\"%s\": Invalid string section header\n", fileName);
|
||||
WARNING("\"%s\": Invalid string section header\n", fileName);
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
size_t sectionStringSize = stringSectionHeader->sh_size;
|
||||
printf("sectionStrings: %ld\n", stringSectionHeader->sh_offset);
|
||||
|
||||
ElfSection* sectionStringSection = new(std::nothrow) ElfSection(".shstrtab",
|
||||
fFD, stringSectionHeader->sh_offset, sectionStringSize);
|
||||
@@ -230,10 +227,9 @@ printf("sectionStrings: %ld\n", stringSectionHeader->sh_offset);
|
||||
int segmentCount = fElfHeader->e_phnum;
|
||||
size_t programHeaderTableSize = programHeaderSize * segmentCount;
|
||||
if (!_CheckRange(programHeadersOffset, programHeaderTableSize)) {
|
||||
fprintf(stderr, "\"%s\": Invalid ELF header\n", fileName);
|
||||
WARNING("\"%s\": Invalid ELF header\n", fileName);
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
printf("programHeaderTable: %lld\n", programHeadersOffset);
|
||||
|
||||
// read the program header table
|
||||
uint8* programHeaderTable = (uint8*)malloc(programHeaderTableSize);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "Image.h"
|
||||
#include "ImageDebugInfo.h"
|
||||
#include "LocatableFile.h"
|
||||
#include "Tracing.h"
|
||||
|
||||
|
||||
// #pragma mark - FunctionsTableModel
|
||||
@@ -346,7 +347,8 @@ ImageFunctionsView::SetImageDebugInfo(ImageDebugInfo* imageDebugInfo)
|
||||
{
|
||||
if (imageDebugInfo == fImageDebugInfo)
|
||||
return;
|
||||
printf("ImageFunctionsView::SetImageDebugInfo(%p)\n", imageDebugInfo);
|
||||
|
||||
TRACE_GUI("ImageFunctionsView::SetImageDebugInfo(%p)\n", imageDebugInfo);
|
||||
|
||||
if (fImageDebugInfo != NULL)
|
||||
fImageDebugInfo->RemoveReference();
|
||||
@@ -369,14 +371,16 @@ printf("ImageFunctionsView::SetImageDebugInfo(%p)\n", imageDebugInfo);
|
||||
if (fImageDebugInfo != NULL)
|
||||
fFunctionsTable->ResizeAllColumnsToPreferred();
|
||||
|
||||
printf("ImageFunctionsView::SetImageDebugInfo(%p) done\n", imageDebugInfo);
|
||||
TRACE_GUI("ImageFunctionsView::SetImageDebugInfo(%p) done\n",
|
||||
imageDebugInfo);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ImageFunctionsView::SetFunction(FunctionInstance* function)
|
||||
{
|
||||
printf("ImageFunctionsView::SetFunction(%p)\n", function);
|
||||
TRACE_GUI("ImageFunctionsView::SetFunction(%p)\n", function);
|
||||
|
||||
TreeTablePath path;
|
||||
if (fFunctionsTableModel->GetFunctionPath(function, path)) {
|
||||
fFunctionsTable->SetNodeExpanded(path, true, true);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <ObjectList.h>
|
||||
|
||||
#include "table/TableColumns.h"
|
||||
#include "Tracing.h"
|
||||
|
||||
|
||||
enum {
|
||||
@@ -181,7 +182,8 @@ ImageListView::SetImage(Image* image)
|
||||
{
|
||||
if (image == fImage)
|
||||
return;
|
||||
printf("ImageListView::SetImage(%p)\n", image);
|
||||
|
||||
TRACE_GUI("ImageListView::SetImage(%p)\n", image);
|
||||
|
||||
if (fImage != NULL)
|
||||
fImage->RemoveReference();
|
||||
@@ -194,14 +196,16 @@ printf("ImageListView::SetImage(%p)\n", image);
|
||||
for (int32 i = 0; Image* other = fImagesTableModel->ImageAt(i); i++) {
|
||||
if (fImage == other) {
|
||||
fImagesTable->SelectRow(i, false);
|
||||
printf("ImageListView::SetImage() done\n");
|
||||
|
||||
TRACE_GUI("ImageListView::SetImage() done\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fImagesTable->DeselectAllRows();
|
||||
printf("ImageListView::SetImage() done\n");
|
||||
|
||||
TRACE_GUI("ImageListView::SetImage() done\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "StackTrace.h"
|
||||
#include "Statement.h"
|
||||
#include "Team.h"
|
||||
#include "Tracing.h"
|
||||
|
||||
|
||||
static const int32 kLeftTextMargin = 3;
|
||||
@@ -1670,7 +1671,8 @@ SourceView::UnsetListener()
|
||||
void
|
||||
SourceView::SetStackTrace(StackTrace* stackTrace)
|
||||
{
|
||||
printf("SourceView::SetStackTrace(%p)\n", stackTrace);
|
||||
TRACE_GUI("SourceView::SetStackTrace(%p)\n", stackTrace);
|
||||
|
||||
if (stackTrace == fStackTrace)
|
||||
return;
|
||||
|
||||
@@ -1758,7 +1760,8 @@ SourceView::UserBreakpointChanged(target_addr_t address)
|
||||
bool
|
||||
SourceView::ScrollToAddress(target_addr_t address)
|
||||
{
|
||||
printf("SourceView::ScrollToAddress(%#llx)\n", address);
|
||||
TRACE_GUI("SourceView::ScrollToAddress(%#llx)\n", address);
|
||||
|
||||
if (fSourceCode == NULL)
|
||||
return false;
|
||||
|
||||
@@ -1779,7 +1782,8 @@ printf("SourceView::ScrollToAddress(%#llx)\n", address);
|
||||
bool
|
||||
SourceView::ScrollToLine(uint32 line)
|
||||
{
|
||||
printf("SourceView::ScrollToLine(%lu)\n", line);
|
||||
TRACE_GUI("SourceView::ScrollToLine(%lu)\n", line);
|
||||
|
||||
if (fSourceCode == NULL || line >= (uint32)fSourceCode->CountLines())
|
||||
return false;
|
||||
|
||||
@@ -1787,17 +1791,18 @@ printf("SourceView::ScrollToLine(%lu)\n", line);
|
||||
float bottom = top + fFontInfo.lineHeight - 1;
|
||||
|
||||
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
|
||||
// least one more line is visible.
|
||||
if (top >= visible.bottom || bottom <= visible.top)
|
||||
{
|
||||
printf(" -> scrolling to (%f, %f)\n", visible.left, top - (visible.Height() + 1) / 2);
|
||||
if (top >= visible.bottom || bottom <= visible.top) {
|
||||
TRACE_GUI(" -> scrolling to (%f, %f)\n", 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);
|
||||
else if (bottom + fFontInfo.lineHeight > visible.bottom)
|
||||
ScrollBy(0, bottom + fFontInfo.lineHeight - visible.bottom);
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "RegistersView.h"
|
||||
#include "StackTrace.h"
|
||||
#include "StackTraceView.h"
|
||||
#include "Tracing.h"
|
||||
#include "TypeComponentPath.h"
|
||||
#include "Variable.h"
|
||||
|
||||
@@ -361,8 +362,10 @@ TeamWindow::UserBreakpointChanged(const Team::BreakpointEvent& event)
|
||||
void
|
||||
TeamWindow::FunctionSourceCodeChanged(Function* function)
|
||||
{
|
||||
printf("TeamWindow::FunctionSourceCodeChanged(%p): source: %p, state: %d\n",
|
||||
function, function->GetSourceCode(), function->SourceCodeState());
|
||||
TRACE_GUI("TeamWindow::FunctionSourceCodeChanged(%p): source: %p, "
|
||||
"state: %d\n", function, function->GetSourceCode(),
|
||||
function->SourceCodeState());
|
||||
|
||||
PostMessage(MSG_FUNCTION_SOURCE_CODE_CHANGED);
|
||||
}
|
||||
|
||||
@@ -807,7 +810,8 @@ TeamWindow::_HandleStackFrameValueRetrieved(StackFrame* stackFrame,
|
||||
void
|
||||
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
|
||||
if (fActiveImage == NULL || imageID != fActiveImage->ID())
|
||||
return;
|
||||
@@ -816,7 +820,9 @@ printf("TeamWindow::_HandleImageDebugInfoChanged(%ld)\n", imageID);
|
||||
|
||||
ImageDebugInfo* imageDebugInfo = fActiveImage != NULL
|
||||
? fActiveImage->GetImageDebugInfo() : NULL;
|
||||
printf(" image debug info: %p\n", imageDebugInfo);
|
||||
|
||||
TRACE_GUI(" image debug info: %p\n", imageDebugInfo);
|
||||
|
||||
Reference<ImageDebugInfo> imageDebugInfoReference(imageDebugInfo);
|
||||
// hold a reference until we've set it
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "StackFrameValues.h"
|
||||
#include "Team.h"
|
||||
#include "Thread.h"
|
||||
#include "Tracing.h"
|
||||
#include "TypeComponentPath.h"
|
||||
#include "Variable.h"
|
||||
|
||||
@@ -32,7 +33,8 @@ public:
|
||||
fVariable(variable),
|
||||
fPath(path),
|
||||
fName(name),
|
||||
fType(type)
|
||||
fType(type),
|
||||
fChildrenAdded(false)
|
||||
{
|
||||
fVariable->AcquireReference();
|
||||
fPath->AcquireReference();
|
||||
@@ -108,6 +110,16 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChildrenAdded() const
|
||||
{
|
||||
return fChildrenAdded;
|
||||
}
|
||||
|
||||
void SetChildrenAdded(bool added)
|
||||
{
|
||||
fChildrenAdded = added;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef BObjectList<ValueNode> ChildList;
|
||||
|
||||
@@ -119,6 +131,7 @@ private:
|
||||
Type* fType;
|
||||
BVariant fValue;
|
||||
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:
|
||||
typedef BObjectList<ValueNode> ValueList;
|
||||
|
||||
@@ -340,6 +360,157 @@ private:
|
||||
delete node;
|
||||
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
|
||||
@@ -353,15 +524,32 @@ private:
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
|
||||
// now walk along the path, finding the respective child node for each
|
||||
// component
|
||||
// Now walk along the path, finding the respective child node for each
|
||||
// component (might be several components at once).
|
||||
int32 componentCount = path->CountComponents();
|
||||
for (int32 i = 0; i < componentCount; i++) {
|
||||
for (int32 i = 0; i < componentCount;) {
|
||||
ValueNode* childNode = NULL;
|
||||
TypeComponent typeComponent = path->ComponentAt(i);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
VariablesView::_Init()
|
||||
{
|
||||
fVariableTable = new TreeTable("variable list", 0, B_FANCY_BORDER);
|
||||
AddChild(fVariableTable->ToView());
|
||||
fVariableTable->SetSortingEnabled(false);
|
||||
|
||||
// columns
|
||||
fVariableTable->AddColumn(new StringTableColumn(0, "Variable", 80, 40, 1000,
|
||||
@@ -510,8 +724,7 @@ VariablesView::_RequestVariableValue(Variable* variable)
|
||||
return;
|
||||
Reference<TypeComponentPath> pathReference(path, true);
|
||||
|
||||
fListener->StackFrameValueRequested(fThread, fStackFrame,
|
||||
variable, path);
|
||||
fListener->StackFrameValueRequested(fThread, fStackFrame, variable, path);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -34,6 +34,11 @@ public:
|
||||
Variable* variable,
|
||||
TypeComponentPath* path);
|
||||
|
||||
private:
|
||||
// TreeTableListener
|
||||
virtual void TreeTableNodeExpandedChanged(TreeTable* table,
|
||||
const TreeTablePath& path, bool expanded);
|
||||
|
||||
private:
|
||||
class ValueNode;
|
||||
class VariableValueColumn;
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "CpuState.h"
|
||||
#include "FunctionInstance.h"
|
||||
#include "Image.h"
|
||||
#include "StackFrameDebugInfo.h"
|
||||
#include "StackFrameValueInfos.h"
|
||||
#include "StackFrameValues.h"
|
||||
#include "Variable.h"
|
||||
|
||||
@@ -18,18 +20,22 @@
|
||||
|
||||
|
||||
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),
|
||||
fCpuState(cpuState),
|
||||
fFrameAddress(frameAddress),
|
||||
fInstructionPointer(instructionPointer),
|
||||
fReturnAddress(0),
|
||||
fDebugInfo(debugInfo),
|
||||
fImage(NULL),
|
||||
fFunction(NULL),
|
||||
fValues(NULL)
|
||||
fValues(NULL),
|
||||
fValueInfos(NULL)
|
||||
{
|
||||
fCpuState->AcquireReference();
|
||||
fDebugInfo->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +49,8 @@ StackFrame::~StackFrame()
|
||||
|
||||
SetImage(NULL);
|
||||
SetFunction(NULL);
|
||||
|
||||
fDebugInfo->ReleaseReference();
|
||||
fCpuState->ReleaseReference();
|
||||
}
|
||||
|
||||
@@ -50,11 +58,25 @@ StackFrame::~StackFrame()
|
||||
status_t
|
||||
StackFrame::Init()
|
||||
{
|
||||
// create values map
|
||||
fValues = new(std::nothrow) StackFrameValues;
|
||||
if (fValues == NULL)
|
||||
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 Image;
|
||||
class FunctionInstance;
|
||||
class StackFrameDebugInfo;
|
||||
class StackFrameValueInfos;
|
||||
class StackFrameValues;
|
||||
class TypeComponentPath;
|
||||
class Variable;
|
||||
@@ -39,7 +41,8 @@ public:
|
||||
StackFrame(stack_frame_type type,
|
||||
CpuState* cpuState,
|
||||
target_addr_t frameAddress,
|
||||
target_addr_t instructionPointer);
|
||||
target_addr_t instructionPointer,
|
||||
StackFrameDebugInfo* debugInfo);
|
||||
~StackFrame();
|
||||
|
||||
status_t Init();
|
||||
@@ -47,6 +50,7 @@ public:
|
||||
stack_frame_type Type() const { return fType; }
|
||||
CpuState* GetCpuState() const { return fCpuState; }
|
||||
target_addr_t FrameAddress() const { return fFrameAddress; }
|
||||
StackFrameDebugInfo* DebugInfo() const { return fDebugInfo; }
|
||||
|
||||
target_addr_t InstructionPointer() const
|
||||
{ return fInstructionPointer; }
|
||||
@@ -68,7 +72,8 @@ public:
|
||||
Variable* LocalVariableAt(int32 index) const;
|
||||
bool AddLocalVariable(Variable* variable);
|
||||
|
||||
StackFrameValues* Values() const { return fValues; }
|
||||
StackFrameValues* Values() const { return fValues; }
|
||||
StackFrameValueInfos* ValueInfos() const { return fValueInfos; }
|
||||
|
||||
// team lock must be held
|
||||
void AddListener(Listener* listener);
|
||||
@@ -87,11 +92,13 @@ private:
|
||||
target_addr_t fFrameAddress;
|
||||
target_addr_t fInstructionPointer;
|
||||
target_addr_t fReturnAddress;
|
||||
StackFrameDebugInfo* fDebugInfo;
|
||||
Image* fImage;
|
||||
FunctionInstance* fFunction;
|
||||
VariableList fParameters;
|
||||
VariableList fLocalVariables;
|
||||
StackFrameValues* fValues;
|
||||
StackFrameValueInfos* fValueInfos;
|
||||
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 "Statement.h"
|
||||
#include "TeamDebugInfo.h"
|
||||
#include "Tracing.h"
|
||||
|
||||
|
||||
// #pragma mark - BreakpointByAddressPredicate
|
||||
@@ -365,30 +366,28 @@ status_t
|
||||
Team::GetStatementAtAddress(target_addr_t address, FunctionInstance*& _function,
|
||||
Statement*& _statement)
|
||||
{
|
||||
printf("Team::GetStatementAtAddress(%#llx)\n", address);
|
||||
TRACE_CODE("Team::GetStatementAtAddress(%#llx)\n", address);
|
||||
|
||||
// get the image at the address
|
||||
Image* image = ImageByAddress(address);
|
||||
if (image == NULL)
|
||||
{
|
||||
printf(" -> no image\n");
|
||||
if (image == NULL) {
|
||||
TRACE_CODE(" -> no image\n");
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
ImageDebugInfo* imageDebugInfo = image->GetImageDebugInfo();
|
||||
if (imageDebugInfo == NULL)
|
||||
{
|
||||
printf(" -> no image debug info\n");
|
||||
if (imageDebugInfo == NULL) {
|
||||
TRACE_CODE(" -> no image debug info\n");
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
// get the function
|
||||
FunctionInstance* functionInstance
|
||||
= imageDebugInfo->FunctionAtAddress(address);
|
||||
if (functionInstance == NULL)
|
||||
{
|
||||
printf(" -> no function instance\n");
|
||||
if (functionInstance == NULL) {
|
||||
TRACE_CODE(" -> no function instance\n");
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
// If the function instance has disassembled code attached, we can get the
|
||||
// statement directly.
|
||||
@@ -408,11 +407,10 @@ printf(" -> no function instance\n");
|
||||
= functionInstance->GetFunctionDebugInfo();
|
||||
status_t error = functionDebugInfo->GetSpecificImageDebugInfo()
|
||||
->GetStatement(functionDebugInfo, address, _statement);
|
||||
if (error != B_OK)
|
||||
{
|
||||
printf(" -> no statement from the specific image debug info\n");
|
||||
if (error != B_OK) {
|
||||
TRACE_CODE(" -> no statement from the specific image debug info\n");
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
_function = functionInstance;
|
||||
return B_OK;
|
||||
@@ -423,7 +421,9 @@ status_t
|
||||
Team::GetStatementAtSourceLocation(SourceCode* sourceCode,
|
||||
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 (DisassembledCode* code = dynamic_cast<DisassembledCode*>(sourceCode)) {
|
||||
Statement* statement = code->StatementAtLocation(location);
|
||||
|
||||
@@ -7,6 +7,14 @@
|
||||
#include "Type.h"
|
||||
|
||||
|
||||
// #pragma mark - BaseType
|
||||
|
||||
|
||||
BaseType::~BaseType()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - DataMember
|
||||
|
||||
|
||||
|
||||
@@ -39,6 +39,14 @@ enum {
|
||||
class Type;
|
||||
|
||||
|
||||
class BaseType : public Referenceable {
|
||||
public:
|
||||
virtual ~BaseType();
|
||||
|
||||
virtual Type* GetType() const = 0;
|
||||
};
|
||||
|
||||
|
||||
class DataMember : public Referenceable {
|
||||
public:
|
||||
virtual ~DataMember();
|
||||
@@ -54,6 +62,7 @@ public:
|
||||
|
||||
virtual const char* Name() 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 int32 CountBaseTypes() const = 0;
|
||||
virtual BaseType* BaseTypeAt(int32 index) const = 0;
|
||||
|
||||
virtual int32 CountDataMembers() const = 0;
|
||||
virtual DataMember* DataMemberAt(int32 index) const = 0;
|
||||
};
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#include "TypeComponentPath.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
#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
|
||||
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
|
||||
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::operator=(const TypeComponentPath& other)
|
||||
{
|
||||
|
||||
@@ -78,6 +78,8 @@ struct TypeComponent {
|
||||
|
||||
uint32 HashValue() const;
|
||||
|
||||
void Dump() const;
|
||||
|
||||
TypeComponent& operator=(const TypeComponent& other)
|
||||
|
||||
{
|
||||
@@ -110,8 +112,14 @@ public:
|
||||
bool AddComponent(const TypeComponent& component);
|
||||
void Clear();
|
||||
|
||||
TypeComponentPath* CreateSubPath(int32 componentCount) const;
|
||||
// returns a new object (or NULL when out
|
||||
// of memory)
|
||||
|
||||
uint32 HashValue() const;
|
||||
|
||||
void Dump() const;
|
||||
|
||||
TypeComponentPath& operator=(const TypeComponentPath& other);
|
||||
|
||||
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
|
||||
ValueLocation::Clear()
|
||||
{
|
||||
|
||||
@@ -80,6 +80,9 @@ public:
|
||||
ValueLocation(const ValuePieceLocation& piece);
|
||||
ValueLocation(const ValueLocation& other);
|
||||
|
||||
bool SetTo(const ValueLocation& other,
|
||||
uint64 bitOffset, uint64 bitSize);
|
||||
|
||||
void Clear();
|
||||
bool AddPiece(const ValuePieceLocation& piece);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user