From 67e0301477b06c7be20198f96580e13a024a81d4 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Wed, 7 Dec 2016 23:55:36 -0500 Subject: [PATCH] Debugger: Adjustments to report generator. DebugReportGenerator: - Due to the changes made with respect to correctly handling switching to disassembly explicitly, the report generator needs to request loading source files as it walks the stack trace in order to get source-based line number information. Fixes crash reports having -1 as the line number in cases where debug information was available, but the user hadn't yet looked at the source file in question. LoadSourceCodeJob: - Cleanup. --- .../controllers/DebugReportGenerator.cpp | 59 +++++++++++++++++-- .../controllers/DebugReportGenerator.h | 1 + src/kits/debugger/jobs/LoadSourceCodeJob.cpp | 11 ++-- 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/src/kits/debugger/controllers/DebugReportGenerator.cpp b/src/kits/debugger/controllers/DebugReportGenerator.cpp index e9cd33c24d..0d6ef1023b 100644 --- a/src/kits/debugger/controllers/DebugReportGenerator.cpp +++ b/src/kits/debugger/controllers/DebugReportGenerator.cpp @@ -22,6 +22,7 @@ #include "DisassembledCode.h" #include "FunctionInstance.h" #include "Image.h" +#include "ImageDebugInfo.h" #include "MessageCodes.h" #include "Register.h" #include "SemaphoreInfo.h" @@ -64,6 +65,7 @@ DebugReportGenerator::DebugReportGenerator(::Team* team, fCurrentBlock(NULL), fBlockRetrievalStatus(B_OK), fTraceWaitingThread(NULL), + fSourceWaitForDisassembly(false), fSourceWaitingFunction(NULL) { fTeam->AddListener(this); @@ -221,11 +223,22 @@ 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); + function_source_state state; + if (fSourceWaitForDisassembly) + state = function->FirstInstance()->SourceCodeState(); + else + state = function->SourceCodeState(); + + switch (state) { + case FUNCTION_SOURCE_LOADED: + case FUNCTION_SOURCE_SUPPRESSED: + case FUNCTION_SOURCE_UNAVAILABLE: + { + release_sem(fTeamDataSem); + // fall through + } + default: + break; } } } @@ -517,7 +530,39 @@ DebugReportGenerator::_DumpDebuggedThreadInfo(BFile& _output, BString sourcePath; target_addr_t ip = frame->InstructionPointer(); - FunctionInstance* functionInstance; + Image* image = fTeam->ImageByAddress(ip); + FunctionInstance* functionInstance = NULL; + if (image != NULL && image->ImageDebugInfoState() + == IMAGE_DEBUG_INFO_LOADED) { + ImageDebugInfo* info = image->GetImageDebugInfo(); + functionInstance = info->FunctionAtAddress(ip); + } + + if (functionInstance != NULL) { + Function* function = functionInstance->GetFunction(); + if (function->SourceCodeState() == FUNCTION_SOURCE_NOT_LOADED + && functionInstance->SourceCodeState() + == FUNCTION_SOURCE_NOT_LOADED) { + fSourceWaitingFunction = function; + fSourceWaitForDisassembly = false; + fSourceWaitingFunction->AddListener(this); + fListener->FunctionSourceCodeRequested(functionInstance); + + locker.Unlock(); + + do { + error = acquire_sem(fTeamDataSem); + } while (error == B_INTERRUPTED); + + if (error != B_OK) + break; + + locker.Lock(); + + fSourceWaitingFunction->RemoveListener(this); + } + } + Statement* statement; if (fTeam->GetStatementAtAddress(ip, functionInstance, statement) == B_OK) { @@ -634,6 +679,7 @@ DebugReportGenerator::_DumpFunctionDisassembly(BFile& _output, // function has been loaded, but the disassembly has not. function->AddListener(this); fSourceWaitingFunction = function; + fSourceWaitForDisassembly = true; fListener->FunctionSourceCodeRequested(instance, true); // fall through case FUNCTION_SOURCE_LOADING: @@ -647,6 +693,7 @@ DebugReportGenerator::_DumpFunctionDisassembly(BFile& _output, return error; teamLocker.Lock(); + fSourceWaitingFunction->RemoveListener(this); break; } default: diff --git a/src/kits/debugger/controllers/DebugReportGenerator.h b/src/kits/debugger/controllers/DebugReportGenerator.h index e88d62f2d7..b8d50df45c 100644 --- a/src/kits/debugger/controllers/DebugReportGenerator.h +++ b/src/kits/debugger/controllers/DebugReportGenerator.h @@ -103,6 +103,7 @@ private: TeamMemoryBlock* fCurrentBlock; status_t fBlockRetrievalStatus; ::Thread* fTraceWaitingThread; + bool fSourceWaitForDisassembly; Function* fSourceWaitingFunction; }; diff --git a/src/kits/debugger/jobs/LoadSourceCodeJob.cpp b/src/kits/debugger/jobs/LoadSourceCodeJob.cpp index 517ee64e0f..a014686c36 100644 --- a/src/kits/debugger/jobs/LoadSourceCodeJob.cpp +++ b/src/kits/debugger/jobs/LoadSourceCodeJob.cpp @@ -91,14 +91,15 @@ LoadSourceCodeJob::Do() // explicitly asked for disassembly. This needs to be done first // since Function will clear the disassembled code states of all // its child instances. + function_source_state state + = fLoadForFunction ? FUNCTION_SOURCE_LOADED + : FUNCTION_SOURCE_SUPPRESSED; if (function->SourceCodeState() == FUNCTION_SOURCE_LOADED) { - FileSourceCode* sourceCode = function->GetSourceCode(); - function->SetSourceCode(sourceCode, - FUNCTION_SOURCE_SUPPRESSED); + FileSourceCode* functionSourceCode = function->GetSourceCode(); + function->SetSourceCode(functionSourceCode, state); } - fFunctionInstance->SetSourceCode(sourceCode, - FUNCTION_SOURCE_SUPPRESSED); + fFunctionInstance->SetSourceCode(sourceCode, state); sourceCode->ReleaseReference(); } } else