From b1975a590faee9dc91f0a6bc626bc5d84475eb24 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Sat, 22 Jun 2013 12:52:52 -0400 Subject: [PATCH] Implement #9775. - When possible, SourceView now adds a context menu option to switch between source and disassembly. If the disassembled code is not yet available, it is asynchronously requested. Adjusted SourceView::Listener and implementing subclasses accordingly to make that request feasible. - Adjust TeamWindow to correctly deal with the possibility of the function source code being available but not loaded. --- .../gui/team_window/SourceView.cpp | 79 ++++++++++++++++++- .../gui/team_window/SourceView.h | 5 ++ .../gui/team_window/TeamWindow.cpp | 27 +++++-- .../gui/team_window/TeamWindow.h | 3 + 4 files changed, 105 insertions(+), 9 deletions(-) diff --git a/src/apps/debugger/user_interface/gui/team_window/SourceView.cpp b/src/apps/debugger/user_interface/gui/team_window/SourceView.cpp index e385a99f9f..4f6f1e8f0e 100644 --- a/src/apps/debugger/user_interface/gui/team_window/SourceView.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/SourceView.cpp @@ -59,6 +59,7 @@ static const char* kEnableBreakpointMessage = "Click to enable breakpoint at " "line %" B_PRId32 "."; static const uint32 MSG_OPEN_SOURCE_FILE = 'mosf'; +static const uint32 MSG_SWITCH_DISASSEMBLY_STATE = 'msds'; static const char* kTrackerSignature = "application/x-vnd.Be-TRAK"; @@ -1758,13 +1759,51 @@ SourceView::TextView::_ScrollToBottom(void) bool SourceView::TextView::_AddGeneralActions(BPopUpMenu* menu, int32 line) { - BMessage* message = new(std::nothrow) BMessage(MSG_OPEN_SOURCE_FILE); + if (fSourceCode == NULL) + return true; + + BMessage* message = NULL; + if (fSourceCode->GetSourceFile() != NULL) { + message = new(std::nothrow) BMessage(MSG_OPEN_SOURCE_FILE); + if (message == NULL) + return false; + message->AddInt32("line", line); + + if (!_AddGeneralActionItem(menu, "Open source file", message)) + return false; + } + + if (fSourceView->fStackFrame == NULL) + return true; + + FunctionInstance* instance = fSourceView->fStackFrame->Function(); + if (instance == NULL) + return true; + + FileSourceCode* code = instance->GetFunction()->GetSourceCode(); + + // if we only have disassembly, this option doesn't apply. + if (code == NULL) + return true; + + // verify that we do in fact know the source file of the function, + // since we can't switch to it if it wasn't found and hasn't been + // located. + BString sourcePath; + code->GetSourceFile()->GetLocatedPath(sourcePath); + if (sourcePath.IsEmpty()) + return true; + + message = new(std::nothrow) BMessage( + MSG_SWITCH_DISASSEMBLY_STATE); if (message == NULL) return false; - message->AddInt32("line", line); - if (!_AddGeneralActionItem(menu, "Open source file", message)) + if (!_AddGeneralActionItem(menu, dynamic_cast( + fSourceCode) != NULL ? "Show source" : "Show disassembly", + message)) { return false; + } return true; } @@ -1938,6 +1977,40 @@ SourceView::MessageReceived(BMessage* message) break; } + case MSG_SWITCH_DISASSEMBLY_STATE: + { + if (fStackFrame == NULL) + break; + + FunctionInstance* instance = fStackFrame->Function(); + if (instance == NULL) + break; + + SourceCode* code = NULL; + if (dynamic_cast(fSourceCode) != NULL) { + if (instance->SourceCodeState() + == FUNCTION_SOURCE_NOT_LOADED) { + fListener->FunctionSourceCodeRequested(instance, true); + break; + } + + code = instance->GetSourceCode(); + } else { + Function* function = instance->GetFunction(); + if (function->SourceCodeState() + == FUNCTION_SOURCE_NOT_LOADED) { + fListener->FunctionSourceCodeRequested(instance, false); + break; + } + + code = function->GetSourceCode(); + } + + if (code != NULL) + SetSourceCode(code); + break; + } + default: BView::MessageReceived(message); break; diff --git a/src/apps/debugger/user_interface/gui/team_window/SourceView.h b/src/apps/debugger/user_interface/gui/team_window/SourceView.h index efe25e6f71..df4132bf6f 100644 --- a/src/apps/debugger/user_interface/gui/team_window/SourceView.h +++ b/src/apps/debugger/user_interface/gui/team_window/SourceView.h @@ -1,5 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2013, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef SOURCE_VIEW_H @@ -13,6 +14,7 @@ class Breakpoint; +class FunctionInstance; class SourceCode; class StackFrame; class StackTrace; @@ -106,6 +108,9 @@ public: target_addr_t address) = 0; virtual void ThreadActionRequested(Thread* thread, uint32 action, target_addr_t address) = 0; + virtual void FunctionSourceCodeRequested( + FunctionInstance* function, + bool forceDisassembly) = 0; }; diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp index 7401b12842..7b456474d6 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp @@ -363,7 +363,9 @@ TeamWindow::MessageReceived(BMessage* message) if (fActiveFunction != NULL && fActiveFunction->GetFunctionDebugInfo() ->SourceFile() != NULL && fActiveSourceCode != NULL - && fActiveSourceCode->GetSourceFile() == NULL) { + && fActiveSourceCode->GetSourceFile() == NULL + && fActiveFunction->GetFunction()->SourceCodeState() + != FUNCTION_SOURCE_NOT_LOADED) { try { if (fFilePanel == NULL) { fFilePanel = new BFilePanel(B_OPEN_PANEL, @@ -694,6 +696,14 @@ TeamWindow::ThreadActionRequested(::Thread* thread, uint32 action, } +void +TeamWindow::FunctionSourceCodeRequested(FunctionInstance* function, + bool forceDisassembly) +{ + fListener->FunctionSourceCodeRequested(function, forceDisassembly); +} + + void TeamWindow::SetWatchpointEnabledRequested(Watchpoint* watchpoint, bool enabled) @@ -1248,15 +1258,17 @@ TeamWindow::_UpdateSourcePathState() if (sourceFile != NULL && !sourceFile->GetLocatedPath(sourceText)) sourceFile->GetPath(sourceText); - if (fActiveSourceCode->GetSourceFile() == NULL && sourceFile != NULL) { + if (fActiveFunction->GetFunction()->SourceCodeState() + != FUNCTION_SOURCE_NOT_LOADED + && fActiveSourceCode->GetSourceFile() == NULL + && sourceFile != NULL) { sourceText.Prepend("Click to locate source file '"); sourceText += "'"; truncatedText = sourceText; fSourcePathView->TruncateString(&truncatedText, B_TRUNCATE_MIDDLE, fSourcePathView->Bounds().Width()); - } else if (sourceFile != NULL) { + } else if (sourceFile != NULL) sourceText.Prepend("File: "); - } } if (!truncatedText.IsEmpty() && truncatedText != sourceText) { @@ -1408,8 +1420,11 @@ TeamWindow::_HandleSourceCodeChanged() // get a reference to the source code AutoLocker< ::Team> locker(fTeam); - SourceCode* sourceCode = fActiveFunction->GetFunction()->GetSourceCode(); - if (sourceCode == NULL) + SourceCode* sourceCode = NULL; + if (fActiveFunction->GetFunction()->SourceCodeState() + == FUNCTION_SOURCE_LOADED) { + sourceCode = fActiveFunction->GetFunction()->GetSourceCode(); + } else sourceCode = fActiveFunction->GetSourceCode(); BReference sourceCodeReference(sourceCode); diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h index 7ccb5af0ab..d734d068f8 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h @@ -110,6 +110,9 @@ private: target_addr_t address); virtual void ThreadActionRequested(::Thread* thread, uint32 action, target_addr_t address); + virtual void FunctionSourceCodeRequested( + FunctionInstance* function, + bool forceDisassembly); // VariablesView::Listener