Debugger: Implement #9960.

- DebugReportGenerator now retrieves and dumps disassembly for the crashing
  function up to the crashing line.
This commit is contained in:
Rene Gollent 2013-09-15 15:32:19 +02:00
parent c75ca47d05
commit 02cac49250
2 changed files with 92 additions and 4 deletions

View File

@ -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;
}

View File

@ -8,6 +8,7 @@
#include <Looper.h>
#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