aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Commands/CommandObjectProcess.cpp
diff options
context:
space:
mode:
authorMed Ismail Bennani <medismail.bennani@gmail.com>2020-02-21 22:43:25 +0100
committerMed Ismail Bennani <medismail.bennani@gmail.com>2020-02-21 22:44:36 +0100
commitd7c403e64043281b9c5883e3e034da5ebaf4985a (patch)
tree297126371dc3e6cdedbf297b933ca726138d60f2 /lldb/source/Commands/CommandObjectProcess.cpp
parent1f04d1b7069bf6c513526f36b8c7327c8dec6604 (diff)
downloadllvm-d7c403e64043281b9c5883e3e034da5ebaf4985a.zip
llvm-d7c403e64043281b9c5883e3e034da5ebaf4985a.tar.gz
llvm-d7c403e64043281b9c5883e3e034da5ebaf4985a.tar.bz2
[lldb/Plugins] Add ability to fetch crash information on crashed processes
Currently, in macOS, when a process crashes, lldb halts inside the implementation disassembly without yielding any useful information. The only way to get more information is to detach from the process, then wait for ReportCrash to generate a report, find the report, then see what error message was included in it. Instead of waiting for this to happen, lldb could locate the error_string and make it available to the user. This patch addresses this issue by enabling the user to fetch extended crash information for crashed processes using `process status --verbose`. Depending on the platform, this will try to gather different crash information into an structured data dictionnary. This dictionnary is generic and extensible, as it contains an array for each different type of crash information. On Darwin Platforms, lldb will iterate over each of the target's images, extract their `__crash_info` section and generated a StructuredData::Array containing, in each entry, the module spec, its UUID, the crash messages and the abort cause. The array will be inserted into the platform's `m_extended_crash_info` dictionnary and `FetchExtendedCrashInformation` will return its JSON representation like this: ``` { "crash-info annotations": [ { "abort-cause": 0, "image": "/usr/lib/system/libsystem_malloc.dylib", "message": "main(76483,0x1000cedc0) malloc: *** error for object 0x1003040a0: pointer being freed was not allocated", "message2": "", "uuid": "5747D0C9-900D-3306-8D70-1E2EA4B7E821" }, ... ], ... } ``` This crash information can also be fetched using the SB API or lldb-rpc protocol using SBTarget::GetExtendedCrashInformation(). rdar://37736535 Differential Revision: https://reviews.llvm.org/D74657 Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>
Diffstat (limited to 'lldb/source/Commands/CommandObjectProcess.cpp')
-rw-r--r--lldb/source/Commands/CommandObjectProcess.cpp77
1 files changed, 76 insertions, 1 deletions
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index 0145122..4ee085e 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -1201,6 +1201,8 @@ protected:
// CommandObjectProcessStatus
#pragma mark CommandObjectProcessStatus
+#define LLDB_OPTIONS_process_status
+#include "CommandOptions.inc"
class CommandObjectProcessStatus : public CommandObjectParsed {
public:
@@ -1209,13 +1211,57 @@ public:
interpreter, "process status",
"Show status and stop location for the current target process.",
"process status",
- eCommandRequiresProcess | eCommandTryTargetAPILock) {}
+ eCommandRequiresProcess | eCommandTryTargetAPILock),
+ m_options() {}
~CommandObjectProcessStatus() override = default;
+ Options *GetOptions() override { return &m_options; }
+
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options(), m_verbose(false) {}
+
+ ~CommandOptions() override = default;
+
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override {
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 'v':
+ m_verbose = true;
+ break;
+ default:
+ llvm_unreachable("Unimplemented option");
+ }
+
+ return {};
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_verbose = false;
+ }
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::makeArrayRef(g_process_status_options);
+ }
+
+ // Instance variables to hold the values for command options.
+ bool m_verbose;
+ };
+
+protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
Stream &strm = result.GetOutputStream();
result.SetStatus(eReturnStatusSuccessFinishNoResult);
+
+ if (command.GetArgumentCount()) {
+ result.AppendError("'process status' takes no arguments");
+ result.SetStatus(eReturnStatusFailed);
+ return result.Succeeded();
+ }
+
// No need to check "process" for validity as eCommandRequiresProcess
// ensures it is valid
Process *process = m_exe_ctx.GetProcessPtr();
@@ -1227,8 +1273,37 @@ public:
process->GetStatus(strm);
process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,
num_frames, num_frames_with_source, stop_format);
+
+ if (m_options.m_verbose) {
+ PlatformSP platform_sp = process->GetTarget().GetPlatform();
+ if (!platform_sp) {
+ result.AppendError("Couldn'retrieve the target's platform");
+ result.SetStatus(eReturnStatusFailed);
+ return result.Succeeded();
+ }
+
+ auto expected_crash_info =
+ platform_sp->FetchExtendedCrashInformation(process->GetTarget());
+
+ if (!expected_crash_info) {
+ result.AppendError(llvm::toString(expected_crash_info.takeError()));
+ result.SetStatus(eReturnStatusFailed);
+ return result.Succeeded();
+ }
+
+ StructuredData::DictionarySP crash_info_sp = *expected_crash_info;
+
+ if (crash_info_sp) {
+ strm.PutCString("Extended Crash Information:\n");
+ crash_info_sp->Dump(strm);
+ }
+ }
+
return result.Succeeded();
}
+
+private:
+ CommandOptions m_options;
};
// CommandObjectProcessHandle