mib updated this revision to Diff 244793.
mib added a comment.
Run clang-format
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D74657/new/
https://reviews.llvm.org/D74657
Files:
lldb/bindings/interface/SBProcess.i
lldb/include/lldb/API/SBProcess.h
lldb/include/lldb/API/SBStructuredData.h
lldb/include/lldb/Target/Process.h
lldb/packages/Python/lldbsuite/test/commands/process/crash-info/Makefile
lldb/packages/Python/lldbsuite/test/commands/process/crash-info/TestProcessCrashInfo.py
lldb/packages/Python/lldbsuite/test/commands/process/crash-info/main.c
lldb/source/API/SBProcess.cpp
lldb/source/Commands/CommandObjectProcess.cpp
lldb/source/Target/Process.cpp
Index: lldb/source/Target/Process.cpp
===================================================================
--- lldb/source/Target/Process.cpp
+++ lldb/source/Target/Process.cpp
@@ -19,6 +19,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/DynamicCheckerFunctions.h"
@@ -36,6 +37,7 @@
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/AssertFrameRecognizer.h"
@@ -1095,6 +1097,112 @@
return nullptr;
}
+StructuredData::ArraySP Process::FetchCrashInfo() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ StructuredData::ArraySP array_sp = std::make_shared<StructuredData::Array>();
+
+ for (ModuleSP module : GetTarget().GetImages().Modules()) {
+ SectionList *sections = module->GetSectionList();
+
+ std::string module_name = module->GetSpecificationDescription();
+
+ if (!sections) {
+ LLDB_LOG(log, "Module {0} doesn't have any section!", module_name);
+ continue;
+ }
+
+ ConstString section_name("__crash_info");
+ SectionSP crash_info = sections->FindSectionByName(section_name);
+ if (!crash_info) {
+ LLDB_LOG(log, "Module {0} doesn't have section {1}!", module_name,
+ section_name);
+ continue;
+ }
+
+ addr_t load_addr = crash_info->GetLoadBaseAddress(&GetTarget());
+
+ if (load_addr == LLDB_INVALID_ADDRESS)
+ continue;
+
+ CrashInfoExtractor extractor = {};
+ extractor.load_addr = load_addr;
+
+ if (!ExtractCrashInfoAnnotations(extractor)) {
+ LLDB_LOG(log, "{Couldn't extract crash info from Module {0}: {1}}",
+ module_name, extractor.error.AsCString());
+ continue;
+ }
+
+ StructuredData::DictionarySP entry_sp =
+ std::make_shared<StructuredData::Dictionary>();
+
+ entry_sp->AddStringItem("image", module->GetFileSpec().GetPath(false));
+ entry_sp->AddStringItem("uuid", module->GetUUID().GetAsString());
+ entry_sp->AddStringItem("message", extractor.message);
+ entry_sp->AddStringItem("message2", extractor.message2);
+ entry_sp->AddIntegerItem("abort-cause", extractor.annotations.abort_cause);
+
+ array_sp->AddItem(entry_sp);
+ }
+
+ return array_sp;
+}
+
+bool Process::ExtractCrashInfoAnnotations(CrashInfoExtractor &extractor) {
+ CrashInfoAnnotations annotations;
+ size_t expected_size = sizeof(CrashInfoAnnotations);
+ size_t bytes_read = ReadMemoryFromInferior(extractor.load_addr, &annotations,
+ expected_size, extractor.error);
+
+ if (expected_size != bytes_read || extractor.error.Fail())
+ return false;
+
+ // initial support added for version 5
+ if (annotations.version < 5) {
+ extractor.error.SetErrorString(
+ "Annotation version lower than 5 unsupported!");
+ return false;
+ }
+
+ if (!annotations.message) {
+ extractor.error.SetErrorString("No message available.");
+ return false;
+ }
+
+ std::string message;
+ bytes_read =
+ ReadCStringFromMemory(annotations.message, message, extractor.error);
+
+ if (message.empty() || bytes_read != message.size() ||
+ extractor.error.Fail()) {
+ extractor.error.SetErrorString("Failed to read the message from memory.");
+ return false;
+ }
+
+ // Remove trailing newline from message
+ if (message[message.size() - 1] == '\n')
+ message.pop_back();
+
+ extractor.annotations = annotations;
+ extractor.message = message;
+
+ if (annotations.message2) {
+ std::string message2;
+ bytes_read =
+ ReadCStringFromMemory(annotations.message2, message2, extractor.error);
+
+ if (!message2.empty() && bytes_read == message2.size() &&
+ extractor.error.Success()) {
+ if (message2[message2.size() - 1] == '\n')
+ message2.pop_back();
+ extractor.message2 = message2;
+ }
+ }
+
+ return true;
+}
+
bool Process::SetExitStatus(int status, const char *cstr) {
// Use a mutex to protect setting the exit status.
std::lock_guard<std::mutex> guard(m_exit_status_mutex);
Index: lldb/source/Commands/CommandObjectProcess.cpp
===================================================================
--- lldb/source/Commands/CommandObjectProcess.cpp
+++ lldb/source/Commands/CommandObjectProcess.cpp
@@ -1472,6 +1472,45 @@
CommandOptions m_options;
};
+// CommandObjectProcessCrashInfo
+#pragma mark CommandObjectProcessCrashInfo
+
+class CommandObjectProcessCrashInfo : public CommandObjectParsed {
+public:
+ CommandObjectProcessCrashInfo(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "process crash-info",
+ "Fetch process' crash information from the module.",
+ "process crash-info",
+ eCommandRequiresProcess |
+ eCommandTryTargetAPILock) {}
+
+ ~CommandObjectProcessCrashInfo() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ Stream &strm = result.GetOutputStream();
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ // No need to check "process" for validity as eCommandRequiresProcess
+ // ensures it is valid
+ Process *process = m_exe_ctx.GetProcessPtr();
+ llvm::Triple::OSType os =
+ process->GetTarget().GetArchitecture().GetTriple().getOS();
+
+ if (os != llvm::Triple::MacOSX && os != llvm::Triple::Darwin) {
+ result.AppendError("Unsupported OS");
+ return result.Succeeded();
+ }
+
+ StructuredData::ArraySP crash_info_sp = process->FetchCrashInfo();
+
+ if (!crash_info_sp)
+ result.AppendError("Couldn't fetch crash info.");
+
+ crash_info_sp->Dump(strm);
+
+ return result.Succeeded();
+ }
+};
+
// CommandObjectMultiwordProcess
CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(
@@ -1488,6 +1527,9 @@
interpreter)));
LoadSubCommand("connect",
CommandObjectSP(new CommandObjectProcessConnect(interpreter)));
+ LoadSubCommand(
+ "crash-info",
+ CommandObjectSP(new CommandObjectProcessCrashInfo(interpreter)));
LoadSubCommand("detach",
CommandObjectSP(new CommandObjectProcessDetach(interpreter)));
LoadSubCommand("load",
Index: lldb/source/API/SBProcess.cpp
===================================================================
--- lldb/source/API/SBProcess.cpp
+++ lldb/source/API/SBProcess.cpp
@@ -18,6 +18,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -555,6 +556,19 @@
return exit_desc;
}
+SBStructuredData SBProcess::GetCrashInfo() {
+ LLDB_RECORD_METHOD_NO_ARGS(lldb::SBStructuredData, SBProcess, GetCrashInfo);
+
+ SBStructuredData data;
+ ProcessSP process_sp(GetSP());
+ if (!process_sp)
+ return LLDB_RECORD_RESULT(data);
+
+ StructuredData::ArraySP fetched_data = process_sp->FetchCrashInfo();
+ data.m_impl_up->SetObjectSP(fetched_data);
+ return LLDB_RECORD_RESULT(data);
+}
+
lldb::pid_t SBProcess::GetProcessID() {
LLDB_RECORD_METHOD_NO_ARGS(lldb::pid_t, SBProcess, GetProcessID);
@@ -1338,6 +1352,7 @@
LLDB_REGISTER_METHOD(lldb::StateType, SBProcess, GetState, ());
LLDB_REGISTER_METHOD(int, SBProcess, GetExitStatus, ());
LLDB_REGISTER_METHOD(const char *, SBProcess, GetExitDescription, ());
+ LLDB_REGISTER_METHOD(SBStructuredData, SBProcess, GetCrashInfo, ());
LLDB_REGISTER_METHOD(lldb::pid_t, SBProcess, GetProcessID, ());
LLDB_REGISTER_METHOD(uint32_t, SBProcess, GetUniqueID, ());
LLDB_REGISTER_METHOD_CONST(lldb::ByteOrder, SBProcess, GetByteOrder, ());
Index: lldb/packages/Python/lldbsuite/test/commands/process/crash-info/main.c
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/commands/process/crash-info/main.c
@@ -0,0 +1,7 @@
+#include <stdlib.h>
+int main() {
+ int *var = malloc(sizeof(int));
+ free(var);
+ free(var);
+ return 0;
+}
Index: lldb/packages/Python/lldbsuite/test/commands/process/crash-info/TestProcessCrashInfo.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/commands/process/crash-info/TestProcessCrashInfo.py
@@ -0,0 +1,65 @@
+"""
+Test lldb process crash info.
+"""
+
+from __future__ import print_function
+
+import os
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class ProcessCrashInfoTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ self.runCmd("settings set auto-confirm true")
+
+ def tearDown(self):
+ self.runCmd("settings clear auto-confirm")
+ TestBase.tearDown(self)
+
+ @skipUnlessDarwin
+ def test_cli(self):
+ """Test that process crash-info fetches an annotation message from the
+ command-line properly."""
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+ self.expect("file " + exe,
+ patterns=["Current executable set to .*a.out"])
+
+ self.expect('process launch',
+ patterns=["Process .* launched: .*a.out"])
+
+ self.expect('process crash-info',
+ patterns=["\"message\".*pointer being freed was not allocated"])
+
+
+ @skipUnlessDarwin
+ def test_api(self):
+ """Test that process crash-info fetches an annotation message from the
+ api properly."""
+ self.build()
+ target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
+ self.assertTrue(target, VALID_TARGET)
+
+ process = target.LaunchSimple(None, None, os.getcwd())
+
+ stream = lldb.SBStream()
+ self.assertTrue(stream)
+
+ crash_info = process.GetCrashInfo()
+
+ error = crash_info.GetAsJSON(stream)
+
+ self.assertTrue(error.Success())
+
+ self.assertTrue(crash_info.IsValid())
+
+ self.assertTrue("pointer being freed was not allocated" in
+ stream.GetData())
Index: lldb/packages/Python/lldbsuite/test/commands/process/crash-info/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/commands/process/crash-info/Makefile
@@ -0,0 +1,4 @@
+C_SOURCES := main.c
+
+include Makefile.rules
+
Index: lldb/include/lldb/Target/Process.h
===================================================================
--- lldb/include/lldb/Target/Process.h
+++ lldb/include/lldb/Target/Process.h
@@ -1267,7 +1267,7 @@
/// LLDB_INVALID_ADDRESS.
///
/// \return
- /// A StructureDataSP object which, if non-empty, will contain the
+ /// A StructuredDataSP object which, if non-empty, will contain the
/// information the DynamicLoader needs to get the initial scan of
/// solibs resolved.
virtual lldb_private::StructuredData::ObjectSP
@@ -1330,6 +1330,8 @@
virtual void DidExit() {}
+ lldb_private::StructuredData::ArraySP FetchCrashInfo();
+
/// Get the Modification ID of the process.
///
/// \return
@@ -2632,6 +2634,28 @@
using StructuredDataPluginMap =
std::map<ConstString, lldb::StructuredDataPluginSP>;
+ typedef struct {
+ uint64_t version; // unsigned long
+ uint64_t message; // char *
+ uint64_t signature_string; // char *
+ uint64_t backtrace; // char *
+ uint64_t message2; // char *
+ uint64_t thread; // uint64_t
+ uint64_t dialog_mode; // unsigned int
+ uint64_t abort_cause; // unsigned int
+ } CrashInfoAnnotations;
+
+ typedef struct {
+ lldb::addr_t load_addr;
+ CrashInfoAnnotations annotations;
+ std::string message;
+ std::string message2;
+ uint64_t abort_cause;
+ Status error;
+ } CrashInfoExtractor;
+
+ bool ExtractCrashInfoAnnotations(CrashInfoExtractor &extractor);
+
// Member variables
std::weak_ptr<Target> m_target_wp; ///< The target that owns this process.
ThreadSafeValue<lldb::StateType> m_public_state;
Index: lldb/include/lldb/API/SBStructuredData.h
===================================================================
--- lldb/include/lldb/API/SBStructuredData.h
+++ lldb/include/lldb/API/SBStructuredData.h
@@ -91,6 +91,7 @@
friend class SBTraceOptions;
friend class SBDebugger;
friend class SBTarget;
+ friend class SBProcess;
friend class SBThread;
friend class SBThreadPlan;
friend class SBBreakpoint;
Index: lldb/include/lldb/API/SBProcess.h
===================================================================
--- lldb/include/lldb/API/SBProcess.h
+++ lldb/include/lldb/API/SBProcess.h
@@ -121,6 +121,8 @@
const char *GetExitDescription();
+ SBStructuredData GetCrashInfo();
+
/// Gets the process ID
///
/// Returns the process identifier for the process as it is known
Index: lldb/bindings/interface/SBProcess.i
===================================================================
--- lldb/bindings/interface/SBProcess.i
+++ lldb/bindings/interface/SBProcess.i
@@ -192,6 +192,9 @@
const char *
GetExitDescription ();
+ SBStructuredData
+ GetCrashInfo ();
+
%feature("autodoc", "
Returns the process ID of the process.") GetProcessID;
lldb::pid_t
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits