[llvm] 2f6cc21 - Add a llvm-gsymutil tool that can convert object files to GSYM and perform lookups.

Greg Clayton via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 25 21:11:16 PST 2020


Author: Greg Clayton
Date: 2020-02-25T21:11:05-08:00
New Revision: 2f6cc21f44ec9f1c3196555d2ac95dd96c48903f

URL: https://github.com/llvm/llvm-project/commit/2f6cc21f44ec9f1c3196555d2ac95dd96c48903f
DIFF: https://github.com/llvm/llvm-project/commit/2f6cc21f44ec9f1c3196555d2ac95dd96c48903f.diff

LOG: Add a llvm-gsymutil tool that can convert object files to GSYM and perform lookups.

Summary:
This patch creates the llvm-gsymutil binary that can convert object files to GSYM using the --convert <path> option. It can also dump and lookup addresses within GSYM files that have been saved to disk.

To dump a file:

llvm-gsymutil /path/to/a.gsym

To perform address lookups, like with atos, on GSYM files:

llvm-gsymutil --address 0x1000 --address 0x1100 /path/to/a.gsym

To convert a mach-o or ELF file, including any DWARF debug info contained within the object files:

llvm-gsymutil --convert /path/to/a.out --out-file /path/to/a.out.gsym

Conversion highlights:
- convert DWARF debug info in mach-o or ELF files to GSYM
- convert symbols in symbol table to GSYM and don't convert symbols that overlap with DWARF debug info
- extract UUID from object files
- extract .text (read + execute) section address ranges and filter out any DWARF or symbols that don't fall in those ranges.
- if .text sections are extracted, and if the last gsym::FunctionInfo object has no size, cap the size to the end of the section the function was contained in

Dumping GSYM files will dump all sections of the GSYM file in textual format.

Reviewers: labath, aadsm, serhiy.redko, jankratochvil, xiaobai, wallace, aprantl, JDevlieghere, jdoerfert

Subscribers: mgorny, hiraditya, llvm-commits

Tags: #llvm

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

Added: 
    llvm/include/llvm/DebugInfo/GSYM/ObjectFileTransformer.h
    llvm/lib/DebugInfo/GSYM/ObjectFileTransformer.cpp
    llvm/test/tools/llvm-gsymutil/cmdline.test
    llvm/test/tools/llvm-gsymutil/elf-dwarf.yaml
    llvm/test/tools/llvm-gsymutil/fat-macho-dwarf.yaml
    llvm/test/tools/llvm-gsymutil/mach-dwarf.yaml
    llvm/tools/llvm-gsym/CMakeLists.txt
    llvm/tools/llvm-gsym/llvm-gsymutil.cpp

Modified: 
    llvm/include/llvm/DebugInfo/GSYM/GsymCreator.h
    llvm/include/llvm/DebugInfo/GSYM/GsymReader.h
    llvm/include/llvm/DebugInfo/GSYM/Range.h
    llvm/lib/DebugInfo/GSYM/CMakeLists.txt
    llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp
    llvm/lib/DebugInfo/GSYM/GsymCreator.cpp
    llvm/lib/DebugInfo/GSYM/GsymReader.cpp
    llvm/lib/DebugInfo/GSYM/LookupResult.cpp
    llvm/lib/DebugInfo/GSYM/Range.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/DebugInfo/GSYM/GsymCreator.h b/llvm/include/llvm/DebugInfo/GSYM/GsymCreator.h
