diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index ac8c3bca02a..e41556c8254 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -171,6 +171,7 @@ local sources = LoadSourceCodeJob.cpp ResolveValueNodeJob.cpp RetrieveMemoryBlockJob.cpp + WriteCoreFileJob.cpp WriteMemoryJob.cpp WriteValueNodeJob.cpp @@ -278,6 +279,7 @@ local sources = CliThreadCommand.cpp CliThreadsCommand.cpp CliVariablesCommand.cpp + CliWriteCoreFileCommand.cpp # user_interface/gui GraphicalUserInterface.cpp diff --git a/src/apps/debugger/MessageCodes.h b/src/apps/debugger/MessageCodes.h index d2ae9d1fbf5..b7b62dcab57 100644 --- a/src/apps/debugger/MessageCodes.h +++ b/src/apps/debugger/MessageCodes.h @@ -97,6 +97,7 @@ enum { MSG_SHOW_CONTAINER_RANGE_PROMPT = 'scrp', MSG_SET_CONTAINER_RANGE = 'chcr', MSG_GENERATE_DEBUG_REPORT = 'gdrp', + MSG_WRITE_CORE_FILE = 'wrcf', MSG_WRITE_VARIABLE_VALUE = 'wrvv', MSG_DEBUG_INFO_NEEDS_USER_INPUT = 'dnui', diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp index 94d1bb7f51f..29562eb677f 100644 --- a/src/apps/debugger/controllers/TeamDebugger.cpp +++ b/src/apps/debugger/controllers/TeamDebugger.cpp @@ -846,6 +846,16 @@ TeamDebugger::MessageReceived(BMessage* message) break; } + case MSG_WRITE_CORE_FILE: + { + entry_ref ref; + if (message->FindRef("target", &ref) != B_OK) + break; + + _HandleWriteCoreFile(ref); + break; + } + case MSG_THREAD_STATE_CHANGED: { int32 threadID; @@ -1304,6 +1314,15 @@ TeamDebugger::DebugReportRequested(entry_ref* targetPath) } +void +TeamDebugger::WriteCoreFileRequested(entry_ref* targetPath) +{ + BMessage message(MSG_WRITE_CORE_FILE); + message.AddRef("target", targetPath); + PostMessage(&message); +} + + void TeamDebugger::TeamRestartRequested() { @@ -2305,6 +2324,19 @@ TeamDebugger::_HandleEvaluateExpression(SourceLanguage* language, } +void +TeamDebugger::_HandleWriteCoreFile(const entry_ref& targetPath) +{ + status_t result = fWorker->ScheduleJob( + new(std::nothrow) WriteCoreFileJob(fTeam, fDebuggerInterface, + targetPath)); + if (result != B_OK) { + _NotifyUser("Write Core File", "Failed to write core file: %s", + strerror(result)); + } +} + + status_t TeamDebugger::_HandleSetArguments(int argc, const char* const* argv) { diff --git a/src/apps/debugger/controllers/TeamDebugger.h b/src/apps/debugger/controllers/TeamDebugger.h index 043e19a1269..6520c7833bc 100644 --- a/src/apps/debugger/controllers/TeamDebugger.h +++ b/src/apps/debugger/controllers/TeamDebugger.h @@ -131,6 +131,8 @@ class TeamDebugger : public BLooper, private UserInterfaceListener, virtual void DebugReportRequested(entry_ref* targetPath); + virtual void WriteCoreFileRequested(entry_ref* targetPath); + virtual void TeamRestartRequested(); virtual bool UserInterfaceQuitRequested( @@ -220,6 +222,8 @@ class TeamDebugger : public BLooper, private UserInterfaceListener, StackFrame* frame, ::Thread* thread); + void _HandleWriteCoreFile(const entry_ref& ref); + status_t _HandleSetArguments(int argc, const char* const* argv); diff --git a/src/apps/debugger/jobs/Jobs.h b/src/apps/debugger/jobs/Jobs.h index e4b3e5bcab4..193cd156419 100644 --- a/src/apps/debugger/jobs/Jobs.h +++ b/src/apps/debugger/jobs/Jobs.h @@ -1,11 +1,12 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2011-2015, Rene Gollent, rene@gollent.com. + * Copyright 2011-2016, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef JOBS_H #define JOBS_H +#include #include #include "ImageDebugInfoLoadingState.h" @@ -54,7 +55,8 @@ enum { JOB_TYPE_WRITE_VALUE_NODE_VALUE, JOB_TYPE_GET_MEMORY_BLOCK, JOB_TYPE_WRITE_MEMORY, - JOB_TYPE_EVALUATE_EXPRESSION + JOB_TYPE_EVALUATE_EXPRESSION, + JOB_TYPE_WRITE_CORE_FILE }; @@ -303,4 +305,22 @@ class ExpressionEvaluationJob : public Job { }; +class WriteCoreFileJob : public Job { +public: + WriteCoreFileJob(Team* team, + DebuggerInterface* debuggerInterface, + const entry_ref& targetPath); + virtual ~WriteCoreFileJob(); + + virtual const JobKey& Key() const; + virtual status_t Do(); + +private: + SimpleJobKey fKey; + Team* fTeam; + DebuggerInterface* fDebuggerInterface; + entry_ref fTargetPath; +}; + + #endif // JOBS_H diff --git a/src/apps/debugger/jobs/WriteCoreFileJob.cpp b/src/apps/debugger/jobs/WriteCoreFileJob.cpp new file mode 100644 index 00000000000..f9aa361c95c --- /dev/null +++ b/src/apps/debugger/jobs/WriteCoreFileJob.cpp @@ -0,0 +1,58 @@ +/* + * Copyright 2016, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ + +#include "Jobs.h" + +#include + +#include + +#include "DebuggerInterface.h" +#include "Team.h" + + + +WriteCoreFileJob::WriteCoreFileJob(Team* team, + DebuggerInterface* interface, const entry_ref& path) + : + fKey(&path, JOB_TYPE_WRITE_CORE_FILE), + fTeam(team), + fDebuggerInterface(interface), + fTargetPath(path) +{ + fDebuggerInterface->AcquireReference(); +} + + +WriteCoreFileJob::~WriteCoreFileJob() +{ + fDebuggerInterface->AcquireReference(); +} + + +const JobKey& +WriteCoreFileJob::Key() const +{ + return fKey; +} + + +status_t +WriteCoreFileJob::Do() +{ + BPath path(&fTargetPath); + status_t error = path.InitCheck(); + if (error != B_OK) + return error; + + error = fDebuggerInterface->WriteCoreFile(path.Path()); + if (error != B_OK) + return error; + + AutoLocker< ::Team> teamLocker(fTeam); + fTeam->NotifyCoreFileChanged(path.Path()); + + return B_OK; +} diff --git a/src/apps/debugger/model/Team.cpp b/src/apps/debugger/model/Team.cpp index 73ad3bcc6a4..0d54b0098c8 100644 --- a/src/apps/debugger/model/Team.cpp +++ b/src/apps/debugger/model/Team.cpp @@ -852,6 +852,17 @@ Team::NotifyDebugReportChanged(const char* reportPath) } +void +Team::NotifyCoreFileChanged(const char* targetPath) +{ + for (ListenerList::Iterator it = fListeners.GetIterator(); + Listener* listener = it.Next();) { + listener->CoreFileChanged(CoreFileChangedEvent( + TEAM_EVENT_CORE_FILE_CHANGED, this, targetPath)); + } +} + + void Team::NotifyMemoryChanged(target_addr_t address, target_size_t size) { @@ -1033,6 +1044,18 @@ Team::DebugReportEvent::DebugReportEvent(uint32 type, Team* team, } +// #pragma mark - CoreFileChangedEvent + + +Team::CoreFileChangedEvent::CoreFileChangedEvent(uint32 type, Team* team, + const char* targetPath) + : + Event(type, team), + fTargetPath(targetPath) +{ +} + + // #pragma mark - MemoryChangedEvent @@ -1221,6 +1244,12 @@ Team::Listener::DebugReportChanged(const Team::DebugReportEvent& event) } +void +Team::Listener::CoreFileChanged(const Team::CoreFileChangedEvent& event) +{ +} + + void Team::Listener::MemoryChanged(const Team::MemoryChangedEvent& event) { diff --git a/src/apps/debugger/model/Team.h b/src/apps/debugger/model/Team.h index a5ea092745b..aaa1dce5095 100644 --- a/src/apps/debugger/model/Team.h +++ b/src/apps/debugger/model/Team.h @@ -57,6 +57,8 @@ enum { TEAM_EVENT_DEBUG_REPORT_CHANGED, + TEAM_EVENT_CORE_FILE_CHANGED, + TEAM_EVENT_MEMORY_CHANGED }; @@ -96,6 +98,7 @@ class Team { class ThreadEvent; class UserBreakpointEvent; class WatchpointEvent; + class CoreFileChangedEvent; class Listener; public: @@ -263,6 +266,10 @@ class Team { void NotifyDebugReportChanged( const char* reportPath); + // core file related service methods + void NotifyCoreFileChanged( + const char* targetPath); + // memory write related service methods void NotifyMemoryChanged(target_addr_t address, target_size_t size); @@ -433,6 +440,15 @@ class Team::DebugReportEvent : public Event { const char* fReportPath; }; +class Team::CoreFileChangedEvent : public Event { +public: + CoreFileChangedEvent(uint32 type, Team* team, + const char* targetPath); + const char* GetTargetPath() const { return fTargetPath; } +protected: + const char* fTargetPath; +}; + class Team::MemoryChangedEvent : public Event { public: @@ -533,6 +549,9 @@ class Team::Listener : public DoublyLinkedListLinkImpl { virtual void DebugReportChanged( const Team::DebugReportEvent& event); + virtual void CoreFileChanged( + const Team::CoreFileChangedEvent& event); + virtual void MemoryChanged( const Team::MemoryChangedEvent& event); }; diff --git a/src/apps/debugger/user_interface/UserInterface.h b/src/apps/debugger/user_interface/UserInterface.h index 8783cdfc180..36474ac0e13 100644 --- a/src/apps/debugger/user_interface/UserInterface.h +++ b/src/apps/debugger/user_interface/UserInterface.h @@ -173,6 +173,8 @@ class UserInterfaceListener { virtual void DebugReportRequested(entry_ref* path) = 0; + virtual void WriteCoreFileRequested(entry_ref* path) = 0; + virtual void TeamRestartRequested() = 0; virtual bool UserInterfaceQuitRequested( diff --git a/src/apps/debugger/user_interface/cli/CliContext.cpp b/src/apps/debugger/user_interface/cli/CliContext.cpp index 9a66b1a309b..00946f1ef25 100644 --- a/src/apps/debugger/user_interface/cli/CliContext.cpp +++ b/src/apps/debugger/user_interface/cli/CliContext.cpp @@ -516,6 +516,17 @@ CliContext::DebugReportChanged(const Team::DebugReportEvent& event) } +void +CliContext::CoreFileChanged(const Team::CoreFileChangedEvent& event) +{ + printf("Successfully saved core file to %s\n", + event.GetTargetPath()); + + _QueueEvent(new(std::nothrow) Event(EVENT_CORE_FILE_CHANGED)); + _SignalInputLoop(EVENT_CORE_FILE_CHANGED); +} + + void CliContext::MemoryBlockRetrieved(TeamMemoryBlock* block) { diff --git a/src/apps/debugger/user_interface/cli/CliContext.h b/src/apps/debugger/user_interface/cli/CliContext.h index 66f35e22d8e..1891ce830e0 100644 --- a/src/apps/debugger/user_interface/cli/CliContext.h +++ b/src/apps/debugger/user_interface/cli/CliContext.h @@ -1,6 +1,6 @@ /* * Copyright 2012, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2014-2015, Rene Gollent, rene@gollent.com. + * Copyright 2014-2016, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef CLI_CONTEXT_H @@ -42,7 +42,8 @@ class CliContext : private Team::Listener, EVENT_VALUE_NODE_CHANGED = 0x40, EVENT_TEAM_MEMORY_BLOCK_RETRIEVED = 0x80, EVENT_EXPRESSION_EVALUATED = 0x100, - EVENT_DEBUG_REPORT_CHANGED = 0x200 + EVENT_DEBUG_REPORT_CHANGED = 0x200, + EVENT_CORE_FILE_CHANGED = 0x400 }; public: @@ -112,6 +113,9 @@ class CliContext : private Team::Listener, virtual void DebugReportChanged( const Team::DebugReportEvent& event); + virtual void CoreFileChanged( + const Team::CoreFileChangedEvent& event); + // TeamMemoryBlock::Listener virtual void MemoryBlockRetrieved(TeamMemoryBlock* block); diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp index faecbe76015..47027d2ebdb 100644 --- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp +++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2011-2015, Rene Gollent, rene@gollent.com. + * Copyright 2011-2016, Rene Gollent, rene@gollent.com. * Copyright 2012, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -28,6 +28,7 @@ #include "CliThreadCommand.h" #include "CliThreadsCommand.h" #include "CliVariablesCommand.h" +#include "CliWriteCoreFileCommand.h" static const char* kDebuggerPrompt = "debugger> "; @@ -311,7 +312,9 @@ CommandLineUserInterface::_RegisterCommands() && _RegisterCommand("thread", new(std::nothrow) CliThreadCommand) && _RegisterCommand("threads", new(std::nothrow) CliThreadsCommand) && _RegisterCommand("variables", - new(std::nothrow) CliVariablesCommand)) { + new(std::nothrow) CliVariablesCommand) + && _RegisterCommand("write-core", + new(std::nothrow) CliWriteCoreFileCommand)) { fCommands.SortItems(&_CompareCommandEntries); return B_OK; } diff --git a/src/apps/debugger/user_interface/cli/commands/CliWriteCoreFileCommand.cpp b/src/apps/debugger/user_interface/cli/commands/CliWriteCoreFileCommand.cpp new file mode 100644 index 00000000000..2c61a057089 --- /dev/null +++ b/src/apps/debugger/user_interface/cli/commands/CliWriteCoreFileCommand.cpp @@ -0,0 +1,51 @@ +/* + * Copyright 2016, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ + + +#include "CliWriteCoreFileCommand.h" + +#include +#include +#include +#include + +#include "CliContext.h" +#include "UiUtils.h" +#include "UserInterface.h" + + +CliWriteCoreFileCommand::CliWriteCoreFileCommand() + : + CliCommand("write core file", + "%s\n" + "Writes a core dump file for the current team.") +{ +} + + +void +CliWriteCoreFileCommand::Execute(int argc, const char* const* argv, CliContext& context) +{ + BPath path; + if (argc > 1) { + path.SetTo(argv[1]); + if (path.InitCheck() != B_OK) { + printf("Invalid core file path %s given.\n", argv[1]); + return; + } + } else { + char buffer[B_FILE_NAME_LENGTH]; + UiUtils::CoreFileNameForTeam(context.GetTeam(), buffer, + sizeof(buffer)); + find_directory(B_DESKTOP_DIRECTORY, &path); + path.Append(buffer); + } + + entry_ref ref; + if (get_ref_for_path(path.Path(), &ref) == B_OK) { + printf("Writing core file to %s...\n", path.Path()); + context.GetUserInterfaceListener()->WriteCoreFileRequested(&ref); + } +} diff --git a/src/apps/debugger/user_interface/cli/commands/CliWriteCoreFileCommand.h b/src/apps/debugger/user_interface/cli/commands/CliWriteCoreFileCommand.h new file mode 100644 index 00000000000..47f288622c9 --- /dev/null +++ b/src/apps/debugger/user_interface/cli/commands/CliWriteCoreFileCommand.h @@ -0,0 +1,20 @@ +/* + * Copyright 2016, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#ifndef CLI_WRITE_CORE_FILE_COMMAND_H +#define CLI_WRITE_CORE_FILE_COMMAND_H + + +#include "CliCommand.h" + + +class CliWriteCoreFileCommand : public CliCommand { +public: + CliWriteCoreFileCommand(); + virtual void Execute(int argc, const char* const* argv, + CliContext& context); +}; + + +#endif // CLI_WRITE_CORE_FILE_COMMAND_H diff --git a/src/apps/debugger/user_interface/util/UiUtils.cpp b/src/apps/debugger/user_interface/util/UiUtils.cpp index 99b47495374..848981f3a8c 100644 --- a/src/apps/debugger/user_interface/util/UiUtils.cpp +++ b/src/apps/debugger/user_interface/util/UiUtils.cpp @@ -1,6 +1,6 @@ /* * Copyright 2012, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2012-2015, Rene Gollent, rene@gollent.com. + * Copyright 2012-2016, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ @@ -257,6 +257,23 @@ UiUtils::ReportNameForTeam(::Team* team, char* buffer, size_t bufferSize) currentTime.Time().Minute(), currentTime.Time().Second()); return buffer; +} + + +/*static*/ const char* +UiUtils::CoreFileNameForTeam(::Team* team, char* buffer, size_t bufferSize) +{ + BPath teamPath(team->Name()); + BDateTime currentTime; + currentTime.SetTime_t(time(NULL)); + snprintf(buffer, bufferSize, "%s-%" B_PRId32 "-debug-%02" B_PRId32 "-%02" + B_PRId32 "-%02" B_PRId32 "-%02" B_PRId32 "-%02" B_PRId32 "-%02" + B_PRId32 ".core", teamPath.Leaf(), team->ID(), + currentTime.Date().Day(), currentTime.Date().Month(), + currentTime.Date().Year(), currentTime.Time().Hour(), + currentTime.Time().Minute(), currentTime.Time().Second()); + + return buffer; } diff --git a/src/apps/debugger/user_interface/util/UiUtils.h b/src/apps/debugger/user_interface/util/UiUtils.h index 9919fca50f8..e96a89b97cd 100644 --- a/src/apps/debugger/user_interface/util/UiUtils.h +++ b/src/apps/debugger/user_interface/util/UiUtils.h @@ -1,5 +1,5 @@ /* - * Copyright 2014-2015, Rene Gollent, rene@gollent.com. + * Copyright 2014-2016, Rene Gollent, rene@gollent.com. * Copyright 2012, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -51,6 +51,9 @@ class UiUtils { static const char* ReportNameForTeam(::Team* team, char* buffer, size_t bufferSize); + static const char* CoreFileNameForTeam(::Team* team, + char* buffer, size_t bufferSize); + // this function assumes the value nodes have already been resolved // (if possible). static void PrintValueNodeGraph(BString& _output,