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