From a4d5ac6a25cf635c201cbb7d20f35b4a73d69e4f Mon Sep 17 00:00:00 2001 From: John Scipione Date: Mon, 17 Dec 2012 16:31:25 -0500 Subject: [PATCH 01/17] Lock Webpositive about window before Quit()ting, thanks Axel. --- src/apps/webpositive/BrowserApp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index e4a0627776..fe99ec9e5f 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -89,7 +89,7 @@ BrowserApp::~BrowserApp() delete fCookies; delete fCookieJar; - if (fAboutWindow != NULL) + if (fAboutWindow != NULL && fAboutWindow->Lock()) fAboutWindow->Quit(); } From 7fe8b2bf2a3e4b1c258ec9a4ec748f71d8a9e226 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Mon, 17 Dec 2012 16:46:41 -0500 Subject: [PATCH 02/17] Also lock fAboutWindow before Quit()ting in other apps --- src/apps/activitymonitor/ActivityView.cpp | 2 +- src/apps/deskcalc/CalcView.cpp | 2 +- src/apps/networkstatus/NetworkStatusView.cpp | 2 +- src/apps/processcontroller/ProcessController.cpp | 2 +- src/apps/workspaces/Workspaces.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/apps/activitymonitor/ActivityView.cpp b/src/apps/activitymonitor/ActivityView.cpp index fc4f32efa0..ad6e5cd3a7 100644 --- a/src/apps/activitymonitor/ActivityView.cpp +++ b/src/apps/activitymonitor/ActivityView.cpp @@ -602,7 +602,7 @@ ActivityView::~ActivityView() delete fSystemInfoHandler; // replicant deleted, destroy the about window - if (fAboutWindow != NULL) + if (fAboutWindow != NULL && fAboutWindow->Lock()) fAboutWindow->Quit(); } diff --git a/src/apps/deskcalc/CalcView.cpp b/src/apps/deskcalc/CalcView.cpp index b2af685692..db300550c3 100644 --- a/src/apps/deskcalc/CalcView.cpp +++ b/src/apps/deskcalc/CalcView.cpp @@ -185,7 +185,7 @@ CalcView::~CalcView() free(fKeypadDescription); // replicant deleted, destroy the about window - if (fAboutWindow != NULL) + if (fAboutWindow != NULL && fAboutWindow->Lock()) fAboutWindow->Quit(); } diff --git a/src/apps/networkstatus/NetworkStatusView.cpp b/src/apps/networkstatus/NetworkStatusView.cpp index ccbdb85b9a..8738aace42 100644 --- a/src/apps/networkstatus/NetworkStatusView.cpp +++ b/src/apps/networkstatus/NetworkStatusView.cpp @@ -139,7 +139,7 @@ NetworkStatusView::NetworkStatusView(BMessage* archive) NetworkStatusView::~NetworkStatusView() { - if (fAboutWindow != NULL) + if (fAboutWindow != NULL && fAboutWindow->Lock()) fAboutWindow->Quit(); } diff --git a/src/apps/processcontroller/ProcessController.cpp b/src/apps/processcontroller/ProcessController.cpp index fbf3127848..5a4b2ff8e0 100644 --- a/src/apps/processcontroller/ProcessController.cpp +++ b/src/apps/processcontroller/ProcessController.cpp @@ -206,7 +206,7 @@ ProcessController::~ProcessController() gPCView = NULL; // replicant deleted, destroy the about window - if (fAboutWindow != NULL) + if (fAboutWindow != NULL && fAboutWindow->Lock()) fAboutWindow->Quit(); } diff --git a/src/apps/workspaces/Workspaces.cpp b/src/apps/workspaces/Workspaces.cpp index f5d5de5467..3dd2af7b0a 100644 --- a/src/apps/workspaces/Workspaces.cpp +++ b/src/apps/workspaces/Workspaces.cpp @@ -374,7 +374,7 @@ WorkspacesView::WorkspacesView(BMessage* archive) WorkspacesView::~WorkspacesView() { - if (fAboutWindow != NULL) + if (fAboutWindow != NULL && fAboutWindow->Lock()) fAboutWindow->Quit(); } From c56757fb7c64e78f9e2b1eb694ee3e9ed9ab1e48 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Mon, 17 Dec 2012 20:46:14 -0500 Subject: [PATCH 03/17] Remove unnecessary frame parameter. Adjust callers. --- src/apps/debugger/controllers/DebugReportGenerator.cpp | 2 +- src/apps/debugger/user_interface/util/UiUtils.cpp | 6 +++--- src/apps/debugger/user_interface/util/UiUtils.h | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/apps/debugger/controllers/DebugReportGenerator.cpp b/src/apps/debugger/controllers/DebugReportGenerator.cpp index a5b985c4a4..5c175c17c5 100644 --- a/src/apps/debugger/controllers/DebugReportGenerator.cpp +++ b/src/apps/debugger/controllers/DebugReportGenerator.cpp @@ -338,7 +338,7 @@ DebugReportGenerator::_DumpDebuggedThreadInfo(BString& _output, containerLocker.Unlock(); _ResolveValueIfNeeded(child->Node(), frame, 1); containerLocker.Lock(); - UiUtils::PrintValueNodeGraph(_output, frame, child, 3, 1); + UiUtils::PrintValueNodeGraph(_output, child, 3, 1); } _output << "\n"; } diff --git a/src/apps/debugger/user_interface/util/UiUtils.cpp b/src/apps/debugger/user_interface/util/UiUtils.cpp index 9559f9f772..fa93d7dd52 100644 --- a/src/apps/debugger/user_interface/util/UiUtils.cpp +++ b/src/apps/debugger/user_interface/util/UiUtils.cpp @@ -163,8 +163,8 @@ UiUtils::ReportNameForTeam(::Team* team, char* buffer, size_t bufferSize) /*static*/ void -UiUtils::PrintValueNodeGraph(BString& _output, StackFrame* frame, - ValueNodeChild* child, int32 indentLevel, int32 maxDepth) +UiUtils::PrintValueNodeGraph(BString& _output, ValueNodeChild* child, + int32 indentLevel, int32 maxDepth) { _output.Append('\t', indentLevel); _output << child->Name(); @@ -215,7 +215,7 @@ UiUtils::PrintValueNodeGraph(BString& _output, StackFrame* frame, // level node contains no data of intereest. if (node->ChildAt(i)->GetType()->Kind() != TYPE_COMPOUND || maxDepth > 1) { - PrintValueNodeGraph(_output, frame, node->ChildAt(i), + PrintValueNodeGraph(_output, node->ChildAt(i), indentLevel + 1, maxDepth - 1); } } diff --git a/src/apps/debugger/user_interface/util/UiUtils.h b/src/apps/debugger/user_interface/util/UiUtils.h index 3e81de83de..437b34c864 100644 --- a/src/apps/debugger/user_interface/util/UiUtils.h +++ b/src/apps/debugger/user_interface/util/UiUtils.h @@ -34,7 +34,6 @@ public: // this function assumes the value nodes have already been resolved // (if possible). static void PrintValueNodeGraph(BString& _output, - StackFrame* frame, ValueNodeChild* child, int32 indentLevel, int32 maxDepth); }; From 596922bb7f69c3f2c267415886e90574efc53d59 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Mon, 17 Dec 2012 20:46:27 -0500 Subject: [PATCH 04/17] Add CLI print variable command. --- src/apps/debugger/Jamfile | 3 +- .../cli/CliPrintVariableCommand.cpp | 172 ++++++++++++++++++ .../cli/CliPrintVariableCommand.h | 33 ++++ .../cli/CommandLineUserInterface.cpp | 2 + 4 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 src/apps/debugger/user_interface/cli/CliPrintVariableCommand.cpp create mode 100644 src/apps/debugger/user_interface/cli/CliPrintVariableCommand.h diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 4a3795c974..0d7ea52b64 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -193,12 +193,13 @@ Application Debugger : CliContext.cpp CliContinueCommand.cpp CliDebugReportCommand.cpp + CliPrintVariableCommand.cpp + CliQuitCommand.cpp CliStackFrameCommand.cpp CliStackTraceCommand.cpp CliStopCommand.cpp CliThreadCommand.cpp CliThreadsCommand.cpp - CliQuitCommand.cpp CliVariablesCommand.cpp CommandLineUserInterface.cpp diff --git a/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.cpp b/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.cpp new file mode 100644 index 0000000000..335dba6f76 --- /dev/null +++ b/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.cpp @@ -0,0 +1,172 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ + + +#include "CliPrintVariableCommand.h" + +#include + +#include + +#include "CliContext.h" +#include "StackFrame.h" +#include "StackTrace.h" +#include "Team.h" +#include "Type.h" +#include "UiUtils.h" +#include "UserInterface.h" +#include "ValueLoader.h" +#include "ValueLocation.h" +#include "ValueNode.h" +#include "ValueNodeContainer.h" +#include "ValueNodeManager.h" + + +CliPrintVariableCommand::CliPrintVariableCommand() + : + CliCommand("print value(s) of a variable", + "%s [--depth n] variable [variable2 ...]\n" + "Prints the value and members of the named variable.") +{ +} + + +void +CliPrintVariableCommand::Execute(int argc, const char* const* argv, + CliContext& context) +{ + if (argc < 2) { + PrintUsage(argv[0]); + return; + } + + ValueNodeManager* manager = context.GetValueNodeManager(); + + ValueNodeContainer* container = manager->GetContainer(); + AutoLocker containerLocker(container); + if (container == NULL || container->CountChildren() == 0) { + printf("No variables available.\n"); + return; + } + + int32 depth = 1; + int32 i = 1; + for (; i < argc; i++) { + if (strcmp(argv[i], "--depth") == 0) { + if (i == argc - 1) { + printf("Error: An argument must be supplied for depth.\n"); + return; + } + char* endPointer; + depth = strtol(argv[i + 1], &endPointer, 0); + if (*endPointer != '\0' || depth < 0) { + printf("Error: Invalid parameter \"%s\"\n", argv[i + 1]); + return; + } + i++; + } + else + break; + } + + if (i == argc) { + printf("Error: At least one variable name must be supplied.\n"); + return; + } + + bool found = false; + while (i < argc) { + // TODO: support variable expressions in addition to just names. + const char* variableName = argv[i++]; + for (int32 j = 0; ValueNodeChild* child = container->ChildAt(j); j++) { + if (child->Name() == variableName) { + found = true; + containerLocker.Unlock(); + _ResolveValueIfNeeded(child->Node(), context, depth); + containerLocker.Lock(); + BString data; + UiUtils::PrintValueNodeGraph(data, child, 1, depth); + printf("%s", data.String()); + } + } + + if (!found) + printf("No such variable: %s\n", variableName); + found = false; + } +} + + +status_t +CliPrintVariableCommand::_ResolveValueIfNeeded(ValueNode* node, + CliContext& context, int32 maxDepth) +{ + StackFrame* frame = context.GetStackTrace()->FrameAt( + context.CurrentStackFrameIndex()); + if (frame == NULL) + return B_BAD_DATA; + + status_t result = B_OK; + ValueNodeManager* manager = context.GetValueNodeManager(); + ValueNodeContainer* container = manager->GetContainer(); + AutoLocker containerLocker(container); + if (node->LocationAndValueResolutionState() == VALUE_NODE_UNRESOLVED) { + context.GetUserInterfaceListener()->ValueNodeValueRequested( + context.CurrentThread()->GetCpuState(), container, node); + + // TODO: implement proper waiting + while (!context.IsTerminating()) { + context.ProcessPendingEvents(); + if (node->LocationAndValueResolutionState() + != VALUE_NODE_UNRESOLVED) { + break; + } + containerLocker.Unlock(); + snooze(20000); + containerLocker.Lock(); + } + } + + if (node->LocationAndValueResolutionState() == B_OK && maxDepth > 0) { + for (int32 i = 0; i < node->CountChildren(); i++) { + ValueNodeChild* child = node->ChildAt(i); + containerLocker.Unlock(); + result = _ResolveLocationIfNeeded(child, frame, context.GetTeam()); + if (result != B_OK) + continue; + + result = manager->AddChildNodes(child); + if (result != B_OK) + continue; + + // since in the case of a pointer to a compound we hide + // the intervening compound, don't consider the hidden node + // a level for the purposes of depth traversal + if (node->GetType()->Kind() == TYPE_ADDRESS + && child->GetType()->Kind() == TYPE_COMPOUND) { + _ResolveValueIfNeeded(child->Node(), context, maxDepth); + } else + _ResolveValueIfNeeded(child->Node(), context, maxDepth - 1); + containerLocker.Lock(); + } + } + + return result; +} + + +status_t +CliPrintVariableCommand::_ResolveLocationIfNeeded(ValueNodeChild* child, + StackFrame* frame, ::Team* team) +{ + ValueLocation* location = NULL; + ValueLoader loader(team->GetArchitecture(), team->GetTeamMemory(), + team->GetTeamTypeInformation(), frame->GetCpuState()); + status_t result = child->ResolveLocation(&loader, location); + child->SetLocation(location, result); + if (location != NULL) + location->ReleaseReference(); + return result; +} diff --git a/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.h b/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.h new file mode 100644 index 0000000000..aae38adcfc --- /dev/null +++ b/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#ifndef CLI_PRINT_VARIABLE_COMMAND_H +#define CLI_PRINT_VARIABLE_COMMAND_H + + +#include "CliCommand.h" + + +class Team; +class StackFrame; +class ValueNode; +class ValueNodeChild; + + +class CliPrintVariableCommand : public CliCommand { +public: + CliPrintVariableCommand(); + virtual void Execute(int argc, const char* const* argv, + CliContext& context); + +private: + status_t _ResolveValueIfNeeded(ValueNode* node, + CliContext& context, int32 maxDepth); + + status_t _ResolveLocationIfNeeded(ValueNodeChild* child, + StackFrame* frame, ::Team* team); +}; + + +#endif // CLI_PRINT_VARIABLE_COMMAND_H diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp index de846471e2..92ef51139c 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 "CliPrintVariableCommand.h" #include "CliQuitCommand.h" #include "CliStackFrameCommand.h" #include "CliStackTraceCommand.h" @@ -313,6 +314,7 @@ CommandLineUserInterface::_RegisterCommands() && _RegisterCommand("continue", new(std::nothrow) CliContinueCommand) && _RegisterCommand("frame", new(std::nothrow) CliStackFrameCommand) && _RegisterCommand("help", new(std::nothrow) HelpCommand(this)) + && _RegisterCommand("print", new(std::nothrow) CliPrintVariableCommand) && _RegisterCommand("quit", new(std::nothrow) CliQuitCommand) && _RegisterCommand("save-report", new(std::nothrow) CliDebugReportCommand) From 6e5f42ccc9b4d6618cd946bade13dd274c79c8d0 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Tue, 18 Dec 2012 14:47:02 +0000 Subject: [PATCH 05/17] Added OpenSSL for x86_64. --- build/jam/BuildFeatures | 12 ++++++++---- build/jam/Haiku64Image | 7 +++++++ build/jam/OptionalPackages | 13 ++++--------- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/build/jam/BuildFeatures b/build/jam/BuildFeatures index 3a3873a111..625998d159 100644 --- a/build/jam/BuildFeatures +++ b/build/jam/BuildFeatures @@ -29,7 +29,11 @@ if [ IsOptionalHaikuImagePackageAdded OpenSSL ] { } if $(HAIKU_GCC_VERSION[1]) >= 4 { - HAIKU_OPENSSL_PACKAGE = openssl-1.0.0j-r1a4-x86-gcc4-2012-08-29.zip ; + if $(TARGET_ARCH) = x86_64 { + HAIKU_OPENSSL_PACKAGE = openssl-1.0.0j-x86_64-2012-12-18.zip ; + } else { + HAIKU_OPENSSL_PACKAGE = openssl-1.0.0j-r1a4-x86-gcc4-2012-08-29.zip ; + } } else { HAIKU_OPENSSL_PACKAGE = openssl-1.0.0j-r1a4-x86-gcc2-2012-08-26.zip ; } @@ -37,9 +41,7 @@ if $(HAIKU_GCC_VERSION[1]) >= 4 { HAIKU_OPENSSL_URL = $(baseURL)/$(HAIKU_OPENSSL_PACKAGE) ; if $(HAIKU_BUILD_FEATURE_SSL) { - if $(TARGET_ARCH) != x86 { - Echo "SSL build feature not available for $(TARGET_ARCH)" ; - } else { + if $(TARGET_ARCH) = x86 || $(TARGET_ARCH) = x86_64 { # Download the zip archive. local zipFile = [ DownloadFile $(HAIKU_OPENSSL_PACKAGE) : $(HAIKU_OPENSSL_URL) ] ; @@ -66,6 +68,8 @@ if $(HAIKU_BUILD_FEATURE_SSL) { = [ FDirName $(HAIKU_OPENSSL_DIR) common include ] ; EnableBuildFeatures openssl ; + } else { + Echo "SSL build feature not available for $(TARGET_ARCH)" ; } } diff --git a/build/jam/Haiku64Image b/build/jam/Haiku64Image index 70878d2559..abc726e629 100644 --- a/build/jam/Haiku64Image +++ b/build/jam/Haiku64Image @@ -119,6 +119,13 @@ AddFilesToHaikuImage system : kernel_$(TARGET_ARCH) ; AddLibrariesToHaikuHybridImage system lib : $(SYSTEM_LIBS) $(PRIVATE_SYSTEM_LIBS) ; +OPTIONAL_LIBS_ALIASES = + libfreetype.so + libjpeg.so + libpng.so + libz.so +; + # libfreetype.so links to the current freetype lib AddSymlinkToHaikuHybridImage system lib : $(HAIKU_FREETYPE_CURRENT_LIB:BS) : $(HAIKU_FREETYPE_CURRENT_LINK) : : true ; diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index 9950e588e2..2511aada12 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -1661,16 +1661,11 @@ if [ IsOptionalHaikuImagePackageAdded OpenSSH ] { # OpenSSL if [ IsOptionalHaikuImagePackageAdded OpenSSL ] { - if $(TARGET_ARCH) != x86 { - Echo "No optional package OpenSSL available for $(TARGET_ARCH)" ; + if $(TARGET_ARCH) = x86 || $(TARGET_ARCH) = x86_64 { + InstallOptionalHaikuImagePackage $(HAIKU_OPENSSL_PACKAGE) + : $(HAIKU_OPENSSL_URL) ; } else { - if $(HAIKU_GCC_VERSION[1]) >= 4 { - InstallOptionalHaikuImagePackage $(HAIKU_OPENSSL_PACKAGE) - : $(HAIKU_OPENSSL_URL) ; - } else { - InstallOptionalHaikuImagePackage $(HAIKU_OPENSSL_PACKAGE) - : $(HAIKU_OPENSSL_URL) ; - } + Echo "No optional package OpenSSL available for $(TARGET_ARCH)" ; } } From b7b5d7636b96de53bb4327684cc1843e56f62320 Mon Sep 17 00:00:00 2001 From: Sergei Reznikov Date: Mon, 17 Dec 2012 22:14:47 +0400 Subject: [PATCH 06/17] 64-bit fixes for kernel with KDEBUG_LEVEL = 0 Signed-off-by: Alex Smith --- src/system/kernel/locks/lock.cpp | 2 +- src/system/kernel/sem.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/system/kernel/locks/lock.cpp b/src/system/kernel/locks/lock.cpp index fda4d321b6..caebd36c5b 100644 --- a/src/system/kernel/locks/lock.cpp +++ b/src/system/kernel/locks/lock.cpp @@ -891,7 +891,7 @@ dump_mutex_info(int argc, char** argv) #if KDEBUG kprintf(" holder: %" B_PRId32 "\n", lock->holder); #else - kprintf(" count: %ld\n", lock->count); + kprintf(" count: %" B_PRId32 "\n", lock->count); #endif kprintf(" waiting threads:"); diff --git a/src/system/kernel/sem.cpp b/src/system/kernel/sem.cpp index 747428e4c9..13fe243b4d 100644 --- a/src/system/kernel/sem.cpp +++ b/src/system/kernel/sem.cpp @@ -209,7 +209,7 @@ dump_sem(struct sem_entry* sem) else unset_debug_variable("_releaser"); #else - kprintf("last acquired by: %ld\n", sem->u.used.last_acquirer); + kprintf("last acquired by: %" B_PRId32 "\n", sem->u.used.last_acquirer); #endif if (sem->u.used.last_acquirer != 0) From 68359a7361c6bf1731b639f789b932c8c5804454 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 18 Dec 2012 17:36:02 -0500 Subject: [PATCH 07/17] Fix missing newline in some cases. --- src/apps/debugger/user_interface/util/UiUtils.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apps/debugger/user_interface/util/UiUtils.cpp b/src/apps/debugger/user_interface/util/UiUtils.cpp index fa93d7dd52..d44f46a8ff 100644 --- a/src/apps/debugger/user_interface/util/UiUtils.cpp +++ b/src/apps/debugger/user_interface/util/UiUtils.cpp @@ -221,7 +221,8 @@ UiUtils::PrintValueNodeGraph(BString& _output, ValueNodeChild* child, } _output.Append('\t', indentLevel); _output << "}\n"; - } + } else + _output << "\n"; return; } From eceaf78610c282b83758a34a51ce6752faed74ee Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 18 Dec 2012 17:36:49 -0500 Subject: [PATCH 08/17] Remove unnecessary code. - ResolveValueNodeJob() already handles location resolution for the NodeChild so this step is unnecessary. --- .../controllers/DebugReportGenerator.cpp | 23 ++----------------- .../controllers/DebugReportGenerator.h | 2 -- .../cli/CliPrintVariableCommand.cpp | 19 --------------- .../cli/CliPrintVariableCommand.h | 3 --- 4 files changed, 2 insertions(+), 45 deletions(-) diff --git a/src/apps/debugger/controllers/DebugReportGenerator.cpp b/src/apps/debugger/controllers/DebugReportGenerator.cpp index 5c175c17c5..983d2d3f5a 100644 --- a/src/apps/debugger/controllers/DebugReportGenerator.cpp +++ b/src/apps/debugger/controllers/DebugReportGenerator.cpp @@ -336,9 +336,9 @@ DebugReportGenerator::_DumpDebuggedThreadInfo(BString& _output, for (int32 i = 0; i < container->CountChildren(); i++) { ValueNodeChild* child = container->ChildAt(i); containerLocker.Unlock(); - _ResolveValueIfNeeded(child->Node(), frame, 1); + _ResolveValueIfNeeded(child->Node(), frame, 2); containerLocker.Lock(); - UiUtils::PrintValueNodeGraph(_output, child, 3, 1); + UiUtils::PrintValueNodeGraph(_output, child, 3, 2); } _output << "\n"; } @@ -380,10 +380,6 @@ DebugReportGenerator::_ResolveValueIfNeeded(ValueNode* node, StackFrame* frame, for (int32 i = 0; i < node->CountChildren(); i++) { ValueNodeChild* child = node->ChildAt(i); containerLocker.Unlock(); - result = _ResolveLocationIfNeeded(child, frame); - if (result != B_OK) - continue; - result = fNodeManager->AddChildNodes(child); if (result != B_OK) continue; @@ -402,18 +398,3 @@ DebugReportGenerator::_ResolveValueIfNeeded(ValueNode* node, StackFrame* frame, return result; } - - -status_t -DebugReportGenerator::_ResolveLocationIfNeeded(ValueNodeChild* child, - StackFrame* frame) -{ - ValueLocation* location = NULL; - ValueLoader loader(fTeam->GetArchitecture(), fTeam->GetTeamMemory(), - fTeam->GetTeamTypeInformation(), frame->GetCpuState()); - status_t result = child->ResolveLocation(&loader, location); - child->SetLocation(location, result); - if (location != NULL) - location->ReleaseReference(); - return result; -} diff --git a/src/apps/debugger/controllers/DebugReportGenerator.h b/src/apps/debugger/controllers/DebugReportGenerator.h index 677334cfd5..01ae75ece0 100644 --- a/src/apps/debugger/controllers/DebugReportGenerator.h +++ b/src/apps/debugger/controllers/DebugReportGenerator.h @@ -52,8 +52,6 @@ private: status_t _DumpDebuggedThreadInfo(BString& output, ::Thread* thread); - status_t _ResolveLocationIfNeeded(ValueNodeChild* child, - StackFrame* frame); status_t _ResolveValueIfNeeded(ValueNode* node, StackFrame* frame, int32 maxDepth); diff --git a/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.cpp b/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.cpp index 335dba6f76..2bb2eb1328 100644 --- a/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.cpp +++ b/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.cpp @@ -133,10 +133,6 @@ CliPrintVariableCommand::_ResolveValueIfNeeded(ValueNode* node, for (int32 i = 0; i < node->CountChildren(); i++) { ValueNodeChild* child = node->ChildAt(i); containerLocker.Unlock(); - result = _ResolveLocationIfNeeded(child, frame, context.GetTeam()); - if (result != B_OK) - continue; - result = manager->AddChildNodes(child); if (result != B_OK) continue; @@ -155,18 +151,3 @@ CliPrintVariableCommand::_ResolveValueIfNeeded(ValueNode* node, return result; } - - -status_t -CliPrintVariableCommand::_ResolveLocationIfNeeded(ValueNodeChild* child, - StackFrame* frame, ::Team* team) -{ - ValueLocation* location = NULL; - ValueLoader loader(team->GetArchitecture(), team->GetTeamMemory(), - team->GetTeamTypeInformation(), frame->GetCpuState()); - status_t result = child->ResolveLocation(&loader, location); - child->SetLocation(location, result); - if (location != NULL) - location->ReleaseReference(); - return result; -} diff --git a/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.h b/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.h index aae38adcfc..fe75363e87 100644 --- a/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.h +++ b/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.h @@ -24,9 +24,6 @@ public: private: status_t _ResolveValueIfNeeded(ValueNode* node, CliContext& context, int32 maxDepth); - - status_t _ResolveLocationIfNeeded(ValueNodeChild* child, - StackFrame* frame, ::Team* team); }; From 486c4d38b276d221d011f33ebce8c0d7d0b22f9c Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 18 Dec 2012 18:11:28 -0500 Subject: [PATCH 09/17] Revert unintended change in previous commit. --- src/apps/debugger/controllers/DebugReportGenerator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/debugger/controllers/DebugReportGenerator.cpp b/src/apps/debugger/controllers/DebugReportGenerator.cpp index 983d2d3f5a..e37ff70840 100644 --- a/src/apps/debugger/controllers/DebugReportGenerator.cpp +++ b/src/apps/debugger/controllers/DebugReportGenerator.cpp @@ -336,9 +336,9 @@ DebugReportGenerator::_DumpDebuggedThreadInfo(BString& _output, for (int32 i = 0; i < container->CountChildren(); i++) { ValueNodeChild* child = container->ChildAt(i); containerLocker.Unlock(); - _ResolveValueIfNeeded(child->Node(), frame, 2); + _ResolveValueIfNeeded(child->Node(), frame, 1); containerLocker.Lock(); - UiUtils::PrintValueNodeGraph(_output, child, 3, 2); + UiUtils::PrintValueNodeGraph(_output, child, 3, 1); } _output << "\n"; } From 03289a339ceabd34eb4f909f13585a780ac4bef2 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 18 Dec 2012 18:10:22 -0500 Subject: [PATCH 10/17] More adjustments to CliContext. - CliContext now listens for value node container events so that commands can request such a wait as well - Implement an event wait mechanism for commands to make use of. Adjust CliStackTrace and CliPrintVariable accordingly. --- .../user_interface/cli/CliContext.cpp | 49 +++++++++++++++++++ .../debugger/user_interface/cli/CliContext.h | 15 +++++- .../cli/CliPrintVariableCommand.cpp | 14 +++--- .../cli/CliStackTraceCommand.cpp | 10 ++-- 4 files changed, 73 insertions(+), 15 deletions(-) diff --git a/src/apps/debugger/user_interface/cli/CliContext.cpp b/src/apps/debugger/user_interface/cli/CliContext.cpp index 7b430dc19d..7654b3ec62 100644 --- a/src/apps/debugger/user_interface/cli/CliContext.cpp +++ b/src/apps/debugger/user_interface/cli/CliContext.cpp @@ -118,6 +118,7 @@ CliContext::Init(Team* team, UserInterfaceListener* listener) fNodeManager = new(std::nothrow) ValueNodeManager(); if (fNodeManager == NULL) return B_NO_MEMORY; + fNodeManager->AddListener(this); return B_OK; } @@ -316,6 +317,25 @@ CliContext::WaitForThreadOrUser() } +void +CliContext::WaitForEvents(int32 eventMask) +{ + for (;;) { + _PrepareToWaitForEvents(eventMask | EVENT_USER_INTERRUPT); + uint32 events = fEventsOccurred; + if ((events & eventMask) == 0) { + events = _WaitForEvents(); + } + + if ((events & EVENT_QUIT) != 0 || (events & eventMask) != 0) { + _SignalInputLoop(eventMask); + ProcessPendingEvents(); + return; + } + } +} + + void CliContext::ProcessPendingEvents() { @@ -404,6 +424,35 @@ CliContext::ThreadStackTraceChanged(const Team::ThreadEvent& threadEvent) } +void +CliContext::ValueNodeChanged(ValueNodeChild* nodeChild, ValueNode* oldNode, + ValueNode* newNode) +{ + _SignalInputLoop(EVENT_VALUE_NODE_CHANGED); +} + + +void +CliContext::ValueNodeChildrenCreated(ValueNode* node) +{ + _SignalInputLoop(EVENT_VALUE_NODE_CHANGED); +} + + +void +CliContext::ValueNodeChildrenDeleted(ValueNode* node) +{ + _SignalInputLoop(EVENT_VALUE_NODE_CHANGED); +} + + +void +CliContext::ValueNodeValueChanged(ValueNode* oldNode) +{ + _SignalInputLoop(EVENT_VALUE_NODE_CHANGED); +} + + void CliContext::_QueueEvent(Event* event) { diff --git a/src/apps/debugger/user_interface/cli/CliContext.h b/src/apps/debugger/user_interface/cli/CliContext.h index faf6bfa3ae..09d79d87f7 100644 --- a/src/apps/debugger/user_interface/cli/CliContext.h +++ b/src/apps/debugger/user_interface/cli/CliContext.h @@ -13,6 +13,7 @@ #include #include "Team.h" +#include "ValueNodeContainer.h" class StackFrame; @@ -22,7 +23,8 @@ class UserInterfaceListener; class ValueNodeManager; -class CliContext : private Team::Listener { +class CliContext : private Team::Listener, + private ValueNodeContainer::Listener { public: enum { EVENT_QUIT = 0x01, @@ -30,7 +32,8 @@ public: EVENT_THREAD_ADDED = 0x04, EVENT_THREAD_REMOVED = 0x08, EVENT_THREAD_STOPPED = 0x10, - EVENT_THREAD_STACK_TRACE_CHANGED = 0x20 + EVENT_THREAD_STACK_TRACE_CHANGED = 0x20, + EVENT_VALUE_NODE_CHANGED = 0x40 }; public: @@ -70,6 +73,7 @@ public: void QuitSession(bool killTeam); void WaitForThreadOrUser(); + void WaitForEvents(int32 eventMask); void ProcessPendingEvents(); private: @@ -87,6 +91,13 @@ private: virtual void ThreadStackTraceChanged( const Team::ThreadEvent& event); + // ValueNodeContainer::Listener + virtual void ValueNodeChanged(ValueNodeChild* nodeChild, + ValueNode* oldNode, ValueNode* newNode); + virtual void ValueNodeChildrenCreated(ValueNode* node); + virtual void ValueNodeChildrenDeleted(ValueNode* node); + virtual void ValueNodeValueChanged(ValueNode* node); + private: void _QueueEvent(Event* event); diff --git a/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.cpp b/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.cpp index 2bb2eb1328..2c984fe7e7 100644 --- a/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.cpp +++ b/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.cpp @@ -116,16 +116,14 @@ CliPrintVariableCommand::_ResolveValueIfNeeded(ValueNode* node, context.GetUserInterfaceListener()->ValueNodeValueRequested( context.CurrentThread()->GetCpuState(), container, node); - // TODO: implement proper waiting - while (!context.IsTerminating()) { - context.ProcessPendingEvents(); - if (node->LocationAndValueResolutionState() - != VALUE_NODE_UNRESOLVED) { - break; - } + + while (node->LocationAndValueResolutionState() + == VALUE_NODE_UNRESOLVED) { containerLocker.Unlock(); - snooze(20000); + context.WaitForEvents(CliContext::EVENT_VALUE_NODE_CHANGED); containerLocker.Lock(); + if (context.IsTerminating()) + return B_ERROR; } } diff --git a/src/apps/debugger/user_interface/cli/CliStackTraceCommand.cpp b/src/apps/debugger/user_interface/cli/CliStackTraceCommand.cpp index 9e7f0330a6..37885e2640 100644 --- a/src/apps/debugger/user_interface/cli/CliStackTraceCommand.cpp +++ b/src/apps/debugger/user_interface/cli/CliStackTraceCommand.cpp @@ -45,11 +45,11 @@ CliStackTraceCommand::Execute(int argc, const char* const* argv, // get its stack trace StackTrace* stackTrace = thread->GetStackTrace(); - if (stackTrace == NULL) { - // TODO: Wait for stack trace! - printf("Current thread doesn't have a stack trace. Waiting not " - "implemented yet\n"); - return; + while (stackTrace == NULL) { + context.WaitForEvents(CliContext::EVENT_THREAD_STACK_TRACE_CHANGED); + if (context.IsTerminating()) + return; + stackTrace = thread->GetStackTrace(); } BReference stackTraceReference(stackTrace); // hold a reference until we're done From 55751d083a85ed8ee7f09ab06aedc598eea23f23 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 18 Dec 2012 21:31:43 -0500 Subject: [PATCH 11/17] Move Tokenizer/Token into ExpressionParser's namespace. --- headers/private/shared/ExpressionParser.h | 8 +++++--- src/kits/shared/ExpressionParser.cpp | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/headers/private/shared/ExpressionParser.h b/headers/private/shared/ExpressionParser.h index 95df720db4..b180b87e17 100644 --- a/headers/private/shared/ExpressionParser.h +++ b/headers/private/shared/ExpressionParser.h @@ -14,8 +14,6 @@ #include -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(); @@ -52,6 +50,10 @@ class ExpressionParser { int64 EvaluateToInt64(const char* expressionString); double EvaluateToDouble(const char* expressionString); + private: + struct Token; + class Tokenizer; + private: MAPM _ParseBinary(); MAPM _ParseSum(); diff --git a/src/kits/shared/ExpressionParser.cpp b/src/kits/shared/ExpressionParser.cpp index c49c67d3a2..b75c0e2c79 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)); From 779b84b17b58a8818cba622a2e416163a06a431f Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 18 Dec 2012 21:32:04 -0500 Subject: [PATCH 12/17] Add memory dumping helper to UiUtils. - Adapted from KDL's db/dw et al. --- .../debugger/user_interface/util/UiUtils.cpp | 62 +++++++++++++++++++ .../debugger/user_interface/util/UiUtils.h | 9 +++ 2 files changed, 71 insertions(+) diff --git a/src/apps/debugger/user_interface/util/UiUtils.cpp b/src/apps/debugger/user_interface/util/UiUtils.cpp index d44f46a8ff..28418222a9 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 #include #include @@ -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 437b34c864..cffb70043e 100644 --- a/src/apps/debugger/user_interface/util/UiUtils.h +++ b/src/apps/debugger/user_interface/util/UiUtils.h @@ -9,13 +9,17 @@ #include +#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); }; From c7f5dd6207ea0c29c149067fe5f46cb95fd3e576 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 18 Dec 2012 21:32:47 -0500 Subject: [PATCH 13/17] Add support for memory block events to CliContext. --- .../user_interface/cli/CliContext.cpp | 36 +++++++++++++++++-- .../debugger/user_interface/cli/CliContext.h | 12 ++++++- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/apps/debugger/user_interface/cli/CliContext.cpp b/src/apps/debugger/user_interface/cli/CliContext.cpp index 7654b3ec62..f939ec1242 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 { - 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 { return fThreadReference.Get(); } + TeamMemoryBlock* GetMemoryBlock() const + { + return fMemoryBlockReference.Get(); + } + private: int fType; BReference fThreadReference; + BReference 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; } } } @@ -424,6 +444,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 09d79d87f7..cb4657a308 100644 --- a/src/apps/debugger/user_interface/cli/CliContext.h +++ b/src/apps/debugger/user_interface/cli/CliContext.h @@ -13,17 +13,20 @@ #include #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; }; From ec7c59ca09cff4de780eb06a10144ff75c86ac5a Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 18 Dec 2012 21:33:21 -0500 Subject: [PATCH 14/17] Add memory dumping commands similar to those in KDL. --- src/apps/debugger/Jamfile | 1 + .../cli/CliDumpMemoryCommand.cpp | 127 ++++++++++++++++++ .../user_interface/cli/CliDumpMemoryCommand.h | 22 +++ .../cli/CommandLineUserInterface.cpp | 19 +++ 4 files changed, 169 insertions(+) create mode 100644 src/apps/debugger/user_interface/cli/CliDumpMemoryCommand.cpp create mode 100644 src/apps/debugger/user_interface/cli/CliDumpMemoryCommand.h diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 0d7ea52b64..b219fe4034 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 0000000000..cd9049a1c2 --- /dev/null +++ b/src/apps/debugger/user_interface/cli/CliDumpMemoryCommand.cpp @@ -0,0 +1,127 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ + + +#include "CliDumpMemoryCommand.h" + +#include +#include + +#include +#include + +#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 0000000000..5c8a0fb00f --- /dev/null +++ b/src/apps/debugger/user_interface/cli/CliDumpMemoryCommand.h @@ -0,0 +1,22 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * 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 92ef51139c..85a204b3d6 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 stackTraceCommandReference2( stackTraceCommandReference.Get()); + BReference dumpCommandReference( + new(std::nothrow) CliDumpMemoryCommand, true); + BReference 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) From 9a4802db55d5e9a02cbc2983b2bf74f2a16bf0a5 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 18 Dec 2012 23:30:18 -0500 Subject: [PATCH 15/17] Add an indent parameter to DumpMemory(). - Adjust callers. --- .../user_interface/cli/CliDumpMemoryCommand.cpp | 2 +- src/apps/debugger/user_interface/util/UiUtils.cpp | 10 +++++++--- src/apps/debugger/user_interface/util/UiUtils.h | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/apps/debugger/user_interface/cli/CliDumpMemoryCommand.cpp b/src/apps/debugger/user_interface/cli/CliDumpMemoryCommand.cpp index cd9049a1c2..4d8c7d8b66 100644 --- a/src/apps/debugger/user_interface/cli/CliDumpMemoryCommand.cpp +++ b/src/apps/debugger/user_interface/cli/CliDumpMemoryCommand.cpp @@ -120,7 +120,7 @@ CliDumpMemoryCommand::Execute(int argc, const char* const* argv, printf("\"\n"); } else { BString output; - UiUtils::DumpMemory(output, block, address, itemSize, displayWidth, + UiUtils::DumpMemory(output, 0, block, address, itemSize, displayWidth, num); printf("%s\n", output.String()); } diff --git a/src/apps/debugger/user_interface/util/UiUtils.cpp b/src/apps/debugger/user_interface/util/UiUtils.cpp index 28418222a9..2b3e2d157f 100644 --- a/src/apps/debugger/user_interface/util/UiUtils.cpp +++ b/src/apps/debugger/user_interface/util/UiUtils.cpp @@ -230,19 +230,23 @@ UiUtils::PrintValueNodeGraph(BString& _output, ValueNodeChild* child, } -/*static*/ void UiUtils::DumpMemory(BString& _output, TeamMemoryBlock* block, - target_addr_t address, int32 itemSize, int32 displayWidth, int32 count) +/*static*/ void UiUtils::DumpMemory(BString& _output, int32 indentLevel, + TeamMemoryBlock* block, target_addr_t address, int32 itemSize, + int32 displayWidth, int32 count) { BString data; int32 j; + _output.Append('\t', indentLevel); for (int32 i = 0; i < count; i++) { uint8* value; if ((i % displayWidth) == 0) { int32 displayed = min_c(displayWidth, (count-i)) * itemSize; - if (i != 0) + if (i != 0) { _output.Append("\n"); + _output.Append('\t', indentLevel); + } data.SetToFormat("[%#" B_PRIx64 "] ", address + i * itemSize); _output += data; diff --git a/src/apps/debugger/user_interface/util/UiUtils.h b/src/apps/debugger/user_interface/util/UiUtils.h index cffb70043e..7f6447d06e 100644 --- a/src/apps/debugger/user_interface/util/UiUtils.h +++ b/src/apps/debugger/user_interface/util/UiUtils.h @@ -42,6 +42,7 @@ public: int32 indentLevel, int32 maxDepth); static void DumpMemory(BString& _output, + int32 indentLevel, TeamMemoryBlock* block, target_addr_t address, int32 itemSize, int32 displayWidth, int32 count); From 3e441f885e85e7f22c41a0e52100d0569bd6874a Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 18 Dec 2012 23:31:08 -0500 Subject: [PATCH 16/17] Add frame dumping capabilities to report generator. - If the top frame of a stopped thread has no arguments or variables available, dump the memory block to which the stack frame belongs, starting at the current stack pointer and extending to the end of the block. --- .../controllers/DebugReportGenerator.cpp | 42 ++++++++++++++++++- .../controllers/DebugReportGenerator.h | 21 +++++++--- 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/apps/debugger/controllers/DebugReportGenerator.cpp b/src/apps/debugger/controllers/DebugReportGenerator.cpp index e37ff70840..4041bfe369 100644 --- a/src/apps/debugger/controllers/DebugReportGenerator.cpp +++ b/src/apps/debugger/controllers/DebugReportGenerator.cpp @@ -46,6 +46,7 @@ DebugReportGenerator::DebugReportGenerator(::Team* team, fNodeManager(NULL), fListener(listener), fWaitingNode(NULL), + fCurrentBlock(NULL), fTraceWaitingThread(NULL) { fTeam->AddListener(this); @@ -61,6 +62,9 @@ DebugReportGenerator::~DebugReportGenerator() fNodeManager->RemoveListener(this); fNodeManager->ReleaseReference(); } + + if (fCurrentBlock != NULL) + fCurrentBlock->ReleaseReference(); } @@ -161,6 +165,19 @@ DebugReportGenerator::ThreadStackTraceChanged(const ::Team::ThreadEvent& event) } +void +DebugReportGenerator::MemoryBlockRetrieved(TeamMemoryBlock* block) +{ + if (fCurrentBlock != NULL) { + fCurrentBlock->ReleaseReference(); + fCurrentBlock = NULL; + } + + fCurrentBlock = block; + release_sem(fTeamDataSem); +} + + void DebugReportGenerator::ValueNodeValueChanged(ValueNode* node) { @@ -323,6 +340,9 @@ DebugReportGenerator::_DumpDebuggedThreadInfo(BString& _output, _output << data; if (frame->CountParameters() == 0 && frame->CountLocalVariables() == 0) { + // only dump the topmost frame + if (i == 0) + _DumpStackFrameMemory(_output, thread->GetCpuState()); continue; } @@ -362,6 +382,24 @@ DebugReportGenerator::_DumpDebuggedThreadInfo(BString& _output, } +void +DebugReportGenerator::_DumpStackFrameMemory(BString& _output, + CpuState* state) +{ + target_addr_t address = state->StackPointer(); + if (fCurrentBlock == NULL || !fCurrentBlock->Contains(address)) { + fListener->InspectRequested(address, this); + status_t result = B_OK; + do { + result = acquire_sem(fTeamDataSem); + } while (result == B_INTERRUPTED); + } + _output << "\t\t\tFrame memory:\n"; + UiUtils::DumpMemory(_output, 3, fCurrentBlock, address, 1, 16, + fCurrentBlock->BaseAddress() + fCurrentBlock->Size() - address); +} + + status_t DebugReportGenerator::_ResolveValueIfNeeded(ValueNode* node, StackFrame* frame, int32 maxDepth) @@ -371,7 +409,9 @@ DebugReportGenerator::_ResolveValueIfNeeded(ValueNode* node, StackFrame* frame, fWaitingNode = node; fListener->ValueNodeValueRequested(frame->GetCpuState(), fNodeManager->GetContainer(), node); - result = acquire_sem(fTeamDataSem); + do { + result = acquire_sem(fTeamDataSem); + } while (result == B_INTERRUPTED); } if (node->LocationAndValueResolutionState() == B_OK && maxDepth > 0) { diff --git a/src/apps/debugger/controllers/DebugReportGenerator.h b/src/apps/debugger/controllers/DebugReportGenerator.h index 01ae75ece0..56bf8a4a7c 100644 --- a/src/apps/debugger/controllers/DebugReportGenerator.h +++ b/src/apps/debugger/controllers/DebugReportGenerator.h @@ -9,6 +9,7 @@ #include #include "Team.h" +#include "TeamMemoryBlock.h" #include "ValueNodeContainer.h" @@ -26,7 +27,7 @@ class ValueNodeManager; class DebugReportGenerator : public BLooper, private Team::Listener, - private ValueNodeContainer::Listener { + private TeamMemoryBlock::Listener, private ValueNodeContainer::Listener { public: DebugReportGenerator(::Team* team, UserInterfaceListener* listener); @@ -39,18 +40,27 @@ public: virtual void MessageReceived(BMessage* message); +private: + // Team::Listener virtual void ThreadStackTraceChanged( const Team::ThreadEvent& event); + // TeamMemoryBlock::Listener + virtual void MemoryBlockRetrieved(TeamMemoryBlock* block); + + // ValueNodeContainer::Listener virtual void ValueNodeValueChanged(ValueNode* node); + private: status_t _GenerateReport(const entry_ref& outputPath); - status_t _GenerateReportHeader(BString& output); - status_t _DumpLoadedImages(BString& output); - status_t _DumpRunningThreads(BString& output); - status_t _DumpDebuggedThreadInfo(BString& output, + status_t _GenerateReportHeader(BString& _output); + status_t _DumpLoadedImages(BString& _output); + status_t _DumpRunningThreads(BString& _output); + status_t _DumpDebuggedThreadInfo(BString& _output, ::Thread* thread); + void _DumpStackFrameMemory(BString& _output, + CpuState* state); status_t _ResolveValueIfNeeded(ValueNode* node, StackFrame* frame, int32 maxDepth); @@ -62,6 +72,7 @@ private: ValueNodeManager* fNodeManager; UserInterfaceListener* fListener; ValueNode* fWaitingNode; + TeamMemoryBlock* fCurrentBlock; ::Thread* fTraceWaitingThread; }; From bbdb6052247f0893e1d9102dd2009f10bfa100ea Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 18 Dec 2012 23:51:12 -0500 Subject: [PATCH 17/17] Switch over to using Debugger as the primary system debugger. - When a crash occurs that requires using consoled, use Debugger in CLI mode. - Closes #1078. --- build/jam/HaikuImage | 6 +-- build/jam/OptionalPackages | 1 - src/servers/debug/DebugServer.cpp | 69 ++++++++++++++++++------------- 3 files changed, 44 insertions(+), 32 deletions(-) diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage index 7074a83e0d..1a0b6f7a80 100644 --- a/build/jam/HaikuImage +++ b/build/jam/HaikuImage @@ -44,8 +44,8 @@ SYSTEM_BIN = [ FFilterByBuildFeatures SYSTEM_APPS = [ FFilterByBuildFeatures AboutSystem ActivityMonitor BootManager@x86 CharacterMap - CodyCam DeskCalc Devices DiskProbe DiskUsage DriveSetup CDPlayer Expander - GLInfo@x86 Icon-O-Matic Installer LaunchBox Magnify Mail + CodyCam DeskCalc Devices DiskProbe DiskUsage DriveSetup CDPlayer Debugger + Expander GLInfo@x86 Icon-O-Matic Installer LaunchBox Magnify Mail MediaConverter MediaPlayer MidiPlayer NetworkStatus PackageInstaller People PoorMan PowerStatus ProcessController Screenshot ShowImage SoundRecorder StyledEdit Terminal TextSearch TV WebWatch Workspaces @@ -75,7 +75,7 @@ SYSTEM_LIBS = [ FFilterByBuildFeatures PRIVATE_SYSTEM_LIBS = [ FFilterByBuildFeatures $(HAIKU_JPEG_CURRENT_LIB) $(HAIKU_LIBPNG_CURRENT_LIB) - $(HAIKU_ZLIB_CURRENT_LIB) + $(HAIKU_ZLIB_CURRENT_LIB) $(HAIKU_FREETYPE_CURRENT_LIB) libalm.so libfluidsynth.so diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index 2511aada12..4036abc0f1 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -643,7 +643,6 @@ if [ IsOptionalHaikuImagePackageAdded DemoPackage_Video ] { # Development if [ IsOptionalHaikuImagePackageAdded Development ] { if $(TARGET_ARCH) = x86 { - AddFilesToHaikuImage system apps : Debugger ; AddSymlinkToHaikuImage home config settings deskbar Applications : /boot/system/apps/Debugger : Debugger ; # autotools diff --git a/src/servers/debug/DebugServer.cpp b/src/servers/debug/DebugServer.cpp index 3fa4b73c43..6727c5203f 100644 --- a/src/servers/debug/DebugServer.cpp +++ b/src/servers/debug/DebugServer.cpp @@ -41,8 +41,8 @@ enum { }; -#define HANDOVER_USE_GDB 1 -//#define HANDOVER_USE_DEBUGGER 1 +//#define HANDOVER_USE_GDB 1 +#define HANDOVER_USE_DEBUGGER 1 #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "DebugServer" @@ -555,44 +555,57 @@ TeamDebugHandler::_EnterDebugger(bool saveReport) "terminal (debugger) for team %" B_PRId32 "...\n", fTeam)); #elif defined(HANDOVER_USE_DEBUGGER) + // prepare the argument vector + BPath debuggerPath; if (debugInConsoled) { - error = _SetupGDBArguments(arguments, debugInConsoled); + error = find_directory(B_SYSTEM_BIN_DIRECTORY, &debuggerPath); if (error != B_OK) { - debug_printf("debug_server: Failed to set up gdb arguments: %s\n", + debug_printf("debug_server: can't find system-bin directory: %s\n", strerror(error)); return error; } - } else { - // prepare the argument vector - BPath debuggerPath; - error = find_directory(B_SYSTEM_APPS_DIRECTORY, &debuggerPath); + error = debuggerPath.Append("consoled"); if (error != B_OK) { - debug_printf("debug_server: can't find system-apps directory: %s\n", - strerror(error)); - return error; - } - error = debuggerPath.Append("Debugger"); - if (error != B_OK) { - debug_printf("debug_server: can't append to system-apps path: %s\n", + debug_printf("debug_server: can't append to system-bin path: %s\n", strerror(error)); return error; } + if (!arguments.Add(debuggerPath.Path())) return B_NO_MEMORY; - - BString debuggerParam; - debuggerParam.SetToFormat("%" B_PRId32, fTeam); - if (saveReport) { - if (!arguments.Add("--save-report")) - return B_NO_MEMORY; - } - if (!arguments.Add("--team") || !arguments.Add(debuggerParam)) - return B_NO_MEMORY; - - // start the debugger - TRACE(("debug_server: TeamDebugHandler::_EnterDebugger(): starting " - "graphical debugger for team %" B_PRId32 "...\n", fTeam)); } + + error = find_directory(B_SYSTEM_APPS_DIRECTORY, &debuggerPath); + if (error != B_OK) { + debug_printf("debug_server: can't find system-apps directory: %s\n", + strerror(error)); + return error; + } + error = debuggerPath.Append("Debugger"); + if (error != B_OK) { + debug_printf("debug_server: can't append to system-apps path: %s\n", + strerror(error)); + return error; + } + if (!arguments.Add(debuggerPath.Path())) + return B_NO_MEMORY; + + if (debugInConsoled && !arguments.Add("--cli")) + return B_NO_MEMORY; + + BString debuggerParam; + debuggerParam.SetToFormat("%" B_PRId32, fTeam); + if (saveReport) { + if (!arguments.Add("--save-report")) + return B_NO_MEMORY; + } + if (!arguments.Add("--team") || !arguments.Add(debuggerParam)) + return B_NO_MEMORY; + + // start the debugger + TRACE(("debug_server: TeamDebugHandler::_EnterDebugger(): starting " + "%s debugger for team %" B_PRId32 "...\n", + debugInConsoled ? "command line" : "graphical", fTeam)); #endif for (int32 i = 0; i < arguments.CountStrings(); i++)