- 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:
Rene Gollent
2013-06-22 16:01:58 -04:00
parent 442f71a7d9
commit b1975a590f
4 changed files with 105 additions and 9 deletions
@@ -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