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 ".";
|
"line %" B_PRId32 ".";
|
||||||
|
|
||||||
static const uint32 MSG_OPEN_SOURCE_FILE = 'mosf';
|
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";
|
static const char* kTrackerSignature = "application/x-vnd.Be-TRAK";
|
||||||
|
|
||||||
@@ -1758,13 +1759,51 @@ SourceView::TextView::_ScrollToBottom(void)
|
|||||||
bool
|
bool
|
||||||
SourceView::TextView::_AddGeneralActions(BPopUpMenu* menu, int32 line)
|
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)
|
if (message == NULL)
|
||||||
return false;
|
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 false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1938,6 +1977,40 @@ SourceView::MessageReceived(BMessage* message)
|
|||||||
break;
|
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:
|
default:
|
||||||
BView::MessageReceived(message);
|
BView::MessageReceived(message);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Copyright 2013, Rene Gollent, rene@gollent.com.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef SOURCE_VIEW_H
|
#ifndef SOURCE_VIEW_H
|
||||||
@@ -13,6 +14,7 @@
|
|||||||
|
|
||||||
|
|
||||||
class Breakpoint;
|
class Breakpoint;
|
||||||
|
class FunctionInstance;
|
||||||
class SourceCode;
|
class SourceCode;
|
||||||
class StackFrame;
|
class StackFrame;
|
||||||
class StackTrace;
|
class StackTrace;
|
||||||
@@ -106,6 +108,9 @@ public:
|
|||||||
target_addr_t address) = 0;
|
target_addr_t address) = 0;
|
||||||
virtual void ThreadActionRequested(Thread* thread,
|
virtual void ThreadActionRequested(Thread* thread,
|
||||||
uint32 action, target_addr_t address) = 0;
|
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
|
if (fActiveFunction != NULL
|
||||||
&& fActiveFunction->GetFunctionDebugInfo()
|
&& fActiveFunction->GetFunctionDebugInfo()
|
||||||
->SourceFile() != NULL && fActiveSourceCode != NULL
|
->SourceFile() != NULL && fActiveSourceCode != NULL
|
||||||
&& fActiveSourceCode->GetSourceFile() == NULL) {
|
&& fActiveSourceCode->GetSourceFile() == NULL
|
||||||
|
&& fActiveFunction->GetFunction()->SourceCodeState()
|
||||||
|
!= FUNCTION_SOURCE_NOT_LOADED) {
|
||||||
try {
|
try {
|
||||||
if (fFilePanel == NULL) {
|
if (fFilePanel == NULL) {
|
||||||
fFilePanel = new BFilePanel(B_OPEN_PANEL,
|
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
|
void
|
||||||
TeamWindow::SetWatchpointEnabledRequested(Watchpoint* watchpoint,
|
TeamWindow::SetWatchpointEnabledRequested(Watchpoint* watchpoint,
|
||||||
bool enabled)
|
bool enabled)
|
||||||
@@ -1248,15 +1258,17 @@ TeamWindow::_UpdateSourcePathState()
|
|||||||
if (sourceFile != NULL && !sourceFile->GetLocatedPath(sourceText))
|
if (sourceFile != NULL && !sourceFile->GetLocatedPath(sourceText))
|
||||||
sourceFile->GetPath(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.Prepend("Click to locate source file '");
|
||||||
sourceText += "'";
|
sourceText += "'";
|
||||||
truncatedText = sourceText;
|
truncatedText = sourceText;
|
||||||
fSourcePathView->TruncateString(&truncatedText, B_TRUNCATE_MIDDLE,
|
fSourcePathView->TruncateString(&truncatedText, B_TRUNCATE_MIDDLE,
|
||||||
fSourcePathView->Bounds().Width());
|
fSourcePathView->Bounds().Width());
|
||||||
} else if (sourceFile != NULL) {
|
} else if (sourceFile != NULL)
|
||||||
sourceText.Prepend("File: ");
|
sourceText.Prepend("File: ");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!truncatedText.IsEmpty() && truncatedText != sourceText) {
|
if (!truncatedText.IsEmpty() && truncatedText != sourceText) {
|
||||||
@@ -1408,8 +1420,11 @@ TeamWindow::_HandleSourceCodeChanged()
|
|||||||
// get a reference to the source code
|
// get a reference to the source code
|
||||||
AutoLocker< ::Team> locker(fTeam);
|
AutoLocker< ::Team> locker(fTeam);
|
||||||
|
|
||||||
SourceCode* sourceCode = fActiveFunction->GetFunction()->GetSourceCode();
|
SourceCode* sourceCode = NULL;
|
||||||
if (sourceCode == NULL)
|
if (fActiveFunction->GetFunction()->SourceCodeState()
|
||||||
|
== FUNCTION_SOURCE_LOADED) {
|
||||||
|
sourceCode = fActiveFunction->GetFunction()->GetSourceCode();
|
||||||
|
} else
|
||||||
sourceCode = fActiveFunction->GetSourceCode();
|
sourceCode = fActiveFunction->GetSourceCode();
|
||||||
|
|
||||||
BReference<SourceCode> sourceCodeReference(sourceCode);
|
BReference<SourceCode> sourceCodeReference(sourceCode);
|
||||||
|
|||||||
@@ -110,6 +110,9 @@ private:
|
|||||||
target_addr_t address);
|
target_addr_t address);
|
||||||
virtual void ThreadActionRequested(::Thread* thread,
|
virtual void ThreadActionRequested(::Thread* thread,
|
||||||
uint32 action, target_addr_t address);
|
uint32 action, target_addr_t address);
|
||||||
|
virtual void FunctionSourceCodeRequested(
|
||||||
|
FunctionInstance* function,
|
||||||
|
bool forceDisassembly);
|
||||||
|
|
||||||
|
|
||||||
// VariablesView::Listener
|
// VariablesView::Listener
|
||||||
|
|||||||
Reference in New Issue
Block a user