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
|
||||
CliDebugReportCommand.cpp
|
||||
CliDumpMemoryCommand.cpp
|
||||
CliDumpStringCommand.cpp
|
||||
CliPrintVariableCommand.cpp
|
||||
CliQuitCommand.cpp
|
||||
CliStackFrameCommand.cpp
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "StackTrace.h"
|
||||
#include "UserInterface.h"
|
||||
#include "Value.h"
|
||||
#include "ValueNodeManager.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*
|
||||
CliContext::PromptUser(const char* prompt)
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "ValueNodeContainer.h"
|
||||
|
||||
|
||||
class SourceLanguage;
|
||||
class StackFrame;
|
||||
class StackTrace;
|
||||
class Team;
|
||||
@@ -77,14 +78,11 @@ public:
|
||||
{ return fCurrentStackFrameIndex; }
|
||||
void SetCurrentStackFrameIndex(int32 index);
|
||||
|
||||
TeamMemoryBlock* CurrentBlock() const { return fCurrentBlock; }
|
||||
status_t EvaluateExpression(const char * expression,
|
||||
SourceLanguage* language, target_addr_t& address);
|
||||
|
||||
ExpressionInfo* GetExpressionInfo() const
|
||||
{ return fExpressionInfo; }
|
||||
status_t GetExpressionResult() const
|
||||
{ return fExpressionResult; }
|
||||
ExpressionResult* GetExpressionValue() const
|
||||
{ return fExpressionValue; }
|
||||
status_t GetMemoryBlock(target_addr_t address,
|
||||
TeamMemoryBlock*& block);
|
||||
|
||||
const char* PromptUser(const char* prompt);
|
||||
void AddLineToInputHistory(const char* line);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "CliContinueCommand.h"
|
||||
#include "CliDebugReportCommand.h"
|
||||
#include "CliDumpMemoryCommand.h"
|
||||
#include "CliDumpStringCommand.h"
|
||||
#include "CliPrintVariableCommand.h"
|
||||
#include "CliQuitCommand.h"
|
||||
#include "CliStackFrameCommand.h"
|
||||
@@ -300,8 +301,14 @@ CommandLineUserInterface::_RegisterCommands()
|
||||
{
|
||||
if (_RegisterCommand("bt sc", new(std::nothrow) CliStackTraceCommand)
|
||||
&& _RegisterCommand("continue", new(std::nothrow) CliContinueCommand)
|
||||
&& _RegisterCommand("db ds dw dl string", new(std::nothrow)
|
||||
CliDumpMemoryCommand)
|
||||
&& _RegisterCommand("db", new(std::nothrow)
|
||||
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("help", new(std::nothrow) HelpCommand(this))
|
||||
&& _RegisterCommand("print", new(std::nothrow) CliPrintVariableCommand)
|
||||
@@ -309,6 +316,8 @@ CommandLineUserInterface::_RegisterCommands()
|
||||
&& _RegisterCommand("save-report",
|
||||
new(std::nothrow) CliDebugReportCommand)
|
||||
&& _RegisterCommand("stop", new(std::nothrow) CliStopCommand)
|
||||
&& _RegisterCommand("string", new(std::nothrow)
|
||||
CliDumpStringCommand())
|
||||
&& _RegisterCommand("thread", new(std::nothrow) CliThreadCommand)
|
||||
&& _RegisterCommand("threads", new(std::nothrow) CliThreadsCommand)
|
||||
&& _RegisterCommand("variables",
|
||||
|
||||
@@ -26,7 +26,7 @@ public:
|
||||
virtual void Execute(int argc, const char* const* argv,
|
||||
CliContext& context) = 0;
|
||||
|
||||
private:
|
||||
protected:
|
||||
const char* fSummary;
|
||||
const char* fUsage;
|
||||
};
|
||||
|
||||
@@ -26,12 +26,23 @@
|
||||
#include "Variable.h"
|
||||
|
||||
|
||||
CliDumpMemoryCommand::CliDumpMemoryCommand()
|
||||
CliDumpMemoryCommand::CliDumpMemoryCommand(int itemSize,
|
||||
const char* itemSizeNoun, int displayWidth)
|
||||
:
|
||||
CliCommand("dump contents of debugged team's memory",
|
||||
"%s [\"]address|expression[\"] [num]\n"
|
||||
"Reads and displays the contents of memory at the target address.")
|
||||
CliCommand(NULL, NULL),
|
||||
itemSize(itemSize),
|
||||
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
|
||||
// than instantiating the specific language directly.
|
||||
fLanguage = new(std::nothrow) CppLanguage();
|
||||
@@ -59,61 +70,13 @@ CliDumpMemoryCommand::Execute(int argc, const char* const* argv,
|
||||
return;
|
||||
}
|
||||
|
||||
ExpressionInfo* info = context.GetExpressionInfo();
|
||||
|
||||
target_addr_t address = 0;
|
||||
info->SetTo(argv[1]);
|
||||
|
||||
context.GetUserInterfaceListener()->ExpressionEvaluationRequested(
|
||||
fLanguage, info);
|
||||
context.WaitForEvents(CliContext::EVENT_EXPRESSION_EVALUATED);
|
||||
if (context.IsTerminating())
|
||||
target_addr_t address;
|
||||
if (context.EvaluateExpression(argv[1], fLanguage, address) != B_OK)
|
||||
return;
|
||||
|
||||
BString errorMessage;
|
||||
ExpressionResult* result = context.GetExpressionValue();
|
||||
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());
|
||||
TeamMemoryBlock* block = NULL;
|
||||
if (context.GetMemoryBlock(address, block) != B_OK)
|
||||
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;
|
||||
if (argc == 3) {
|
||||
@@ -127,44 +90,8 @@ CliDumpMemoryCommand::Execute(int argc, const char* const* argv,
|
||||
if (num <= 0)
|
||||
num = displayWidth;
|
||||
|
||||
TeamMemoryBlock* block = context.CurrentBlock();
|
||||
if (block == NULL || !block->Contains(address)) {
|
||||
context.GetUserInterfaceListener()->InspectRequested(address,
|
||||
&context);
|
||||
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());
|
||||
}
|
||||
BString output;
|
||||
UiUtils::DumpMemory(output, 0, block, address, itemSize, displayWidth,
|
||||
num);
|
||||
printf("%s\n", output.String());
|
||||
}
|
||||
|
||||
@@ -8,13 +8,17 @@
|
||||
|
||||
#include "CliCommand.h"
|
||||
|
||||
#include <String.h>
|
||||
|
||||
|
||||
class SourceLanguage;
|
||||
|
||||
|
||||
class CliDumpMemoryCommand : public CliCommand {
|
||||
public:
|
||||
CliDumpMemoryCommand();
|
||||
CliDumpMemoryCommand(int itemSize,
|
||||
const char* itemSizeNoun,
|
||||
int displayWidth);
|
||||
virtual ~CliDumpMemoryCommand();
|
||||
|
||||
virtual void Execute(int argc, const char* const* argv,
|
||||
@@ -22,6 +26,10 @@ public:
|
||||
|
||||
private:
|
||||
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