[lld] r276921 - [lld][MachO] Add debug info support for MachO.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 27 14:31:25 PDT 2016


Author: lhames
Date: Wed Jul 27 16:31:25 2016
New Revision: 276921

URL: http://llvm.org/viewvc/llvm-project?rev=276921&view=rev
Log:
[lld][MachO] Add debug info support for MachO.

This patch causes LLD to build stabs debugging symbols for files containing
DWARF debug info, and to propagate existing stabs symbols for object files
built using '-r' mode. This enables debugging of binaries generated by LLD
from MachO objects.


Added:
    lld/trunk/lib/ReaderWriter/MachO/DebugInfo.h
    lld/trunk/test/mach-o/debug-syms.yaml
Modified:
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
    lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt
    lld/trunk/lib/ReaderWriter/MachO/File.h
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp?rev=276921&r1=276920&r2=276921&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp Wed Jul 27 16:31:25 2016
@@ -463,7 +463,10 @@ ArchHandler_x86_64::getPairReferenceInfo
       return ec;
     uint64_t encodedAddend = (int64_t)*(const little64_t *)fixupContent;
     if (inAtom == fromTarget) {
-      *kind = delta64;
+      if (inAtom->contentType() == DefinedAtom::typeCFI)
+        *kind = unwindFDEToFunction;
+      else
+        *kind = delta64;
       *addend = encodedAddend + offsetInAtom;
     } else if (inAtom == *target) {
       *kind = negDelta64;

Modified: lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt?rev=276921&r1=276920&r2=276921&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt (original)
+++ lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt Wed Jul 27 16:31:25 2016
@@ -21,6 +21,7 @@ add_lld_library(lldMachO
   LINK_LIBS
     lldCore
     lldYAML
+    LLVMDebugInfoDWARF
     LLVMObject
     LLVMSupport
     ${PTHREAD_LIB}

Added: lld/trunk/lib/ReaderWriter/MachO/DebugInfo.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/DebugInfo.h?rev=276921&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/DebugInfo.h (added)
+++ lld/trunk/lib/ReaderWriter/MachO/DebugInfo.h Wed Jul 27 16:31:25 2016
@@ -0,0 +1,310 @@
+//===- lib/ReaderWriter/MachO/File.h ----------------------------*- C++ -*-===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_MACHO_DEBUGINFO_H
+#define LLD_READER_WRITER_MACHO_DEBUGINFO_H
+
+#include "lld/Core/Atom.h"
+#include <vector>
+
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+
+namespace lld {
+namespace mach_o {
+
+class DebugInfo {
+public:
+  enum class Kind {
+    Dwarf,
+    Stabs
+  };
+
+  Kind kind() const { return _kind; }
+
+  void setAllocator(std::unique_ptr<llvm::BumpPtrAllocator> allocator) {
+    _allocator = std::move(allocator);
+  }
+
+protected:
+  DebugInfo(Kind kind) : _kind(kind) {}
+
+private:
+  std::unique_ptr<llvm::BumpPtrAllocator> _allocator;
+  Kind _kind;
+};
+
+struct TranslationUnitSource {
+  StringRef name;
+  StringRef path;
+};
+
+class DwarfDebugInfo : public DebugInfo {
+public:
+  DwarfDebugInfo(TranslationUnitSource tu)
+    : DebugInfo(Kind::Dwarf), _tu(std::move(tu)) {}
+
+  static inline bool classof(const DebugInfo *di) {
+    return di->kind() == Kind::Dwarf;
+  }
+
+  const TranslationUnitSource &translationUnitSource() const { return _tu; }
+
+private:
+  TranslationUnitSource _tu;
+};
+
+struct Stab {
+  Stab(const Atom* atom, uint8_t type, uint8_t other, uint16_t desc,
+       uint32_t value, StringRef str)
+    : atom(atom), type(type), other(other), desc(desc), value(value),
+      str(str) {}
+
+  const class Atom*   atom;
+  uint8_t             type;
+  uint8_t             other;
+  uint16_t            desc;
+  uint32_t            value;
+  StringRef           str;
+};
+
+inline raw_ostream& operator<<(raw_ostream &os, Stab &s) {
+  os << "Stab -- atom: " << llvm::format("%p", s.atom) << ", type: " << (uint32_t)s.type
+     << ", other: " << (uint32_t)s.other << ", desc: " << s.desc << ", value: " << s.value
+     << ", str: '" << s.str << "'";
+  return os;
+}
+
+class StabsDebugInfo : public DebugInfo {
+public:
+
+  typedef std::vector<Stab> StabsList;
+
+  StabsDebugInfo(StabsList stabs)
+    : DebugInfo(Kind::Stabs), _stabs(std::move(stabs)) {}
+
+  static inline bool classof(const DebugInfo *di) {
+    return di->kind() == Kind::Stabs;
+  }
+
+  const StabsList& stabs() const { return _stabs; }
+
+public:
+  StabsList _stabs;
+};
+
+} // end namespace mach_o
+} // end namespace lld
+
+#endif // LLD_READER_WRITER_MACHO_DEBUGINFO_H
+//===- lib/ReaderWriter/MachO/File.h ----------------------------*- C++ -*-===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_MACHO_DEBUGINFO_H
+#define LLD_READER_WRITER_MACHO_DEBUGINFO_H
+
+#include "lld/Core/Atom.h"
+#include <vector>
+
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+
+namespace lld {
+namespace mach_o {
+
+class DebugInfo {
+public:
+  enum class Kind {
+    Dwarf,
+    Stabs
+  };
+
+  Kind kind() const { return _kind; }
+
+protected:
+  DebugInfo(Kind kind) : _kind(kind) {}
+
+private:
+  Kind _kind;
+};
+
+
+struct TranslationUnitSource {
+  StringRef name;
+  StringRef path;
+};
+
+class DwarfDebugInfo : public DebugInfo {
+public:
+  DwarfDebugInfo(TranslationUnitSource tu)
+    : DebugInfo(Kind::Dwarf), _tu(std::move(tu)) {}
+
+  static inline bool classof(const DebugInfo *di) {
+    return di->kind() == Kind::Dwarf;
+  }
+
+  const TranslationUnitSource &translationUnitSource() const { return _tu; }
+
+private:
+  TranslationUnitSource _tu;
+};
+
+struct Stab {
+  Stab(const Atom* atom, uint8_t type, uint8_t other, uint16_t desc,
+       uint32_t value, StringRef str)
+    : atom(atom), type(type), other(other), desc(desc), value(value),
+      str(str) {}
+
+  const class Atom*   atom;
+  uint8_t             type;
+  uint8_t             other;
+  uint16_t            desc;
+  uint32_t            value;
+  StringRef           str;
+};
+
+inline raw_ostream& operator<<(raw_ostream &os, Stab &s) {
+  os << "Stab -- atom: " << llvm::format("%p", s.atom) << ", type: " << (uint32_t)s.type
+     << ", other: " << (uint32_t)s.other << ", desc: " << s.desc << ", value: " << s.value
+     << ", str: '" << s.str << "'";
+  return os;
+}
+
+class StabsDebugInfo : public DebugInfo {
+public:
+
+  typedef std::vector<Stab> StabsList;
+
+  StabsDebugInfo(StabsList stabs)
+    : DebugInfo(Kind::Stabs), _stabs(std::move(stabs)) {}
+
+  static inline bool classof(const DebugInfo *di) {
+    return di->kind() == Kind::Stabs;
+  }
+
+  const StabsList& stabs() const { return _stabs; }
+
+public:
+  StabsList _stabs;
+};
+
+} // end namespace mach_o
+} // end namespace lld
+
+#endif // LLD_READER_WRITER_MACHO_DEBUGINFO_H
+//===- lib/ReaderWriter/MachO/File.h ----------------------------*- C++ -*-===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_MACHO_DEBUGINFO_H
+#define LLD_READER_WRITER_MACHO_DEBUGINFO_H
+
+#include "lld/Core/Atom.h"
+#include <vector>
+
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+
+namespace lld {
+namespace mach_o {
+
+class DebugInfo {
+public:
+  enum class Kind {
+    Dwarf,
+    Stabs
+  };
+
+  Kind kind() const { return _kind; }
+
+protected:
+  DebugInfo(Kind kind) : _kind(kind) {}
+
+private:
+  Kind _kind;
+};
+
+
+struct TranslationUnitSource {
+  StringRef name;
+  StringRef path;
+};
+
+class DwarfDebugInfo : public DebugInfo {
+public:
+  DwarfDebugInfo(TranslationUnitSource tu)
+    : DebugInfo(Kind::Dwarf), _tu(std::move(tu)) {}
+
+  static inline bool classof(const DebugInfo *di) {
+    return di->kind() == Kind::Dwarf;
+  }
+
+  const TranslationUnitSource &translationUnitSource() const { return _tu; }
+
+private:
+  TranslationUnitSource _tu;
+};
+
+struct Stab {
+  Stab(const Atom* atom, uint8_t type, uint8_t other, uint16_t desc,
+       uint32_t value, StringRef str)
+    : atom(atom), type(type), other(other), desc(desc), value(value),
+      str(str) {}
+
+  const class Atom*   atom;
+  uint8_t             type;
+  uint8_t             other;
+  uint16_t            desc;
+  uint32_t            value;
+  StringRef           str;
+};
+
+inline raw_ostream& operator<<(raw_ostream &os, Stab &s) {
+  os << "Stab -- atom: " << llvm::format("%p", s.atom) << ", type: " << (uint32_t)s.type
+     << ", other: " << (uint32_t)s.other << ", desc: " << s.desc << ", value: " << s.value
+     << ", str: '" << s.str << "'";
+  return os;
+}
+
+class StabsDebugInfo : public DebugInfo {
+public:
+
+  typedef std::vector<Stab> StabsList;
+
+  StabsDebugInfo(StabsList stabs)
+    : DebugInfo(Kind::Stabs), _stabs(std::move(stabs)) {}
+
+  static inline bool classof(const DebugInfo *di) {
+    return di->kind() == Kind::Stabs;
+  }
+
+  const StabsList& stabs() const { return _stabs; }
+
+public:
+  StabsList _stabs;
+};
+
+} // end namespace mach_o
+} // end namespace lld
+
+#endif // LLD_READER_WRITER_MACHO_DEBUGINFO_H

Modified: lld/trunk/lib/ReaderWriter/MachO/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/File.h?rev=276921&r1=276920&r2=276921&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/File.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/File.h Wed Jul 27 16:31:25 2016
@@ -11,11 +11,13 @@
 #define LLD_READER_WRITER_MACHO_FILE_H
 
 #include "Atoms.h"
+#include "DebugInfo.h"
 #include "MachONormalizedFile.h"
 #include "lld/Core/SharedLibraryFile.h"
 #include "lld/Core/Simple.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Format.h"
 #include <unordered_map>
 
 namespace lld {
@@ -25,11 +27,15 @@ using lld::mach_o::normalized::Section;
 
 class MachOFile : public SimpleFile {
 public:
+
+  /// Real file constructor - for on-disk files.
   MachOFile(std::unique_ptr<MemoryBuffer> mb, MachOLinkingContext *ctx)
     : SimpleFile(mb->getBufferIdentifier(), File::kindMachObject),
       _mb(std::move(mb)), _ctx(ctx) {}
 
-  MachOFile(StringRef path) : SimpleFile(path, File::kindMachObject) {}
+  /// Dummy file constructor - for virtual files.
+  MachOFile(StringRef path)
+    : SimpleFile(path, File::kindMachObject) {}
 
   void addDefinedAtom(StringRef name, Atom::Scope scope,
                       DefinedAtom::ContentType type, DefinedAtom::Merge merge,
@@ -225,6 +231,13 @@ public:
     return F->kind() == File::kindMachObject;
   }
 
+  void setDebugInfo(std::unique_ptr<DebugInfo> debugInfo) {
+    _debugInfo = std::move(debugInfo);
+  }
+
+  DebugInfo* debugInfo() const { return _debugInfo.get(); }
+  std::unique_ptr<DebugInfo> takeDebugInfo() { return std::move(_debugInfo); }
+
 protected:
   std::error_code doParse() override {
     // Convert binary file to normalized mach-o.
@@ -265,6 +278,7 @@ private:
       MachOLinkingContext::objc_unknown;
   uint32_t                       _swiftVersion = 0;
   normalized::FileFlags        _flags = llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
+  std::unique_ptr<DebugInfo>   _debugInfo;
 };
 
 class MachODylibFile : public SharedLibraryFile {

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h?rev=276921&r1=276920&r2=276921&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h Wed Jul 27 16:31:25 2016
@@ -42,6 +42,7 @@
 #ifndef LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
 #define LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
 
+#include "DebugInfo.h"
 #include "lld/Core/Error.h"
 #include "lld/Core/LLVM.h"
 #include "lld/ReaderWriter/MachOLinkingContext.h"
@@ -91,8 +92,22 @@ struct Relocation {
   bool                isExtern;
   Hex32               value;
   uint32_t            symbol;
+
+#ifndef NDEBUG
+  raw_ostream& operator<<(raw_ostream &OS) const {
+    dump(OS);
+    return OS;
+  }
+
+  void dump(raw_ostream &OS = llvm::dbgs()) const;
+#endif
 };
 
+inline raw_ostream& operator<<(raw_ostream &OS, const Relocation &R) {
+  R.dump(OS);
+  return OS;
+}
+
 /// A typedef so that YAML I/O can treat this vector as a sequence.
 typedef std::vector<Relocation> Relocations;
 
@@ -226,7 +241,6 @@ struct DataInCode {
   DataRegionType  kind;
 };
 
-
 /// A typedef so that YAML I/O can encode/decode mach_header.flags.
 LLVM_YAML_STRONG_TYPEDEF(uint32_t, FileFlags)
 
@@ -242,6 +256,7 @@ struct NormalizedFile {
   std::vector<Symbol>         localSymbols;
   std::vector<Symbol>         globalSymbols;
   std::vector<Symbol>         undefinedSymbols;
+  std::vector<Symbol>         stabsSymbols;
 
   // Maps to load commands with no LINKEDIT content (final linked images only).
   std::vector<DependentDylib> dependentDylibs;

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp?rev=276921&r1=276920&r2=276921&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp Wed Jul 27 16:31:25 2016
@@ -390,12 +390,14 @@ readBinary(std::unique_ptr<MemoryBuffer>
           if (sin->n_strx > strSize)
             return true;
           sout.name  = &strings[sin->n_strx];
-          sout.type  = (NListType)(sin->n_type & N_TYPE);
+          sout.type = static_cast<NListType>(sin->n_type & (N_STAB|N_TYPE));
           sout.scope = (sin->n_type & (N_PEXT|N_EXT));
           sout.sect  = sin->n_sect;
           sout.desc  = sin->n_desc;
           sout.value = sin->n_value;
-          if (sout.type == N_UNDF)
+          if (sin->n_type & N_STAB)
+            f->stabsSymbols.push_back(sout);
+          else if (sout.type == N_UNDF)
             f->undefinedSymbols.push_back(sout);
           else if (sin->n_type & N_EXT)
             f->globalSymbols.push_back(sout);
@@ -429,6 +431,8 @@ readBinary(std::unique_ptr<MemoryBuffer>
             f->undefinedSymbols.push_back(sout);
           else if (sout.scope == (SymbolScope)N_EXT)
             f->globalSymbols.push_back(sout);
+          else if (sin->n_type & N_STAB)
+            f->stabsSymbols.push_back(sout);
           else
             f->localSymbols.push_back(sout);
         }
@@ -535,7 +539,7 @@ public:
   loadFile(std::unique_ptr<MemoryBuffer> mb,
            const Registry &registry) const override {
     std::unique_ptr<File> ret =
-        llvm::make_unique<MachOFile>(std::move(mb), &_ctx);
+      llvm::make_unique<MachOFile>(std::move(mb), &_ctx);
     return std::move(ret);
   }
 

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp?rev=276921&r1=276920&r2=276921&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp Wed Jul 27 16:31:25 2016
@@ -789,8 +789,8 @@ llvm::Error MachOFileLayout::writeLoadCo
     st->cmd     = LC_SYMTAB;
     st->cmdsize = sizeof(symtab_command);
     st->symoff  = _startOfSymbols;
-    st->nsyms   = _file.localSymbols.size() + _file.globalSymbols.size()
-                                            + _file.undefinedSymbols.size();
+    st->nsyms   = _file.stabsSymbols.size() + _file.localSymbols.size() +
+                  _file.globalSymbols.size() + _file.undefinedSymbols.size();
     st->stroff  = _startOfSymbolStrings;
     st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
     if (_swap)
@@ -876,8 +876,8 @@ llvm::Error MachOFileLayout::writeLoadCo
     st->cmd     = LC_SYMTAB;
     st->cmdsize = sizeof(symtab_command);
     st->symoff  = _startOfSymbols;
-    st->nsyms   = _file.localSymbols.size() + _file.globalSymbols.size()
-                                            + _file.undefinedSymbols.size();
+    st->nsyms   = _file.stabsSymbols.size() + _file.localSymbols.size() +
+                  _file.globalSymbols.size() + _file.undefinedSymbols.size();
     st->stroff  = _startOfSymbolStrings;
     st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
     if (_swap)
@@ -890,7 +890,8 @@ llvm::Error MachOFileLayout::writeLoadCo
       dst->cmd            = LC_DYSYMTAB;
       dst->cmdsize        = sizeof(dysymtab_command);
       dst->ilocalsym      = _symbolTableLocalsStartIndex;
-      dst->nlocalsym      = _file.localSymbols.size();
+      dst->nlocalsym      = _file.stabsSymbols.size() +
+                            _file.localSymbols.size();
       dst->iextdefsym     = _symbolTableGlobalsStartIndex;
       dst->nextdefsym     = _file.globalSymbols.size();
       dst->iundefsym      = _symbolTableUndefinesStartIndex;
@@ -1102,6 +1103,7 @@ void MachOFileLayout::writeSymbolTable()
   uint32_t symOffset = _startOfSymbols;
   uint32_t strOffset = _startOfSymbolStrings;
   _buffer[strOffset++] = '\0'; // Reserve n_strx offset of zero to mean no name.
+  appendSymbols(_file.stabsSymbols, symOffset, strOffset);
   appendSymbols(_file.localSymbols, symOffset, strOffset);
   appendSymbols(_file.globalSymbols, symOffset, strOffset);
   appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
@@ -1414,10 +1416,14 @@ void MachOFileLayout::buildExportTrie()
 void MachOFileLayout::computeSymbolTableSizes() {
   // MachO symbol tables have three ranges: locals, globals, and undefines
   const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
-  _symbolTableSize = nlistSize * (_file.localSymbols.size()
+  _symbolTableSize = nlistSize * (_file.stabsSymbols.size()
+                                + _file.localSymbols.size()
                                 + _file.globalSymbols.size()
                                 + _file.undefinedSymbols.size());
   _symbolStringPoolSize = 1; // Always reserve 1-byte for the empty string.
+  for (const Symbol &sym : _file.stabsSymbols) {
+    _symbolStringPoolSize += (sym.name.size()+1);
+  }
   for (const Symbol &sym : _file.localSymbols) {
     _symbolStringPoolSize += (sym.name.size()+1);
   }
@@ -1428,7 +1434,8 @@ void MachOFileLayout::computeSymbolTable
     _symbolStringPoolSize += (sym.name.size()+1);
   }
   _symbolTableLocalsStartIndex = 0;
-  _symbolTableGlobalsStartIndex = _file.localSymbols.size();
+  _symbolTableGlobalsStartIndex = _file.stabsSymbols.size() +
+                                  _file.localSymbols.size();
   _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
                                     + _file.globalSymbols.size();
 

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp?rev=276921&r1=276920&r2=276921&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp Wed Jul 27 16:31:25 2016
@@ -22,6 +22,7 @@
 
 #include "MachONormalizedFile.h"
 #include "ArchHandler.h"
+#include "DebugInfo.h"
 #include "MachONormalizedFileBinaryUtils.h"
 #include "lld/Core/Error.h"
 #include "lld/Core/LLVM.h"
@@ -34,6 +35,7 @@
 #include "llvm/Support/MachO.h"
 #include <map>
 #include <system_error>
+#include <unordered_set>
 
 using llvm::StringRef;
 using llvm::isa;
@@ -120,6 +122,7 @@ public:
   void      copySectionInfo(NormalizedFile &file);
   void      updateSectionInfo(NormalizedFile &file);
   void      buildAtomToAddressMap();
+  llvm::Error synthesizeDebugNotes(NormalizedFile &file);
   llvm::Error addSymbols(const lld::File &atomFile, NormalizedFile &file);
   void      addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file);
   void      addRebaseAndBindingInfo(const lld::File &, NormalizedFile &file);
@@ -201,6 +204,7 @@ private:
   bool                          _allSourceFilesHaveMinVersions = true;
   LoadCommandType               _minVersionCommandType = (LoadCommandType)0;
   uint32_t                      _minVersion = 0;
+  std::vector<lld::mach_o::Stab> _stabs;
 };
 
 Util::~Util() {
@@ -785,6 +789,156 @@ void Util::buildAtomToAddressMap() {
   }
 }
 
+llvm::Error Util::synthesizeDebugNotes(NormalizedFile &file) {
+
+  // Bail out early if we don't need to generate a debug map.
+  if (_ctx.debugInfoMode() == MachOLinkingContext::DebugInfoMode::noDebugMap)
+    return llvm::Error::success();
+
+  std::vector<const DefinedAtom*> atomsNeedingDebugNotes;
+  std::set<const mach_o::MachOFile*> filesWithStabs;
+  bool objFileHasDwarf = false;
+  const File *objFile = nullptr;
+
+  for (SectionInfo *sect : _sectionInfos) {
+    for (const AtomInfo &info : sect->atomsAndOffsets) {
+      if (const DefinedAtom *atom = dyn_cast<DefinedAtom>(info.atom)) {
+
+        // FIXME: No stabs/debug-notes for symbols that wouldn't be in the
+        //        symbol table.
+        // FIXME: No stabs/debug-notes for kernel dtrace probes.
+
+        if (atom->contentType() == DefinedAtom::typeCFI ||
+            atom->contentType() == DefinedAtom::typeCString)
+          continue;
+
+        // Whenever we encounter a new file, update the 'objfileHasDwarf' flag.
+        if (&info.atom->file() != objFile) {
+          objFileHasDwarf = false;
+          if (const mach_o::MachOFile *atomFile =
+              dyn_cast<mach_o::MachOFile>(&info.atom->file())) {
+            if (atomFile->debugInfo()) {
+              if (isa<mach_o::DwarfDebugInfo>(atomFile->debugInfo()))
+                objFileHasDwarf = true;
+              else if (isa<mach_o::StabsDebugInfo>(atomFile->debugInfo()))
+                filesWithStabs.insert(atomFile);
+            }
+          }
+        }
+
+        // If this atom is from a file that needs dwarf, add it to the list.
+        if (objFileHasDwarf)
+          atomsNeedingDebugNotes.push_back(info.atom);
+      }
+    }
+  }
+
+  // Sort atoms needing debug notes by file ordinal, then atom ordinal.
+  std::sort(atomsNeedingDebugNotes.begin(), atomsNeedingDebugNotes.end(),
+            [](const DefinedAtom *lhs, const DefinedAtom *rhs) {
+              if (lhs->file().ordinal() != rhs->file().ordinal())
+                return (lhs->file().ordinal() < rhs->file().ordinal());
+              return (lhs->ordinal() < rhs->ordinal());
+            });
+
+  // FIXME: Handle <rdar://problem/17689030>: Add -add_ast_path option to \
+  //        linker which add N_AST stab entry to output
+  // See OutputFile::synthesizeDebugNotes in ObjectFile.cpp in ld64.
+
+  StringRef oldFileName = "";
+  StringRef oldDirPath = "";
+  bool wroteStartSO = false;
+  std::unordered_set<std::string> seenFiles;
+  for (const DefinedAtom *atom : atomsNeedingDebugNotes) {
+    const auto &atomFile = cast<mach_o::MachOFile>(atom->file());
+    assert(dyn_cast_or_null<lld::mach_o::DwarfDebugInfo>(atomFile.debugInfo())
+           && "file for atom needing debug notes does not contain dwarf");
+    auto &dwarf = cast<lld::mach_o::DwarfDebugInfo>(*atomFile.debugInfo());
+
+    auto &tu = dwarf.translationUnitSource();
+    StringRef newFileName = tu.name;
+    StringRef newDirPath = tu.path;
+
+    // Add an SO whenever the TU source file changes.
+    if (newFileName != oldFileName || newDirPath != oldDirPath) {
+      // Translation unit change, emit ending SO
+      if (oldFileName != "")
+        _stabs.push_back(mach_o::Stab(nullptr, N_SO, 1, 0, 0, ""));
+
+      oldFileName = newFileName;
+      oldDirPath = newDirPath;
+
+      // If newDirPath doesn't end with a '/' we need to add one:
+      if (newDirPath.back() != '/') {
+        std::string *p = file.ownedAllocations.Allocate<std::string>();
+        new (p) std::string();
+        *p = (newDirPath + "/").str();
+        newDirPath = *p;
+      }
+
+      // New translation unit, emit start SOs:
+      _stabs.push_back(mach_o::Stab(nullptr, N_SO, 0, 0, 0, newDirPath));
+      _stabs.push_back(mach_o::Stab(nullptr, N_SO, 0, 0, 0, newFileName));
+
+      // Synthesize OSO for start of file.
+      std::string *fullPath = file.ownedAllocations.Allocate<std::string>();
+      new (fullPath) std::string();
+      {
+        SmallString<1024> pathBuf(atomFile.path());
+        if (auto EC = llvm::sys::fs::make_absolute(pathBuf))
+          return llvm::errorCodeToError(EC);
+        *fullPath = pathBuf.str();
+      }
+
+      // Get mod time.
+      uint32_t modTime = 0;
+      llvm::sys::fs::file_status stat;
+      if (!llvm::sys::fs::status(*fullPath, stat))
+        if (llvm::sys::fs::exists(stat))
+          modTime = stat.getLastModificationTime().toEpochTime();
+
+      _stabs.push_back(mach_o::Stab(nullptr, N_OSO, _ctx.getCPUSubType(), 1,
+                                    modTime, *fullPath));
+      // <rdar://problem/6337329> linker should put cpusubtype in n_sect field
+      // of nlist entry for N_OSO debug note entries.
+      wroteStartSO = true;
+    }
+
+    if (atom->contentType() == DefinedAtom::typeCode) {
+      // Synthesize BNSYM and start FUN stabs.
+      _stabs.push_back(mach_o::Stab(atom, N_BNSYM, 1, 0, 0, ""));
+      _stabs.push_back(mach_o::Stab(atom, N_FUN, 1, 0, 0, atom->name()));
+      // Synthesize any SOL stabs needed
+      // FIXME: add SOL stabs.
+      _stabs.push_back(mach_o::Stab(nullptr, N_FUN, 0, 0,
+                                    atom->rawContent().size(), ""));
+      _stabs.push_back(mach_o::Stab(nullptr, N_ENSYM, 1, 0,
+                                    atom->rawContent().size(), ""));
+    } else {
+      if (atom->scope() == Atom::scopeTranslationUnit)
+        _stabs.push_back(mach_o::Stab(atom, N_STSYM, 1, 0, 0, atom->name()));
+      else
+        _stabs.push_back(mach_o::Stab(nullptr, N_GSYM, 1, 0, 0, atom->name()));
+    }
+  }
+
+  // Emit ending SO if necessary.
+  if (wroteStartSO)
+    _stabs.push_back(mach_o::Stab(nullptr, N_SO, 1, 0, 0, ""));
+
+  // Copy any stabs from .o file.
+  for (const auto *objFile : filesWithStabs) {
+    const auto &stabsList =
+      cast<mach_o::StabsDebugInfo>(objFile->debugInfo())->stabs();
+    for (auto &stab : stabsList) {
+      // FIXME: Drop stabs whose atoms have been dead-stripped.
+      _stabs.push_back(stab);
+    }
+  }
+
+  return llvm::Error::success();
+}
+
 uint16_t Util::descBits(const DefinedAtom* atom) {
   uint16_t desc = 0;
   switch (atom->merge()) {
@@ -868,10 +1022,27 @@ llvm::Error Util::getSymbolTableRegion(c
   llvm_unreachable("atom->scope() unknown enum value");
 }
 
+
+
 llvm::Error Util::addSymbols(const lld::File &atomFile,
                              NormalizedFile &file) {
   bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
-  // Mach-O symbol table has three regions: locals, globals, undefs.
+  // Mach-O symbol table has four regions: stabs, locals, globals, undefs.
+
+  // Add all stabs.
+  for (auto &stab : _stabs) {
+    Symbol sym;
+    sym.type = static_cast<NListType>(stab.type);
+    sym.scope = 0;
+    sym.sect = stab.other;
+    sym.desc = stab.desc;
+    if (stab.atom)
+      sym.value = _atomToAddress[stab.atom];
+    else
+      sym.value = stab.value;
+    sym.name = stab.str;
+    file.stabsSymbols.push_back(sym);
+  }
 
   // Add all local (non-global) symbols in address order
   std::vector<AtomAndIndex> globals;
@@ -1404,6 +1575,8 @@ normalizedFromAtoms(const lld::File &ato
   util.copySectionInfo(normFile);
   util.assignAddressesToSections(normFile);
   util.buildAtomToAddressMap();
+  if (auto err = util.synthesizeDebugNotes(normFile))
+    return std::move(err);
   util.updateSectionInfo(normFile);
   util.copySectionContent(normFile);
   if (auto ec = util.addSymbols(atomFile, normFile)) {

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp?rev=276921&r1=276920&r2=276921&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp Wed Jul 27 16:31:25 2016
@@ -27,7 +27,11 @@
 #include "MachONormalizedFileBinaryUtils.h"
 #include "lld/Core/Error.h"
 #include "lld/Core/LLVM.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/Support/DataExtractor.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/MachO.h"
 #include "llvm/Support/LEB128.h"
@@ -499,7 +503,7 @@ const Section* findSectionCoveringAddres
 
 const MachODefinedAtom *
 findAtomCoveringAddress(const NormalizedFile &normalizedFile, MachOFile &file,
-                        uint64_t addr, Reference::Addend *addend) {
+                        uint64_t addr, Reference::Addend &addend) {
   const Section *sect = nullptr;
   sect = findSectionCoveringAddress(normalizedFile, addr);
   if (!sect)
@@ -509,7 +513,7 @@ findAtomCoveringAddress(const Normalized
   uint64_t offsetInSect = addr - sect->address;
   auto atom =
       file.findAtomCoveringAddress(*sect, offsetInSect, &offsetInTarget);
-  *addend = offsetInTarget;
+  addend = offsetInTarget;
   return atom;
 }
 
@@ -548,19 +552,23 @@ llvm::Error convertRelocs(const Section
                            -> llvm::Error {
     // Find symbol from index.
     const Symbol *sym = nullptr;
+    uint32_t numStabs  = normalizedFile.stabsSymbols.size();
     uint32_t numLocal  = normalizedFile.localSymbols.size();
     uint32_t numGlobal = normalizedFile.globalSymbols.size();
     uint32_t numUndef  = normalizedFile.undefinedSymbols.size();
-    if (symbolIndex < numLocal) {
-      sym = &normalizedFile.localSymbols[symbolIndex];
-    } else if (symbolIndex < numLocal+numGlobal) {
-      sym = &normalizedFile.globalSymbols[symbolIndex-numLocal];
-    } else if (symbolIndex < numLocal+numGlobal+numUndef) {
-      sym = &normalizedFile.undefinedSymbols[symbolIndex-numLocal-numGlobal];
+    assert(symbolIndex >= numStabs && "Searched for stab via atomBySymbol?");
+    if (symbolIndex < numStabs+numLocal) {
+      sym = &normalizedFile.localSymbols[symbolIndex-numStabs];
+    } else if (symbolIndex < numStabs+numLocal+numGlobal) {
+      sym = &normalizedFile.globalSymbols[symbolIndex-numStabs-numLocal];
+    } else if (symbolIndex < numStabs+numLocal+numGlobal+numUndef) {
+      sym = &normalizedFile.undefinedSymbols[symbolIndex-numStabs-numLocal-
+                                             numGlobal];
     } else {
       return llvm::make_error<GenericError>(Twine("symbol index (")
                                      + Twine(symbolIndex) + ") out of range");
     }
+
     // Find atom from symbol.
     if ((sym->type & N_TYPE) == N_SECT) {
       if (sym->sect > normalizedFile.sections.size())
@@ -685,6 +693,296 @@ bool isDebugInfoSection(const Section &s
   return section.segmentName.equals("__DWARF");
 }
 
+static const Atom* findDefinedAtomByName(MachOFile &file, Twine name) {
+  std::string strName = name.str();
+  for (auto *atom : file.defined())
+    if (atom->name() == strName)
+      return atom;
+  return nullptr;
+}
+
+static StringRef copyDebugString(StringRef str, BumpPtrAllocator &alloc) {
+  std::string *strCopy = alloc.Allocate<std::string>();
+  *strCopy = str;
+  return *strCopy;
+}
+
+llvm::Error parseStabs(MachOFile &file,
+                       const NormalizedFile &normalizedFile,
+                       bool copyRefs) {
+
+  if (normalizedFile.stabsSymbols.empty())
+    return llvm::Error::success();
+
+  // FIXME: Kill this off when we can move to sane yaml parsing.
+  std::unique_ptr<BumpPtrAllocator> allocator;
+  if (copyRefs)
+    allocator = llvm::make_unique<BumpPtrAllocator>();
+
+  enum { start, inBeginEnd } state = start;
+
+  const Atom *currentAtom = nullptr;
+  uint64_t currentAtomAddress = 0;
+  StabsDebugInfo::StabsList stabsList;
+  for (const auto &stabSym : normalizedFile.stabsSymbols) {
+    Stab stab(nullptr, stabSym.type, stabSym.sect, stabSym.desc,
+              stabSym.value, stabSym.name);
+    switch (state) {
+    case start:
+      switch (static_cast<StabType>(stabSym.type)) {
+      case N_BNSYM:
+        state = inBeginEnd;
+        currentAtomAddress = stabSym.value;
+        Reference::Addend addend;
+        currentAtom = findAtomCoveringAddress(normalizedFile, file,
+                                              currentAtomAddress, addend);
+        if (addend != 0)
+          return llvm::make_error<GenericError>(
+                   "Non-zero addend for BNSYM '" + stabSym.name + "' in " +
+                   file.path());
+        if (currentAtom)
+          stab.atom = currentAtom;
+        else {
+          // FIXME: ld64 just issues a warning here - should we match that?
+          return llvm::make_error<GenericError>(
+                   "can't find atom for stabs BNSYM at " +
+                   Twine::utohexstr(stabSym.value) + " in " + file.path());
+        }
+        break;
+      case N_SO:
+      case N_OSO:
+        // Not associated with an atom, just copy.
+        if (copyRefs)
+          stab.str = copyDebugString(stabSym.name, *allocator);
+        else
+          stab.str = stabSym.name;
+        break;
+      case N_GSYM: {
+        auto colonIdx = stabSym.name.find(':');
+        if (colonIdx != StringRef::npos) {
+          StringRef name = stabSym.name.substr(0, colonIdx);
+          currentAtom = findDefinedAtomByName(file, "_" + name);
+          stab.atom = currentAtom;
+          if (copyRefs)
+            stab.str = copyDebugString(stabSym.name, *allocator);
+          else
+            stab.str = stabSym.name;
+        } else {
+          currentAtom = findDefinedAtomByName(file, stabSym.name);
+          stab.atom = currentAtom;
+          if (copyRefs)
+            stab.str = copyDebugString(stabSym.name, *allocator);
+          else
+            stab.str = stabSym.name;
+        }
+        if (stab.atom == nullptr)
+          return llvm::make_error<GenericError>(
+                   "can't find atom for N_GSYM stabs" + stabSym.name +
+                   " in " + file.path());
+        break;
+      }
+      case N_FUN:
+        return llvm::make_error<GenericError>(
+                 "old-style N_FUN stab '" + stabSym.name + "' unsupported");
+      default:
+        return llvm::make_error<GenericError>(
+                 "unrecognized stab symbol '" + stabSym.name + "'");
+      }
+      break;
+    case inBeginEnd:
+      stab.atom = currentAtom;
+      switch (static_cast<StabType>(stabSym.type)) {
+      case N_ENSYM:
+        state = start;
+        currentAtom = nullptr;
+        break;
+      case N_FUN:
+        // Just copy the string.
+        if (copyRefs)
+          stab.str = copyDebugString(stabSym.name, *allocator);
+        else
+          stab.str = stabSym.name;
+        break;
+      default:
+        return llvm::make_error<GenericError>(
+                 "unrecognized stab symbol '" + stabSym.name + "'");
+      }
+    }
+    llvm::dbgs() << "Adding to stabsList: " << stab << "\n";
+    stabsList.push_back(stab);
+  }
+
+  file.setDebugInfo(llvm::make_unique<StabsDebugInfo>(std::move(stabsList)));
+
+  // FIXME: Kill this off when we fix YAML memory ownership.
+  file.debugInfo()->setAllocator(std::move(allocator));
+
+  return llvm::Error::success();
+}
+
+static llvm::DataExtractor
+dataExtractorFromSection(const NormalizedFile &normalizedFile,
+                         const Section &S) {
+  const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
+  const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
+  StringRef SecData(reinterpret_cast<const char*>(S.content.data()),
+                    S.content.size());
+  return llvm::DataExtractor(SecData, !isBig, is64 ? 8 : 4);
+}
+
+// FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
+//        inspection" code if possible.
+static uint32_t getCUAbbrevOffset(llvm::DataExtractor abbrevData,
+                                  uint64_t abbrCode) {
+  uint64_t curCode;
+  uint32_t offset = 0;
+  while ((curCode = abbrevData.getULEB128(&offset)) != abbrCode) {
+    // Tag
+    abbrevData.getULEB128(&offset);
+    // DW_CHILDREN
+    abbrevData.getU8(&offset);
+    // Attributes
+    while (abbrevData.getULEB128(&offset) | abbrevData.getULEB128(&offset))
+      ;
+  }
+  return offset;
+}
+
+// FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
+//        inspection" code if possible.
+static Expected<const char *>
+getIndexedString(const NormalizedFile &normalizedFile,
+                 uint32_t form, llvm::DataExtractor infoData,
+                 uint32_t &infoOffset, const Section &stringsSection) {
+  if (form == llvm::dwarf::DW_FORM_string)
+   return infoData.getCStr(&infoOffset);
+  if (form != llvm::dwarf::DW_FORM_strp)
+    return llvm::make_error<GenericError>(
+        "string field encoded without DW_FORM_strp");
+  uint32_t stringOffset = infoData.getU32(&infoOffset);
+  llvm::DataExtractor stringsData =
+    dataExtractorFromSection(normalizedFile, stringsSection);
+  return stringsData.getCStr(&stringOffset);
+}
+
+// FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
+//        inspection" code if possible.
+static llvm::Expected<TranslationUnitSource>
+readCompUnit(const NormalizedFile &normalizedFile,
+             const Section &info,
+             const Section &abbrev,
+             const Section &strings,
+             StringRef path) {
+  // FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
+  //        inspection" code if possible.
+  uint32_t offset = 0;
+  auto infoData = dataExtractorFromSection(normalizedFile, info);
+  uint32_t length = infoData.getU32(&offset);
+  if (length == 0xffffffff)
+    infoData.getU64(&offset);
+  else if (length > 0xffffff00)
+    return llvm::make_error<GenericError>("Malformed DWARF in " + path);
+
+  uint16_t version = infoData.getU16(&offset);
+
+  if (version < 2 || version > 4)
+    return llvm::make_error<GenericError>("Unsupported DWARF version in " +
+                                          path);
+
+  infoData.getU32(&offset); // Abbrev offset (should be zero)
+  uint8_t addrSize = infoData.getU8(&offset);
+
+  uint32_t abbrCode = infoData.getULEB128(&offset);
+  auto abbrevData = dataExtractorFromSection(normalizedFile, abbrev);
+  uint32_t abbrevOffset = getCUAbbrevOffset(abbrevData, abbrCode);
+  uint64_t tag = abbrevData.getULEB128(&abbrevOffset);
+  if (tag != llvm::dwarf::DW_TAG_compile_unit)
+    return llvm::make_error<GenericError>("top level DIE is not a compile unit");
+  // DW_CHILDREN
+  abbrevData.getU8(&abbrevOffset);
+  uint32_t name;
+  uint32_t form;
+  TranslationUnitSource tu;
+  while ((name = abbrevData.getULEB128(&abbrevOffset)) |
+             (form = abbrevData.getULEB128(&abbrevOffset)) &&
+         (name != 0 || form != 0)) {
+    switch (name) {
+    case llvm::dwarf::DW_AT_name: {
+      if (auto eName = getIndexedString(normalizedFile, form, infoData, offset,
+                                        strings))
+          tu.name = *eName;
+      else
+        return eName.takeError();
+      break;
+    }
+    case llvm::dwarf::DW_AT_comp_dir: {
+      if (auto eName = getIndexedString(normalizedFile, form, infoData, offset,
+                                        strings))
+        tu.path = *eName;
+      else
+        return eName.takeError();
+      break;
+    }
+    default:
+      llvm::DWARFFormValue::skipValue(form, infoData, &offset, version,
+                                      addrSize);
+    }
+  }
+  return tu;
+}
+
+llvm::Error parseDebugInfo(MachOFile &file,
+                           const NormalizedFile &normalizedFile, bool copyRefs) {
+
+  // Find the interesting debug info sections.
+  const Section *debugInfo = nullptr;
+  const Section *debugAbbrev = nullptr;
+  const Section *debugStrings = nullptr;
+
+  for (auto &s : normalizedFile.sections) {
+    if (s.segmentName == "__DWARF") {
+      if (s.sectionName == "__debug_info")
+        debugInfo = &s;
+      else if (s.sectionName == "__debug_abbrev")
+        debugAbbrev = &s;
+      else if (s.sectionName == "__debug_str")
+        debugStrings = &s;
+    }
+  }
+
+  if (!debugInfo)
+    return parseStabs(file, normalizedFile, copyRefs);
+
+  if (debugInfo->content.size() == 0)
+    return llvm::Error::success();
+
+  if (debugInfo->content.size() < 12)
+    return llvm::make_error<GenericError>("Malformed __debug_info section in " +
+                                          file.path() + ": too small");
+
+  if (!debugAbbrev)
+    return llvm::make_error<GenericError>("Missing __dwarf_abbrev section in " +
+                                          file.path());
+
+  if (auto tuOrErr = readCompUnit(normalizedFile, *debugInfo, *debugAbbrev,
+                                  *debugStrings, file.path())) {
+    // FIXME: Kill of allocator and code under 'copyRefs' when we fix YAML
+    //        memory ownership.
+    std::unique_ptr<BumpPtrAllocator> allocator;
+    if (copyRefs) {
+      allocator = llvm::make_unique<BumpPtrAllocator>();
+      tuOrErr->name = copyDebugString(tuOrErr->name, *allocator);
+      tuOrErr->path = copyDebugString(tuOrErr->path, *allocator);
+    }
+    file.setDebugInfo(llvm::make_unique<DwarfDebugInfo>(std::move(*tuOrErr)));
+    if (copyRefs)
+      file.debugInfo()->setAllocator(std::move(allocator));
+  } else
+    return tuOrErr.takeError();
+
+  return llvm::Error::success();
+}
+
 static int64_t readSPtr(bool is64, bool isBig, const uint8_t *addr) {
   if (is64)
     return read64(addr, isBig);
@@ -853,7 +1151,7 @@ static llvm::Error processCIE(const Norm
       const MachODefinedAtom *func = nullptr;
       Reference::Addend addend;
       func = findAtomCoveringAddress(normalizedFile, file, funcAddress,
-                                     &addend);
+                                     addend);
       atom->addReference(Reference::KindNamespace::mach_o, handler.kindArch(),
                          handler.unwindRefToPersonalityFunctionKind(),
                          PersonalityFunctionField, func, addend);
@@ -936,7 +1234,7 @@ static llvm::Error processFDE(const Norm
     }
     Reference::Addend addend;
     auto *target = findAtomCoveringAddress(normalizedFile, file,
-                                           targetAddress, &addend);
+                                           targetAddress, addend);
     atom->addReference(Reference::KindNamespace::mach_o, handler.kindArch(),
                        refKind, refAddress, target, addend);
 
@@ -1095,7 +1393,6 @@ llvm::Error parseObjCImageInfo(const Sec
   return llvm::Error();
 }
 
-
 /// Converts normalized mach-o file into an lld::File and lld::Atoms.
 llvm::Expected<std::unique_ptr<lld::File>>
 objectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
@@ -1136,10 +1433,11 @@ normalizedObjectToAtoms(MachOFile *file,
   // Create atoms from each section.
   for (auto &sect : normalizedFile.sections) {
     DEBUG(llvm::dbgs() << "Creating atoms: "; sect.dump());
+
+    // If this is a debug-info section parse it specially.
     if (isDebugInfoSection(sect))
       continue;
 
-
     // If the file contains an objc_image_info struct, then we should parse the
     // ObjC flags and Swift version.
     if (isObjCImageInfo(sect)) {
@@ -1248,6 +1546,10 @@ normalizedObjectToAtoms(MachOFile *file,
   for (const DefinedAtom* defAtom : file->defined()) {
     reinterpret_cast<const SimpleDefinedAtom*>(defAtom)->sortReferences();
   }
+
+  if (auto err = parseDebugInfo(*file, normalizedFile, copyRefs))
+    return err;
+
   return llvm::Error();
 }
 
@@ -1325,6 +1627,13 @@ normalizedToAtoms(const NormalizedFile &
 }
 
 #ifndef NDEBUG
+void Relocation::dump(llvm::raw_ostream &OS) const {
+  OS << "Relocation (offset=" << llvm::format_hex(offset, 8, true)
+     << ", scatered=" << scattered << ", type=" << type << ", length=" << length
+     << ", pcrel=" << pcRel << ", isExtern=" << isExtern << ", value="
+     << llvm::format_hex(value, 8, true) << ", symbol=" << symbol << ")\n";
+}
+
 void Section::dump(llvm::raw_ostream &OS) const {
   OS << "Section (\"" << segmentName << ", " << sectionName << "\"";
   OS << ", addr: " << llvm::format_hex(address, 16, true);

Added: lld/trunk/test/mach-o/debug-syms.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/debug-syms.yaml?rev=276921&view=auto
==============================================================================
--- lld/trunk/test/mach-o/debug-syms.yaml (added)
+++ lld/trunk/test/mach-o/debug-syms.yaml Wed Jul 27 16:31:25 2016
@@ -0,0 +1,249 @@
+# RUN: lld -flavor darwin -arch x86_64 -o %t %s -lSystem && \
+# RUN:   llvm-nm -no-sort -debug-syms %t | FileCheck %s
+
+# CHECK:      0000000000000000 - 00 0000    SO /Users/lhames/Projects/lld/lld-svn-tot/scratch/
+# CHECK-NEXT: 0000000000000000 - 00 0000    SO hw.c
+# CHECK-NEXT:    {{[0-9a-f]+}} - 03 0001   OSO {{.*}}/test/mach-o/debug-syms.yaml
+# CHECK-NEXT: 0000000100000fa0 - 01 0000 BNSYM 
+# CHECK-NEXT: 0000000100000fa0 - 01 0000   FUN _main
+# CHECK-NEXT: 0000000000000016 - 00 0000   FUN 
+# CHECK-NEXT: 0000000000000016 - 01 0000 ENSYM 
+# CHECK-NEXT: 0000000000000000 - 01 0000    SO 
+
+--- !mach-o
+arch:            x86_64
+file-type:       MH_OBJECT
+flags:           [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+compat-version:  0.0
+current-version: 0.0
+has-UUID:        false
+OS:              unknown
+min-os-version-kind: LC_VERSION_MIN_MACOSX
+sections:        
+  - segment:         __TEXT
+    section:         __text
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+    alignment:       16
+    address:         0x0000000000000000
+    content:         [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0xC7, 0x45, 
+                       0xFC, 0x00, 0x00, 0x00, 0x00, 0x89, 0x7D, 0xF8, 
+                       0x48, 0x89, 0x75, 0xF0, 0x5D, 0xC3 ]
+  - segment:         __DWARF
+    section:         __debug_str
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_DEBUG ]
+    address:         0x0000000000000016
+    content:         [ 0x41, 0x70, 0x70, 0x6C, 0x65, 0x20, 0x4C, 0x4C, 
+                       0x56, 0x4D, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 
+                       0x6F, 0x6E, 0x20, 0x38, 0x2E, 0x30, 0x2E, 0x30, 
+                       0x20, 0x28, 0x63, 0x6C, 0x61, 0x6E, 0x67, 0x2D, 
+                       0x38, 0x30, 0x30, 0x2E, 0x30, 0x2E, 0x32, 0x34, 
+                       0x2E, 0x31, 0x29, 0x00, 0x68, 0x77, 0x2E, 0x63, 
+                       0x00, 0x2F, 0x55, 0x73, 0x65, 0x72, 0x73, 0x2F, 
+                       0x6C, 0x68, 0x61, 0x6D, 0x65, 0x73, 0x2F, 0x50, 
+                       0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x73, 0x2F, 
+                       0x6C, 0x6C, 0x64, 0x2F, 0x6C, 0x6C, 0x64, 0x2D, 
+                       0x73, 0x76, 0x6E, 0x2D, 0x74, 0x6F, 0x74, 0x2F, 
+                       0x73, 0x63, 0x72, 0x61, 0x74, 0x63, 0x68, 0x00, 
+                       0x6D, 0x61, 0x69, 0x6E, 0x00, 0x69, 0x6E, 0x74, 
+                       0x00, 0x61, 0x72, 0x67, 0x63, 0x00, 0x61, 0x72, 
+                       0x67, 0x76, 0x00, 0x63, 0x68, 0x61, 0x72, 0x00 ]
+  - segment:         __DWARF
+    section:         __debug_loc
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_DEBUG ]
+    address:         0x000000000000008E
+  - segment:         __DWARF
+    section:         __debug_abbrev
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_DEBUG ]
+    address:         0x000000000000008E
+    content:         [ 0x01, 0x11, 0x01, 0x25, 0x0E, 0x13, 0x05, 0x03, 
+                       0x0E, 0x10, 0x06, 0x1B, 0x0E, 0x11, 0x01, 0x12, 
+                       0x01, 0x00, 0x00, 0x02, 0x2E, 0x01, 0x11, 0x01, 
+                       0x12, 0x01, 0x40, 0x0A, 0x03, 0x0E, 0x3A, 0x0B, 
+                       0x3B, 0x0B, 0x27, 0x0C, 0x49, 0x13, 0x3F, 0x0C, 
+                       0x00, 0x00, 0x03, 0x05, 0x00, 0x02, 0x0A, 0x03, 
+                       0x0E, 0x3A, 0x0B, 0x3B, 0x0B, 0x49, 0x13, 0x00, 
+                       0x00, 0x04, 0x24, 0x00, 0x03, 0x0E, 0x3E, 0x0B, 
+                       0x0B, 0x0B, 0x00, 0x00, 0x05, 0x0F, 0x00, 0x49, 
+                       0x13, 0x00, 0x00, 0x00 ]
+  - segment:         __DWARF
+    section:         __debug_info
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_DEBUG ]
+    address:         0x00000000000000DA
+    content:         [ 0x7F, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 
+                       0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 
+                       0x0C, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 
+                       0x56, 0x60, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 
+                       0x6A, 0x00, 0x00, 0x00, 0x01, 0x03, 0x02, 0x91, 
+                       0x78, 0x69, 0x00, 0x00, 0x00, 0x01, 0x01, 0x6A, 
+                       0x00, 0x00, 0x00, 0x03, 0x02, 0x91, 0x70, 0x6E, 
+                       0x00, 0x00, 0x00, 0x01, 0x01, 0x71, 0x00, 0x00, 
+                       0x00, 0x00, 0x04, 0x65, 0x00, 0x00, 0x00, 0x05, 
+                       0x04, 0x05, 0x76, 0x00, 0x00, 0x00, 0x05, 0x7B, 
+                       0x00, 0x00, 0x00, 0x04, 0x73, 0x00, 0x00, 0x00, 
+                       0x06, 0x01, 0x00 ]
+    relocations:     
+      - offset:          0x00000037
+        type:            X86_64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          1
+      - offset:          0x0000002F
+        type:            X86_64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          1
+      - offset:          0x00000026
+        type:            X86_64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          1
+      - offset:          0x0000001E
+        type:            X86_64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          1
+  - segment:         __DWARF
+    section:         __debug_ranges
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_DEBUG ]
+    address:         0x000000000000015D
+  - segment:         __DWARF
+    section:         __debug_macinfo
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_DEBUG ]
+    address:         0x000000000000015D
+    content:         [ 0x00 ]
+  - segment:         __DWARF
+    section:         __apple_names
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_DEBUG ]
+    address:         0x000000000000015E
+    content:         [ 0x48, 0x53, 0x41, 0x48, 0x01, 0x00, 0x00, 0x00, 
+                       0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
+                       0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 
+                       0x00, 0x00, 0x00, 0x00, 0x6A, 0x7F, 0x9A, 0x7C, 
+                       0x2C, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 
+                       0x01, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 
+                       0x00, 0x00, 0x00, 0x00 ]
+  - segment:         __DWARF
+    section:         __apple_objc
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_DEBUG ]
+    address:         0x000000000000019A
+    content:         [ 0x48, 0x53, 0x41, 0x48, 0x01, 0x00, 0x00, 0x00, 
+                       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 
+                       0xFF, 0xFF, 0xFF, 0xFF ]
+  - segment:         __DWARF
+    section:         __apple_namespac
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_DEBUG ]
+    address:         0x00000000000001BE
+    content:         [ 0x48, 0x53, 0x41, 0x48, 0x01, 0x00, 0x00, 0x00, 
+                       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 
+                       0xFF, 0xFF, 0xFF, 0xFF ]
+  - segment:         __DWARF
+    section:         __apple_types
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_DEBUG ]
+    address:         0x00000000000001E2
+    content:         [ 0x48, 0x53, 0x41, 0x48, 0x01, 0x00, 0x00, 0x00, 
+                       0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 
+                       0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 
+                       0x03, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0B, 0x00, 
+                       0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
+                       0x30, 0x80, 0x88, 0x0B, 0x63, 0x20, 0x95, 0x7C, 
+                       0x40, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 
+                       0x65, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
+                       0x6A, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 
+                       0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x01, 
+                       0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x24, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+  - segment:         __DWARF
+    section:         __apple_exttypes
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_DEBUG ]
+    address:         0x0000000000000248
+    content:         [ 0x48, 0x53, 0x41, 0x48, 0x01, 0x00, 0x00, 0x00, 
+                       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x06, 0x00, 
+                       0xFF, 0xFF, 0xFF, 0xFF ]
+  - segment:         __LD
+    section:         __compact_unwind
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_DEBUG ]
+    alignment:       8
+    address:         0x0000000000000270
+    content:         [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+    relocations:     
+      - offset:          0x00000000
+        type:            X86_64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          1
+  - segment:         __TEXT
+    section:         __eh_frame
+    type:            S_COALESCED
+    attributes:      [  ]
+    alignment:       8
+    address:         0x0000000000000290
+    content:         [ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x01, 0x7A, 0x52, 0x00, 0x01, 0x78, 0x10, 0x01, 
+                       0x10, 0x0C, 0x07, 0x08, 0x90, 0x01, 0x00, 0x00, 
+                       0x24, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 
+                       0x50, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+                       0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x00, 0x41, 0x0E, 0x10, 0x86, 0x02, 0x43, 0x0D, 
+                       0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+  - segment:         __DWARF
+    section:         __debug_line
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_DEBUG ]
+    address:         0x00000000000002D0
+    content:         [ 0x37, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1B, 0x00, 
+                       0x00, 0x00, 0x01, 0x01, 0xFB, 0x0E, 0x0D, 0x00, 
+                       0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 
+                       0x00, 0x00, 0x01, 0x00, 0x68, 0x77, 0x2E, 0x63, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x01, 0x05, 0x03, 0x0A, 0x08, 0x3D, 0x02, 0x02, 
+                       0x00, 0x01, 0x01 ]
+    relocations:     
+      - offset:          0x00000028
+        type:            X86_64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          1
+global-symbols:  
+  - name:            _main
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000000
+page-size:       0x00000000
+...




More information about the llvm-commits mailing list