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.
This commit is contained in:
@@ -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<DisassembledCode*>(
|
||||
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<FileSourceCode*>(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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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<SourceCode> sourceCodeReference(sourceCode);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user