[Lldb-commits] [lldb] r348773 - Re-commit "Introduce ObjectFileBreakpad"

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Mon Dec 10 09:16:38 PST 2018


Author: labath
Date: Mon Dec 10 09:16:38 2018
New Revision: 348773

URL: http://llvm.org/viewvc/llvm-project?rev=348773&view=rev
Log:
Re-commit "Introduce ObjectFileBreakpad"

This re-commits r348592, which was reverted due to a failing test on
macos.

The issue was that I was passing a null pointer for the
"CreateMemoryInstance" callback when registering ObjectFileBreakpad,
which caused crashes when attemping to load modules from memory. The
correct thing to do is to pass a callback which always returns a null
pointer (as breakpad files are never loaded in inferior memory).

It turns out that there is only one test which exercises this code path,
and it's mac-only, so I've create a new test which should run everywhere
(except windows, as one cannot delete an executable which is being run).
Unfortunately, this test still fails on linux for other reasons, but at
least it gives us something to aim for.

The original commit message was:
This patch adds the scaffolding necessary for lldb to recognise symbol
files generated by breakpad. These (textual) files contain just enough
information to be able to produce a backtrace from a crash
dump. This information includes:
- UUID, architecture and name of the module
- line tables
- list of symbols
- unwind information

A minimal breakpad file could look like this:
MODULE Linux x86_64 0000000024B5D199F0F766FFFFFF5DC30 a.out
INFO CODE_ID 00000000B52499D1F0F766FFFFFF5DC3
FILE 0 /tmp/a.c
FUNC 1010 10 0 _start
1010 4 4 0
1014 5 5 0
1019 5 6 0
101e 2 7 0
PUBLIC 1010 0 _start
STACK CFI INIT 1010 10 .cfa: $rsp 8 + .ra: .cfa -8 + ^
STACK CFI 1011 $rbp: .cfa -16 + ^ .cfa: $rsp 16 +
STACK CFI 1014 .cfa: $rbp 16 +

Even though this data would normally be considered "symbol" information,
in the current lldb infrastructure it is assumed every SymbolFile object
is backed by an ObjectFile instance. So, in order to better interoperate
with the rest of the code (particularly symbol vendors).

In this patch I just parse the breakpad header, which is enough to
populate the UUID and architecture fields of the ObjectFile interface.
The rough plan for followup patches is to expose the individual parts of
the breakpad file as ObjectFile "sections", which can then be used by
other parts of the codebase (SymbolFileBreakpad ?) to vend the necessary
information.

Reviewers: clayborg, zturner, lemo, amccarth

Subscribers: mgorny, fedor.sergeev, markmentovai, lldb-commits

Differential Revision: https://reviews.llvm.org/D55214

Added:
    lldb/trunk/lit/Modules/Breakpad/Inputs/bad-module-id-1.syms
    lldb/trunk/lit/Modules/Breakpad/Inputs/bad-module-id-2.syms
    lldb/trunk/lit/Modules/Breakpad/Inputs/bad-module-id-3.syms
    lldb/trunk/lit/Modules/Breakpad/Inputs/identification-linux.syms
    lldb/trunk/lit/Modules/Breakpad/Inputs/identification-macosx.syms
    lldb/trunk/lit/Modules/Breakpad/Inputs/identification-windows.syms
    lldb/trunk/lit/Modules/Breakpad/breakpad-identification.test
    lldb/trunk/lit/Modules/Breakpad/lit.local.cfg
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/deleted-executable/
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/deleted-executable/Makefile
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp
    lldb/trunk/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt
    lldb/trunk/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
    lldb/trunk/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h
Modified:
    lldb/trunk/include/lldb/Symbol/ObjectFile.h
    lldb/trunk/source/API/SystemInitializerFull.cpp
    lldb/trunk/source/Plugins/ObjectFile/CMakeLists.txt
    lldb/trunk/source/Symbol/ObjectFile.cpp
    lldb/trunk/tools/lldb-test/SystemInitializerTest.cpp
    lldb/trunk/tools/lldb-test/lldb-test.cpp

