diff options
Diffstat (limited to 'lldb/source/Commands/CommandObjectMemory.cpp')
-rw-r--r-- | lldb/source/Commands/CommandObjectMemory.cpp | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp index bfbb296..8144f48 100644 --- a/lldb/source/Commands/CommandObjectMemory.cpp +++ b/lldb/source/Commands/CommandObjectMemory.cpp @@ -33,8 +33,10 @@ #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" #include "lldb/Interpreter/OptionValueString.h" #include "lldb/Symbol/TypeList.h" +#include "lldb/Target/MemoryHistory.h" #include "lldb/Target/Process.h" #include "lldb/Target/StackFrame.h" +#include "lldb/Target/Thread.h" using namespace lldb; using namespace lldb_private; @@ -1667,6 +1669,96 @@ protected: OptionGroupWriteMemory m_memory_options; }; +//---------------------------------------------------------------------- +// Get malloc/free history of a memory address. +//---------------------------------------------------------------------- +class CommandObjectMemoryHistory : public CommandObjectParsed +{ +public: + + CommandObjectMemoryHistory (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "memory history", + "Prints out the recorded stack traces for allocation/deallocation of a memory address.", + NULL, + eFlagRequiresTarget | eFlagRequiresProcess | eFlagProcessMustBePaused | eFlagProcessMustBeLaunched) + { + CommandArgumentEntry arg1; + CommandArgumentData addr_arg; + + // Define the first (and only) variant of this arg. + addr_arg.arg_type = eArgTypeAddress; + addr_arg.arg_repetition = eArgRepeatPlain; + + // There is only one variant this argument could be; put it into the argument entry. + arg1.push_back (addr_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back (arg1); + } + + virtual + ~CommandObjectMemoryHistory () + { + } + + virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) + { + return m_cmd_name.c_str(); + } + +protected: + virtual bool + DoExecute (Args& command, CommandReturnObject &result) + { + const size_t argc = command.GetArgumentCount(); + + if (argc == 0 || argc > 1) + { + result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + Error error; + lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx, + command.GetArgumentAtIndex(0), + LLDB_INVALID_ADDRESS, + &error); + + if (addr == LLDB_INVALID_ADDRESS) + { + result.AppendError("invalid address expression"); + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + Stream *output_stream = &result.GetOutputStream(); + + const ProcessSP &process_sp = m_exe_ctx.GetProcessSP(); + const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp); + + if (! memory_history.get()) + { + result.AppendError("no available memory history provider"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + HistoryThreads thread_list = memory_history->GetHistoryThreads(addr); + + for (auto thread : thread_list) { + thread->GetStatus(*output_stream, 0, UINT32_MAX, 0); + } + + result.SetStatus(eReturnStatusSuccessFinishResult); + + return true; + } + +}; + //------------------------------------------------------------------------- // CommandObjectMemory @@ -1681,6 +1773,7 @@ CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) : LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter))); LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter))); LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter))); + LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter))); } CommandObjectMemory::~CommandObjectMemory () |