Debugger: improve command help text
Improve the help text of the db, dw, ds, dl, and string commands. This is accomplished by * Splitting CliDumpMemoryCommand into CliDumpMemoryCommand and CliDumpStringCommand * Moving code shared between the two into CliContext * Removing functions in CliContext that were replaced by this movement * Allowing customizing the help text for CliDumpMemoryCommand for each command it represents * Changing the help text for CliDumpStringCommand Change-Id: If4f9e0c20f00f3e3d6c6769216fabb3160aea0a4 Reviewed-on: https://review.haiku-os.org/c/haiku/+/6332 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
92f36c4a61
commit
44daad619e
@@ -73,6 +73,7 @@ local sources =
|
|||||||
CliContinueCommand.cpp
|
CliContinueCommand.cpp
|
||||||
CliDebugReportCommand.cpp
|
CliDebugReportCommand.cpp
|
||||||
CliDumpMemoryCommand.cpp
|
CliDumpMemoryCommand.cpp
|
||||||
|
CliDumpStringCommand.cpp
|
||||||
CliPrintVariableCommand.cpp
|
CliPrintVariableCommand.cpp
|
||||||
CliQuitCommand.cpp
|
CliQuitCommand.cpp
|
||||||
CliStackFrameCommand.cpp
|
CliStackFrameCommand.cpp
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "StackTrace.h"
|
#include "StackTrace.h"
|
||||||
#include "UserInterface.h"
|
#include "UserInterface.h"
|
||||||
|
#include "Value.h"
|
||||||
#include "ValueNodeManager.h"
|
#include "ValueNodeManager.h"
|
||||||
#include "Variable.h"
|
#include "Variable.h"
|
||||||
|
|
||||||
@@ -288,6 +289,57 @@ CliContext::SetCurrentStackFrameIndex(int32 index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
CliContext::EvaluateExpression(const char* expression,
|
||||||
|
SourceLanguage* language, target_addr_t& address)
|
||||||
|
{
|
||||||
|
fExpressionInfo->SetTo(expression);
|
||||||
|
|
||||||
|
fListener->ExpressionEvaluationRequested(
|
||||||
|
language, fExpressionInfo);
|
||||||
|
WaitForEvents(CliContext::EVENT_EXPRESSION_EVALUATED);
|
||||||
|
if (fTerminating)
|
||||||
|
return B_INTERRUPTED;
|
||||||
|
|
||||||
|
BString errorMessage;
|
||||||
|
if (fExpressionValue != NULL) {
|
||||||
|
if (fExpressionValue->Kind() == EXPRESSION_RESULT_KIND_PRIMITIVE) {
|
||||||
|
Value* value = fExpressionValue->PrimitiveValue();
|
||||||
|
BVariant variantValue;
|
||||||
|
value->ToVariant(variantValue);
|
||||||
|
if (variantValue.Type() == B_STRING_TYPE)
|
||||||
|
errorMessage.SetTo(variantValue.ToString());
|
||||||
|
else
|
||||||
|
address = variantValue.ToUInt64();
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
errorMessage = strerror(fExpressionResult);
|
||||||
|
|
||||||
|
if (!errorMessage.IsEmpty()) {
|
||||||
|
printf("Unable to evaluate expression: %s\n",
|
||||||
|
errorMessage.String());
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
CliContext::GetMemoryBlock(target_addr_t address, TeamMemoryBlock*& block)
|
||||||
|
{
|
||||||
|
if (fCurrentBlock == NULL || !fCurrentBlock->Contains(address)) {
|
||||||
|
GetUserInterfaceListener()->InspectRequested(address, this);
|
||||||
|
WaitForEvents(CliContext::EVENT_TEAM_MEMORY_BLOCK_RETRIEVED);
|
||||||
|
if (fTerminating)
|
||||||
|
return B_INTERRUPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
block = fCurrentBlock;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
CliContext::PromptUser(const char* prompt)
|
CliContext::PromptUser(const char* prompt)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "ValueNodeContainer.h"
|
#include "ValueNodeContainer.h"
|
||||||
|
|
||||||
|
|
||||||
|
class SourceLanguage;
|
||||||
class StackFrame;
|
class StackFrame;
|
||||||
class StackTrace;
|
class StackTrace;
|
||||||
class Team;
|
class Team;
|
||||||
@@ -77,14 +78,11 @@ public:
|
|||||||
{ return fCurrentStackFrameIndex; }
|
{ return fCurrentStackFrameIndex; }
|
||||||
void SetCurrentStackFrameIndex(int32 index);
|
void SetCurrentStackFrameIndex(int32 index);
|
||||||
|
|
||||||
TeamMemoryBlock* CurrentBlock() const { return fCurrentBlock; }
|
status_t EvaluateExpression(const char * expression,
|
||||||
|
SourceLanguage* language, target_addr_t& address);
|
||||||
|
|
||||||
ExpressionInfo* GetExpressionInfo() const
|
status_t GetMemoryBlock(target_addr_t address,
|
||||||
{ return fExpressionInfo; }
|
TeamMemoryBlock*& block);
|
||||||
status_t GetExpressionResult() const
|
|
||||||
{ return fExpressionResult; }
|
|
||||||
ExpressionResult* GetExpressionValue() const
|
|
||||||
{ return fExpressionValue; }
|
|
||||||
|
|
||||||
const char* PromptUser(const char* prompt);
|
const char* PromptUser(const char* prompt);
|
||||||
void AddLineToInputHistory(const char* line);
|
void AddLineToInputHistory(const char* line);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "CliContinueCommand.h"
|
#include "CliContinueCommand.h"
|
||||||
#include "CliDebugReportCommand.h"
|
#include "CliDebugReportCommand.h"
|
||||||
#include "CliDumpMemoryCommand.h"
|
#include "CliDumpMemoryCommand.h"
|
||||||
|
#include "CliDumpStringCommand.h"
|
||||||
#include "CliPrintVariableCommand.h"
|
#include "CliPrintVariableCommand.h"
|
||||||
#include "CliQuitCommand.h"
|
#include "CliQuitCommand.h"
|
||||||
#include "CliStackFrameCommand.h"
|
#include "CliStackFrameCommand.h"
|
||||||
@@ -300,8 +301,14 @@ CommandLineUserInterface::_RegisterCommands()
|
|||||||
{
|
{
|
||||||
if (_RegisterCommand("bt sc", new(std::nothrow) CliStackTraceCommand)
|
if (_RegisterCommand("bt sc", new(std::nothrow) CliStackTraceCommand)
|
||||||
&& _RegisterCommand("continue", new(std::nothrow) CliContinueCommand)
|
&& _RegisterCommand("continue", new(std::nothrow) CliContinueCommand)
|
||||||
&& _RegisterCommand("db ds dw dl string", new(std::nothrow)
|
&& _RegisterCommand("db", new(std::nothrow)
|
||||||
CliDumpMemoryCommand)
|
CliDumpMemoryCommand(1, "byte", 16))
|
||||||
|
&& _RegisterCommand("ds", new(std::nothrow)
|
||||||
|
CliDumpMemoryCommand(2, "short", 8))
|
||||||
|
&& _RegisterCommand("dw", new(std::nothrow)
|
||||||
|
CliDumpMemoryCommand(4, "word", 4))
|
||||||
|
&& _RegisterCommand("dl", new(std::nothrow)
|
||||||
|
CliDumpMemoryCommand(8, "long", 2))
|
||||||
&& _RegisterCommand("frame", new(std::nothrow) CliStackFrameCommand)
|
&& _RegisterCommand("frame", new(std::nothrow) CliStackFrameCommand)
|
||||||
&& _RegisterCommand("help", new(std::nothrow) HelpCommand(this))
|
&& _RegisterCommand("help", new(std::nothrow) HelpCommand(this))
|
||||||
&& _RegisterCommand("print", new(std::nothrow) CliPrintVariableCommand)
|
&& _RegisterCommand("print", new(std::nothrow) CliPrintVariableCommand)
|
||||||
@@ -309,6 +316,8 @@ CommandLineUserInterface::_RegisterCommands()
|
|||||||
&& _RegisterCommand("save-report",
|
&& _RegisterCommand("save-report",
|
||||||
new(std::nothrow) CliDebugReportCommand)
|
new(std::nothrow) CliDebugReportCommand)
|
||||||
&& _RegisterCommand("stop", new(std::nothrow) CliStopCommand)
|
&& _RegisterCommand("stop", new(std::nothrow) CliStopCommand)
|
||||||
|
&& _RegisterCommand("string", new(std::nothrow)
|
||||||
|
CliDumpStringCommand())
|
||||||
&& _RegisterCommand("thread", new(std::nothrow) CliThreadCommand)
|
&& _RegisterCommand("thread", new(std::nothrow) CliThreadCommand)
|
||||||
&& _RegisterCommand("threads", new(std::nothrow) CliThreadsCommand)
|
&& _RegisterCommand("threads", new(std::nothrow) CliThreadsCommand)
|
||||||
&& _RegisterCommand("variables",
|
&& _RegisterCommand("variables",
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public:
|
|||||||
virtual void Execute(int argc, const char* const* argv,
|
virtual void Execute(int argc, const char* const* argv,
|
||||||
CliContext& context) = 0;
|
CliContext& context) = 0;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
const char* fSummary;
|
const char* fSummary;
|
||||||
const char* fUsage;
|
const char* fUsage;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,12 +26,23 @@
|
|||||||
#include "Variable.h"
|
#include "Variable.h"
|
||||||
|
|
||||||
|
|
||||||
CliDumpMemoryCommand::CliDumpMemoryCommand()
|
CliDumpMemoryCommand::CliDumpMemoryCommand(int itemSize,
|
||||||
|
const char* itemSizeNoun, int displayWidth)
|
||||||
:
|
:
|
||||||
CliCommand("dump contents of debugged team's memory",
|
CliCommand(NULL, NULL),
|
||||||
"%s [\"]address|expression[\"] [num]\n"
|
itemSize(itemSize),
|
||||||
"Reads and displays the contents of memory at the target address.")
|
displayWidth(displayWidth)
|
||||||
{
|
{
|
||||||
|
// BString manages the lifetime of the const char* put in fSummary and fUsage
|
||||||
|
fSummaryString.SetToFormat("dump contents of debugged team's memory in %s-sized increments",
|
||||||
|
itemSizeNoun);
|
||||||
|
fUsageString.SetToFormat("%%s [\"]address|expression[\"] [num]\n"
|
||||||
|
"Reads and displays the contents of memory at the target address in %d-byte increments",
|
||||||
|
itemSize);
|
||||||
|
|
||||||
|
fSummary = fSummaryString.String();
|
||||||
|
fUsage = fUsageString.String();
|
||||||
|
|
||||||
// TODO: this should be retrieved via some indirect helper rather
|
// TODO: this should be retrieved via some indirect helper rather
|
||||||
// than instantiating the specific language directly.
|
// than instantiating the specific language directly.
|
||||||
fLanguage = new(std::nothrow) CppLanguage();
|
fLanguage = new(std::nothrow) CppLanguage();
|
||||||
@@ -59,61 +70,13 @@ CliDumpMemoryCommand::Execute(int argc, const char* const* argv,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpressionInfo* info = context.GetExpressionInfo();
|
target_addr_t address;
|
||||||
|
if (context.EvaluateExpression(argv[1], fLanguage, address) != B_OK)
|
||||||
target_addr_t address = 0;
|
|
||||||
info->SetTo(argv[1]);
|
|
||||||
|
|
||||||
context.GetUserInterfaceListener()->ExpressionEvaluationRequested(
|
|
||||||
fLanguage, info);
|
|
||||||
context.WaitForEvents(CliContext::EVENT_EXPRESSION_EVALUATED);
|
|
||||||
if (context.IsTerminating())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BString errorMessage;
|
TeamMemoryBlock* block = NULL;
|
||||||
ExpressionResult* result = context.GetExpressionValue();
|
if (context.GetMemoryBlock(address, block) != B_OK)
|
||||||
if (result != NULL) {
|
|
||||||
if (result->Kind() == EXPRESSION_RESULT_KIND_PRIMITIVE) {
|
|
||||||
Value* value = result->PrimitiveValue();
|
|
||||||
BVariant variantValue;
|
|
||||||
value->ToVariant(variantValue);
|
|
||||||
if (variantValue.Type() == B_STRING_TYPE)
|
|
||||||
errorMessage.SetTo(variantValue.ToString());
|
|
||||||
else
|
|
||||||
address = variantValue.ToUInt64();
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
errorMessage = strerror(context.GetExpressionResult());
|
|
||||||
|
|
||||||
if (!errorMessage.IsEmpty()) {
|
|
||||||
printf("Unable to evaluate expression: %s\n",
|
|
||||||
errorMessage.String());
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
int32 itemSize = 0;
|
|
||||||
int32 displayWidth = 0;
|
|
||||||
|
|
||||||
// build the format string
|
|
||||||
if (strcmp(argv[0], "db") == 0) {
|
|
||||||
itemSize = 1;
|
|
||||||
displayWidth = 16;
|
|
||||||
} else if (strcmp(argv[0], "ds") == 0) {
|
|
||||||
itemSize = 2;
|
|
||||||
displayWidth = 8;
|
|
||||||
} else if (strcmp(argv[0], "dw") == 0) {
|
|
||||||
itemSize = 4;
|
|
||||||
displayWidth = 4;
|
|
||||||
} else if (strcmp(argv[0], "dl") == 0) {
|
|
||||||
itemSize = 8;
|
|
||||||
displayWidth = 2;
|
|
||||||
} else if (strcmp(argv[0], "string") == 0) {
|
|
||||||
itemSize = 1;
|
|
||||||
displayWidth = -1;
|
|
||||||
} else {
|
|
||||||
printf("dump called in an invalid way!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 num = 0;
|
int32 num = 0;
|
||||||
if (argc == 3) {
|
if (argc == 3) {
|
||||||
@@ -127,44 +90,8 @@ CliDumpMemoryCommand::Execute(int argc, const char* const* argv,
|
|||||||
if (num <= 0)
|
if (num <= 0)
|
||||||
num = displayWidth;
|
num = displayWidth;
|
||||||
|
|
||||||
TeamMemoryBlock* block = context.CurrentBlock();
|
BString output;
|
||||||
if (block == NULL || !block->Contains(address)) {
|
UiUtils::DumpMemory(output, 0, block, address, itemSize, displayWidth,
|
||||||
context.GetUserInterfaceListener()->InspectRequested(address,
|
num);
|
||||||
&context);
|
printf("%s\n", output.String());
|
||||||
context.WaitForEvents(CliContext::EVENT_TEAM_MEMORY_BLOCK_RETRIEVED);
|
|
||||||
if (context.IsTerminating())
|
|
||||||
return;
|
|
||||||
block = context.CurrentBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(argv[0], "string")) {
|
|
||||||
printf("%p \"", (char*)address);
|
|
||||||
|
|
||||||
target_addr_t offset = address;
|
|
||||||
char c;
|
|
||||||
while (block->Contains(offset)) {
|
|
||||||
c = *(block->Data() + offset - block->BaseAddress());
|
|
||||||
|
|
||||||
if (c == '\0')
|
|
||||||
break;
|
|
||||||
if (c == '\n')
|
|
||||||
printf("\\n");
|
|
||||||
else if (c == '\t')
|
|
||||||
printf("\\t");
|
|
||||||
else {
|
|
||||||
if (!isprint(c))
|
|
||||||
c = '.';
|
|
||||||
|
|
||||||
printf("%c", c);
|
|
||||||
}
|
|
||||||
++offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\"\n");
|
|
||||||
} else {
|
|
||||||
BString output;
|
|
||||||
UiUtils::DumpMemory(output, 0, block, address, itemSize, displayWidth,
|
|
||||||
num);
|
|
||||||
printf("%s\n", output.String());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,13 +8,17 @@
|
|||||||
|
|
||||||
#include "CliCommand.h"
|
#include "CliCommand.h"
|
||||||
|
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
|
||||||
class SourceLanguage;
|
class SourceLanguage;
|
||||||
|
|
||||||
|
|
||||||
class CliDumpMemoryCommand : public CliCommand {
|
class CliDumpMemoryCommand : public CliCommand {
|
||||||
public:
|
public:
|
||||||
CliDumpMemoryCommand();
|
CliDumpMemoryCommand(int itemSize,
|
||||||
|
const char* itemSizeNoun,
|
||||||
|
int displayWidth);
|
||||||
virtual ~CliDumpMemoryCommand();
|
virtual ~CliDumpMemoryCommand();
|
||||||
|
|
||||||
virtual void Execute(int argc, const char* const* argv,
|
virtual void Execute(int argc, const char* const* argv,
|
||||||
@@ -22,6 +26,10 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
SourceLanguage* fLanguage;
|
SourceLanguage* fLanguage;
|
||||||
|
BString fSummaryString;
|
||||||
|
BString fUsageString;
|
||||||
|
int itemSize;
|
||||||
|
int displayWidth;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009-2011, Ingo Weinhold, [email protected].
|
||||||
|
* Copyright 2002-2010, Axel Dörfler, [email protected].
|
||||||
|
* Copyright 2012-2016, Rene Gollent, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||||
|
* Distributed under the terms of the NewOS License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "CliDumpStringCommand.h"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
|
#include "CliContext.h"
|
||||||
|
#include "CppLanguage.h"
|
||||||
|
#include "Team.h"
|
||||||
|
#include "TeamMemoryBlock.h"
|
||||||
|
#include "UiUtils.h"
|
||||||
|
#include "UserInterface.h"
|
||||||
|
#include "Value.h"
|
||||||
|
#include "Variable.h"
|
||||||
|
|
||||||
|
|
||||||
|
CliDumpStringCommand::CliDumpStringCommand()
|
||||||
|
:
|
||||||
|
CliCommand("dump contents of a string in the debugged team's memory",
|
||||||
|
"%s [\"]address|expression[\"]\n"
|
||||||
|
"Reads and displays the contents of a null-terminated string at the target address.")
|
||||||
|
{
|
||||||
|
// TODO: this should be retrieved via some indirect helper rather
|
||||||
|
// than instantiating the specific language directly.
|
||||||
|
fLanguage = new(std::nothrow) CppLanguage();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CliDumpStringCommand::~CliDumpStringCommand()
|
||||||
|
{
|
||||||
|
if (fLanguage != NULL)
|
||||||
|
fLanguage->ReleaseReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CliDumpStringCommand::Execute(int argc, const char* const* argv,
|
||||||
|
CliContext& context)
|
||||||
|
{
|
||||||
|
if (argc < 2) {
|
||||||
|
PrintUsage(argv[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fLanguage == NULL) {
|
||||||
|
printf("Unable to evaluate expression: %s\n", strerror(B_NO_MEMORY));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_addr_t address;
|
||||||
|
if (context.EvaluateExpression(argv[1], fLanguage, address) != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TeamMemoryBlock* block = NULL;
|
||||||
|
if (context.GetMemoryBlock(address, block) != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
printf("%p \"", (char*)address);
|
||||||
|
|
||||||
|
target_addr_t offset = address;
|
||||||
|
char c;
|
||||||
|
while (block->Contains(offset)) {
|
||||||
|
c = *(block->Data() + offset - block->BaseAddress());
|
||||||
|
|
||||||
|
if (c == '\0')
|
||||||
|
break;
|
||||||
|
if (c == '\n')
|
||||||
|
printf("\\n");
|
||||||
|
else if (c == '\t')
|
||||||
|
printf("\\t");
|
||||||
|
else {
|
||||||
|
if (!isprint(c))
|
||||||
|
c = '.';
|
||||||
|
|
||||||
|
printf("%c", c);
|
||||||
|
}
|
||||||
|
++offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\"\n");
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2014, Rene Gollent, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef CLI_DUMP_STRING_COMMAND_H
|
||||||
|
#define CLI_DUMP_STRING_COMMAND_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "CliCommand.h"
|
||||||
|
|
||||||
|
|
||||||
|
class SourceLanguage;
|
||||||
|
|
||||||
|
|
||||||
|
class CliDumpStringCommand : public CliCommand {
|
||||||
|
public:
|
||||||
|
CliDumpStringCommand();
|
||||||
|
virtual ~CliDumpStringCommand();
|
||||||
|
|
||||||
|
virtual void Execute(int argc, const char* const* argv,
|
||||||
|
CliContext& context);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SourceLanguage* fLanguage;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CLI_DUMP_STRING_COMMAND_H
|
||||||
Reference in New Issue
Block a user