Modified: lldb/trunk/include/lldb/Symbol/ObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ObjectFile.h?rev=348773&r1=348772&r2=348773&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ObjectFile.h (original)
+++ lldb/trunk/include/lldb/Symbol/ObjectFile.h Mon Dec 10 09:16:38 2018
@@ -817,4 +817,16 @@ private:
 
 } // namespace lldb_private
 
+namespace llvm {
+template <> struct format_provider<lldb_private::ObjectFile::Type> {
+  static void format(const lldb_private::ObjectFile::Type &type,
+                     raw_ostream &OS, StringRef Style);
+};
+
+template <> struct format_provider<lldb_private::ObjectFile::Strata> {
+  static void format(const lldb_private::ObjectFile::Strata &strata,
+                     raw_ostream &OS, StringRef Style);
+};
+} // namespace llvm
+
 #endif // liblldb_ObjectFile_h_

Added: lldb/trunk/lit/Modules/Breakpad/Inputs/bad-module-id-1.syms
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Modules/Breakpad/Inputs/bad-module-id-1.syms?rev=348773&view=auto
==============================================================================
--- lldb/trunk/lit/Modules/Breakpad/Inputs/bad-module-id-1.syms (added)
+++ lldb/trunk/lit/Modules/Breakpad/Inputs/bad-module-id-1.syms Mon Dec 10 09:16:38 2018
@@ -0,0 +1,2 @@
+MODULE Linux x86_64 E5894855+C35D+CCCCCCCCCCCCCCCCCCCC0 linux.out
+PUBLIC 1000 0 _start

Added: lldb/trunk/lit/Modules/Breakpad/Inputs/bad-module-id-2.syms
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Modules/Breakpad/Inputs/bad-module-id-2.syms?rev=348773&view=auto
==============================================================================
--- lldb/trunk/lit/Modules/Breakpad/Inputs/bad-module-id-2.syms (added)
+++ lldb/trunk/lit/Modules/Breakpad/Inputs/bad-module-id-2.syms Mon Dec 10 09:16:38 2018
@@ -0,0 +1,2 @@
+MODULE Linux x86_64 E5894855C35DCCCCCCCCCCCCCCCCC linux.out
+PUBLIC 1000 0 _start

Added: lldb/trunk/lit/Modules/Breakpad/Inputs/bad-module-id-3.syms
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Modules/Breakpad/Inputs/bad-module-id-3.syms?rev=348773&view=auto
==============================================================================
--- lldb/trunk/lit/Modules/Breakpad/Inputs/bad-module-id-3.syms (added)
+++ lldb/trunk/lit/Modules/Breakpad/Inputs/bad-module-id-3.syms Mon Dec 10 09:16:38 2018
@@ -0,0 +1,2 @@
+MODULE Linux x86_64 E58X4855C35DCCCCCCCCXCCCCCCCCCCC0 linux.out
+PUBLIC 1000 0 _start

Added: lldb/trunk/lit/Modules/Breakpad/Inputs/identification-linux.syms
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Modules/Breakpad/Inputs/identification-linux.syms?rev=348773&view=auto
==============================================================================
--- lldb/trunk/lit/Modules/Breakpad/Inputs/identification-linux.syms (added)
+++ lldb/trunk/lit/Modules/Breakpad/Inputs/identification-linux.syms Mon Dec 10 09:16:38 2018
@@ -0,0 +1,6 @@
+MODULE Linux x86_64 E5894855C35DCCCCCCCCCCCCCCCCCCCC0 linux.out
+INFO CODE_ID 554889E55DC3CCCCCCCCCCCCCCCCCCCC
+PUBLIC 1000 0 _start
+STACK CFI INIT 1000 6 .cfa: $rsp 8 + .ra: .cfa -8 + ^
+STACK CFI 1001 $rbp: .cfa -16 + ^ .cfa: $rsp 16 +
+STACK CFI 1004 .cfa: $rbp 16 +

