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
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to