From 92d6655640a788eea5faacbabe1aaed78da7ee11 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Sun, 15 Sep 2013 15:32:19 +0200 Subject: [PATCH] Debugger: Implement #9960. - DebugReportGenerator now retrieves and dumps disassembly for the crashing function up to the crashing line. --- .../controllers/DebugReportGenerator.cpp | 87 ++++++++++++++++++- .../controllers/DebugReportGenerator.h | 9 +- 2 files changed, 92 insertions(+), 4 deletions(-) diff --git a/src/apps/debugger/controllers/DebugReportGenerator.cpp b/src/apps/debugger/controllers/DebugReportGenerator.cpp index 66ac0f2966..60cdba9026 100644 --- a/src/apps/debugger/controllers/DebugReportGenerator.cpp +++ b/src/apps/debugger/controllers/DebugReportGenerator.cpp @@ -18,12 +18,15 @@ #include "AreaInfo.h" #include "CpuState.h" #include "DebuggerInterface.h" +#include "DisassembledCode.h" +#include "FunctionInstance.h" #include "Image.h" #include "MessageCodes.h" #include "Register.h" #include "SemaphoreInfo.h" #include "StackFrame.h" #include "StackTrace.h" +#include "Statement.h" #include "StringUtils.h" #include "SystemInfo.h" #include "Team.h" @@ -51,7 +54,8 @@ DebugReportGenerator::DebugReportGenerator(::Team* team, fWaitingNode(NULL), fCurrentBlock(NULL), fBlockRetrievalStatus(B_OK), - fTraceWaitingThread(NULL) + fTraceWaitingThread(NULL), + fSourceWaitingFunction(NULL) { fTeam->AddListener(this); fArchitecture->AcquireReference(); @@ -204,6 +208,20 @@ DebugReportGenerator::ValueNodeValueChanged(ValueNode* node) } +void +DebugReportGenerator::FunctionSourceCodeChanged(Function* function) +{ + AutoLocker< ::Team> teamLocker(fTeam); + if (function == fSourceWaitingFunction) { + if (function->FirstInstance()->SourceCodeState() + == FUNCTION_SOURCE_LOADED + || function->FirstInstance()->SourceCodeState() + == FUNCTION_SOURCE_UNAVAILABLE) { + release_sem(fTeamDataSem); + } + } +} + status_t DebugReportGenerator::_GenerateReportHeader(BString& _output) { @@ -452,9 +470,12 @@ DebugReportGenerator::_DumpDebuggedThreadInfo(BString& _output, && frame->CountLocalVariables() == 0) { // only dump the topmost frame if (i == 0) { + locker.Unlock(); + _DumpFunctionDisassembly(_output, frame->InstructionPointer()); _DumpStackFrameMemory(_output, thread->GetCpuState(), frame->FrameAddress(), thread->GetTeam()->GetArchitecture() ->StackGrowthDirection()); + locker.Lock(); } continue; } @@ -495,6 +516,66 @@ DebugReportGenerator::_DumpDebuggedThreadInfo(BString& _output, } +void +DebugReportGenerator::_DumpFunctionDisassembly(BString& _output, + target_addr_t instructionPointer) +{ + AutoLocker< ::Team> teamLocker(fTeam); + BString data; + FunctionInstance* instance = NULL; + Statement* statement = NULL; + status_t error = fTeam->GetStatementAtAddress(instructionPointer, instance, + statement); + if (error != B_OK) { + data.SetToFormat("Unable to retrieve disassembly for IP %#" B_PRIx64 + ": %s\n", instructionPointer, strerror(error)); + _output << data; + return; + } + + DisassembledCode* code = instance->GetSourceCode(); + Function* function = instance->GetFunction(); + if (code == NULL) { + switch (function->SourceCodeState()) { + case FUNCTION_SOURCE_NOT_LOADED: + function->AddListener(this); + fSourceWaitingFunction = function; + fListener->FunctionSourceCodeRequested(instance, true); + // fall through + case FUNCTION_SOURCE_LOADING: + { + teamLocker.Unlock(); + error = acquire_sem(fTeamDataSem); + if (error != B_OK) + return; + teamLocker.Lock(); + break; + } + default: + return; + } + + if (instance->SourceCodeState() == FUNCTION_SOURCE_UNAVAILABLE) + return; + + error = fTeam->GetStatementAtAddress(instructionPointer, instance, + statement); + code = instance->GetSourceCode(); + } + + SourceLocation location = statement->StartSourceLocation(); + + _output << "\t\t\tDisassembly:\n"; + for (int32 i = 0; i < location.Line(); i++) { + _output << "\t\t\t\t" << code->LineAt(i); + if (i == location.Line() - 1) + _output << " <--"; + _output << "\n"; + } + _output << "\n"; +} + + void DebugReportGenerator::_DumpStackFrameMemory(BString& _output, CpuState* state, target_addr_t framePointer, uint8 stackDirection) @@ -519,11 +600,11 @@ DebugReportGenerator::_DumpStackFrameMemory(BString& _output, _output << "\t\t\tFrame memory:\n"; if (fBlockRetrievalStatus == B_OK) { - UiUtils::DumpMemory(_output, 3, fCurrentBlock, startAddress, 1, 16, + UiUtils::DumpMemory(_output, 4 , fCurrentBlock, startAddress, 1, 16, endAddress - startAddress); } else { BString data; - data.SetToFormat("\t\t\tUnavailable (%s)\n", strerror( + data.SetToFormat("\t\t\t\tUnavailable (%s)\n", strerror( fBlockRetrievalStatus)); _output += data; } diff --git a/src/apps/debugger/controllers/DebugReportGenerator.h b/src/apps/debugger/controllers/DebugReportGenerator.h index 13746e9502..121bb5a20c 100644 --- a/src/apps/debugger/controllers/DebugReportGenerator.h +++ b/src/apps/debugger/controllers/DebugReportGenerator.h @@ -8,6 +8,7 @@ #include +#include "Function.h" #include "Team.h" #include "TeamMemoryBlock.h" #include "ValueNodeContainer.h" @@ -30,7 +31,8 @@ class ValueNodeManager; class DebugReportGenerator : public BLooper, private Team::Listener, - private TeamMemoryBlock::Listener, private ValueNodeContainer::Listener { + private TeamMemoryBlock::Listener, private ValueNodeContainer::Listener, + private Function::Listener { public: DebugReportGenerator(::Team* team, UserInterfaceListener* listener, @@ -58,6 +60,8 @@ private: // ValueNodeContainer::Listener virtual void ValueNodeValueChanged(ValueNode* node); + // Function::Listener + virtual void FunctionSourceCodeChanged(Function* function); private: status_t _GenerateReport(const entry_ref& outputPath); @@ -68,6 +72,8 @@ private: status_t _DumpRunningThreads(BString& _output); status_t _DumpDebuggedThreadInfo(BString& _output, ::Thread* thread); + void _DumpFunctionDisassembly(BString& _output, + target_addr_t instructionPointer); void _DumpStackFrameMemory(BString& _output, CpuState* state, target_addr_t framePointer, @@ -97,6 +103,7 @@ private: TeamMemoryBlock* fCurrentBlock; status_t fBlockRetrievalStatus; ::Thread* fTraceWaitingThread; + Function* fSourceWaitingFunction; }; #endif // DEBUG_REPORT_GENERATOR_H