Added: lldb/trunk/lit/Modules/Breakpad/Inputs/identification-macosx.syms
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Modules/Breakpad/Inputs/identification-macosx.syms?rev=348773&view=auto
==============================================================================
--- lldb/trunk/lit/Modules/Breakpad/Inputs/identification-macosx.syms (added)
+++ lldb/trunk/lit/Modules/Breakpad/Inputs/identification-macosx.syms Mon Dec 10 09:16:38 2018
@@ -0,0 +1,6 @@
+MODULE mac x86_64 D98C0E682089AA1BEACD6A8C1F16707B0 mac.out
+PUBLIC 0 0 _mh_execute_header
+PUBLIC f30 0 start
+STACK CFI INIT f30 6 .cfa: $rsp 8 + .ra: .cfa -8 + ^
+STACK CFI f31 $rbp: .cfa -16 + ^ .cfa: $rsp 16 +
+STACK CFI f34 .cfa: $rbp 16 +

Added: lldb/trunk/lit/Modules/Breakpad/Inputs/identification-windows.syms
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Modules/Breakpad/Inputs/identification-windows.syms?rev=348773&view=auto
==============================================================================
--- lldb/trunk/lit/Modules/Breakpad/Inputs/identification-windows.syms (added)
+++ lldb/trunk/lit/Modules/Breakpad/Inputs/identification-windows.syms Mon Dec 10 09:16:38 2018
@@ -0,0 +1,4 @@
+MODULE windows x86 A0C9165780B5490981A1925EA62165C01 a.pdb
+INFO CODE_ID 5C01672A4000 a.exe
+FILE 1 c:\tmp\a.cpp
+PUBLIC 1000 0 main

Added: lldb/trunk/lit/Modules/Breakpad/breakpad-identification.test
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Modules/Breakpad/breakpad-identification.test?rev=348773&view=auto
==============================================================================
--- lldb/trunk/lit/Modules/Breakpad/breakpad-identification.test (added)
+++ lldb/trunk/lit/Modules/Breakpad/breakpad-identification.test Mon Dec 10 09:16:38 2018
@@ -0,0 +1,32 @@
+RUN: lldb-test object-file %p/Inputs/identification-linux.syms | FileCheck %s --check-prefix=LINUX
+RUN: lldb-test object-file %p/Inputs/identification-macosx.syms | FileCheck %s --check-prefix=MAC
+RUN: lldb-test object-file %p/Inputs/identification-windows.syms | FileCheck %s --check-prefix=WINDOWS
+RUN: not lldb-test object-file %p/Inputs/bad-module-id-1.syms 2>&1 | FileCheck %s --check-prefix=ERROR
+RUN: not lldb-test object-file %p/Inputs/bad-module-id-2.syms 2>&1 | FileCheck %s --check-prefix=ERROR
+RUN: not lldb-test object-file %p/Inputs/bad-module-id-3.syms 2>&1 | FileCheck %s --check-prefix=ERROR
+
+LINUX: Plugin name: breakpad
+LINUX: Architecture: x86_64--linux
+LINUX: UUID: 554889E5-5DC3-CCCC-CCCC-CCCCCCCCCCCC
+LINUX: Executable: false
+LINUX: Stripped: false
+LINUX: Type: debug info
+LINUX: Strata: user
+
+MAC: Plugin name: breakpad
+MAC: Architecture: x86_64--macosx
+MAC: UUID: 680E8CD9-8920-1BAA-EACD-6A8C1F16707B
+MAC: Executable: false
+MAC: Stripped: false
+MAC: Type: debug info
+MAC: Strata: user
+
+WINDOWS: Plugin name: breakpad
+WINDOWS: Architecture: i386--windows
+WINDOWS: UUID: 5716C9A0-B580-0949-81A1-925EA62165C0-01000000
+WINDOWS: Executable: false
+WINDOWS: Stripped: false
+WINDOWS: Type: debug info
+WINDOWS: Strata: user
+
+ERROR: not recognised as an object file

