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