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/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 9950e588e2..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 @@ -1661,16 +1660,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)" ; } } 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/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/debugger/Jamfile b/src/apps/debugger/Jamfile index 4a3795c974..b219fe4034 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -193,12 +193,14 @@ Application Debugger : CliContext.cpp CliContinueCommand.cpp CliDebugReportCommand.cpp + CliDumpMemoryCommand.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/controllers/DebugReportGenerator.cpp b/src/apps/debugger/controllers/DebugReportGenerator.cpp index a5b985c4a4..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; } @@ -338,7 +358,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"; } @@ -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) { @@ -380,10 +420,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 +438,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..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,21 +40,28 @@ 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 _ResolveLocationIfNeeded(ValueNodeChild* child, - StackFrame* frame); status_t _ResolveValueIfNeeded(ValueNode* node, StackFrame* frame, int32 maxDepth); @@ -64,6 +72,7 @@ private: ValueNodeManager* fNodeManager; UserInterfaceListener* fListener; ValueNode* fWaitingNode; + TeamMemoryBlock* fCurrentBlock; ::Thread* fTraceWaitingThread; }; diff --git a/src/apps/debugger/user_interface/cli/CliContext.cpp b/src/apps/debugger/user_interface/cli/CliContext.cpp index 7b430dc19d..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; } @@ -118,6 +126,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; } @@ -150,6 +159,11 @@ CliContext::Cleanup() fNodeManager->ReleaseReference(); fNodeManager = NULL; } + + if (fCurrentBlock != NULL) { + fCurrentBlock->ReleaseReference(); + fCurrentBlock = NULL; + } } @@ -316,6 +330,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() { @@ -356,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; } } } @@ -404,6 +444,45 @@ 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) +{ + _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..cb4657a308 100644 --- a/src/apps/debugger/user_interface/cli/CliContext.h +++ b/src/apps/debugger/user_interface/cli/CliContext.h @@ -13,16 +13,21 @@ #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 { +class CliContext : private Team::Listener, + public TeamMemoryBlock::Listener, + private ValueNodeContainer::Listener { public: enum { EVENT_QUIT = 0x01, @@ -30,7 +35,9 @@ 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, + EVENT_TEAM_MEMORY_BLOCK_RETRIEVED = 0x80 }; public: @@ -64,12 +71,15 @@ public: { return fCurrentStackFrameIndex; } void SetCurrentStackFrameIndex(int32 index); + TeamMemoryBlock* CurrentBlock() const { return fCurrentBlock; } + const char* PromptUser(const char* prompt); void AddLineToInputHistory(const char* line); void QuitSession(bool killTeam); void WaitForThreadOrUser(); + void WaitForEvents(int32 eventMask); void ProcessPendingEvents(); private: @@ -87,6 +97,16 @@ 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); + virtual void ValueNodeChildrenCreated(ValueNode* node); + virtual void ValueNodeChildrenDeleted(ValueNode* node); + virtual void ValueNodeValueChanged(ValueNode* node); + private: void _QueueEvent(Event* event); @@ -113,6 +133,7 @@ private: Thread* fCurrentThread; StackTrace* fCurrentStackTrace; int32 fCurrentStackFrameIndex; + TeamMemoryBlock* fCurrentBlock; EventList fPendingEvents; }; 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..4d8c7d8b66 --- /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, 0, 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/CliPrintVariableCommand.cpp b/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.cpp new file mode 100644 index 0000000000..2c984fe7e7 --- /dev/null +++ b/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.cpp @@ -0,0 +1,151 @@ +/* + * 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); + + + while (node->LocationAndValueResolutionState() + == VALUE_NODE_UNRESOLVED) { + containerLocker.Unlock(); + context.WaitForEvents(CliContext::EVENT_VALUE_NODE_CHANGED); + containerLocker.Lock(); + if (context.IsTerminating()) + return B_ERROR; + } + } + + if (node->LocationAndValueResolutionState() == B_OK && maxDepth > 0) { + for (int32 i = 0; i < node->CountChildren(); i++) { + ValueNodeChild* child = node->ChildAt(i); + containerLocker.Unlock(); + 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; +} 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..fe75363e87 --- /dev/null +++ b/src/apps/debugger/user_interface/cli/CliPrintVariableCommand.h @@ -0,0 +1,30 @@ +/* + * 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); +}; + + +#endif // CLI_PRINT_VARIABLE_COMMAND_H 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 diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp index de846471e2..85a204b3d6 100644 --- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp +++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp @@ -18,6 +18,8 @@ #include "CliContext.h" #include "CliContinueCommand.h" #include "CliDebugReportCommand.h" +#include "CliDumpMemoryCommand.h" +#include "CliPrintVariableCommand.h" #include "CliQuitCommand.h" #include "CliStackFrameCommand.h" #include "CliStackTraceCommand.h" @@ -309,10 +311,29 @@ 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) && _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) diff --git a/src/apps/debugger/user_interface/util/UiUtils.cpp b/src/apps/debugger/user_interface/util/UiUtils.cpp index 9559f9f772..2b3e2d157f 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" @@ -163,8 +165,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,13 +217,78 @@ 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); } } _output.Append('\t', indentLevel); _output << "}\n"; - } + } else + _output << "\n"; return; } + + +/*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) { + _output.Append("\n"); + _output.Append('\t', indentLevel); + } + + 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 3e81de83de..7f6447d06e 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, @@ -34,9 +38,14 @@ 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); + + static void DumpMemory(BString& _output, + int32 indentLevel, + TeamMemoryBlock* block, + target_addr_t address, int32 itemSize, + int32 displayWidth, int32 count); }; 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/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(); } 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(); } 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)); 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++) 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)