hrev45030 adds 4 changesets to branch 'master' old head: 03289a339ceabd34eb4f909f13585a780ac4bef2 new head: ec7c59ca09cff4de780eb06a10144ff75c86ac5a overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=ec7c59c+%5E03289a3 ---------------------------------------------------------------------------- 55751d0: Move Tokenizer/Token into ExpressionParser's namespace. 779b84b: Add memory dumping helper to UiUtils. - Adapted from KDL's db/dw et al. c7f5dd6: Add support for memory block events to CliContext. ec7c59c: Add memory dumping commands similar to those in KDL. [ Rene Gollent <anevilyak@xxxxxxxxx> ] ---------------------------------------------------------------------------- 10 files changed, 292 insertions(+), 10 deletions(-) headers/private/shared/ExpressionParser.h | 8 +- src/apps/debugger/Jamfile | 1 + .../debugger/user_interface/cli/CliContext.cpp | 36 +++++- .../debugger/user_interface/cli/CliContext.h | 12 +- .../user_interface/cli/CliDumpMemoryCommand.cpp | 127 +++++++++++++++++++ .../user_interface/cli/CliDumpMemoryCommand.h | 22 ++++ .../cli/CommandLineUserInterface.cpp | 19 +++ .../debugger/user_interface/util/UiUtils.cpp | 62 +++++++++ src/apps/debugger/user_interface/util/UiUtils.h | 9 ++ src/kits/shared/ExpressionParser.cpp | 6 +- ############################################################################ Commit: 55751d083a85ed8ee7f09ab06aedc598eea23f23 URL: http://cgit.haiku-os.org/haiku/commit/?id=55751d0 Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Wed Dec 19 02:31:43 2012 UTC Move Tokenizer/Token into ExpressionParser's namespace. ---------------------------------------------------------------------------- diff --git a/headers/private/shared/ExpressionParser.h b/headers/private/shared/ExpressionParser.h index 95df720..b180b87 100644 --- a/headers/private/shared/ExpressionParser.h +++ b/headers/private/shared/ExpressionParser.h @@ -14,8 +14,6 @@ #include <String.h> -class Tokenizer; - class ParseException { public: ParseException(const char* message, int32 position) @@ -35,10 +33,10 @@ class ParseException { }; struct Function; -struct Token; class MAPM; class ExpressionParser { + public: ExpressionParser(); ~ExpressionParser(); @@ -53,6 +51,10 @@ class ExpressionParser { double EvaluateToDouble(const char* expressionString); private: + struct Token; + class Tokenizer; + + private: MAPM _ParseBinary(); MAPM _ParseSum(); MAPM _ParseProduct(); diff --git a/src/kits/shared/ExpressionParser.cpp b/src/kits/shared/ExpressionParser.cpp index c49c67d..b75c0e2 100644 --- a/src/kits/shared/ExpressionParser.cpp +++ b/src/kits/shared/ExpressionParser.cpp @@ -47,7 +47,7 @@ enum { TOKEN_END_OF_LINE }; -struct Token { +struct ExpressionParser::Token { Token() : string(""), type(TOKEN_NONE), @@ -89,7 +89,7 @@ struct Token { }; -class Tokenizer { +class ExpressionParser::Tokenizer { public: Tokenizer() : fString(""), @@ -594,7 +594,7 @@ ExpressionParser::_ParseFunction(const Token& token) if (strcmp("e", token.string.String()) == 0) return _ParseFactorial(MAPM(MM_E)); else if (strcasecmp("pi", token.string.String()) == 0 - || ((unsigned char)token.string.String()[0] == 0xCF + || ((unsigned char)token.string.String()[0] == 0xCF && (unsigned char)token.string.String()[1] == 0x80)) { // UTF-8 small greek letter PI return _ParseFactorial(MAPM(MM_PI)); ############################################################################ Commit: 779b84b17b58a8818cba622a2e416163a06a431f URL: http://cgit.haiku-os.org/haiku/commit/?id=779b84b Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Wed Dec 19 02:32:04 2012 UTC Add memory dumping helper to UiUtils. - Adapted from KDL's db/dw et al. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/user_interface/util/UiUtils.cpp b/src/apps/debugger/user_interface/util/UiUtils.cpp index d44f46a..2841822 100644 --- a/src/apps/debugger/user_interface/util/UiUtils.cpp +++ b/src/apps/debugger/user_interface/util/UiUtils.cpp @@ -7,6 +7,7 @@ #include "UiUtils.h" +#include <ctype.h> #include <stdio.h> #include <DateTime.h> @@ -18,6 +19,7 @@ #include "Image.h" #include "StackFrame.h" #include "Team.h" +#include "TeamMemoryBlock.h" #include "Thread.h" #include "Type.h" #include "Value.h" @@ -226,3 +228,63 @@ UiUtils::PrintValueNodeGraph(BString& _output, ValueNodeChild* child, return; } + + +/*static*/ void UiUtils::DumpMemory(BString& _output, TeamMemoryBlock* block, + target_addr_t address, int32 itemSize, int32 displayWidth, int32 count) +{ + BString data; + + int32 j; + for (int32 i = 0; i < count; i++) { + uint8* value; + + if ((i % displayWidth) == 0) { + int32 displayed = min_c(displayWidth, (count-i)) * itemSize; + if (i != 0) + _output.Append("\n"); + + data.SetToFormat("[%#" B_PRIx64 "] ", address + i * itemSize); + _output += data; + char c; + for (j = 0; j < displayed; j++) { + if (!block->Contains(address + displayed)) + break; + c = *(block->Data() + address - block->BaseAddress() + + (i * itemSize) + j); + if (!isprint(c)) + c = '.'; + + _output += c; + } + if (count > displayWidth) { + // make sure the spacing in the last line is correct + for (j = displayed; j < displayWidth * itemSize; j++) + _output += ' '; + } + _output.Append(" "); + } + + value = block->Data() + address - block->BaseAddress() + + i * itemSize; + + switch (itemSize) { + case 1: + data.SetToFormat(" %02" B_PRIx8, *(uint8*)value); + break; + case 2: + data.SetToFormat(" %04" B_PRIx16, *(uint16*)value); + break; + case 4: + data.SetToFormat(" %08" B_PRIx32, *(uint32*)value); + break; + case 8: + data.SetToFormat(" %016" B_PRIx64, *(uint64*)value); + break; + } + + _output += data; + } + + _output.Append("\n"); +} diff --git a/src/apps/debugger/user_interface/util/UiUtils.h b/src/apps/debugger/user_interface/util/UiUtils.h index 437b34c..cffb700 100644 --- a/src/apps/debugger/user_interface/util/UiUtils.h +++ b/src/apps/debugger/user_interface/util/UiUtils.h @@ -9,13 +9,17 @@ #include <image.h> +#include "Types.h" + class BString; class BVariant; class StackFrame; class Team; +class TeamMemoryBlock; class ValueNodeChild; + class UiUtils { public: static const char* ThreadStateToString(int state, @@ -36,6 +40,11 @@ public: static void PrintValueNodeGraph(BString& _output, ValueNodeChild* child, int32 indentLevel, int32 maxDepth); + + static void DumpMemory(BString& _output, + TeamMemoryBlock* block, + target_addr_t address, int32 itemSize, + int32 displayWidth, int32 count); }; ############################################################################ Commit: c7f5dd6207ea0c29c149067fe5f46cb95fd3e576 URL: http://cgit.haiku-os.org/haiku/commit/?id=c7f5dd6 Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Wed Dec 19 02:32:47 2012 UTC Add support for memory block events to CliContext. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/user_interface/cli/CliContext.cpp b/src/apps/debugger/user_interface/cli/CliContext.cpp index 7654b3e..f939ec1 100644 --- a/src/apps/debugger/user_interface/cli/CliContext.cpp +++ b/src/apps/debugger/user_interface/cli/CliContext.cpp @@ -26,10 +26,11 @@ static CliContext* sCurrentContext; struct CliContext::Event : DoublyLinkedListLinkImpl<CliContext::Event> { - Event(int type, Thread* thread = NULL) + Event(int type, Thread* thread = NULL, TeamMemoryBlock* block = NULL) : fType(type), - fThreadReference(thread) + fThreadReference(thread), + fMemoryBlockReference(block) { } @@ -43,9 +44,15 @@ struct CliContext::Event : DoublyLinkedListLinkImpl<CliContext::Event> { return fThreadReference.Get(); } + TeamMemoryBlock* GetMemoryBlock() const + { + return fMemoryBlockReference.Get(); + } + private: int fType; BReference<Thread> fThreadReference; + BReference<TeamMemoryBlock> fMemoryBlockReference; }; @@ -68,7 +75,8 @@ CliContext::CliContext() fTerminating(false), fCurrentThread(NULL), fCurrentStackTrace(NULL), - fCurrentStackFrameIndex(-1) + fCurrentStackFrameIndex(-1), + fCurrentBlock(NULL) { sCurrentContext = this; } @@ -151,6 +159,11 @@ CliContext::Cleanup() fNodeManager->ReleaseReference(); fNodeManager = NULL; } + + if (fCurrentBlock != NULL) { + fCurrentBlock->ReleaseReference(); + fCurrentBlock = NULL; + } } @@ -376,6 +389,13 @@ CliContext::ProcessPendingEvents() SetCurrentStackFrameIndex(0); } break; + case EVENT_TEAM_MEMORY_BLOCK_RETRIEVED: + if (fCurrentBlock != NULL) { + fCurrentBlock->ReleaseReference(); + fCurrentBlock = NULL; + } + fCurrentBlock = event->GetMemoryBlock(); + break; } } } @@ -425,6 +445,16 @@ CliContext::ThreadStackTraceChanged(const Team::ThreadEvent& threadEvent) void +CliContext::MemoryBlockRetrieved(TeamMemoryBlock* block) +{ + _QueueEvent( + new(std::nothrow) Event(EVENT_TEAM_MEMORY_BLOCK_RETRIEVED, + NULL, block)); + _SignalInputLoop(EVENT_TEAM_MEMORY_BLOCK_RETRIEVED); +} + + +void CliContext::ValueNodeChanged(ValueNodeChild* nodeChild, ValueNode* oldNode, ValueNode* newNode) { diff --git a/src/apps/debugger/user_interface/cli/CliContext.h b/src/apps/debugger/user_interface/cli/CliContext.h index 09d79d8..cb4657a 100644 --- a/src/apps/debugger/user_interface/cli/CliContext.h +++ b/src/apps/debugger/user_interface/cli/CliContext.h @@ -13,17 +13,20 @@ #include <Locker.h> #include "Team.h" +#include "TeamMemoryBlock.h" #include "ValueNodeContainer.h" class StackFrame; class StackTrace; class Team; +class TeamMemoryBlock; class UserInterfaceListener; class ValueNodeManager; class CliContext : private Team::Listener, + public TeamMemoryBlock::Listener, private ValueNodeContainer::Listener { public: enum { @@ -33,7 +36,8 @@ public: EVENT_THREAD_REMOVED = 0x08, EVENT_THREAD_STOPPED = 0x10, EVENT_THREAD_STACK_TRACE_CHANGED = 0x20, - EVENT_VALUE_NODE_CHANGED = 0x40 + EVENT_VALUE_NODE_CHANGED = 0x40, + EVENT_TEAM_MEMORY_BLOCK_RETRIEVED = 0x80 }; public: @@ -67,6 +71,8 @@ public: { return fCurrentStackFrameIndex; } void SetCurrentStackFrameIndex(int32 index); + TeamMemoryBlock* CurrentBlock() const { return fCurrentBlock; } + const char* PromptUser(const char* prompt); void AddLineToInputHistory(const char* line); @@ -91,6 +97,9 @@ private: virtual void ThreadStackTraceChanged( const Team::ThreadEvent& event); + // TeamMemoryBlock::Listener + virtual void MemoryBlockRetrieved(TeamMemoryBlock* block); + // ValueNodeContainer::Listener virtual void ValueNodeChanged(ValueNodeChild* nodeChild, ValueNode* oldNode, ValueNode* newNode); @@ -124,6 +133,7 @@ private: Thread* fCurrentThread; StackTrace* fCurrentStackTrace; int32 fCurrentStackFrameIndex; + TeamMemoryBlock* fCurrentBlock; EventList fPendingEvents; }; ############################################################################ Revision: hrev45030 Commit: ec7c59ca09cff4de780eb06a10144ff75c86ac5a URL: http://cgit.haiku-os.org/haiku/commit/?id=ec7c59c Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Wed Dec 19 02:33:21 2012 UTC Add memory dumping commands similar to those in KDL. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 0d7ea52..b219fe4 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -193,6 +193,7 @@ Application Debugger : CliContext.cpp CliContinueCommand.cpp CliDebugReportCommand.cpp + CliDumpMemoryCommand.cpp CliPrintVariableCommand.cpp CliQuitCommand.cpp CliStackFrameCommand.cpp diff --git a/src/apps/debugger/user_interface/cli/CliDumpMemoryCommand.cpp b/src/apps/debugger/user_interface/cli/CliDumpMemoryCommand.cpp new file mode 100644 index 0000000..cd9049a --- /dev/null +++ b/src/apps/debugger/user_interface/cli/CliDumpMemoryCommand.cpp @@ -0,0 +1,127 @@ +/* + * Copyright 2012, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ + + +#include "CliDumpMemoryCommand.h" + +#include <ctype.h> +#include <stdio.h> + +#include <AutoLocker.h> +#include <ExpressionParser.h> + +#include "CliContext.h" +#include "Team.h" +#include "TeamMemoryBlock.h" +#include "UiUtils.h" +#include "UserInterface.h" + + +CliDumpMemoryCommand::CliDumpMemoryCommand() + : + CliCommand("dump contents of debugged team's memory", + "%s [\"]address|expression[\"] [num]\n" + "Reads and displays the contents of memory at the target address.") +{ +} + + +void +CliDumpMemoryCommand::Execute(int argc, const char* const* argv, + CliContext& context) +{ + if (argc < 2) { + PrintUsage(argv[0]); + return; + } + + target_addr_t address; + ExpressionParser parser; + parser.SetSupportHexInput(true); + + try { + address = parser.EvaluateToInt64(argv[1]); + } catch(...) { + printf("Error parsing address/expression.\n"); + 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) { + char *remainder; + num = strtol(argv[2], &remainder, 0); + if (*remainder != '\0') { + printf("Error: invalid parameter \"%s\"\n", argv[2]); + } + } + + 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, block, address, itemSize, displayWidth, + num); + printf("%s\n", output.String()); + } +} diff --git a/src/apps/debugger/user_interface/cli/CliDumpMemoryCommand.h b/src/apps/debugger/user_interface/cli/CliDumpMemoryCommand.h new file mode 100644 index 0000000..5c8a0fb --- /dev/null +++ b/src/apps/debugger/user_interface/cli/CliDumpMemoryCommand.h @@ -0,0 +1,22 @@ +/* + * Copyright 2012, Rene Gollent, rene@xxxxxxxxxxx. + * Distributed under the terms of the MIT License. + */ +#ifndef CLI_DUMP_MEMORY_COMMAND_H +#define CLI_DUMP_MEMORY_COMMAND_H + + +#include "CliCommand.h" + + +class CliDumpMemoryCommand : public CliCommand { +public: + CliDumpMemoryCommand(); + virtual void Execute(int argc, const char* const* argv, + CliContext& context); + +private: +}; + + +#endif // CLI_DUMP_MEMORY_COMMAND_H diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp index 92ef511..85a204b 100644 --- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp +++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp @@ -18,6 +18,7 @@ #include "CliContext.h" #include "CliContinueCommand.h" #include "CliDebugReportCommand.h" +#include "CliDumpMemoryCommand.h" #include "CliPrintVariableCommand.h" #include "CliQuitCommand.h" #include "CliStackFrameCommand.h" @@ -310,6 +311,24 @@ CommandLineUserInterface::_RegisterCommands() BReference<CliCommand> stackTraceCommandReference2( stackTraceCommandReference.Get()); + BReference<CliCommand> dumpCommandReference( + new(std::nothrow) CliDumpMemoryCommand, true); + BReference<CliCommand> dumpCommandReference2( + dumpCommandReference.Get()); + if (!_RegisterCommand("db", dumpCommandReference.Detach())) + return B_NO_MEMORY; + dumpCommandReference = dumpCommandReference2.Get(); + if (!_RegisterCommand("ds", dumpCommandReference.Detach())) + return B_NO_MEMORY; + dumpCommandReference = dumpCommandReference2.Get(); + if (!_RegisterCommand("dw", dumpCommandReference.Detach())) + return B_NO_MEMORY; + dumpCommandReference = dumpCommandReference2.Get(); + if (!_RegisterCommand("dl", dumpCommandReference.Detach())) + return B_NO_MEMORY; + if (!_RegisterCommand("string", dumpCommandReference2.Detach())) + return B_NO_MEMORY; + if (_RegisterCommand("bt", stackTraceCommandReference.Detach()) && _RegisterCommand("continue", new(std::nothrow) CliContinueCommand) && _RegisterCommand("frame", new(std::nothrow) CliStackFrameCommand)