index fc98516e5731..f29a147d4403 100644
--- a/llvm/include/llvm/DebugInfo/GSYM/GsymCreator.h
+++ b/llvm/include/llvm/DebugInfo/GSYM/GsymCreator.h
@@ -141,6 +141,8 @@ class GsymCreator {
   std::vector<llvm::gsym::FileEntry> Files;
   std::vector<uint8_t> UUID;
   Optional<AddressRanges> ValidTextRanges;
+  AddressRanges Ranges;
+  llvm::Optional<uint64_t> BaseAddress;
   bool Finalized = false;
 
 public:
@@ -231,6 +233,17 @@ class GsymCreator {
   /// object.
   size_t getNumFunctionInfos() const;
 
+  /// Check if an address has already been added as a function info.
+  ///
+  /// FunctionInfo data can come from many sources: debug info, symbol tables,
+  /// exception information, and more. Symbol tables should be added after
+  /// debug info and can use this function to see if a symbol's start address
+  /// has already been added to the GsymReader. Calling this before adding
+  /// a function info from a source other than debug info avoids clients adding
+  /// many redundant FunctionInfo objects from many sources only for them to be
+  /// removed during the finalize() call.
+  bool hasFunctionInfoForAddress(uint64_t Addr) const;
+
   /// Set valid .text address ranges that all functions must be contained in.
   void SetValidTextRanges(AddressRanges &TextRanges) {
     ValidTextRanges = TextRanges;
@@ -262,6 +275,20 @@ class GsymCreator {
   ///          text ranges have been set, false otherwise.
   bool IsValidTextAddress(uint64_t Addr) const;
 
+  /// Set the base address to use for the GSYM file.
+  ///
+  /// Setting the base address to use for the GSYM file. Object files typically
+  /// get loaded from a base address when the OS loads them into memory. Using
+  /// GSYM files for symbolication becomes easier if the base address in the
+  /// GSYM header is the same address as it allows addresses to be easily slid
+  /// and allows symbolication without needing to find the original base
+  /// address in the original object file.
+  ///
+  /// \param  Addr The address to use as the base address of the GSYM file
+  ///              when it is saved to disk.
+  void setBaseAddress(uint64_t Addr) {
+    BaseAddress = Addr;
+  }
 };
 
 } // namespace gsym

diff  --git a/llvm/include/llvm/DebugInfo/GSYM/GsymReader.h b/llvm/include/llvm/DebugInfo/GSYM/GsymReader.h
index 3301889c5db0..2a4eac77d946 100644
--- a/llvm/include/llvm/DebugInfo/GSYM/GsymReader.h
+++ b/llvm/include/llvm/DebugInfo/GSYM/GsymReader.h
@@ -257,11 +257,15 @@ class GsymReader {
   /// \returns The matching address offset index. This index will be used to
   /// extract the FunctionInfo data's offset from the AddrInfoOffsets array.
   template <class T>
-  uint64_t getAddressOffsetIndex(const uint64_t AddrOffset) const {
+  llvm::Optional<uint64_t> getAddressOffsetIndex(const uint64_t AddrOffset) const {
     ArrayRef<T> AIO = getAddrOffsets<T>();
     const auto Begin = AIO.begin();
     const auto End = AIO.end();
     auto Iter = std::lower_bound(Begin, End, AddrOffset);
+    // Watch for addresses that fall between the gsym::Header::BaseAddress and
+    // the first address offset.
+    if (Iter == Begin && AddrOffset < *Begin)
+      return llvm::None;
     if (Iter == End || AddrOffset < *Iter)
       --Iter;
     return std::distance(Begin, Iter);

diff  --git a/llvm/include/llvm/DebugInfo/GSYM/ObjectFileTransformer.h b/llvm/include/llvm/DebugInfo/GSYM/ObjectFileTransformer.h
new file mode 100644
index 000000000000..84a8d98fe365
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/GSYM/ObjectFileTransformer.h
@@ -0,0 +1,51 @@
+//===- ObjectFileTransformer.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_GSYM_OBJECTFILETRANSFORMER_H
+#define LLVM_DEBUGINFO_GSYM_OBJECTFILETRANSFORMER_H
+
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+namespace object {
+class ObjectFile;
+}
+
+namespace gsym {
+
+struct CUInfo;
+class GsymCreator;
+
+class ObjectFileTransformer {
+public:
+  /// Extract any object file data that is needed by the GsymCreator.
+  ///
+  /// The extracted information includes the UUID of the binary and converting
+  /// all function symbols from any symbol tables into FunctionInfo objects.
+  ///
+  /// \param Obj The object file that contains the DWARF debug info.
+  ///
+  /// \param Log The stream to log warnings and non fatal issues to.
+  ///
+  /// \param Gsym The GSYM creator to populate with the function information
+  /// from the debug info.
+  ///
+  /// \returns An error indicating any fatal issues that happen when parsing
+  /// the DWARF, or Error::success() if all goes well.
+  static llvm::Error convert(const object::ObjectFile &Obj,
+                             raw_ostream &Log,
+                             GsymCreator &Gsym);
+};
+
+} // namespace gsym
+} // namespace llvm
+
+#endif // #ifndef LLVM_DEBUGINFO_GSYM_OBJECTFILETRANSFORMER_H

diff  --git a/llvm/include/llvm/DebugInfo/GSYM/Range.h b/llvm/include/llvm/DebugInfo/GSYM/Range.h
index 49e316eae3cf..b3e7692543bf 100644
--- a/llvm/include/llvm/DebugInfo/GSYM/Range.h
+++ b/llvm/include/llvm/DebugInfo/GSYM/Range.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_DEBUGINFO_GSYM_RANGE_H
 #define LLVM_DEBUGINFO_GSYM_RANGE_H
 
+#include "llvm/ADT/Optional.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
 #include <stdint.h>
@@ -89,6 +90,7 @@ class AddressRanges {
   bool empty() const { return Ranges.empty(); }
   bool contains(uint64_t Addr) const;
   bool contains(AddressRange Range) const;
+  Optional<AddressRange> getRangeThatContains(uint64_t Addr) const;
   void insert(AddressRange Range);
   size_t size() const { return Ranges.size(); }
   bool operator==(const AddressRanges &RHS) const {

diff  --git a/llvm/lib/DebugInfo/GSYM/CMakeLists.txt b/llvm/lib/DebugInfo/GSYM/CMakeLists.txt
index a33b5ce59ea1..90e56bd6f6da 100644
--- a/llvm/lib/DebugInfo/GSYM/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/GSYM/CMakeLists.txt
@@ -12,6 +12,7 @@ add_llvm_component_library(LLVMDebugInfoGSYM
   InlineInfo.cpp
   LineTable.cpp
   LookupResult.cpp
+  ObjectFileTransformer.cpp
   Range.cpp
 
   ADDITIONAL_HEADER_DIRS

diff  --git a/llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp b/llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp
index f8afd2c98050..cef1b9498c5c 100644
--- a/llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp
+++ b/llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp
@@ -170,7 +170,7 @@ llvm::Expected<LookupResult> FunctionInfo::lookup(DataExtractor &Data,
   // This function will be called with the result of a binary search of the
   // address table, we must still make sure the address does not fall into a
   // gap between functions are after the last function.
-  if (Addr >= LR.FuncRange.End)
+  if (LR.FuncRange.size() > 0 && !LR.FuncRange.contains(Addr))
     return createStringError(std::errc::io_error,
         "address 0x%" PRIx64 " is not in GSYM", Addr);
 

diff  --git a/llvm/lib/DebugInfo/GSYM/GsymCreator.cpp b/llvm/lib/DebugInfo/GSYM/GsymCreator.cpp
index a8b03afd69da..3a84ac41e86c 100644
--- a/llvm/lib/DebugInfo/GSYM/GsymCreator.cpp
+++ b/llvm/lib/DebugInfo/GSYM/GsymCreator.cpp
@@ -62,7 +62,8 @@ llvm::Error GsymCreator::encode(FileWriter &O) const {
   if (Funcs.size() > UINT32_MAX)
     return createStringError(std::errc::invalid_argument,
                              "too many FunctionInfos");
-  const uint64_t MinAddr = Funcs.front().startAddress();
+
+  const uint64_t MinAddr = BaseAddress ? *BaseAddress : Funcs.front().startAddress();
   const uint64_t MaxAddr = Funcs.back().startAddress();
   const uint64_t AddrDelta = MaxAddr - MinAddr;
   Header Hdr;
@@ -238,6 +239,17 @@ llvm::Error GsymCreator::finalize(llvm::raw_ostream &OS) {
     Prev = Curr++;
   }
 
+  // If our last function info entry doesn't have a size and if we have valid
+  // text ranges, we should set the size of the last entry since any search for
+  // a high address might match our last entry. By fixing up this size, we can
+  // help ensure we don't cause lookups to always return the last symbol that
+  // has no size when doing lookups.
+  if (!Funcs.empty() && Funcs.back().Range.size() == 0 && ValidTextRanges) {
+    if (auto Range = ValidTextRanges->getRangeThatContains(
+          Funcs.back().Range.Start)) {
+      Funcs.back().Range.End = Range->End;
+    }
+  }
   OS << "Pruned " << NumBefore - Funcs.size() << " functions, ended with "
      << Funcs.size() << " total\n";
   return Error::success();
@@ -263,6 +275,7 @@ uint32_t GsymCreator::insertString(StringRef S, bool Copy) {
 
 void GsymCreator::addFunctionInfo(FunctionInfo &&FI) {
   std::lock_guard<std::recursive_mutex> Guard(Mutex);
+  Ranges.insert(FI.Range);
   Funcs.emplace_back(FI);
 }
 
@@ -294,3 +307,8 @@ bool GsymCreator::IsValidTextAddress(uint64_t Addr) const {
     return ValidTextRanges->contains(Addr);
   return true; // No valid text ranges has been set, so accept all ranges.
 }
+
+bool GsymCreator::hasFunctionInfoForAddress(uint64_t Addr) const {
+  std::lock_guard<std::recursive_mutex> Guard(Mutex);
+  return Ranges.contains(Addr);
+}

diff  --git a/llvm/lib/DebugInfo/GSYM/GsymReader.cpp b/llvm/lib/DebugInfo/GSYM/GsymReader.cpp
index 39e811da4e91..2ad18bf63d5d 100644
--- a/llvm/lib/DebugInfo/GSYM/GsymReader.cpp
+++ b/llvm/lib/DebugInfo/GSYM/GsymReader.cpp
@@ -225,20 +225,33 @@ Optional<uint64_t> GsymReader::getAddressInfoOffset(size_t Index) const {
 
 Expected<uint64_t>
 GsymReader::getAddressIndex(const uint64_t Addr) const {
-  if (Addr < Hdr->BaseAddress)
-    return createStringError(std::errc::invalid_argument,
-                             "address 0x%" PRIx64 " is not in GSYM", Addr);
-  const uint64_t AddrOffset = Addr - Hdr->BaseAddress;
-  switch (Hdr->AddrOffSize) {
-  case 1: return getAddressOffsetIndex<uint8_t>(AddrOffset);
-  case 2: return getAddressOffsetIndex<uint16_t>(AddrOffset);
-  case 4: return getAddressOffsetIndex<uint32_t>(AddrOffset);
-  case 8: return getAddressOffsetIndex<uint64_t>(AddrOffset);
-  default: break;
+  if (Addr >= Hdr->BaseAddress) {
+    const uint64_t AddrOffset = Addr - Hdr->BaseAddress;
+    Optional<uint64_t> AddrOffsetIndex;
+    switch (Hdr->AddrOffSize) {
+    case 1:
+      AddrOffsetIndex = getAddressOffsetIndex<uint8_t>(AddrOffset);
+      break;
+    case 2:
+      AddrOffsetIndex = getAddressOffsetIndex<uint16_t>(AddrOffset);
+      break;
+    case 4:
+      AddrOffsetIndex = getAddressOffsetIndex<uint32_t>(AddrOffset);
+      break;
+    case 8:
+      AddrOffsetIndex = getAddressOffsetIndex<uint64_t>(AddrOffset);
+      break;
+    default:
+      return createStringError(std::errc::invalid_argument,
+                               "unsupported address offset size %u",
+                               Hdr->AddrOffSize);
+    }
+    if (AddrOffsetIndex)
+      return *AddrOffsetIndex;
   }
   return createStringError(std::errc::invalid_argument,
-                           "unsupported address offset size %u",
-                           Hdr->AddrOffSize);
+                           "address 0x%" PRIx64 " is not in GSYM", Addr);
+
 }
 
 llvm::Expected<FunctionInfo> GsymReader::getFunctionInfo(uint64_t Addr) const {

diff  --git a/llvm/lib/DebugInfo/GSYM/LookupResult.cpp b/llvm/lib/DebugInfo/GSYM/LookupResult.cpp
index 0d9ad8b22728..8a624226b1d3 100644
--- a/llvm/lib/DebugInfo/GSYM/LookupResult.cpp
+++ b/llvm/lib/DebugInfo/GSYM/LookupResult.cpp
@@ -35,19 +35,24 @@ std::string LookupResult::getSourceFile(uint32_t Index) const {
 }
 
 raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const SourceLocation &SL) {
-  OS << SL.Name << " @ ";
-  if (!SL.Dir.empty()) {
-    OS << SL.Dir;
-    if (SL.Dir.contains('\\') and not SL.Dir.contains('/'))
-      OS << '\\';
+  OS << SL.Name;
+  if (SL.Offset > 0)
+    OS << " + " << SL.Offset;
+  if (SL.Dir.size() || SL.Base.size()) {
+    OS << " @ ";
+    if (!SL.Dir.empty()) {
+      OS << SL.Dir;
+      if (SL.Dir.contains('\\') and not SL.Dir.contains('/'))
+        OS << '\\';
+      else
+        OS << '/';
+    }
+    if (SL.Base.empty())
+      OS << "<invalid-file>";
     else
-      OS << '/';
+      OS << SL.Base;
+    OS << ':' << SL.Line;
   }
-  if (SL.Base.empty())
-    OS << "<invalid-file>";
-  else
-    OS << SL.Base;
-  OS << ':' << SL.Line;
   return OS;
 }
 

diff  --git a/llvm/lib/DebugInfo/GSYM/ObjectFileTransformer.cpp b/llvm/lib/DebugInfo/GSYM/ObjectFileTransformer.cpp
new file mode 100644
index 000000000000..eb392dd83d6a
--- /dev/null
+++ b/llvm/lib/DebugInfo/GSYM/ObjectFileTransformer.cpp
@@ -0,0 +1,107 @@
+//===- ObjectFileTransformer.cpp --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <unordered_set>
+
+#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/MachOUniversal.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "llvm/DebugInfo/GSYM/ObjectFileTransformer.h"
+#include "llvm/DebugInfo/GSYM/GsymCreator.h"
+
+using namespace llvm;
+using namespace gsym;
+
+constexpr uint32_t NT_GNU_BUILD_ID_TAG = 0x03;
+
+static std::vector<uint8_t> getUUID(const object::ObjectFile &Obj) {
+  // Extract the UUID from the object file
+  std::vector<uint8_t> UUID;
+  if (auto *MachO = dyn_cast<object::MachOObjectFile>(&Obj)) {
+    const ArrayRef<uint8_t> MachUUID = MachO->getUuid();
+    if (!MachUUID.empty())
+      UUID.assign(MachUUID.data(), MachUUID.data() + MachUUID.size());
+  } else if (isa<object::ELFObjectFileBase>(&Obj)) {
+    const StringRef GNUBuildID(".note.gnu.build-id");
+    for (const object::SectionRef &Sect : Obj.sections()) {
+      Expected<StringRef> SectNameOrErr = Sect.getName();
+      if (!SectNameOrErr) {
+        consumeError(SectNameOrErr.takeError());
+        continue;
+      }
+      StringRef SectName(*SectNameOrErr);
+      if (SectName != GNUBuildID)
+        continue;
+      StringRef BuildIDData;
+      Expected<StringRef> E = Sect.getContents();
+      if (E)
+        BuildIDData = *E;
+      else {
+        consumeError(E.takeError());
+        continue;
+      }
+      DataExtractor Decoder(BuildIDData, Obj.makeTriple().isLittleEndian(), 8);
+      uint64_t Offset = 0;
+      const uint32_t NameSize = Decoder.getU32(&Offset);
+      const uint32_t PayloadSize = Decoder.getU32(&Offset);
+      const uint32_t PayloadType = Decoder.getU32(&Offset);
+      StringRef Name(Decoder.getFixedLengthString(&Offset, NameSize));
+      if (Name == "GNU" && PayloadType == NT_GNU_BUILD_ID_TAG) {
+        Offset = alignTo(Offset, 4);
+        StringRef UUIDBytes(Decoder.getBytes(&Offset, PayloadSize));
+        if (!UUIDBytes.empty()) {
+          auto Ptr = reinterpret_cast<const uint8_t *>(UUIDBytes.data());
+          UUID.assign(Ptr, Ptr + UUIDBytes.size());
+        }
+      }
+    }
+  }
+  return UUID;
+}
+
+llvm::Error ObjectFileTransformer::convert(const object::ObjectFile &Obj,
+                                           raw_ostream &Log,
+                                           GsymCreator &Gsym) {
+  using namespace llvm::object;
+
+  const bool IsMachO = isa<MachOObjectFile>(&Obj);
+  const bool IsELF = isa<ELFObjectFileBase>(&Obj);
+
+  // Read build ID.
+  Gsym.setUUID(getUUID(Obj));
+
+  // Parse the symbol table.
+  size_t NumBefore = Gsym.getNumFunctionInfos();
+  for (const object::SymbolRef &Sym : Obj.symbols()) {
+    Expected<SymbolRef::Type> SymType = Sym.getType();
+    const uint64_t Addr = Sym.getValue();
+    if (!SymType || SymType.get() != SymbolRef::Type::ST_Function ||
+        !Gsym.IsValidTextAddress(Addr) || Gsym.hasFunctionInfoForAddress(Addr))
+      continue;
+    // Function size for MachO files will be 0
+    constexpr bool NoCopy = false;
+    const uint64_t size = IsELF ? ELFSymbolRef(Sym).getSize() : 0;
+    Expected<StringRef> Name = Sym.getName();
+    if (!Name) {
+      logAllUnhandledErrors(Name.takeError(), Log, "ObjectFileTransformer: ");
+      continue;
+    }
+    // Remove the leading '_' character in any symbol names if there is one
+    // for mach-o files.
+    if (IsMachO)
+      Name->consume_front("_");
+    Gsym.addFunctionInfo(FunctionInfo(Addr, size,
+                                      Gsym.insertString(*Name, NoCopy)));
+  }
+  size_t FunctionsAddedCount = Gsym.getNumFunctionInfos() - NumBefore;
+  Log << "Loaded " << FunctionsAddedCount << " functions from symbol table.\n";
+  return Error::success();
+}

diff  --git a/llvm/lib/DebugInfo/GSYM/Range.cpp b/llvm/lib/DebugInfo/GSYM/Range.cpp
index f78101e49bf8..044ddb8ba1ba 100644
--- a/llvm/lib/DebugInfo/GSYM/Range.cpp
+++ b/llvm/lib/DebugInfo/GSYM/Range.cpp
@@ -53,6 +53,16 @@ bool AddressRanges::contains(AddressRange Range) const {
   return Range.End <= It[-1].End;
 }
 
+Optional<AddressRange>
+AddressRanges::getRangeThatContains(uint64_t Addr) const {
+  auto It = std::partition_point(
+      Ranges.begin(), Ranges.end(),
+      [=](const AddressRange &R) { return R.Start <= Addr; });
+  if (It != Ranges.begin() && Addr < It[-1].End)
+    return It[-1];
+  return llvm::None;
+}
+
 raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const AddressRange &R) {
   return OS << '[' << HEX64(R.Start) << " - " << HEX64(R.End) << ")";
 }

diff  --git a/llvm/test/tools/llvm-gsymutil/cmdline.test b/llvm/test/tools/llvm-gsymutil/cmdline.test
new file mode 100644
index 000000000000..e9c764f31253
--- /dev/null
+++ b/llvm/test/tools/llvm-gsymutil/cmdline.test
@@ -0,0 +1,21 @@
+RUN: llvm-gsymutil -h 2>&1 | FileCheck --check-prefix=HELP %s
+RUN: llvm-gsymutil --help 2>&1 | FileCheck --check-prefix=HELP %s
+HELP: OVERVIEW: A tool for dumping, searching and creating GSYM files.
+HELP: USAGE: llvm-gsymutil{{[^ ]*}} [options] <input GSYM files>
+HELP: OPTIONS:
+HELP: Conversion Options:
+HELP: --arch=<arch>
+HELP: --convert=<path>
+HELP: --num-threads=<n>
+HELP: --out-file=<path>
+HELP: --verify
+HELP: Generic Options:
+HELP: --help
+HELP: --version
+HELP: Lookup Options:
+HELP: --address=<addr>
+HELP: Options:
+HELP: --verbose
+
+RUN: llvm-gsymutil --version 2>&1 | FileCheck --check-prefix=VERSION %s
+VERSION: {{ version }}

diff  --git a/llvm/test/tools/llvm-gsymutil/elf-dwarf.yaml b/llvm/test/tools/llvm-gsymutil/elf-dwarf.yaml
new file mode 100644
index 000000000000..fe696e42fab4
--- /dev/null
+++ b/llvm/test/tools/llvm-gsymutil/elf-dwarf.yaml
@@ -0,0 +1,687 @@
+## Test loading an ELF file with DWARF. First we make the ELF file from yaml,
+## then we convert the ELF file to GSYM, then we do lookups on the newly
+## created GSYM, and finally we dump the entire GSYM.
+
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-gsymutil --convert %t -o %t.gsym 2>&1 | FileCheck %s --check-prefix=CONVERT
+# RUN: llvm-gsymutil --address=0x400391 --address=0x4004cd %t.gsym 2>&1 | FileCheck %s --check-prefix=ADDR
+# RUN: llvm-gsymutil --address=0x400391 --address=0x4004cd --verbose %t.gsym 2>&1 | FileCheck %s --check-prefix=ADDRV --dump-input=always
+# RUN: llvm-gsymutil %t.gsym 2>&1 | FileCheck %s --check-prefix=DUMP
+
+# ADDR: Looking up addresses in "{{.*\.yaml\.tmp\.gsym}}":
+# ADDR: 0x0000000000400391: _init
+# ADDR: 0x00000000004004cd: main @ /tmp/main.cpp:1
+
+# ADDRV: Looking up addresses in "{{.*\.yaml\.tmp\.gsym}}":
+# ADDRV: FunctionInfo for 0x0000000000400391:
+# ADDRV: [0x0000000000400390 - 0x0000000000400390) "_init"
+# ADDRV: LookupResult for 0x0000000000400391:
+# ADDRV: 0x0000000000400391: _init
+# ADDRV: FunctionInfo for 0x00000000004004cd:
+# ADDRV: [0x00000000004004cd - 0x00000000004004df) "main"
+# ADDRV: LineTable:
+# ADDRV:   0x00000000004004cd /tmp/main.cpp:1
+# ADDRV:   0x00000000004004d8 /tmp/main.cpp:2
+# ADDRV:   0x00000000004004dd /tmp/main.cpp:3
+# ADDRV: LookupResult for 0x00000000004004cd:
+# ADDRV: 0x00000000004004cd: main @ /tmp/main.cpp:1
+
+# CONVERT: Input file: {{.*\.yaml\.tmp}}
+# CONVERT: Output file (x86_64): {{.*\.yaml\.tmp\.gsym}}
+# CONVERT: Loaded 1 functions from DWARF.
+# CONVERT: Loaded 9 functions from symbol table.
+# CONVERT: Pruned 0 functions, ended with 10 total
+
+# DUMP:      Header:
+# DUMP-NEXT:   Magic        = 0x4753594d
+# DUMP-NEXT:   Version      = 0x0001
+# DUMP-NEXT:   AddrOffSize  = 0x02
+# DUMP-NEXT:   UUIDSize     = 0x14
+# DUMP-NEXT:   BaseAddress  = 0x0000000000400000
+# DUMP-NEXT:   NumAddresses = 0x0000000a
+# DUMP-NEXT:   StrtabOffset = 0x00000080
+# DUMP-NEXT:   StrtabSize   = 0x00000091
+# DUMP-NEXT:   UUID         = 0e62be89cad89206110ed1375b618656f32ac906
+
+# DUMP:      Address Table:
+# DUMP-NEXT: INDEX  OFFSET16 (ADDRESS)
+# DUMP-NEXT: ====== ===============================
+# DUMP-NEXT: [   0] 0x0390 (0x0000000000400390)
+# DUMP-NEXT: [   1] 0x03e0 (0x00000000004003e0)
+# DUMP-NEXT: [   2] 0x0410 (0x0000000000400410)
+# DUMP-NEXT: [   3] 0x0440 (0x0000000000400440)
+# DUMP-NEXT: [   4] 0x0480 (0x0000000000400480)
+# DUMP-NEXT: [   5] 0x04a0 (0x00000000004004a0)
+# DUMP-NEXT: [   6] 0x04cd (0x00000000004004cd)
+# DUMP-NEXT: [   7] 0x04e0 (0x00000000004004e0)
+# DUMP-NEXT: [   8] 0x0550 (0x0000000000400550)
+# DUMP-NEXT: [   9] 0x0554 (0x0000000000400554)
+
+# DUMP:      Address Info Offsets:
+# DUMP-NEXT: INDEX  Offset
+# DUMP-NEXT: ====== ==========
+# DUMP-NEXT: [   0] 0x00000114
+# DUMP-NEXT: [   1] 0x00000124
+# DUMP-NEXT: [   2] 0x00000134
+# DUMP-NEXT: [   3] 0x00000144
+# DUMP-NEXT: [   4] 0x00000154
+# DUMP-NEXT: [   5] 0x00000164
+# DUMP-NEXT: [   6] 0x00000174
+# DUMP-NEXT: [   7] 0x00000194
+# DUMP-NEXT: [   8] 0x000001a4
+# DUMP-NEXT: [   9] 0x000001b4
+
+# DUMP:      Files:
+# DUMP-NEXT: INDEX  DIRECTORY  BASENAME   PATH
+# DUMP-NEXT: ====== ========== ========== ==============================
+# DUMP-NEXT: [   0] 0x00000000 0x00000000
+# DUMP-NEXT: [   1] 0x00000006 0x0000000b /tmp/main.cpp
+
+# DUMP:      String table:
+# DUMP-NEXT: 0x00000000: ""
+# DUMP-NEXT: 0x00000001: "main"
+# DUMP-NEXT: 0x00000006: "/tmp"
+# DUMP-NEXT: 0x0000000b: "main.cpp"
+# DUMP-NEXT: 0x00000014: "deregister_tm_clones"
+# DUMP-NEXT: 0x00000029: "register_tm_clones"
+# DUMP-NEXT: 0x0000003c: "__do_global_dtors_aux"
+# DUMP-NEXT: 0x00000052: "frame_dummy"
+# DUMP-NEXT: 0x0000005e: "__libc_csu_fini"
+# DUMP-NEXT: 0x0000006e: "_fini"
+# DUMP-NEXT: 0x00000074: "__libc_csu_init"
+# DUMP-NEXT: 0x00000084: "_start"
+# DUMP-NEXT: 0x0000008b: "_init"
+# DUMP:      FunctionInfo @ 0x00000114: [0x0000000000400390 - 0x0000000000400390) "_init"
+# DUMP:      FunctionInfo @ 0x00000124: [0x00000000004003e0 - 0x00000000004003e0) "_start"
+# DUMP:      FunctionInfo @ 0x00000134: [0x0000000000400410 - 0x0000000000400410) "deregister_tm_clones"
+# DUMP:      FunctionInfo @ 0x00000144: [0x0000000000400440 - 0x0000000000400440) "register_tm_clones"
+# DUMP:      FunctionInfo @ 0x00000154: [0x0000000000400480 - 0x0000000000400480) "__do_global_dtors_aux"
+# DUMP:      FunctionInfo @ 0x00000164: [0x00000000004004a0 - 0x00000000004004a0) "frame_dummy"
+# DUMP:      FunctionInfo @ 0x00000174: [0x00000000004004cd - 0x00000000004004df) "main"
+# DUMP-NEXT: LineTable:
+# DUMP-NEXT:   0x00000000004004cd /tmp/main.cpp:1
+# DUMP-NEXT:   0x00000000004004d8 /tmp/main.cpp:2
+# DUMP-NEXT:   0x00000000004004dd /tmp/main.cpp:3
+# DUMP:      FunctionInfo @ 0x00000194: [0x00000000004004e0 - 0x0000000000400545) "__libc_csu_init"
+# DUMP:      FunctionInfo @ 0x000001a4: [0x0000000000400550 - 0x0000000000400552) "__libc_csu_fini"
+# DUMP:      FunctionInfo @ 0x000001b4: [0x0000000000400554 - 0x000000000040055d) "_fini"
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_X86_64
+  Entry:           0x00000000004003E0
+Sections:
+  - Name:            .interp
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x0000000000400238
+    AddressAlign:    0x0000000000000001
+    Content:         2F6C696236342F6C642D6C696E75782D7838362D36342E736F2E3200
+  - Name:            .note.ABI-tag
+    Type:            SHT_NOTE
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x0000000000400254
+    AddressAlign:    0x0000000000000004
+    Notes:
+      - Name:            GNU
+        Desc:            '00000000020000000600000020000000'
+        Type:            0x00000001
+  - Name:            .note.gnu.build-id
+    Type:            SHT_NOTE
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x0000000000400274
+    AddressAlign:    0x0000000000000004
+    Notes:
+      - Name:            GNU
+        Desc:            0E62BE89CAD89206110ED1375B618656F32AC906
+        Type:            0x00000003
+  - Name:            .gnu.hash
+    Type:            SHT_GNU_HASH
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x0000000000400298
+    Link:            .dynsym
+    AddressAlign:    0x0000000000000008
+    Header:
+      SymNdx:          0x00000001
+      Shift2:          0x00000000
+    BloomFilter:     [ 0x0000000000000000 ]
+    HashBuckets:     [ 0x00000000 ]
+    HashValues:      [  ]
+  - Name:            .gnu.version
+    Type:            SHT_GNU_versym
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x0000000000400338
+    Link:            .dynsym
+    AddressAlign:    0x0000000000000002
+    EntSize:         0x0000000000000002
+    Entries:         [ 0, 2, 0 ]
+  - Name:            .gnu.version_r
+    Type:            SHT_GNU_verneed
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x0000000000400340
+    Link:            .dynstr
+    AddressAlign:    0x0000000000000008
+    Info:            0x0000000000000001
+    Dependencies:
+      - Version:         1
+        File:            libc.so.6
+        Entries:
+          - Name:            GLIBC_2.2.5
+            Hash:            157882997
+            Flags:           0
+            Other:           2
+  - Name:            .rela.dyn
+    Type:            SHT_RELA
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x0000000000400360
+    Link:            .dynsym
+    AddressAlign:    0x0000000000000008
+    EntSize:         0x0000000000000018
+    Relocations:
+      - Offset:          0x0000000000600FF8
+        Symbol:          __gmon_start__
+        Type:            R_X86_64_GLOB_DAT
+  - Name:            .rela.plt
+    Type:            SHT_RELA
+    Flags:           [ SHF_ALLOC, SHF_INFO_LINK ]
+    Address:         0x0000000000400378
+    Link:            .dynsym
+    AddressAlign:    0x0000000000000008
+    EntSize:         0x0000000000000018
+    Info:            .got.plt
+    Relocations:
+      - Offset:          0x0000000000601018
+        Symbol:          __libc_start_main
+        Type:            R_X86_64_JUMP_SLOT
+  - Name:            .init
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x0000000000400390
+    AddressAlign:    0x0000000000000004
+    Content:         4883EC08488B055D0C20004885C07405E82B0000004883C408C3
+  - Name:            .plt
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x00000000004003B0
+    AddressAlign:    0x0000000000000010
+    EntSize:         0x0000000000000010
+    Content:         FF35520C2000FF25540C20000F1F4000FF25520C20006800000000E9E0FFFFFF
+  - Name:            .plt.got
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x00000000004003D0
+    AddressAlign:    0x0000000000000008
+    Content:         FF25220C20006690
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x00000000004003E0
+    AddressAlign:    0x0000000000000010
+    Content:         31ED4989D15E4889E24883E4F0505449C7C05005400048C7C1E004400048C7C7CD044000E8B7FFFFFFF4660F1F440000B82F10600055482D281060004883F80E4889E577025DC3B8000000004885C074F45DBF28106000FFE00F1F8000000000B82810600055482D2810600048C1F8034889E54889C248C1EA3F4801D048D1F875025DC3BA000000004885D274F45D4889C6BF28106000FFE20F1F8000000000803D9D0B2000007511554889E5E87EFFFFFF5DC6058A0B200001F3C30F1F400048833D7809200000741EB8000000004885C0741455BF200E60004889E5FFD05DE97BFFFFFF0F1F00E973FFFFFF554889E5897DFC488975F0B8000000005DC39041574189FF41564989F641554989D541544C8D251809200055488D2D18092000534C29E531DB48C1FD034883EC08E87DFEFFFF4885ED741E0F1F8400000000004C89EA4C89F64489FF41FF14DC4883C3014839EB75EA4883C4085B5D415C415D415E415FC390662E0F1F840000000000F3C3
+  - Name:            .fini
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x0000000000400554
+    AddressAlign:    0x0000000000000004
+    Content:         4883EC084883C408C3
+  - Name:            .rodata
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x0000000000400560
+    AddressAlign:    0x0000000000000008
+    Content:         '01000200000000000000000000000000'
+  - Name:            .eh_frame_hdr
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x0000000000400570
+    AddressAlign:    0x0000000000000004
+    Content:         011B033B340000000500000040FEFFFF8000000070FEFFFF500000005DFFFFFFA800000070FFFFFFC8000000E0FFFFFF10010000
+  - Name:            .eh_frame
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x00000000004005A8
+    AddressAlign:    0x0000000000000008
+    Content:         1400000000000000017A5200017810011B0C070890010710140000001C00000018FEFFFF2A00000000000000000000001400000000000000017A5200017810011B0C070890010000240000001C000000B8FDFFFF20000000000E10460E184A0F0B770880003F1A3B2A332422000000001C00000044000000ADFEFFFF1200000000410E108602430D064D0C07080000004400000064000000A0FEFFFF6500000000420E108F02450E188E03450E208D04450E288C05480E308606480E3883074D0E406C0E38410E30410E28420E20420E18420E10420E080014000000AC000000C8FEFFFF02000000000000000000000000000000
+  - Name:            .init_array
+    Type:            SHT_INIT_ARRAY
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x0000000000600E10
+    AddressAlign:    0x0000000000000008
+    EntSize:         0x0000000000000008
+    Content:         A004400000000000
+  - Name:            .fini_array
+    Type:            SHT_FINI_ARRAY
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x0000000000600E18
+    AddressAlign:    0x0000000000000008
+    EntSize:         0x0000000000000008
+    Content:         '8004400000000000'
+  - Name:            .jcr
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x0000000000600E20
+    AddressAlign:    0x0000000000000008
+    Content:         '0000000000000000'
+  - Name:            .dynamic
+    Type:            SHT_DYNAMIC
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x0000000000600E28
+    Link:            .dynstr
+    AddressAlign:    0x0000000000000008
+    EntSize:         0x0000000000000010
+    Entries:
+      - Tag:             DT_NEEDED
+        Value:           0x0000000000000001
+      - Tag:             DT_INIT
+        Value:           0x0000000000400390
+      - Tag:             DT_FINI
+        Value:           0x0000000000400554
+      - Tag:             DT_INIT_ARRAY
+        Value:           0x0000000000600E10
+      - Tag:             DT_INIT_ARRAYSZ
+        Value:           0x0000000000000008
+      - Tag:             DT_FINI_ARRAY
+        Value:           0x0000000000600E18
+      - Tag:             DT_FINI_ARRAYSZ
+        Value:           0x0000000000000008
+      - Tag:             DT_GNU_HASH
+        Value:           0x0000000000400298
+      - Tag:             DT_STRTAB
+        Value:           0x0000000000400300
+      - Tag:             DT_SYMTAB
+        Value:           0x00000000004002B8
+      - Tag:             DT_STRSZ
+        Value:           0x0000000000000038
+      - Tag:             DT_SYMENT
+        Value:           0x0000000000000018
+      - Tag:             DT_DEBUG
+        Value:           0x0000000000000000
+      - Tag:             DT_PLTGOT
+        Value:           0x0000000000601000
+      - Tag:             DT_PLTRELSZ
+        Value:           0x0000000000000018
+      - Tag:             DT_PLTREL
+        Value:           0x0000000000000007
+      - Tag:             DT_JMPREL
+        Value:           0x0000000000400378
+      - Tag:             DT_RELA
+        Value:           0x0000000000400360
+      - Tag:             DT_RELASZ
+        Value:           0x0000000000000018
+      - Tag:             DT_RELAENT
+        Value:           0x0000000000000018
+      - Tag:             DT_VERNEED
+        Value:           0x0000000000400340
+      - Tag:             DT_VERNEEDNUM
+        Value:           0x0000000000000001
+      - Tag:             DT_VERSYM
+        Value:           0x0000000000400338
+      - Tag:             DT_NULL
+        Value:           0x0000000000000000
+      - Tag:             DT_NULL
+        Value:           0x0000000000000000
+      - Tag:             DT_NULL
+        Value:           0x0000000000000000
+      - Tag:             DT_NULL
+        Value:           0x0000000000000000
+      - Tag:             DT_NULL
+        Value:           0x0000000000000000
+      - Tag:             DT_NULL
+        Value:           0x0000000000000000
+  - Name:            .got
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x0000000000600FF8
+    AddressAlign:    0x0000000000000008
+    EntSize:         0x0000000000000008
+    Content:         '0000000000000000'
+  - Name:            .got.plt
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x0000000000601000
+    AddressAlign:    0x0000000000000008
+    EntSize:         0x0000000000000008
+    Content:         280E60000000000000000000000000000000000000000000C603400000000000
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x0000000000601020
+    AddressAlign:    0x0000000000000001
+    Content:         '00000000'
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x0000000000601024
+    AddressAlign:    0x0000000000000001
+    Size:            0x0000000000000004
+  - Name:            .comment
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_MERGE, SHF_STRINGS ]
+    AddressAlign:    0x0000000000000001
+    EntSize:         0x0000000000000001
+    Content:         4743433A2028474E552920342E382E3520323031353036323320285265642048617420342E382E352D33362900
+  - Name:            .debug_aranges
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         2C000000020000000000080000000000CD04400000000000120000000000000000000000000000000000000000000000
+  - Name:            .debug_info
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         8700000004000000000008011D000000040F00000005000000CD04400000000000120000000000000000000000020A00000001016B000000CD044000000000001200000000000000019C6B000000031800000001016B00000002916C030000000001017200000002916000040405696E740005087800000005087E00000006830000000701066B00000000
+  - Name:            .debug_abbrev
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         011101250E130B030E1B0E1101120710170000022E013F19030E3A0B3B0B491311011207401897421901130000030500030E3A0B3B0B4913021800000424000B0B3E0B03080000050F000B0B49130000062600491300000724000B0B3E0B030E000000
+  - Name:            .debug_line
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         3800000002001F0000000101FB0E0D000101010100000001000001006D61696E2E6370700000000000000902CD0440000000000001AD590202000101
+  - Name:            .debug_str
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_MERGE, SHF_STRINGS ]
+    AddressAlign:    0x0000000000000001
+    EntSize:         0x0000000000000001
+    Content:         61726776002F746D70006D61696E006D61696E2E637070006172676300474E5520432B2B20342E382E3520323031353036323320285265642048617420342E382E352D333629202D6D74756E653D67656E65726963202D6D617263683D7838362D3634202D67202D4F30006368617200
+ProgramHeaders:
+  - Type: PT_LOAD
+    Flags: [ PF_X, PF_R ]
+    VAddr: 0x0000000000400000
+    PAddr: 0x0000000000400000
+    Align: 1024
+    Sections:
+      - Section: .interp
+      - Section: .interp
+      - Section: .note.ABI-tag
+      - Section: .note.gnu.build-id
+      - Section: .gnu.hash
+      - Section: .dynsym
+      - Section: .dynstr
+      - Section: .gnu.version
+      - Section: .gnu.version_r
+      - Section: .rela.dyn
+      - Section: .rela.plt
+      - Section: .init
+      - Section: .plt
+      - Section: .plt.got
+      - Section: .text
+      - Section: .fini
+      - Section: .rodata
+      - Section: .eh_frame_hdr
+      - Section: .eh_frame
+Symbols:
+  - Name:            .interp
+    Type:            STT_SECTION
+    Section:         .interp
+    Value:           0x0000000000400238
+  - Name:            .note.ABI-tag
+    Type:            STT_SECTION
+    Section:         .note.ABI-tag
+    Value:           0x0000000000400254
+  - Name:            .note.gnu.build-id
+    Type:            STT_SECTION
+    Section:         .note.gnu.build-id
+    Value:           0x0000000000400274
+  - Name:            .gnu.hash
+    Type:            STT_SECTION
+    Section:         .gnu.hash
+    Value:           0x0000000000400298
+  - Name:            .dynsym
+    Type:            STT_SECTION
+    Section:         .dynsym
+    Value:           0x00000000004002B8
+  - Name:            .dynstr
+    Type:            STT_SECTION
+    Section:         .dynstr
+    Value:           0x0000000000400300
+  - Name:            .gnu.version
+    Type:            STT_SECTION
+    Section:         .gnu.version
+    Value:           0x0000000000400338
+  - Name:            .gnu.version_r
+    Type:            STT_SECTION
+    Section:         .gnu.version_r
+    Value:           0x0000000000400340
+  - Name:            .rela.dyn
+    Type:            STT_SECTION
+    Section:         .rela.dyn
+    Value:           0x0000000000400360
+  - Name:            .rela.plt
+    Type:            STT_SECTION
+    Section:         .rela.plt
+    Value:           0x0000000000400378
+  - Name:            .init
+    Type:            STT_SECTION
+    Section:         .init
+    Value:           0x0000000000400390
+  - Name:            .plt
+    Type:            STT_SECTION
+    Section:         .plt
+    Value:           0x00000000004003B0
+  - Name:            .plt.got
+    Type:            STT_SECTION
+    Section:         .plt.got
+    Value:           0x00000000004003D0
+  - Name:            .text
+    Type:            STT_SECTION
+    Section:         .text
+    Value:           0x00000000004003E0
+  - Name:            .fini
+    Type:            STT_SECTION
+    Section:         .fini
+    Value:           0x0000000000400554
+  - Name:            .rodata
+    Type:            STT_SECTION
+    Section:         .rodata
+    Value:           0x0000000000400560
+  - Name:            .eh_frame_hdr
+    Type:            STT_SECTION
+    Section:         .eh_frame_hdr
+    Value:           0x0000000000400570
+  - Name:            .eh_frame
+    Type:            STT_SECTION
+    Section:         .eh_frame
+    Value:           0x00000000004005A8
+  - Name:            .init_array
+    Type:            STT_SECTION
+    Section:         .init_array
+    Value:           0x0000000000600E10
+  - Name:            .fini_array
+    Type:            STT_SECTION
+    Section:         .fini_array
+    Value:           0x0000000000600E18
+  - Name:            .jcr
+    Type:            STT_SECTION
+    Section:         .jcr
+    Value:           0x0000000000600E20
+  - Name:            .dynamic
+    Type:            STT_SECTION
+    Section:         .dynamic
+    Value:           0x0000000000600E28
+  - Name:            .got
+    Type:            STT_SECTION
+    Section:         .got
+    Value:           0x0000000000600FF8
+  - Name:            .got.plt
+    Type:            STT_SECTION
+    Section:         .got.plt
+    Value:           0x0000000000601000
+  - Name:            .data
+    Type:            STT_SECTION
+    Section:         .data
+    Value:           0x0000000000601020
+  - Name:            .bss
+    Type:            STT_SECTION
+    Section:         .bss
+    Value:           0x0000000000601024
+  - Name:            .comment
+    Type:            STT_SECTION
+    Section:         .comment
+  - Name:            .debug_aranges
+    Type:            STT_SECTION
+    Section:         .debug_aranges
+  - Name:            .debug_info
+    Type:            STT_SECTION
+    Section:         .debug_info
+  - Name:            .debug_abbrev
+    Type:            STT_SECTION
+    Section:         .debug_abbrev
+  - Name:            .debug_line
+    Type:            STT_SECTION
+    Section:         .debug_line
+  - Name:            .debug_str
+    Type:            STT_SECTION
+    Section:         .debug_str
+  - Name:            crtstuff.c
+    Type:            STT_FILE
+    Index:           SHN_ABS
+  - Name:            __JCR_LIST__
+    Type:            STT_OBJECT
+    Section:         .jcr
+    Value:           0x0000000000600E20
+  - Name:            deregister_tm_clones
+    Type:            STT_FUNC
+    Section:         .text
+    Value:           0x0000000000400410
+  - Name:            register_tm_clones
+    Type:            STT_FUNC
+    Section:         .text
+    Value:           0x0000000000400440
+  - Name:            __do_global_dtors_aux
+    Type:            STT_FUNC
+    Section:         .text
+    Value:           0x0000000000400480
+  - Name:            completed.6355
+    Type:            STT_OBJECT
+    Section:         .bss
+    Value:           0x0000000000601024
+    Size:            0x0000000000000001
+  - Name:            __do_global_dtors_aux_fini_array_entry
+    Type:            STT_OBJECT
+    Section:         .fini_array
+    Value:           0x0000000000600E18
+  - Name:            frame_dummy
+    Type:            STT_FUNC
+    Section:         .text
+    Value:           0x00000000004004A0
+  - Name:            __frame_dummy_init_array_entry
+    Type:            STT_OBJECT
+    Section:         .init_array
+    Value:           0x0000000000600E10
+  - Name:            main.cpp
+    Type:            STT_FILE
+    Index:           SHN_ABS
+  - Name:            'crtstuff.c [1]'
+    Type:            STT_FILE
+    Index:           SHN_ABS
+  - Name:            __FRAME_END__
+    Type:            STT_OBJECT
+    Section:         .eh_frame
+    Value:           0x0000000000400698
+  - Name:            __JCR_END__
+    Type:            STT_OBJECT
+    Section:         .jcr
+    Value:           0x0000000000600E20
+  - Type:            STT_FILE
+    Index:           SHN_ABS
+  - Name:            __init_array_end
+    Section:         .init_array
+    Value:           0x0000000000600E18
+  - Name:            _DYNAMIC
+    Type:            STT_OBJECT
+    Section:         .dynamic
+    Value:           0x0000000000600E28
+  - Name:            __init_array_start
+    Section:         .init_array
+    Value:           0x0000000000600E10
+  - Name:            __GNU_EH_FRAME_HDR
+    Section:         .eh_frame_hdr
+    Value:           0x0000000000400570
+  - Name:            _GLOBAL_OFFSET_TABLE_
+    Type:            STT_OBJECT
+    Section:         .got.plt
+    Value:           0x0000000000601000
+  - Name:            __libc_csu_fini
+    Type:            STT_FUNC
+    Section:         .text
+    Binding:         STB_GLOBAL
+    Value:           0x0000000000400550
+    Size:            0x0000000000000002
+  - Name:            data_start
+    Section:         .data
+    Binding:         STB_WEAK
+    Value:           0x0000000000601020
+  - Name:            _edata
+    Section:         .data
+    Binding:         STB_GLOBAL
+    Value:           0x0000000000601024
+  - Name:            _fini
+    Type:            STT_FUNC
+    Section:         .fini
+    Binding:         STB_GLOBAL
+    Value:           0x0000000000400554
+  - Name:            '__libc_start_main@@GLIBC_2.2.5'
+    Type:            STT_FUNC
+    Binding:         STB_GLOBAL
+  - Name:            __data_start
+    Section:         .data
+    Binding:         STB_GLOBAL
+    Value:           0x0000000000601020
+  - Name:            __gmon_start__
+    Binding:         STB_WEAK
+  - Name:            __dso_handle
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0x0000000000400568
+    Other:           [ STV_HIDDEN ]
+  - Name:            _IO_stdin_used
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0x0000000000400560
+    Size:            0x0000000000000004
+  - Name:            __libc_csu_init
+    Type:            STT_FUNC
+    Section:         .text
+    Binding:         STB_GLOBAL
+    Value:           0x00000000004004E0
+    Size:            0x0000000000000065
+  - Name:            _end
+    Section:         .bss
+    Binding:         STB_GLOBAL
+    Value:           0x0000000000601028
+  - Name:            _start
+    Type:            STT_FUNC
+    Section:         .text
+    Binding:         STB_GLOBAL
+    Value:           0x00000000004003E0
+  - Name:            __bss_start
+    Section:         .bss
+    Binding:         STB_GLOBAL
+    Value:           0x0000000000601024
+  - Name:            main
+    Type:            STT_FUNC
+    Section:         .text
+    Binding:         STB_GLOBAL
+    Value:           0x00000000004004CD
+    Size:            0x0000000000000012
+  - Name:            __TMC_END__
+    Type:            STT_OBJECT
+    Section:         .data
+    Binding:         STB_GLOBAL
+    Value:           0x0000000000601028
+    Other:           [ STV_HIDDEN ]
+  - Name:            _init
+    Type:            STT_FUNC
+    Section:         .init
+    Binding:         STB_GLOBAL
+    Value:           0x0000000000400390
+DynamicSymbols:
+  - Name:            __libc_start_main
+    Type:            STT_FUNC
+    Binding:         STB_GLOBAL
+  - Name:            __gmon_start__
+    Binding:         STB_WEAK
+...

diff  --git a/llvm/test/tools/llvm-gsymutil/fat-macho-dwarf.yaml b/llvm/test/tools/llvm-gsymutil/fat-macho-dwarf.yaml
new file mode 100644
index 000000000000..4eec1aa1632d
--- /dev/null
+++ b/llvm/test/tools/llvm-gsymutil/fat-macho-dwarf.yaml
@@ -0,0 +1,995 @@
+## For mach-o files we might have a universal (fat) mach-o file which
+## complicates the GSYM creation process as we need to be prepared to parse
+## more than one architecture. If no architectures are specified or more than
+## one architectures are specified on the command line, then all architectures
+## will be parsed and each GSYM file will have the architecture name appended
+## as an extension (.armv7 or .arm64). If a single architecture is specified,
+## then the GSYM file will be created in the normal location.
+
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-gsymutil --convert %t --arch armv7 -o %t.armv7.gsym 2>&1 | FileCheck %s --check-prefix=ARMV7
+# RUN: llvm-gsymutil --convert %t --arch arm64 -o %t.arm64.gsym 2>&1 | FileCheck %s --check-prefix=ARM64
+# RUN: llvm-gsymutil --convert %t -o %t.gsym 2>&1 | FileCheck %s --check-prefix=FAT
+
+# ARMV7:      Input file: {{.*\.yaml\.tmp}}
+# ARMV7-NEXT: Output file (armv7): {{.*\.yaml\.tmp\.armv7\.gsym}}
+# ARMV7-NEXT: Loaded 1 functions from DWARF.
+# ARMV7-NEXT: Loaded 0 functions from symbol table.
+# ARMV7-NEXT: Pruned 0 functions, ended with 1 total
+
+# ARM64:      Input file: {{.*\.yaml\.tmp}}
+# ARM64-NEXT: Output file (arm64): {{.*\.yaml\.tmp\.arm64\.gsym}}
+# ARM64-NEXT: Loaded 1 functions from DWARF.
+# ARM64-NEXT: Loaded 0 functions from symbol table.
+# ARM64-NEXT: Pruned 0 functions, ended with 1 total
+
+# FAT:      Input file: {{.*\.yaml\.tmp}}
+# FAT-NEXT: Output file (armv7): {{.*\.yaml\.tmp\.gsym\.armv7}}
+# FAT-NEXT: Loaded 1 functions from DWARF.
+# FAT-NEXT: Loaded 0 functions from symbol table.
+# FAT-NEXT: Pruned 0 functions, ended with 1 total
+# FAT-NEXT: Output file (arm64): {{.*\.yaml\.tmp\.gsym\.arm64}}
+# FAT-NEXT: Loaded 1 functions from DWARF.
+# FAT-NEXT: Loaded 0 functions from symbol table.
+# FAT-NEXT: Pruned 0 functions, ended with 1 total
+
+--- !fat-mach-o
+FatHeader:
+  magic:           0xCAFEBABE
+  nfat_arch:       2
+FatArchs:
+  - cputype:         0x0000000C
+    cpusubtype:      0x00000009
+    offset:          0x0000000000000040
+    size:            8884
+    align:           5
+  - cputype:         0x0100000C
+    cpusubtype:      0x00000000
+    offset:          0x0000000000002300
+    size:            8908
+    align:           5
+Slices:
+  - !mach-o
+    FileHeader:
+      magic:           0xFEEDFACE
+      cputype:         0x0000000C
+      cpusubtype:      0x00000009
+      filetype:        0x0000000A
+      ncmds:           6
+      sizeofcmds:      1088
+      flags:           0x00000000
+    LoadCommands:
+      - cmd:             LC_UUID
+        cmdsize:         24
+        uuid:            7B08A997-C561-3D42-B774-0C3CD02345C7
+      - cmd:             LC_SYMTAB
+        cmdsize:         24
+        symoff:          4096
+        nsyms:           2
+        stroff:          4120
+        strsize:         28
+      - cmd:             LC_SEGMENT
+        cmdsize:         56
+        segname:         __PAGEZERO
+        vmaddr:          0
+        vmsize:          16384
+        fileoff:         0
+        filesize:        0
+        maxprot:         0
+        initprot:        0
+        nsects:          0
+        flags:           0
+      - cmd:             LC_SEGMENT
+        cmdsize:         124
+        segname:         __TEXT
+        vmaddr:          16384
+        vmsize:          32768
+        fileoff:         0
+        filesize:        0
+        maxprot:         5
+        initprot:        5
+        nsects:          1
+        flags:           0
+        Sections:
+          - sectname:        __text
+            segname:         __TEXT
+            addr:            0x000000000000BFF0
+            size:            16
+            offset:          0x00000000
+            align:           1
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x80000400
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         CEFAEDFE0C000000090000000A000000
+      - cmd:             LC_SEGMENT
+        cmdsize:         56
+        segname:         __LINKEDIT
+        vmaddr:          49152
+        vmsize:          4096
+        fileoff:         4096
+        filesize:        52
+        maxprot:         1
+        initprot:        1
+        nsects:          0
+        flags:           0
+      - cmd:             LC_SEGMENT
+        cmdsize:         804
+        segname:         __DWARF
+        vmaddr:          53248
+        vmsize:          4096
+        fileoff:         8192
+        filesize:        692
+        maxprot:         7
+        initprot:        3
+        nsects:          11
+        flags:           0
+        Sections:
+          - sectname:        __debug_line
+            segname:         __DWARF
+            addr:            0x000000000000D000
+            size:            59
+            offset:          0x00002000
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         37000000040020000000010101FB0E0D000101010100000001000001006D61696E2E6370700000000000000502F0BF00000105020A9F0206000101
+          - sectname:        __debug_pubnames
+            segname:         __DWARF
+            addr:            0x000000000000D03B
+            size:            27
+            offset:          0x0000203B
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         1700000002000000000077000000260000006D61696E0000000000
+          - sectname:        __debug_pubtypes
+            segname:         __DWARF
+            addr:            0x000000000000D056
+            size:            35
+            offset:          0x00002056
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         1F0000000200000000007700000059000000696E74006F000000636861720000000000
+          - sectname:        __debug_aranges
+            segname:         __DWARF
+            addr:            0x000000000000D079
+            size:            32
+            offset:          0x00002079
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         1C000000020000000000040000000000F0BF0000100000000000000000000000
+          - sectname:        __debug_info
+            segname:         __DWARF
+            addr:            0x000000000000D099
+            size:            119
+            offset:          0x00002099
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         73000000040000000000040101000000040031000000000000003A000000F0BF00001000000002F0BF00001000000001573F0000000101590000000103027D044400000001015900000003027D004900000001016000000000044E00000005040565000000056A000000066F0000000452000000060100
+          - sectname:        __debug_abbrev
+            segname:         __DWARF
+            addr:            0x000000000000D110
+            size:            87
+            offset:          0x00002110
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         011101250E1305030E10171B0EB44219110112060000022E01110112064018030E3A0B3B0B49103F19E37F0C00000305000218030E3A0B3B0B49100000042400030E3E0B0B0B0000050F00491000000626004910000000
+          - sectname:        __debug_str
+            segname:         __DWARF
+            addr:            0x000000000000D167
+            size:            87
+            offset:          0x00002167
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         004170706C6520636C616E672076657273696F6E2031312E302E302028636C616E672D313130302E302E33332E313729006D61696E2E637070002F746D70006D61696E0061726763006172677600696E74006368617200
+          - sectname:        __apple_names
+            segname:         __DWARF
+            addr:            0x000000000000D1BE
+            size:            60
+            offset:          0x000021BE
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         485341480100000001000000010000000C000000000000000100000001000600000000006A7F9A7C2C0000003F000000010000002600000000000000
+          - sectname:        __apple_namespac
+            segname:         __DWARF
+            addr:            0x000000000000D1FA
+            size:            36
+            offset:          0x000021FA
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         485341480100000001000000000000000C000000000000000100000001000600FFFFFFFF
+          - sectname:        __apple_types
+            segname:         __DWARF
+            addr:            0x000000000000D21E
+            size:            114
+            offset:          0x0000221E
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         48534148010000000200000002000000180000000000000004000000010006000300050005000B000600060000000000010000003080880B6320957C440000005B0000004E0000000100000059000000240000A4283A0C0000000052000000010000006F00000024000057D77B9300000000
+          - sectname:        __apple_objc
+            segname:         __DWARF
+            addr:            0x000000000000D290
+            size:            36
+            offset:          0x00002290
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         485341480100000001000000000000000C000000000000000100000001000600FFFFFFFF
+    LinkEditData:
+      NameList:
+        - n_strx:          2
+          n_type:          0x0F
+          n_sect:          1
+          n_desc:          16
+          n_value:         16384
+        - n_strx:          22
+          n_type:          0x0F
+          n_sect:          1
+          n_desc:          8
+          n_value:         49136
+      StringTable:
+        - ''
+        - ''
+        - __mh_execute_header
+        - _main
+    DWARF:
+      debug_str:
+        - ''
+        - 'Apple clang version 11.0.0 (clang-1100.0.33.17)'
+        - main.cpp
+        - '/tmp'
+        - main
+        - argc
+        - argv
+        - int
+        - char
+      debug_abbrev:
+        - Code:            0x00000001
+          Tag:             DW_TAG_compile_unit
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_producer
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_language
+              Form:            DW_FORM_data2
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_stmt_list
+              Form:            DW_FORM_sec_offset
+            - Attribute:       DW_AT_comp_dir
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_GNU_pubnames
+              Form:            DW_FORM_flag_present
+            - Attribute:       DW_AT_low_pc
+              Form:            DW_FORM_addr
+            - Attribute:       DW_AT_high_pc
+              Form:            DW_FORM_data4
+        - Code:            0x00000002
+          Tag:             DW_TAG_subprogram
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_low_pc
+              Form:            DW_FORM_addr
+            - Attribute:       DW_AT_high_pc
+              Form:            DW_FORM_data4
+            - Attribute:       DW_AT_frame_base
+              Form:            DW_FORM_exprloc
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_decl_file
+              Form:            DW_FORM_data1
+            - Attribute:       DW_AT_decl_line
+              Form:            DW_FORM_data1
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref_addr
+            - Attribute:       DW_AT_external
+              Form:            DW_FORM_flag_present
+            - Attribute:       DW_AT_APPLE_isa
+              Form:            DW_FORM_flag
+        - Code:            0x00000003
+          Tag:             DW_TAG_formal_parameter
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_location
+              Form:            DW_FORM_exprloc
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_decl_file
+              Form:            DW_FORM_data1
+            - Attribute:       DW_AT_decl_line
+              Form:            DW_FORM_data1
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref_addr
+        - Code:            0x00000004
+          Tag:             DW_TAG_base_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_encoding
+              Form:            DW_FORM_data1
+            - Attribute:       DW_AT_byte_size
+              Form:            DW_FORM_data1
+        - Code:            0x00000005
+          Tag:             DW_TAG_pointer_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref_addr
+        - Code:            0x00000006
+          Tag:             DW_TAG_const_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref_addr
+      debug_aranges:
+        - Length:
+            TotalLength:     28
+          Version:         2
+          CuOffset:        0
+          AddrSize:        4
+          SegSize:         0
+          Descriptors:
+            - Address:         0x000000000000BFF0
+              Length:          16
+      debug_pubnames:
+        Length:
+          TotalLength:     23
+        Version:         2
+        UnitOffset:      0
+        UnitSize:        119
+        Entries:
+          - DieOffset:       0x00000026
+            Name:            main
+      debug_pubtypes:
+        Length:
+          TotalLength:     31
+        Version:         2
+        UnitOffset:      0
+        UnitSize:        119
+        Entries:
+          - DieOffset:       0x00000059
+            Name:            int
+          - DieOffset:       0x0000006F
+            Name:            char
+      debug_info:
+        - Length:
+            TotalLength:     115
+          Version:         4
+          AbbrOffset:      0
+          AddrSize:        4
+          Entries:
+            - AbbrCode:        0x00000001
+              Values:
+                - Value:           0x0000000000000001
+                - Value:           0x0000000000000004
+                - Value:           0x0000000000000031
+                - Value:           0x0000000000000000
+                - Value:           0x000000000000003A
+                - Value:           0x0000000000000001
+                - Value:           0x000000000000BFF0
+                - Value:           0x0000000000000010
+            - AbbrCode:        0x00000002
+              Values:
+                - Value:           0x000000000000BFF0
+                - Value:           0x0000000000000010
+                - Value:           0x0000000000000001
+                  BlockData:       [ 0x57 ]
+                - Value:           0x000000000000003F
+                - Value:           0x0000000000000001
+                - Value:           0x0000000000000001
+                - Value:           0x0000000000000059
+                - Value:           0x0000000000000001
+                - Value:           0x0000000000000001
+            - AbbrCode:        0x00000003
+              Values:
+                - Value:           0x0000000000000002
+                  BlockData:       [ 0x7D, 0x04 ]
+                - Value:           0x0000000000000044
+                - Value:           0x0000000000000001
+                - Value:           0x0000000000000001
+                - Value:           0x0000000000000059
+            - AbbrCode:        0x00000003
+              Values:
+                - Value:           0x0000000000000002
+                  BlockData:       [ 0x7D, 0x00 ]
+                - Value:           0x0000000000000049
+                - Value:           0x0000000000000001
+                - Value:           0x0000000000000001
+                - Value:           0x0000000000000060
+            - AbbrCode:        0x00000000
+              Values:          []
+            - AbbrCode:        0x00000004
+              Values:
+                - Value:           0x000000000000004E
+                - Value:           0x0000000000000005
+                - Value:           0x0000000000000004
+            - AbbrCode:        0x00000005
+              Values:
+                - Value:           0x0000000000000065
+            - AbbrCode:        0x00000005
+              Values:
+                - Value:           0x000000000000006A
+            - AbbrCode:        0x00000006
+              Values:
+                - Value:           0x000000000000006F
+            - AbbrCode:        0x00000004
+              Values:
+                - Value:           0x0000000000000052
+                - Value:           0x0000000000000006
+                - Value:           0x0000000000000001
+            - AbbrCode:        0x00000000
+              Values:          []
+      debug_line:
+        - Length:
+            TotalLength:     55
+          Version:         4
+          PrologueLength:  32
+          MinInstLength:   1
+          MaxOpsPerInst:   1
+          DefaultIsStmt:   1
+          LineBase:        251
+          LineRange:       14
+          OpcodeBase:      13
+          StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
+          IncludeDirs:     []
+          Files:
+            - Name:            main.cpp
+              DirIdx:          0
+              ModTime:         0
+              Length:          0
+          Opcodes:
+            - Opcode:          DW_LNS_extended_op
+              ExtLen:          5
+              SubOpcode:       DW_LNE_set_address
+              Data:            49136
+            - Opcode:          DW_LNS_copy
+              Data:            0
+            - Opcode:          DW_LNS_set_column
+              Data:            2
+            - Opcode:          DW_LNS_set_prologue_end
+              Data:            0
+            - Opcode:          0x9F
+              Data:            0
+            - Opcode:          DW_LNS_advance_pc
+              Data:            6
+            - Opcode:          DW_LNS_extended_op
+              ExtLen:          1
+              SubOpcode:       DW_LNE_end_sequence
+              Data:            0
+  - !mach-o
+    FileHeader:
+      magic:           0xFEEDFACF
+      cputype:         0x0100000C
+      cpusubtype:      0x00000000
+      filetype:        0x0000000A
+      ncmds:           7
+      sizeofcmds:      1400
+      flags:           0x00000000
+      reserved:        0x00000000
+    LoadCommands:
+      - cmd:             LC_UUID
+        cmdsize:         24
+        uuid:            E74896D8-32D6-3EB2-BB23-4AA9A0F54CB2
+      - cmd:             LC_BUILD_VERSION
+        cmdsize:         24
+        platform:        2
+        minos:           852480
+        sdk:             852480
+        ntools:          0
+      - cmd:             LC_SYMTAB
+        cmdsize:         24
+        symoff:          4096
+        nsyms:           2
+        stroff:          4128
+        strsize:         28
+      - cmd:             LC_SEGMENT_64
+        cmdsize:         72
+        segname:         __PAGEZERO
+        vmaddr:          0
+        vmsize:          4294967296
+        fileoff:         0
+        filesize:        0
+        maxprot:         0
+        initprot:        0
+        nsects:          0
+        flags:           0
+      - cmd:             LC_SEGMENT_64
+        cmdsize:         232
+        segname:         __TEXT
+        vmaddr:          4294967296
+        vmsize:          32768
+        fileoff:         0
+        filesize:        0
+        maxprot:         5
+        initprot:        5
+        nsects:          2
+        flags:           0
+        Sections:
+          - sectname:        __text
+            segname:         __TEXT
+            addr:            0x0000000100007F9C
+            size:            28
+            offset:          0x00000000
+            align:           2
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x80000400
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         CFFAEDFE0C000001000000000A000000070000007805000000000000
+          - sectname:        __unwind_info
+            segname:         __TEXT
+            addr:            0x0000000100007FB8
+            size:            72
+            offset:          0x00000000
+            align:           2
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         CFFAEDFE0C000001000000000A000000070000007805000000000000000000001B00000018000000E74896D832D63EB2BB234AA9A0F54CB232000000180000000200000000020D00
+      - cmd:             LC_SEGMENT_64
+        cmdsize:         72
+        segname:         __LINKEDIT
+        vmaddr:          4295000064
+        vmsize:          4096
+        fileoff:         4096
+        filesize:        60
+        maxprot:         1
+        initprot:        1
+        nsects:          0
+        flags:           0
+      - cmd:             LC_SEGMENT_64
+        cmdsize:         952
+        segname:         __DWARF
+        vmaddr:          4295004160
+        vmsize:          4096
+        fileoff:         8192
+        filesize:        716
+        maxprot:         7
+        initprot:        3
+        nsects:          11
+        flags:           0
+        Sections:
+          - sectname:        __debug_line
+            segname:         __DWARF
+            addr:            0x0000000100009000
+            size:            63
+            offset:          0x00002000
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         3B000000040020000000010101FB0E0D000101010100000001000001006D61696E2E63707000000000000009029C7F0000010000000105020AF3020C000101
+          - sectname:        __debug_pubnames
+            segname:         __DWARF
+            addr:            0x000000010000903F
+            size:            27
+            offset:          0x0000203F
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         170000000200000000007E0000002A0000006D61696E0000000000
+          - sectname:        __debug_pubtypes
+            segname:         __DWARF
+            addr:            0x000000010000905A
+            size:            35
+            offset:          0x0000205A
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         1F0000000200000000007E00000060000000696E740076000000636861720000000000
+          - sectname:        __debug_aranges
+            segname:         __DWARF
+            addr:            0x000000010000907D
+            size:            48
+            offset:          0x0000207D
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         2C0000000200000000000800000000009C7F0000010000001C0000000000000000000000000000000000000000000000
+          - sectname:        __debug_info
+            segname:         __DWARF
+            addr:            0x00000001000090AD
+            size:            126
+            offset:          0x000020AD
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         7A000000040000000000080101000000040031000000000000003A0000009C7F0000010000001C000000029C7F0000010000001C000000016F3F0000000101600000000302910844000000010160000000030291004900000001016700000000044E0000000504056C000000057100000006760000000452000000060100
+          - sectname:        __debug_abbrev
+            segname:         __DWARF
+            addr:            0x000000010000912B
+            size:            84
+            offset:          0x0000212B
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         011101250E1305030E10171B0EB44219110112060000022E01110112064018030E3A0B3B0B49103F1900000305000218030E3A0B3B0B49100000042400030E3E0B0B0B0000050F00491000000626004910000000
+          - sectname:        __debug_str
+            segname:         __DWARF
+            addr:            0x000000010000917F
+            size:            87
+            offset:          0x0000217F
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         004170706C6520636C616E672076657273696F6E2031312E302E302028636C616E672D313130302E302E33332E313729006D61696E2E637070002F746D70006D61696E0061726763006172677600696E74006368617200
+          - sectname:        __apple_names
+            segname:         __DWARF
+            addr:            0x00000001000091D6
+            size:            60
+            offset:          0x000021D6
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         485341480100000001000000010000000C000000000000000100000001000600000000006A7F9A7C2C0000003F000000010000002A00000000000000
+          - sectname:        __apple_namespac
+            segname:         __DWARF
+            addr:            0x0000000100009212
+            size:            36
+            offset:          0x00002212
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         485341480100000001000000000000000C000000000000000100000001000600FFFFFFFF
+          - sectname:        __apple_types
+            segname:         __DWARF
+            addr:            0x0000000100009236
+            size:            114
+            offset:          0x00002236
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         48534148010000000200000002000000180000000000000004000000010006000300050005000B000600060000000000010000003080880B6320957C440000005B0000004E0000000100000060000000240000A4283A0C0000000052000000010000007600000024000057D77B9300000000
+          - sectname:        __apple_objc
+            segname:         __DWARF
+            addr:            0x00000001000092A8
+            size:            36
+            offset:          0x000022A8
+            align:           0
+            reloff:          0x00000000
+            nreloc:          0
+            flags:           0x00000000
+            reserved1:       0x00000000
+            reserved2:       0x00000000
+            reserved3:       0x00000000
+            content:         485341480100000001000000000000000C000000000000000100000001000600FFFFFFFF
+    LinkEditData:
+      NameList:
+        - n_strx:          2
+          n_type:          0x0F
+          n_sect:          1
+          n_desc:          16
+          n_value:         4294967296
+        - n_strx:          22
+          n_type:          0x0F
+          n_sect:          1
+          n_desc:          0
+          n_value:         4294999964
+      StringTable:
+        - ''
+        - ''
+        - __mh_execute_header
+        - _main
+    DWARF:
+      debug_str:
+        - ''
+        - 'Apple clang version 11.0.0 (clang-1100.0.33.17)'
+        - main.cpp
+        - '/tmp'
+        - main
+        - argc
+        - argv
+        - int
+        - char
+      debug_abbrev:
+        - Code:            0x00000001
+          Tag:             DW_TAG_compile_unit
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_producer
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_language
+              Form:            DW_FORM_data2
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_stmt_list
+              Form:            DW_FORM_sec_offset
+            - Attribute:       DW_AT_comp_dir
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_GNU_pubnames
+              Form:            DW_FORM_flag_present
+            - Attribute:       DW_AT_low_pc
+              Form:            DW_FORM_addr
+            - Attribute:       DW_AT_high_pc
+              Form:            DW_FORM_data4
+        - Code:            0x00000002
+          Tag:             DW_TAG_subprogram
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_low_pc
+              Form:            DW_FORM_addr
+            - Attribute:       DW_AT_high_pc
+              Form:            DW_FORM_data4
+            - Attribute:       DW_AT_frame_base
+              Form:            DW_FORM_exprloc
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_decl_file
+              Form:            DW_FORM_data1
+            - Attribute:       DW_AT_decl_line
+              Form:            DW_FORM_data1
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref_addr
+            - Attribute:       DW_AT_external
+              Form:            DW_FORM_flag_present
+        - Code:            0x00000003
+          Tag:             DW_TAG_formal_parameter
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_location
+              Form:            DW_FORM_exprloc
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_decl_file
+              Form:            DW_FORM_data1
+            - Attribute:       DW_AT_decl_line
+              Form:            DW_FORM_data1
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref_addr
+        - Code:            0x00000004
+          Tag:             DW_TAG_base_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_encoding
+              Form:            DW_FORM_data1
+            - Attribute:       DW_AT_byte_size
+              Form:            DW_FORM_data1
+        - Code:            0x00000005
+          Tag:             DW_TAG_pointer_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref_addr
+        - Code:            0x00000006
+          Tag:             DW_TAG_const_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref_addr
+      debug_aranges:
+        - Length:
+            TotalLength:     44
+          Version:         2
+          CuOffset:        0
+          AddrSize:        8
+          SegSize:         0
+          Descriptors:
+            - Address:         0x0000000100007F9C
+              Length:          28
+      debug_pubnames:
+        Length:
+          TotalLength:     23
+        Version:         2
+        UnitOffset:      0
+        UnitSize:        126
+        Entries:
+          - DieOffset:       0x0000002A
+            Name:            main
+      debug_pubtypes:
+        Length:
+          TotalLength:     31
+        Version:         2
+        UnitOffset:      0
+        UnitSize:        126
+        Entries:
+          - DieOffset:       0x00000060
+            Name:            int
+          - DieOffset:       0x00000076
+            Name:            char
+      debug_info:
+        - Length:
+            TotalLength:     122
+          Version:         4
+          AbbrOffset:      0
+          AddrSize:        8
+          Entries:
+            - AbbrCode:        0x00000001
+              Values:
+                - Value:           0x0000000000000001
+                - Value:           0x0000000000000004
+                - Value:           0x0000000000000031
+                - Value:           0x0000000000000000
+                - Value:           0x000000000000003A
+                - Value:           0x0000000000000001
+                - Value:           0x0000000100007F9C
+                - Value:           0x000000000000001C
+            - AbbrCode:        0x00000002
+              Values:
+                - Value:           0x0000000100007F9C
+                - Value:           0x000000000000001C
+                - Value:           0x0000000000000001
+                  BlockData:       [ 0x6F ]
+                - Value:           0x000000000000003F
+                - Value:           0x0000000000000001
+                - Value:           0x0000000000000001
+                - Value:           0x0000000000000060
+                - Value:           0x0000000000000001
+            - AbbrCode:        0x00000003
+              Values:
+                - Value:           0x0000000000000002
+                  BlockData:       [ 0x91, 0x08 ]
+                - Value:           0x0000000000000044
+                - Value:           0x0000000000000001
+                - Value:           0x0000000000000001
+                - Value:           0x0000000000000060
+            - AbbrCode:        0x00000003
+              Values:
+                - Value:           0x0000000000000002
+                  BlockData:       [ 0x91, 0x00 ]
+                - Value:           0x0000000000000049
+                - Value:           0x0000000000000001
+                - Value:           0x0000000000000001
+                - Value:           0x0000000000000067
+            - AbbrCode:        0x00000000
+              Values:          []
+            - AbbrCode:        0x00000004
+              Values:
+                - Value:           0x000000000000004E
+                - Value:           0x0000000000000005
+                - Value:           0x0000000000000004
+            - AbbrCode:        0x00000005
+              Values:
+                - Value:           0x000000000000006C
+            - AbbrCode:        0x00000005
+              Values:
+                - Value:           0x0000000000000071
+            - AbbrCode:        0x00000006
+              Values:
+                - Value:           0x0000000000000076
+            - AbbrCode:        0x00000004
+              Values:
+                - Value:           0x0000000000000052
+                - Value:           0x0000000000000006
+                - Value:           0x0000000000000001
+            - AbbrCode:        0x00000000
+              Values:          []
+      debug_line:
+        - Length:
+            TotalLength:     59
+          Version:         4
+          PrologueLength:  32
+          MinInstLength:   1
+          MaxOpsPerInst:   1
+          DefaultIsStmt:   1
+          LineBase:        251
+          LineRange:       14
+          OpcodeBase:      13
+          StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
+          IncludeDirs:     []
+          Files:
+            - Name:            main.cpp
+              DirIdx:          0
+              ModTime:         0
+              Length:          0
+          Opcodes:
+            - Opcode:          DW_LNS_extended_op
+              ExtLen:          9
+              SubOpcode:       DW_LNE_set_address
+              Data:            4294999964
+            - Opcode:          DW_LNS_copy
+              Data:            0
+            - Opcode:          DW_LNS_set_column
+              Data:            2
+            - Opcode:          DW_LNS_set_prologue_end
+              Data:            0
+            - Opcode:          0xF3
+              Data:            0
+            - Opcode:          DW_LNS_advance_pc
+              Data:            12
+            - Opcode:          DW_LNS_extended_op
+              ExtLen:          1
+              SubOpcode:       DW_LNE_end_sequence
+              Data:            0
+...

diff  --git a/llvm/test/tools/llvm-gsymutil/mach-dwarf.yaml b/llvm/test/tools/llvm-gsymutil/mach-dwarf.yaml
new file mode 100644
index 000000000000..8580637cdde0
--- /dev/null
+++ b/llvm/test/tools/llvm-gsymutil/mach-dwarf.yaml
@@ -0,0 +1,784 @@
+## Test loading a skinny mach-o file with DWARF. First we make the mach-o file,
+## from yaml, then we convert the object file to a GSYM file, then we do
+## lookups on the newly created GSYM, and finally we dump the entire GSYM.
+
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-gsymutil --convert %t -o %t.gsym 2>&1 | FileCheck %s --check-prefix=CONVERT
+# RUN: llvm-gsymutil --address=0 --address=0x100000000 --address=0x100000f90 --address=0x100000faa --address=0x200000000 %t.gsym 2>&1 | FileCheck %s --check-prefix=ADDR
+# RUN: llvm-gsymutil --verbose --address=0x100000000 --address=0x100000f90 --address=0x100000faa %t.gsym 2>&1 | FileCheck %s --check-prefix=ADDRV
+# RUN: llvm-gsymutil %t.gsym 2>&1 | FileCheck %s --check-prefix=DUMP
+
+# CONVERT: Input file: {{.*\.yaml\.tmp}}
+# CONVERT: Output file (x86_64): {{.*\.yaml\.tmp\.gsym}}
+# CONVERT: Loaded 2 functions from DWARF.
+# CONVERT: Loaded 0 functions from symbol table.
+# CONVERT: Pruned 0 functions, ended with 2 total
+
+# ADDR:      Looking up addresses in "{{.*\.yaml\.tmp\.gsym}}":
+# ADDR-NEXT: 0x0000000000000000: error: address 0x0 is not in GSYM
+# ADDR-NEXT: 0x0000000100000000: error: address 0x100000000 is not in GSYM
+# ADDR-NEXT: 0x0000000100000f90: main @ /tmp/main.cpp:4
+# ADDR-NEXT: 0x0000000100000faa: _Z3fooi @ /tmp/main.cpp:2 [inlined]
+# ADDR-NEXT:                     main + 26 @ /tmp/main.cpp:5
+# ADDR-NEXT: 0x0000000200000000: error: address 0x200000000 is not in GSYM
+
+# ADDRV:      error: address 0x100000000 is not in GSYM
+# ADDRV:      FunctionInfo for 0x0000000100000f90:
+# ADDRV-NEXT: [0x0000000100000f90 - 0x0000000100000fb5) "main"
+# ADDRV-NEXT: LineTable:
+# ADDRV-NEXT:   0x0000000100000f90 /tmp/main.cpp:4
+# ADDRV-NEXT:   0x0000000100000fa4 /tmp/main.cpp:5
+# ADDRV-NEXT:   0x0000000100000faa /tmp/main.cpp:2
+# ADDRV-NEXT:   0x0000000100000fb0 /tmp/main.cpp:5
+# ADDRV-NEXT:   0x0000000100000fb3 /tmp/main.cpp:6
+# ADDRV-NEXT: InlineInfo:
+# ADDRV-NEXT: [0x0000000100000f90 - 0x0000000100000fb5) main
+# ADDRV-NEXT:   [0x0000000100000faa - 0x0000000100000fb0) _Z3fooi called from /tmp/main.cpp:5
+
+# ADDRV:      LookupResult for 0x0000000100000f90:
+# ADDRV-NEXT: 0x0000000100000f90: main @ /tmp/main.cpp:4
+
+# ADDRV:      FunctionInfo for 0x0000000100000faa:
+# ADDRV-NEXT: [0x0000000100000f90 - 0x0000000100000fb5) "main"
+# ADDRV-NEXT: LineTable:
+# ADDRV-NEXT:   0x0000000100000f90 /tmp/main.cpp:4
+# ADDRV-NEXT:   0x0000000100000fa4 /tmp/main.cpp:5
+# ADDRV-NEXT:   0x0000000100000faa /tmp/main.cpp:2
+# ADDRV-NEXT:   0x0000000100000fb0 /tmp/main.cpp:5
+# ADDRV-NEXT:   0x0000000100000fb3 /tmp/main.cpp:6
+# ADDRV-NEXT: InlineInfo:
+# ADDRV-NEXT: [0x0000000100000f90 - 0x0000000100000fb5) main
+# ADDRV-NEXT:   [0x0000000100000faa - 0x0000000100000fb0) _Z3fooi called from /tmp/main.cpp:5
+
+# ADDRV:      LookupResult for 0x0000000100000faa:
+# ADDRV-NEXT: 0x0000000100000faa: _Z3fooi @ /tmp/main.cpp:2 [inlined]
+# ADDRV-NEXT:                     main + 26 @ /tmp/main.cpp:5
+
+# DUMP:      Header:
+# DUMP-NEXT:   Magic        = 0x4753594d
+# DUMP-NEXT:   Version      = 0x0001
+# DUMP-NEXT:   AddrOffSize  = 0x02
+# DUMP-NEXT:   UUIDSize     = 0x10
+# DUMP-NEXT:   BaseAddress  = 0x0000000100000000
+# DUMP-NEXT:   NumAddresses = 0x00000002
+# DUMP-NEXT:   StrtabOffset = 0x00000050
+# DUMP-NEXT:   StrtabSize   = 0x0000001c
+# DUMP-NEXT:   UUID         = f6241b5209ed3bbea6bc8a7f5a4817cd
+
+# DUMP:      Address Table:
+# DUMP-NEXT: INDEX  OFFSET16 (ADDRESS)
+# DUMP-NEXT: ====== ===============================
+# DUMP-NEXT: [   0] 0x0f70 (0x0000000100000f70)
+# DUMP-NEXT: [   1] 0x0f90 (0x0000000100000f90)
+
+# DUMP:      Address Info Offsets:
+# DUMP-NEXT: INDEX  Offset
+# DUMP-NEXT: ====== ==========
+# DUMP-NEXT: [   0] 0x0000006c
+# DUMP-NEXT: [   1] 0x0000008c
+
+# DUMP:      Files:
+# DUMP-NEXT: INDEX  DIRECTORY  BASENAME   PATH
+# DUMP-NEXT: ====== ========== ========== ==============================
+# DUMP-NEXT: [   0] 0x00000000 0x00000000
+# DUMP-NEXT: [   1] 0x00000009 0x0000000e /tmp/main.cpp
+
+# DUMP:      String table:
+# DUMP-NEXT: 0x00000000: ""
+# DUMP-NEXT: 0x00000001: "_Z3fooi"
+# DUMP-NEXT: 0x00000009: "/tmp"
+# DUMP-NEXT: 0x0000000e: "main.cpp"
+# DUMP-NEXT: 0x00000017: "main"
+
+# DUMP:      FunctionInfo @ 0x0000006c: [0x0000000100000f70 - 0x0000000100000f81) "_Z3fooi"
+# DUMP-NEXT: LineTable:
+# DUMP-NEXT:   0x0000000100000f70 /tmp/main.cpp:1
+# DUMP-NEXT:   0x0000000100000f77 /tmp/main.cpp:2
+# DUMP-NEXT: FunctionInfo @ 0x0000008c: [0x0000000100000f90 - 0x0000000100000fb5) "main"
+# DUMP-NEXT: LineTable:
+# DUMP-NEXT:   0x0000000100000f90 /tmp/main.cpp:4
+# DUMP-NEXT:   0x0000000100000fa4 /tmp/main.cpp:5
+# DUMP-NEXT:   0x0000000100000faa /tmp/main.cpp:2
+# DUMP-NEXT:   0x0000000100000fb0 /tmp/main.cpp:5
+# DUMP-NEXT:   0x0000000100000fb3 /tmp/main.cpp:6
+# DUMP-NEXT: InlineInfo:
+# DUMP-NEXT: [0x0000000100000f90 - 0x0000000100000fb5) main
+# DUMP-NEXT:   [0x0000000100000faa - 0x0000000100000fb0) _Z3fooi called from /tmp/main.cpp:5
+
+--- !mach-o
+FileHeader:
+  magic:           0xFEEDFACF
+  cputype:         0x01000007
+  cpusubtype:      0x00000003
+  filetype:        0x0000000A
+  ncmds:           7
+  sizeofcmds:      1400
+  flags:           0x00000000
+  reserved:        0x00000000
+LoadCommands:
+  - cmd:             LC_UUID
+    cmdsize:         24
+    uuid:            F6241B52-09ED-3BBE-A6BC-8A7F5A4817CD
+  - cmd:             LC_BUILD_VERSION
+    cmdsize:         24
+    platform:        1
+    minos:           658944
+    sdk:             658944
+    ntools:          0
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          4096
+    nsyms:           3
+    stroff:          4144
+    strsize:         37
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         72
+    segname:         __PAGEZERO
+    vmaddr:          0
+    vmsize:          4294967296
+    fileoff:         0
+    filesize:        0
+    maxprot:         0
+    initprot:        0
+    nsects:          0
+    flags:           0
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         232
+    segname:         __TEXT
+    vmaddr:          4294967296
+    vmsize:          4096
+    fileoff:         0
+    filesize:        0
+    maxprot:         5
+    initprot:        5
+    nsects:          2
+    flags:           0
+    Sections:
+      - sectname:        __text
+        segname:         __TEXT
+        addr:            0x0000000100000F70
+        size:            69
+        offset:          0x00000000
+        align:           4
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x80000400
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+        content:         CFFAEDFE07000001030000000A000000070000007805000000000000000000001B00000018000000F6241B5209ED3BBEA6BC8A7F5A4817CD32000000180000000100000000
+      - sectname:        __unwind_info
+        segname:         __TEXT
+        addr:            0x0000000100000FB8
+        size:            72
+        offset:          0x00000000
+        align:           2
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+        content:         CFFAEDFE07000001030000000A000000070000007805000000000000000000001B00000018000000F6241B5209ED3BBEA6BC8A7F5A4817CD320000001800000001000000000E0A00
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         72
+    segname:         __LINKEDIT
+    vmaddr:          4294971392
+    vmsize:          4096
+    fileoff:         4096
+    filesize:        85
+    maxprot:         1
+    initprot:        1
+    nsects:          0
+    flags:           0
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         952
+    segname:         __DWARF
+    vmaddr:          4294975488
+    vmsize:          4096
+    fileoff:         8192
+    filesize:        1055
+    maxprot:         7
+    initprot:        3
+    nsects:          11
+    flags:           0
+    Sections:
+      - sectname:        __debug_line
+        segname:         __DWARF
+        addr:            0x0000000100002000
+        size:            106
+        offset:          0x00002000
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+        content:         66000000040020000000010101FB0E0D000101010100000001000001006D61696E2E6370700000000000000902700F00000100000001050C0A75050B063C05033C0204000101000902900F00000100000015050E0A083D050C63050B063C0506063F05023D0202000101
+      - sectname:        __debug_pubnames
+        segname:         __DWARF
+        addr:            0x000000010000206A
+        size:            47
+        offset:          0x0000206A
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+        content:         2B000000020000000000E00000002A0000005F5A33666F6F69002A000000666F6F00690000006D61696E0000000000
+      - sectname:        __debug_pubtypes
+        segname:         __DWARF
+        addr:            0x0000000100002099
+        size:            35
+        offset:          0x00002099
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+        content:         1F000000020000000000E000000062000000696E7400D8000000636861720000000000
+      - sectname:        __debug_aranges
+        segname:         __DWARF
+        addr:            0x00000001000020BC
+        size:            64
+        offset:          0x000020BC
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+        content:         3C000000020000000000080000000000700F0000010000001100000000000000900F000001000000250000000000000000000000000000000000000000000000
+      - sectname:        __debug_info
+        segname:         __DWARF
+        addr:            0x00000001000020FC
+        size:            224
+        offset:          0x000020FC
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+        content:         DC000000040000000000080101000000040031000000000000003A000000700F0000010000004500000002700F000001000000110000000156460000000302917C5600000000043F0000004700000001016200000001054B00000001016200000000064D000000050407900F000001000000250000000156510000000104620000000802917456000000010462000000080291685B0000000104C9000000090291644B0000000105620000000A46000000AA0F0000010000000600000001050302917C5600000000000BCE0000000BD30000000CD80000000660000000060100
+      - sectname:        __debug_abbrev
+        segname:         __DWARF
+        addr:            0x00000001000021DC
+        size:            168
+        offset:          0x000021DC
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+        content:         011101250E1305030E10171B0EB44219110112060000022E0111011206401831100000030500021831100000042E016E0E030E3A0B3B0B49103F19200B0000050500030E3A0B3B0B49100000062400030E3E0B0B0B0000072E01110112064018030E3A0B3B0B49103F1900000805000218030E3A0B3B0B491000000934000218030E3A0B3B0B491000000A1D01311011011206580B590B00000B0F00491000000C26004910000000
+      - sectname:        __debug_str
+        segname:         __DWARF
+        addr:            0x0000000100002284
+        size:            101
+        offset:          0x00002284
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+        content:         004170706C6520636C616E672076657273696F6E2031312E302E302028636C616E672D313130302E302E33332E313729006D61696E2E637070002F746D70005F5A33666F6F6900666F6F006900696E74006D61696E00617267630061726776006368617200
+      - sectname:        __apple_names
+        segname:         __DWARF
+        addr:            0x00000001000022E9
+        size:            124
+        offset:          0x000022E9
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+        content:         485341480100000003000000030000000C0000000000000001000000010006000000000002000000FFFFFFFF8973880BDE28616A6A7F9A7C44000000580000006C00000047000000020000002A000000AC000000000000003F000000020000002A000000AC0000000000000051000000010000006900000000000000
+      - sectname:        __apple_namespac
+        segname:         __DWARF
+        addr:            0x0000000100002365
+        size:            36
+        offset:          0x00002365
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+        content:         485341480100000001000000000000000C000000000000000100000001000600FFFFFFFF
+      - sectname:        __apple_types
+        segname:         __DWARF
+        addr:            0x0000000100002389
+        size:            114
+        offset:          0x00002389
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+        content:         48534148010000000200000002000000180000000000000004000000010006000300050005000B000600060000000000010000003080880B6320957C440000005B0000004D0000000100000062000000240000A4283A0C000000006000000001000000D800000024000057D77B9300000000
+      - sectname:        __apple_objc
+        segname:         __DWARF
+        addr:            0x00000001000023FB
+        size:            36
+        offset:          0x000023FB
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+        content:         485341480100000001000000000000000C000000000000000100000001000600FFFFFFFF
+LinkEditData:
+  NameList:
+    - n_strx:          2
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         4294971248
+    - n_strx:          11
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          16
+      n_value:         4294967296
+    - n_strx:          31
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         4294971280
+  StringTable:
+    - ''
+    - ''
+    - __Z3fooi
+    - __mh_execute_header
+    - _main
+DWARF:
+  debug_str:
+    - ''
+    - 'Apple clang version 11.0.0 (clang-1100.0.33.17)'
+    - main.cpp
+    - '/tmp'
+    - _Z3fooi
+    - foo
+    - i
+    - int
+    - main
+    - argc
+    - argv
+    - char
+  debug_abbrev:
+    - Code:            0x00000001
+      Tag:             DW_TAG_compile_unit
+      Children:        DW_CHILDREN_yes
+      Attributes:
+        - Attribute:       DW_AT_producer
+          Form:            DW_FORM_strp
+        - Attribute:       DW_AT_language
+          Form:            DW_FORM_data2
+        - Attribute:       DW_AT_name
+          Form:            DW_FORM_strp
+        - Attribute:       DW_AT_stmt_list
+          Form:            DW_FORM_sec_offset
+        - Attribute:       DW_AT_comp_dir
+          Form:            DW_FORM_strp
+        - Attribute:       DW_AT_GNU_pubnames
+          Form:            DW_FORM_flag_present
+        - Attribute:       DW_AT_low_pc
+          Form:            DW_FORM_addr
+        - Attribute:       DW_AT_high_pc
+          Form:            DW_FORM_data4
+    - Code:            0x00000002
+      Tag:             DW_TAG_subprogram
+      Children:        DW_CHILDREN_yes
+      Attributes:
+        - Attribute:       DW_AT_low_pc
+          Form:            DW_FORM_addr
+        - Attribute:       DW_AT_high_pc
+          Form:            DW_FORM_data4
+        - Attribute:       DW_AT_frame_base
+          Form:            DW_FORM_exprloc
+        - Attribute:       DW_AT_abstract_origin
+          Form:            DW_FORM_ref_addr
+    - Code:            0x00000003
+      Tag:             DW_TAG_formal_parameter
+      Children:        DW_CHILDREN_no
+      Attributes:
+        - Attribute:       DW_AT_location
+          Form:            DW_FORM_exprloc
+        - Attribute:       DW_AT_abstract_origin
+          Form:            DW_FORM_ref_addr
+    - Code:            0x00000004
+      Tag:             DW_TAG_subprogram
+      Children:        DW_CHILDREN_yes
+      Attributes:
+        - Attribute:       DW_AT_linkage_name
+          Form:            DW_FORM_strp
+        - Attribute:       DW_AT_name
+          Form:            DW_FORM_strp
+        - Attribute:       DW_AT_decl_file
+          Form:            DW_FORM_data1
+        - Attribute:       DW_AT_decl_line
+          Form:            DW_FORM_data1
+        - Attribute:       DW_AT_type
+          Form:            DW_FORM_ref_addr
+        - Attribute:       DW_AT_external
+          Form:            DW_FORM_flag_present
+        - Attribute:       DW_AT_inline
+          Form:            DW_FORM_data1
+    - Code:            0x00000005
+      Tag:             DW_TAG_formal_parameter
+      Children:        DW_CHILDREN_no
+      Attributes:
+        - Attribute:       DW_AT_name
+          Form:            DW_FORM_strp
+        - Attribute:       DW_AT_decl_file
+          Form:            DW_FORM_data1
+        - Attribute:       DW_AT_decl_line
+          Form:            DW_FORM_data1
+        - Attribute:       DW_AT_type
+          Form:            DW_FORM_ref_addr
+    - Code:            0x00000006
+      Tag:             DW_TAG_base_type
+      Children:        DW_CHILDREN_no
+      Attributes:
+        - Attribute:       DW_AT_name
+          Form:            DW_FORM_strp
+        - Attribute:       DW_AT_encoding
+          Form:            DW_FORM_data1
+        - Attribute:       DW_AT_byte_size
+          Form:            DW_FORM_data1
+    - Code:            0x00000007
+      Tag:             DW_TAG_subprogram
+      Children:        DW_CHILDREN_yes
+      Attributes:
+        - Attribute:       DW_AT_low_pc
+          Form:            DW_FORM_addr
+        - Attribute:       DW_AT_high_pc
+          Form:            DW_FORM_data4
+        - Attribute:       DW_AT_frame_base
+          Form:            DW_FORM_exprloc
+        - Attribute:       DW_AT_name
+          Form:            DW_FORM_strp
+        - Attribute:       DW_AT_decl_file
+          Form:            DW_FORM_data1
+        - Attribute:       DW_AT_decl_line
+          Form:            DW_FORM_data1
+        - Attribute:       DW_AT_type
+          Form:            DW_FORM_ref_addr
+        - Attribute:       DW_AT_external
+          Form:            DW_FORM_flag_present
+    - Code:            0x00000008
+      Tag:             DW_TAG_formal_parameter
+      Children:        DW_CHILDREN_no
+      Attributes:
+        - Attribute:       DW_AT_location
+          Form:            DW_FORM_exprloc
+        - Attribute:       DW_AT_name
+          Form:            DW_FORM_strp
+        - Attribute:       DW_AT_decl_file
+          Form:            DW_FORM_data1
+        - Attribute:       DW_AT_decl_line
+          Form:            DW_FORM_data1
+        - Attribute:       DW_AT_type
+          Form:            DW_FORM_ref_addr
+    - Code:            0x00000009
+      Tag:             DW_TAG_variable
+      Children:        DW_CHILDREN_no
+      Attributes:
+        - Attribute:       DW_AT_location
+          Form:            DW_FORM_exprloc
+        - Attribute:       DW_AT_name
+          Form:            DW_FORM_strp
+        - Attribute:       DW_AT_decl_file
+          Form:            DW_FORM_data1
+        - Attribute:       DW_AT_decl_line
+          Form:            DW_FORM_data1
+        - Attribute:       DW_AT_type
+          Form:            DW_FORM_ref_addr
+    - Code:            0x0000000A
+      Tag:             DW_TAG_inlined_subroutine
+      Children:        DW_CHILDREN_yes
+      Attributes:
+        - Attribute:       DW_AT_abstract_origin
+          Form:            DW_FORM_ref_addr
+        - Attribute:       DW_AT_low_pc
+          Form:            DW_FORM_addr
+        - Attribute:       DW_AT_high_pc
+          Form:            DW_FORM_data4
+        - Attribute:       DW_AT_call_file
+          Form:            DW_FORM_data1
+        - Attribute:       DW_AT_call_line
+          Form:            DW_FORM_data1
+    - Code:            0x0000000B
+      Tag:             DW_TAG_pointer_type
+      Children:        DW_CHILDREN_no
+      Attributes:
+        - Attribute:       DW_AT_type
+          Form:            DW_FORM_ref_addr
+    - Code:            0x0000000C
+      Tag:             DW_TAG_const_type
+      Children:        DW_CHILDREN_no
+      Attributes:
+        - Attribute:       DW_AT_type
+          Form:            DW_FORM_ref_addr
+  debug_aranges:
+    - Length:
+        TotalLength:     60
+      Version:         2
+      CuOffset:        0
+      AddrSize:        8
+      SegSize:         0
+      Descriptors:
+        - Address:         0x0000000100000F70
+          Length:          17
+        - Address:         0x0000000100000F90
+          Length:          37
+  debug_pubnames:
+    Length:
+      TotalLength:     43
+    Version:         2
+    UnitOffset:      0
+    UnitSize:        224
+    Entries:
+      - DieOffset:       0x0000002A
+        Name:            _Z3fooi
+      - DieOffset:       0x0000002A
+        Name:            foo
+      - DieOffset:       0x00000069
+        Name:            main
+  debug_pubtypes:
+    Length:
+      TotalLength:     31
+    Version:         2
+    UnitOffset:      0
+    UnitSize:        224
+    Entries:
+      - DieOffset:       0x00000062
+        Name:            int
+      - DieOffset:       0x000000D8
+        Name:            char
+  debug_info:
+    - Length:
+        TotalLength:     220
+      Version:         4
+      AbbrOffset:      0
+      AddrSize:        8
+      Entries:
+        - AbbrCode:        0x00000001
+          Values:
+            - Value:           0x0000000000000001
+            - Value:           0x0000000000000004
+            - Value:           0x0000000000000031
+            - Value:           0x0000000000000000
+            - Value:           0x000000000000003A
+            - Value:           0x0000000000000001
+            - Value:           0x0000000100000F70
+            - Value:           0x0000000000000045
+        - AbbrCode:        0x00000002
+          Values:
+            - Value:           0x0000000100000F70
+            - Value:           0x0000000000000011
+            - Value:           0x0000000000000001
+              BlockData:       [ 0x56 ]
+            - Value:           0x0000000000000046
+        - AbbrCode:        0x00000003
+          Values:
+            - Value:           0x0000000000000002
+              BlockData:       [ 0x91, 0x7C ]
+            - Value:           0x0000000000000056
+        - AbbrCode:        0x00000000
+          Values:          []
+        - AbbrCode:        0x00000004
+          Values:
+            - Value:           0x000000000000003F
+            - Value:           0x0000000000000047
+            - Value:           0x0000000000000001
+            - Value:           0x0000000000000001
+            - Value:           0x0000000000000062
+            - Value:           0x0000000000000001
+            - Value:           0x0000000000000001
+        - AbbrCode:        0x00000005
+          Values:
+            - Value:           0x000000000000004B
+            - Value:           0x0000000000000001
+            - Value:           0x0000000000000001
+            - Value:           0x0000000000000062
+        - AbbrCode:        0x00000000
+          Values:          []
+        - AbbrCode:        0x00000006
+          Values:
+            - Value:           0x000000000000004D
+            - Value:           0x0000000000000005
+            - Value:           0x0000000000000004
+        - AbbrCode:        0x00000007
+          Values:
+            - Value:           0x0000000100000F90
+            - Value:           0x0000000000000025
+            - Value:           0x0000000000000001
+              BlockData:       [ 0x56 ]
+            - Value:           0x0000000000000051
+            - Value:           0x0000000000000001
+            - Value:           0x0000000000000004
+            - Value:           0x0000000000000062
+            - Value:           0x0000000000000001
+        - AbbrCode:        0x00000008
+          Values:
+            - Value:           0x0000000000000002
+              BlockData:       [ 0x91, 0x74 ]
+            - Value:           0x0000000000000056
+            - Value:           0x0000000000000001
+            - Value:           0x0000000000000004
+            - Value:           0x0000000000000062
+        - AbbrCode:        0x00000008
+          Values:
+            - Value:           0x0000000000000002
+              BlockData:       [ 0x91, 0x68 ]
+            - Value:           0x000000000000005B
+            - Value:           0x0000000000000001
+            - Value:           0x0000000000000004
+            - Value:           0x00000000000000C9
+        - AbbrCode:        0x00000009
+          Values:
+            - Value:           0x0000000000000002
+              BlockData:       [ 0x91, 0x64 ]
+            - Value:           0x000000000000004B
+            - Value:           0x0000000000000001
+            - Value:           0x0000000000000005
+            - Value:           0x0000000000000062
+        - AbbrCode:        0x0000000A
+          Values:
+            - Value:           0x0000000000000046
+            - Value:           0x0000000100000FAA
+            - Value:           0x0000000000000006
+            - Value:           0x0000000000000001
+            - Value:           0x0000000000000005
+        - AbbrCode:        0x00000003
+          Values:
+            - Value:           0x0000000000000002
+              BlockData:       [ 0x91, 0x7C ]
+            - Value:           0x0000000000000056
+        - AbbrCode:        0x00000000
+          Values:          []
+        - AbbrCode:        0x00000000
+          Values:          []
+        - AbbrCode:        0x0000000B
+          Values:
+            - Value:           0x00000000000000CE
+        - AbbrCode:        0x0000000B
+          Values:
+            - Value:           0x00000000000000D3
+        - AbbrCode:        0x0000000C
+          Values:
+            - Value:           0x00000000000000D8
+        - AbbrCode:        0x00000006
+          Values:
+            - Value:           0x0000000000000060
+            - Value:           0x0000000000000006
+            - Value:           0x0000000000000001
+        - AbbrCode:        0x00000000
+          Values:          []
+  debug_line:
+    - Length:
+        TotalLength:     102
+      Version:         4
+      PrologueLength:  32
+      MinInstLength:   1
+      MaxOpsPerInst:   1
+      DefaultIsStmt:   1
+      LineBase:        251
+      LineRange:       14
+      OpcodeBase:      13
+      StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
+      IncludeDirs:     []
+      Files:
+        - Name:            main.cpp
+          DirIdx:          0
+          ModTime:         0
+          Length:          0
+      Opcodes:
+        - Opcode:          DW_LNS_extended_op
+          ExtLen:          9
+          SubOpcode:       DW_LNE_set_address
+          Data:            4294971248
+        - Opcode:          DW_LNS_copy
+          Data:            0
+        - Opcode:          DW_LNS_set_column
+          Data:            12
+        - Opcode:          DW_LNS_set_prologue_end
+          Data:            0
+        - Opcode:          0x75
+          Data:            0
+        - Opcode:          DW_LNS_set_column
+          Data:            11
+        - Opcode:          DW_LNS_negate_stmt
+          Data:            0
+        - Opcode:          0x3C
+          Data:            0
+        - Opcode:          DW_LNS_set_column
+          Data:            3
+        - Opcode:          0x3C
+          Data:            0
+        - Opcode:          DW_LNS_advance_pc
+          Data:            4
+        - Opcode:          DW_LNS_extended_op
+          ExtLen:          1
+          SubOpcode:       DW_LNE_end_sequence
+          Data:            0
+        - Opcode:          DW_LNS_extended_op
+          ExtLen:          9
+          SubOpcode:       DW_LNE_set_address
+          Data:            4294971280
+        - Opcode:          0x15
+          Data:            0
+        - Opcode:          DW_LNS_set_column
+          Data:            14
+        - Opcode:          DW_LNS_set_prologue_end
+          Data:            0
+        - Opcode:          DW_LNS_const_add_pc
+          Data:            0
+        - Opcode:          0x3D
+          Data:            0
+        - Opcode:          DW_LNS_set_column
+          Data:            12
+        - Opcode:          0x63
+          Data:            0
+        - Opcode:          DW_LNS_set_column
+          Data:            11
+        - Opcode:          DW_LNS_negate_stmt
+          Data:            0
+        - Opcode:          0x3C
+          Data:            0
+        - Opcode:          DW_LNS_set_column
+          Data:            6
+        - Opcode:          DW_LNS_negate_stmt
+          Data:            0
+        - Opcode:          0x3F
+          Data:            0
+        - Opcode:          DW_LNS_set_column
+          Data:            2
+        - Opcode:          0x3D
+          Data:            0
+        - Opcode:          DW_LNS_advance_pc
+          Data:            2
+        - Opcode:          DW_LNS_extended_op
+          ExtLen:          1
+          SubOpcode:       DW_LNE_end_sequence
+          Data:            0
+...

diff  --git a/llvm/tools/llvm-gsym/CMakeLists.txt b/llvm/tools/llvm-gsym/CMakeLists.txt
new file mode 100644
index 000000000000..38763b272a2e
--- /dev/null
+++ b/llvm/tools/llvm-gsym/CMakeLists.txt
@@ -0,0 +1,19 @@
+set(LLVM_LINK_COMPONENTS
+  ${LLVM_TARGETS_TO_BUILD}
+  DebugInfoDWARF
+  DebugInfoGSYM
+  AsmPrinter
+  AllTargetsDescs
+  AllTargetsInfos
+  MC
+  Object
+  Support
+  Target
+  )
+
+add_llvm_tool(llvm-gsymutil
+  llvm-gsymutil.cpp
+
+  DEPENDS
+  intrinsics_gen
+  )

diff  --git a/llvm/tools/llvm-gsym/llvm-gsymutil.cpp b/llvm/tools/llvm-gsym/llvm-gsymutil.cpp
new file mode 100644
index 000000000000..c7d6cf33da67
--- /dev/null
+++ b/llvm/tools/llvm-gsym/llvm-gsymutil.cpp
@@ -0,0 +1,503 @@
+//===-- llvm-gsymutil.cpp - GSYM dumping and creation utility for llvm ----===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/MachOUniversal.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cstring>
+#include <inttypes.h>
+#include <map>
+#include <string>
+#include <system_error>
+#include <vector>
+
+#include "llvm/DebugInfo/GSYM/DwarfTransformer.h"
+#include "llvm/DebugInfo/GSYM/FunctionInfo.h"
+#include "llvm/DebugInfo/GSYM/GsymCreator.h"
+#include "llvm/DebugInfo/GSYM/GsymReader.h"
+#include "llvm/DebugInfo/GSYM/InlineInfo.h"
+#include "llvm/DebugInfo/GSYM/LookupResult.h"
+#include "llvm/DebugInfo/GSYM/ObjectFileTransformer.h"
+
+using namespace llvm;
+using namespace gsym;
+using namespace object;
+
+/// @}
+/// Command line options.
+/// @{
+
+namespace {
+using namespace cl;
+
+OptionCategory GeneralOptions("Options");
+OptionCategory ConversionOptions("Conversion Options");
+OptionCategory LookupOptions("Lookup Options");
+
+static opt<bool> Help("h", desc("Alias for -help"), Hidden,
+                      cat(GeneralOptions));
+
+static opt<bool> Verbose("verbose",
+                         desc("Enable verbose logging and encoding details."),
+                         cat(GeneralOptions));
+
+static list<std::string> InputFilenames(Positional, desc("<input GSYM files>"),
+                                        ZeroOrMore, cat(GeneralOptions));
+
+static opt<std::string>
+    ConvertFilename("convert", cl::init(""),
+                    cl::desc("Convert the specified file to the GSYM format.\n"
+                             "Supported files include ELF and mach-o files "
+                             "that will have their debug info (DWARF) and "
+                             "symbol table converted."),
+                    cl::value_desc("path"), cat(ConversionOptions));
+
+static list<std::string>
+    ArchFilters("arch",
+                desc("Process debug information for the specified CPU "
+                     "architecture only.\nArchitectures may be specified by "
+                     "name or by number.\nThis option can be specified "
+                     "multiple times, once for each desired architecture."),
+                cl::value_desc("arch"), cat(ConversionOptions));
+
+static opt<std::string>
+    OutputFilename("out-file", cl::init(""),
+                   cl::desc("Specify the path where the converted GSYM file "
+                            "will be saved.\nWhen not specified, a '.gsym' "
+                            "extension will be appended to the file name "
+                            "specified in the --convert option."),
+                   cl::value_desc("path"), cat(ConversionOptions));
+static alias OutputFilenameAlias("o", desc("Alias for -out-file."),
+                                 aliasopt(OutputFilename),
+                                 cat(ConversionOptions));
+
+static opt<bool> Verify("verify",
+                        desc("Verify the generated GSYM file against the "
+                             "information in the file that was converted."),
+                        cat(ConversionOptions));
+
+static opt<unsigned>
+    NumThreads("num-threads",
+               desc("Specify the maximum number (n) of simultaneous threads "
+                    "to use when converting files to GSYM.\nDefaults to the "
+                    "number of cores on the current machine."),
+               cl::value_desc("n"), cat(ConversionOptions));
+
+static list<uint64_t> LookupAddresses("address",
+                                      desc("Lookup an address in a GSYM file"),
+                                      cl::value_desc("addr"),
+                                      cat(LookupOptions));
+
+
+
+} // namespace
+/// @}
+//===----------------------------------------------------------------------===//
+
+static void error(StringRef Prefix, llvm::Error Err) {
+  if (!Err)
+    return;
+  errs() << Prefix << ": " << Err << "\n";
+  consumeError(std::move(Err));
+  exit(1);
+}
+
+static void error(StringRef Prefix, std::error_code EC) {
+  if (!EC)
+    return;
+  errs() << Prefix << ": " << EC.message() << "\n";
+  exit(1);
+}
+
+
+/// If the input path is a .dSYM bundle (as created by the dsymutil tool),
+/// replace it with individual entries for each of the object files inside the
+/// bundle otherwise return the input path.
+static std::vector<std::string> expandBundle(const std::string &InputPath) {
+  std::vector<std::string> BundlePaths;
+  SmallString<256> BundlePath(InputPath);
+  // Manually open up the bundle to avoid introducing additional dependencies.
+  if (sys::fs::is_directory(BundlePath) &&
+      sys::path::extension(BundlePath) == ".dSYM") {
+    std::error_code EC;
+    sys::path::append(BundlePath, "Contents", "Resources", "DWARF");
+    for (sys::fs::directory_iterator Dir(BundlePath, EC), DirEnd;
+         Dir != DirEnd && !EC; Dir.increment(EC)) {
+      const std::string &Path = Dir->path();
+      sys::fs::file_status Status;
+      EC = sys::fs::status(Path, Status);
+      error(Path, EC);
+      switch (Status.type()) {
+      case sys::fs::file_type::regular_file:
+      case sys::fs::file_type::symlink_file:
+      case sys::fs::file_type::type_unknown:
+        BundlePaths.push_back(Path);
+        break;
+      default: /*ignore*/;
+      }
+    }
+    error(BundlePath, EC);
+  }
+  if (!BundlePaths.size())
+    BundlePaths.push_back(InputPath);
+  return BundlePaths;
+}
+
+static uint32_t getCPUType(MachOObjectFile &MachO) {
+  if (MachO.is64Bit())
+    return MachO.getHeader64().cputype;
+  else
+    return MachO.getHeader().cputype;
+}
+
+/// Return true if the object file has not been filtered by an --arch option.
+static bool filterArch(MachOObjectFile &Obj) {
+  if (ArchFilters.empty())
+    return true;
+
+  StringRef ObjArch = Obj.getArchTriple().getArchName();
+
+  for (auto Arch : ArchFilters) {
+    // Match name.
+    if (Arch == ObjArch)
+      return true;
+
+    // Match architecture number.
+    unsigned Value;
+    if (!StringRef(Arch).getAsInteger(0, Value))
+      if (Value == getCPUType(Obj))
+        return true;
+  }
+  return false;
+}
+
+/// Determine the virtual address that is considered the base address of an ELF
+/// object file.
+///
+/// The base address of an ELF file is the the "p_vaddr" of the first program
+/// header whose "p_type" is PT_LOAD.
+///
+/// \param ELFFile An ELF object file we will search.
+///
+/// \returns A valid image base address if we are able to extract one.
+template <class ELFT>
+static llvm::Optional<uint64_t>
+getImageBaseAddress(const object::ELFFile<ELFT> *ELFFile) {
+  auto PhdrRangeOrErr = ELFFile->program_headers();
+  if (!PhdrRangeOrErr) {
+    consumeError(PhdrRangeOrErr.takeError());
+    return llvm::None;
+  }
+  for (const typename ELFT::Phdr &Phdr : *PhdrRangeOrErr)
+    if (Phdr.p_type == ELF::PT_LOAD)
+      return (uint64_t)Phdr.p_vaddr;
+  return llvm::None;
+}
+
+/// Determine the virtual address that is considered the base address of mach-o
+/// object file.
+///
+/// The base address of a mach-o file is the vmaddr of the  "__TEXT" segment.
+///
+/// \param MachO A mach-o object file we will search.
+///
+/// \returns A valid image base address if we are able to extract one.
+static llvm::Optional<uint64_t>
+getImageBaseAddress(const object::MachOObjectFile *MachO) {
+  for (const auto &Command : MachO->load_commands()) {
+    if (Command.C.cmd == MachO::LC_SEGMENT) {
+      MachO::segment_command SLC = MachO->getSegmentLoadCommand(Command);
+      StringRef SegName = SLC.segname;
+      if (SegName == "__TEXT")
+        return SLC.vmaddr;
+    } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
+      MachO::segment_command_64 SLC = MachO->getSegment64LoadCommand(Command);
+      StringRef SegName = SLC.segname;
+      if (SegName == "__TEXT")
+        return SLC.vmaddr;
+    }
+  }
+  return llvm::None;
+}
+
+/// Determine the virtual address that is considered the base address of an
+/// object file.
+///
+/// Since GSYM files are used for symbolication, many clients will need to
+/// easily adjust addresses they find in stack traces so the lookups happen
+/// on unslid addresses from the original object file. If the base address of
+/// a GSYM file is set to the base address of the image, then this address
+/// adjusting is much easier.
+///
+/// \param Obj An object file we will search.
+///
+/// \returns A valid image base address if we are able to extract one.
+static llvm::Optional<uint64_t> getImageBaseAddress(object::ObjectFile &Obj) {
+  if (const auto *MachO = dyn_cast<object::MachOObjectFile>(&Obj))
+    return getImageBaseAddress(MachO);
+  else if (const auto *ELFObj = dyn_cast<object::ELF32LEObjectFile>(&Obj))
+    return getImageBaseAddress(ELFObj->getELFFile());
+  else if (const auto *ELFObj = dyn_cast<object::ELF32BEObjectFile>(&Obj))
+    return getImageBaseAddress(ELFObj->getELFFile());
+  else if (const auto *ELFObj = dyn_cast<object::ELF64LEObjectFile>(&Obj))
+    return getImageBaseAddress(ELFObj->getELFFile());
+  else if (const auto *ELFObj = dyn_cast<object::ELF64BEObjectFile>(&Obj))
+    return getImageBaseAddress(ELFObj->getELFFile());
+  return llvm::None;
+}
+
+
+static llvm::Error handleObjectFile(ObjectFile &Obj,
+                                    const std::string &OutFile) {
+  auto ThreadCount =
+      NumThreads > 0 ? NumThreads : std::thread::hardware_concurrency();
+  auto &OS = outs();
+
+  GsymCreator Gsym;
+
+  // See if we can figure out the base address for a given object file, and if
+  // we can, then set the base address to use to this value. This will ease
+  // symbolication since clients can slide the GSYM lookup addresses by using
+  // the load bias of the shared library.
+  if (auto ImageBaseAddr = getImageBaseAddress(Obj))
+    Gsym.setBaseAddress(*ImageBaseAddr);
+
+  // We need to know where the valid sections are that contain instructions.
+  // See header documentation for DWARFTransformer::SetValidTextRanges() for
+  // defails.
+  AddressRanges TextRanges;
+  for (const object::SectionRef &Sect : Obj.sections()) {
+    if (!Sect.isText())
+      continue;
+    const uint64_t Size = Sect.getSize();
+    if (Size == 0)
+      continue;
+    const uint64_t StartAddr = Sect.getAddress();
+    TextRanges.insert(AddressRange(StartAddr, StartAddr + Size));
+  }
+
+  // Make sure there is DWARF to convert first.
+  std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(Obj);
+  if (!DICtx)
+    return createStringError(std::errc::invalid_argument,
+                             "unable to create DWARF context");
+  logAllUnhandledErrors(DICtx->loadRegisterInfo(Obj), OS,
+                        "DwarfTransformer: ");
+
+  // Make a DWARF transformer object and populate the ranges of the code
+  // so we don't end up adding invalid functions to GSYM data.
+  DwarfTransformer DT(*DICtx, OS, Gsym);
+  if (!TextRanges.empty())
+    Gsym.SetValidTextRanges(TextRanges);
+
+  // Convert all DWARF to GSYM.
+  if (auto Err = DT.convert(ThreadCount))
+    return Err;
+
+  // Get the UUID and convert symbol table to GSYM.
+  if (auto Err = ObjectFileTransformer::convert(Obj, OS, Gsym))
+    return Err;
+
+  // Finalize the GSYM to make it ready to save to disk. This will remove
+  // duplicate FunctionInfo entries where we might have found an entry from
+  // debug info and also a symbol table entry from the object file.
+  if (auto Err = Gsym.finalize(OS))
+    return Err;
+
+  // Save the GSYM file to disk.
+  support::endianness Endian = Obj.makeTriple().isLittleEndian() ?
+      support::little : support::big;
+  if (auto Err = Gsym.save(OutFile.c_str(), Endian))
+    return Err;
+
+  // Verify the DWARF if requested. This will ensure all the info in the DWARF
+  // can be looked up in the GSYM and that all lookups get matching data.
+  if (Verify) {
+    if (auto Err = DT.verify(OutFile))
+      return Err;
+  }
+
+  return Error::success();
+}
+
+static llvm::Error handleBuffer(StringRef Filename, MemoryBufferRef Buffer,
+                                const std::string &OutFile) {
+  Expected<std::unique_ptr<Binary>> BinOrErr = object::createBinary(Buffer);
+  error(Filename, errorToErrorCode(BinOrErr.takeError()));
+
+  if (auto *Obj = dyn_cast<ObjectFile>(BinOrErr->get())) {
+    auto ArchName = Obj->makeTriple().getArchName();
+    outs() << "Output file (" << ArchName << "): " << OutFile << "\n";
+    if (auto Err = handleObjectFile(*Obj, OutFile.c_str()))
+      return Err;
+  } else if (auto *Fat = dyn_cast<MachOUniversalBinary>(BinOrErr->get())) {
+    // Iterate over all contained architectures and filter out any that were
+    // not specified with the "--arch <arch>" option. If the --arch option was
+    // not specified on the command line, we will process all architectures.
+    std::vector< std::unique_ptr<MachOObjectFile> > FilterObjs;
+    for (auto &ObjForArch : Fat->objects()) {
+      if (auto MachOOrErr = ObjForArch.getAsObjectFile()) {
+        auto &Obj = **MachOOrErr;
+        if (filterArch(Obj))
+          FilterObjs.emplace_back(MachOOrErr->release());
+      } else {
+        error(Filename, MachOOrErr.takeError());
+      }
+    }
+    if (FilterObjs.empty())
+      error(Filename, createStringError(std::errc::invalid_argument,
+                                        "no matching architectures found"));
+
+    // Now handle each architecture we need to convert.
+    for (auto &Obj: FilterObjs) {
+      auto ArchName = Obj->getArchTriple().getArchName();
+      std::string ArchOutFile(OutFile);
+      // If we are only handling a single architecture, then we will use the
+      // normal output file. If we are handling multiple architectures append
+      // the architecture name to the end of the out file path so that we
+      // don't overwrite the previous architecture's gsym file.
+      if (FilterObjs.size() > 1) {
+        ArchOutFile.append(1, '.');
+        ArchOutFile.append(ArchName.str());
+      }
+      outs() << "Output file (" << ArchName << "): " << ArchOutFile << "\n";
+      if (auto Err = handleObjectFile(*Obj, ArchOutFile))
+        return Err;
+    }
+  }
+  return Error::success();
+}
+
+static llvm::Error handleFileConversionToGSYM(StringRef Filename,
+                                              const std::string &OutFile) {
+  ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =
+      MemoryBuffer::getFileOrSTDIN(Filename);
+  error(Filename, BuffOrErr.getError());
+  std::unique_ptr<MemoryBuffer> Buffer = std::move(BuffOrErr.get());
+  return handleBuffer(Filename, *Buffer, OutFile);
+}
+
+static llvm::Error convertFileToGSYM(raw_ostream &OS) {
+  // Expand any .dSYM bundles to the individual object files contained therein.
+  std::vector<std::string> Objects;
+  std::string OutFile = OutputFilename;
+  if (OutFile.empty()) {
+    OutFile = ConvertFilename;
+    OutFile += ".gsym";
+  }
+
+  OS << "Input file: " << ConvertFilename << "\n";
+
+  auto Objs = expandBundle(ConvertFilename);
+  Objects.insert(Objects.end(), Objs.begin(), Objs.end());
+
+  for (auto Object : Objects) {
+    if (auto Err = handleFileConversionToGSYM(Object, OutFile))
+      return Err;
+  }
+  return Error::success();
+}
+
+int main(int argc, char const *argv[]) {
+  // Print a stack trace if we signal out.
+  sys::PrintStackTraceOnErrorSignal(argv[0]);
+  PrettyStackTraceProgram X(argc, argv);
+  llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+  llvm::InitializeAllTargetInfos();
+  llvm::InitializeAllTargetMCs();
+  llvm::InitializeAllTargets();
+  llvm::InitializeAllAsmPrinters();
+
+  const char *Overview =
+      "A tool for dumping, searching and creating GSYM files.\n\n"
+      "Specify one or more GSYM paths as arguments to dump all of the "
+      "information in each GSYM file.\n"
+      "Specify a single GSYM file along with one or more --lookup options to "
+      "lookup addresses within that GSYM file.\n"
+      "Use the --convert option to specify a file with option --out-file "
+      "option to convert to GSYM format.\n";
+  HideUnrelatedOptions(
+      {&GeneralOptions, &ConversionOptions, &LookupOptions});
+  cl::ParseCommandLineOptions(argc, argv, Overview);
+
+  if (Help) {
+    PrintHelpMessage(/*Hidden =*/false, /*Categorized =*/true);
+    return 0;
+  }
+
+  raw_ostream &OS = outs();
+
+  if (!ConvertFilename.empty()) {
+    // Convert DWARF to GSYM
+    if (!InputFilenames.empty()) {
+      OS << "error: no input files can be specified when using the --convert "
+            "option.\n";
+      return 1;
+    }
+    // Call error() if we have an error and it will exit with a status of 1
+    if (auto Err = convertFileToGSYM(OS))
+      error("DWARF conversion failed: ", std::move(Err));
+    return 0;
+  }
+
+  // Dump or access data inside GSYM files
+  for (const auto &GSYMPath : InputFilenames) {
+    auto Gsym = GsymReader::openFile(GSYMPath);
+    if (!Gsym)
+      error(GSYMPath, Gsym.takeError());
+
+    if (LookupAddresses.empty()) {
+      Gsym->dump(outs());
+      continue;
+    }
+
+    // Lookup an address in a GSYM file and print any matches.
+    OS << "Looking up addresses in \"" << GSYMPath << "\":\n";
+    for (auto Addr: LookupAddresses) {
+      if (auto Result = Gsym->lookup(Addr)) {
+        // If verbose is enabled dump the full function info for the address.
+        if (Verbose) {
+          if (auto FI = Gsym->getFunctionInfo(Addr)) {
+            OS << "FunctionInfo for " << HEX64(Addr) << ":\n";
+            Gsym->dump(OS, *FI);
+            OS << "\nLookupResult for " << HEX64(Addr) << ":\n";
+          }
+        }
+        OS << Result.get();
+      } else {
+        if (Verbose)
+          OS << "\nLookupResult for " << HEX64(Addr) << ":\n";
+        OS << HEX64(Addr) << ": ";
+        logAllUnhandledErrors(Result.takeError(), OS, "error: ");
+      }
+      if (Verbose)
+        OS << "\n";
+    }
+  }
+  return EXIT_SUCCESS;
+}


        


More information about the llvm-commits mailing list