Added: lldb/trunk/lit/Modules/Breakpad/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Modules/Breakpad/lit.local.cfg?rev=348773&view=auto
==============================================================================
--- lldb/trunk/lit/Modules/Breakpad/lit.local.cfg (added)
+++ lldb/trunk/lit/Modules/Breakpad/lit.local.cfg Mon Dec 10 09:16:38 2018
@@ -0,0 +1 @@
+config.suffixes = ['.test']

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/deleted-executable/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/deleted-executable/Makefile?rev=348773&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/deleted-executable/Makefile (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/deleted-executable/Makefile Mon Dec 10 09:16:38 2018
@@ -0,0 +1,5 @@
+LEVEL = ../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py?rev=348773&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py Mon Dec 10 09:16:38 2018
@@ -0,0 +1,31 @@
+"""
+Test process attach/resume.
+"""
+
+from __future__ import print_function
+
+
+import os
+import time
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestDeletedExecutable(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+    NO_DEBUG_INFO_TESTCASE = True
+
+    @skipIfWindows # cannot delete a running executable
+    @expectedFailureAll(oslist=["linux"]) # determining the architecture of the process fails
+    def test(self):
+        self.build()
+        exe = self.getBuildArtifact("a.out")
+
+        popen = self.spawnSubprocess(exe)
+        self.addTearDownHook(self.cleanupSubprocesses)
+        os.remove(exe)
+
+        self.runCmd("process attach -p " + str(popen.pid))
+        self.runCmd("kill")

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp?rev=348773&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp Mon Dec 10 09:16:38 2018
@@ -0,0 +1,9 @@
+#include <chrono>
+#include <thread>
+
+int main(int argc, char const *argv[])
+{
+    lldb_enable_attach();
+
+    std::this_thread::sleep_for(std::chrono::seconds(30));
+}

Modified: lldb/trunk/source/API/SystemInitializerFull.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SystemInitializerFull.cpp?rev=348773&r1=348772&r2=348773&view=diff
==============================================================================
--- lldb/trunk/source/API/SystemInitializerFull.cpp (original)
+++ lldb/trunk/source/API/SystemInitializerFull.cpp Mon Dec 10 09:16:38 2018
@@ -62,6 +62,7 @@
 #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h"
 #include "Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h"
 #include "Plugins/MemoryHistory/asan/MemoryHistoryASan.h"
+#include "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h"
 #include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
 #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
 #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
@@ -268,6 +269,7 @@ SystemInitializerFull::Initialize(const
   if (auto e = SystemInitializerCommon::Initialize(options))
     return e;
 
+  breakpad::ObjectFileBreakpad::Initialize();
   ObjectFileELF::Initialize();
   ObjectFileMachO::Initialize();
   ObjectFilePECOFF::Initialize();
@@ -525,6 +527,7 @@ void SystemInitializerFull::Terminate()
   PlatformDarwinKernel::Terminate();
 #endif
 
+  breakpad::ObjectFileBreakpad::Terminate();
   ObjectFileELF::Terminate();
   ObjectFileMachO::Terminate();
   ObjectFilePECOFF::Terminate();

Added: lldb/trunk/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt?rev=348773&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt (added)
+++ lldb/trunk/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt Mon Dec 10 09:16:38 2018
@@ -0,0 +1,11 @@
+add_lldb_library(lldbPluginObjectFileBreakpad PLUGIN
+  ObjectFileBreakpad.cpp
+
+  LINK_LIBS
+    lldbCore
+    lldbHost
+    lldbSymbol
+    lldbUtility
+  LINK_COMPONENTS
+    Support
+  )

Added: lldb/trunk/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp?rev=348773&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp (added)
+++ lldb/trunk/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp Mon Dec 10 09:16:38 2018
@@ -0,0 +1,245 @@
+//===-- ObjectFileBreakpad.cpp -------------------------------- -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Utility/DataBuffer.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::breakpad;
+
+namespace {
+struct Header {
+  ArchSpec arch;
+  UUID uuid;
+  static llvm::Optional<Header> parse(llvm::StringRef text);
+};
+} // namespace
+
+static llvm::Triple::OSType toOS(llvm::StringRef str) {
+  using llvm::Triple;
+  return llvm::StringSwitch<Triple::OSType>(str)
+      .Case("Linux", Triple::Linux)
+      .Case("mac", Triple::MacOSX)
+      .Case("windows", Triple::Win32)
+      .Default(Triple::UnknownOS);
+}
+
+static llvm::Triple::ArchType toArch(llvm::StringRef str) {
+  using llvm::Triple;
+  return llvm::StringSwitch<Triple::ArchType>(str)
+      .Case("arm", Triple::arm)
+      .Case("arm64", Triple::aarch64)
+      .Case("mips", Triple::mips)
+      .Case("ppc", Triple::ppc)
+      .Case("ppc64", Triple::ppc64)
+      .Case("s390", Triple::systemz)
+      .Case("sparc", Triple::sparc)
+      .Case("sparcv9", Triple::sparcv9)
+      .Case("x86", Triple::x86)
+      .Case("x86_64", Triple::x86_64)
+      .Default(Triple::UnknownArch);
+}
+
+static llvm::StringRef consume_front(llvm::StringRef &str, size_t n) {
+  llvm::StringRef result = str.take_front(n);
+  str = str.drop_front(n);
+  return result;
+}
+
+static UUID parseModuleId(llvm::Triple::OSType os, llvm::StringRef str) {
+  struct uuid_data {
+    llvm::support::ulittle32_t uuid1;
+    llvm::support::ulittle16_t uuid2[2];
+    uint8_t uuid3[8];
+    llvm::support::ulittle32_t age;
+  } data;
+  static_assert(sizeof(data) == 20, "");
+  // The textual module id encoding should be between 33 and 40 bytes long,
+  // depending on the size of the age field, which is of variable length.
+  // The first three chunks of the id are encoded in big endian, so we need to
+  // byte-swap those.
+  if (str.size() < 33 || str.size() > 40)
+    return UUID();
+  uint32_t t;
+  if (to_integer(consume_front(str, 8), t, 16))
+    data.uuid1 = t;
+  else
+    return UUID();
+  for (int i = 0; i < 2; ++i) {
+    if (to_integer(consume_front(str, 4), t, 16))
+      data.uuid2[i] = t;
+    else
+      return UUID();
+  }
+  for (int i = 0; i < 8; ++i) {
+    if (!to_integer(consume_front(str, 2), data.uuid3[i], 16))
+      return UUID();
+  }
+  if (to_integer(str, t, 16))
+    data.age = t;
+  else
+    return UUID();
+
+  // On non-windows, the age field should always be zero, so we don't include to
+  // match the native uuid format of these platforms.
+  return UUID::fromData(&data, os == llvm::Triple::Win32 ? 20 : 16);
+}
+
+llvm::Optional<Header> Header::parse(llvm::StringRef text) {
+  // A valid module should start with something like:
+  // MODULE Linux x86_64 E5894855C35DCCCCCCCCCCCCCCCCCCCC0 a.out
+  // optionally followed by
+  // INFO CODE_ID 554889E55DC3CCCCCCCCCCCCCCCCCCCC [a.exe]
+  llvm::StringRef token, line;
+  std::tie(line, text) = text.split('\n');
+  std::tie(token, line) = getToken(line);
+  if (token != "MODULE")
+    return llvm::None;
+
+  std::tie(token, line) = getToken(line);
+  llvm::Triple triple;
+  triple.setOS(toOS(token));
+  if (triple.getOS() == llvm::Triple::UnknownOS)
+    return llvm::None;
+
+  std::tie(token, line) = getToken(line);
+  triple.setArch(toArch(token));
+  if (triple.getArch() == llvm::Triple::UnknownArch)
+    return llvm::None;
+
+  llvm::StringRef module_id;
+  std::tie(module_id, line) = getToken(line);
+
+  std::tie(line, text) = text.split('\n');
+  std::tie(token, line) = getToken(line);
+  if (token == "INFO") {
+    std::tie(token, line) = getToken(line);
+    if (token != "CODE_ID")
+      return llvm::None;
+
+    std::tie(token, line) = getToken(line);
+    // If we don't have any text following the code id (e.g. on linux), we
+    // should use the module id as UUID. Otherwise, we revert back to the module
+    // id.
+    if (line.trim().empty()) {
+      UUID uuid;
+      if (uuid.SetFromStringRef(token, token.size() / 2) != token.size())
+        return llvm::None;
+
+      return Header{ArchSpec(triple), uuid};
+    }
+  }
+
+  // We reach here if we don't have a INFO CODE_ID section, or we chose not to
+  // use it. In either case, we need to properly decode the module id, whose
+  // fields are encoded in big-endian.
+  UUID uuid = parseModuleId(triple.getOS(), module_id);
+  if (!uuid)
+    return llvm::None;
+
+  return Header{ArchSpec(triple), uuid};
+}
+
+void ObjectFileBreakpad::Initialize() {
+  PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                GetPluginDescriptionStatic(), CreateInstance,
+                                nullptr, GetModuleSpecifications);
+}
+
+void ObjectFileBreakpad::Terminate() {
+  PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+ConstString ObjectFileBreakpad::GetPluginNameStatic() {
+  static ConstString g_name("breakpad");
+  return g_name;
+}
+
+ObjectFile *ObjectFileBreakpad::CreateInstance(
+    const ModuleSP &module_sp, DataBufferSP &data_sp, offset_t data_offset,
+    const FileSpec *file, offset_t file_offset, offset_t length) {
+  if (!data_sp) {
+    data_sp = MapFileData(*file, length, file_offset);
+    if (!data_sp)
+      return nullptr;
+    data_offset = 0;
+  }
+  auto text = toStringRef(data_sp->GetData());
+  llvm::Optional<Header> header = Header::parse(text);
+  if (!header)
+    return nullptr;
+
+  // Update the data to contain the entire file if it doesn't already
+  if (data_sp->GetByteSize() < length) {
+    data_sp = MapFileData(*file, length, file_offset);
+    if (!data_sp)
+      return nullptr;
+    data_offset = 0;
+  }
+
+  return new ObjectFileBreakpad(module_sp, data_sp, data_offset, file,
+                                file_offset, length, std::move(header->arch),
+                                std::move(header->uuid));
+}
+
+ObjectFile *ObjectFileBreakpad::CreateMemoryInstance(
+    const ModuleSP &module_sp, DataBufferSP &data_sp,
+    const ProcessSP &process_sp, addr_t header_addr) {
+  return nullptr;
+}
+
+size_t ObjectFileBreakpad::GetModuleSpecifications(
+    const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,
+    offset_t file_offset, offset_t length, ModuleSpecList &specs) {
+  auto text = toStringRef(data_sp->GetData());
+  llvm::Optional<Header> header = Header::parse(text);
+  if (!header)
+    return 0;
+  ModuleSpec spec(file, std::move(header->arch));
+  spec.GetUUID() = std::move(header->uuid);
+  specs.Append(spec);
+  return 1;
+}
+
+ObjectFileBreakpad::ObjectFileBreakpad(const ModuleSP &module_sp,
+                                       DataBufferSP &data_sp,
+                                       offset_t data_offset,
+                                       const FileSpec *file, offset_t offset,
+                                       offset_t length, ArchSpec arch,
+                                       UUID uuid)
+    : ObjectFile(module_sp, file, offset, length, data_sp, data_offset),
+      m_arch(std::move(arch)), m_uuid(std::move(uuid)) {}
+
+bool ObjectFileBreakpad::ParseHeader() {
+  // We already parsed the header during initialization.
+  return true;
+}
+
+Symtab *ObjectFileBreakpad::GetSymtab() {
+  // TODO
+  return nullptr;
+}
+
+bool ObjectFileBreakpad::GetArchitecture(ArchSpec &arch) {
+  arch = m_arch;
+  return true;
+}
+
+bool ObjectFileBreakpad::GetUUID(UUID *uuid) {
+  *uuid = m_uuid;
+  return true;
+}
+
+void ObjectFileBreakpad::CreateSections(SectionList &unified_section_list) {
+  // TODO
+}

Added: lldb/trunk/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h?rev=348773&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h (added)
+++ lldb/trunk/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h Mon Dec 10 09:16:38 2018
@@ -0,0 +1,109 @@
+//===-- ObjectFileBreakpad.h ---------------------------------- -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_OBJECTFILE_BREAKPAD_OBJECTFILEBREAKPAD_H
+#define LLDB_PLUGINS_OBJECTFILE_BREAKPAD_OBJECTFILEBREAKPAD_H
+
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "llvm/ADT/Triple.h"
+
+namespace lldb_private {
+namespace breakpad {
+
+class ObjectFileBreakpad : public ObjectFile {
+public:
+  //------------------------------------------------------------------
+  // Static Functions
+  //------------------------------------------------------------------
+  static void Initialize();
+  static void Terminate();
+
+  static ConstString GetPluginNameStatic();
+  static const char *GetPluginDescriptionStatic() {
+    return "Breakpad object file reader.";
+  }
+
+  static ObjectFile *
+  CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
+                 lldb::offset_t data_offset, const FileSpec *file,
+                 lldb::offset_t file_offset, lldb::offset_t length);
+
+  static ObjectFile *CreateMemoryInstance(const lldb::ModuleSP &module_sp,
+                                          lldb::DataBufferSP &data_sp,
+                                          const lldb::ProcessSP &process_sp,
+                                          lldb::addr_t header_addr);
+
+  static size_t GetModuleSpecifications(const FileSpec &file,
+                                        lldb::DataBufferSP &data_sp,
+                                        lldb::offset_t data_offset,
+                                        lldb::offset_t file_offset,
+                                        lldb::offset_t length,
+                                        ModuleSpecList &specs);
+
+  //------------------------------------------------------------------
+  // PluginInterface protocol
+  //------------------------------------------------------------------
+  ConstString GetPluginName() override { return GetPluginNameStatic(); }
+
+  uint32_t GetPluginVersion() override { return 1; }
+
+  //------------------------------------------------------------------
+  // ObjectFile Protocol.
+  //------------------------------------------------------------------
+
+  bool ParseHeader() override;
+
+  lldb::ByteOrder GetByteOrder() const override {
+    return m_arch.GetByteOrder();
+  }
+
+  bool IsExecutable() const override { return false; }
+
+  uint32_t GetAddressByteSize() const override {
+    return m_arch.GetAddressByteSize();
+  }
+
+  AddressClass GetAddressClass(lldb::addr_t file_addr) override {
+    return AddressClass::eInvalid;
+  }
+
+  Symtab *GetSymtab() override;
+
+  bool IsStripped() override { return false; }
+
+  void CreateSections(SectionList &unified_section_list) override;
+
+  void Dump(Stream *s) override {}
+
+  bool GetArchitecture(ArchSpec &arch) override;
+
+  bool GetUUID(UUID *uuid) override;
+
+  FileSpecList GetDebugSymbolFilePaths() override { return FileSpecList(); }
+
+  uint32_t GetDependentModules(FileSpecList &files) override { return 0; }
+
+  Type CalculateType() override { return eTypeDebugInfo; }
+
+  Strata CalculateStrata() override { return eStrataUser; }
+
+private:
+  ArchSpec m_arch;
+  UUID m_uuid;
+
+  ObjectFileBreakpad(const lldb::ModuleSP &module_sp,
+                     lldb::DataBufferSP &data_sp, lldb::offset_t data_offset,
+                     const FileSpec *file, lldb::offset_t offset,
+                     lldb::offset_t length, ArchSpec arch, UUID uuid);
+};
+
+} // namespace breakpad
+} // namespace lldb_private
+#endif // LLDB_PLUGINS_OBJECTFILE_BREAKPAD_OBJECTFILEBREAKPAD_H

Modified: lldb/trunk/source/Plugins/ObjectFile/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/CMakeLists.txt?rev=348773&r1=348772&r2=348773&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/ObjectFile/CMakeLists.txt Mon Dec 10 09:16:38 2018
@@ -1,4 +1,5 @@
+add_subdirectory(Breakpad)
 add_subdirectory(ELF)
 add_subdirectory(Mach-O)
 add_subdirectory(PECOFF)
-add_subdirectory(JIT)
\ No newline at end of file
+add_subdirectory(JIT)

Modified: lldb/trunk/source/Symbol/ObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ObjectFile.cpp?rev=348773&r1=348772&r2=348773&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ObjectFile.cpp (original)
+++ lldb/trunk/source/Symbol/ObjectFile.cpp Mon Dec 10 09:16:38 2018
@@ -688,3 +688,63 @@ DataBufferSP ObjectFile::MapFileData(con
                                      uint64_t Offset) {
   return FileSystem::Instance().CreateDataBuffer(file.GetPath(), Size, Offset);
 }
+
+void llvm::format_provider<ObjectFile::Type>::format(
+    const ObjectFile::Type &type, raw_ostream &OS, StringRef Style) {
+  switch (type) {
+  case ObjectFile::eTypeInvalid:
+    OS << "invalid";
+    break;
+  case ObjectFile::eTypeCoreFile:
+    OS << "core file";
+    break;
+  case ObjectFile::eTypeExecutable:
+    OS << "executable";
+    break;
+  case ObjectFile::eTypeDebugInfo:
+    OS << "debug info";
+    break;
+  case ObjectFile::eTypeDynamicLinker:
+    OS << "dynamic linker";
+    break;
+  case ObjectFile::eTypeObjectFile:
+    OS << "object file";
+    break;
+  case ObjectFile::eTypeSharedLibrary:
+    OS << "shared library";
+    break;
+  case ObjectFile::eTypeStubLibrary:
+    OS << "stub library";
+    break;
+  case ObjectFile::eTypeJIT:
+    OS << "jit";
+    break;
+  case ObjectFile::eTypeUnknown:
+    OS << "unknown";
+    break;
+  }
+}
+
+void llvm::format_provider<ObjectFile::Strata>::format(
+    const ObjectFile::Strata &strata, raw_ostream &OS, StringRef Style) {
+  switch (strata) {
+  case ObjectFile::eStrataInvalid:
+    OS << "invalid";
+    break;
+  case ObjectFile::eStrataUnknown:
+    OS << "unknown";
+    break;
+  case ObjectFile::eStrataUser:
+    OS << "user";
+    break;
+  case ObjectFile::eStrataKernel:
+    OS << "kernel";
+    break;
+  case ObjectFile::eStrataRawImage:
+    OS << "raw image";
+    break;
+  case ObjectFile::eStrataJIT:
+    OS << "jit";
+    break;
+  }
+}

Modified: lldb/trunk/tools/lldb-test/SystemInitializerTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-test/SystemInitializerTest.cpp?rev=348773&r1=348772&r2=348773&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-test/SystemInitializerTest.cpp (original)
+++ lldb/trunk/tools/lldb-test/SystemInitializerTest.cpp Mon Dec 10 09:16:38 2018
@@ -52,6 +52,7 @@
 #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h"
 #include "Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h"
 #include "Plugins/MemoryHistory/asan/MemoryHistoryASan.h"
+#include "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h"
 #include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
 #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
 #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
@@ -116,6 +117,7 @@ SystemInitializerTest::Initialize(const
   if (auto e = SystemInitializerCommon::Initialize(options))
     return e;
 
+  breakpad::ObjectFileBreakpad::Initialize();
   ObjectFileELF::Initialize();
   ObjectFileMachO::Initialize();
   ObjectFilePECOFF::Initialize();
@@ -331,6 +333,7 @@ void SystemInitializerTest::Terminate()
   PlatformDarwinKernel::Terminate();
 #endif
 
+  breakpad::ObjectFileBreakpad::Terminate();
   ObjectFileELF::Terminate();
   ObjectFileMachO::Terminate();
   ObjectFilePECOFF::Terminate();

Modified: lldb/trunk/tools/lldb-test/lldb-test.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-test/lldb-test.cpp?rev=348773&r1=348772&r2=348773&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-test/lldb-test.cpp (original)
+++ lldb/trunk/tools/lldb-test/lldb-test.cpp Mon Dec 10 09:16:38 2018
@@ -726,6 +726,14 @@ static int dumpObjectFiles(Debugger &Dbg
     ModuleSpec Spec{FileSpec(File)};
 
     auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
+
+    ObjectFile *ObjectPtr = ModulePtr->GetObjectFile();
+    if (!ObjectPtr) {
+      WithColor::error() << File << " not recognised as an object file\n";
+      HadErrors = 1;
+      continue;
+    }
+
     // Fetch symbol vendor before we get the section list to give the symbol
     // vendor a chance to populate it.
     ModulePtr->GetSymbolVendor();
@@ -736,9 +744,14 @@ static int dumpObjectFiles(Debugger &Dbg
       continue;
     }
 
+    Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName());
     Printer.formatLine("Architecture: {0}",
                        ModulePtr->GetArchitecture().GetTriple().getTriple());
     Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString());
+    Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable());
+    Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped());
+    Printer.formatLine("Type: {0}", ObjectPtr->GetType());
+    Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata());
 
     size_t Count = Sections->GetNumSections(0);
     Printer.formatLine("Showing {0} sections", Count);




More information about the lldb-commits mailing list