[lld] r209704 - [mach-o] Support parsing of non-lazy-pointer sections

Nick Kledzik kledzik at apple.com
Tue May 27 18:16:36 PDT 2014


Author: kledzik
Date: Tue May 27 20:16:35 2014
New Revision: 209704

URL: http://llvm.org/viewvc/llvm-project?rev=209704&view=rev
Log:
[mach-o] Support parsing of non-lazy-pointer sections

Added:
    lld/trunk/test/mach-o/parse-non-lazy-pointers.yaml
Modified:
    lld/trunk/lib/Core/SymbolTable.cpp
    lld/trunk/lib/ReaderWriter/MachO/Atoms.h
    lld/trunk/lib/ReaderWriter/MachO/File.h
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp

Modified: lld/trunk/lib/Core/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/SymbolTable.cpp?rev=209704&r1=209703&r2=209704&view=diff
==============================================================================
--- lld/trunk/lib/Core/SymbolTable.cpp (original)
+++ lld/trunk/lib/Core/SymbolTable.cpp Tue May 27 20:16:35 2014
@@ -49,7 +49,10 @@ bool SymbolTable::add(const DefinedAtom
   if (atom.merge() == DefinedAtom::mergeByContent) {
     // Named atoms cannot be merged by content.
     assert(atom.name().empty());
-    return addByContent(atom);
+    // Currently only read-only constants can be merged.
+    if (atom.permissions() == DefinedAtom::permR__)
+      return addByContent(atom);
+    // TODO: support mergeByContent of data atoms by comparing content & fixups.
   }
   return false;
 }
@@ -338,8 +341,6 @@ bool SymbolTable::AtomMappingInfo::isEqu
 }
 
 bool SymbolTable::addByContent(const DefinedAtom &newAtom) {
-  // Currently only read-only constants can be merged.
-  assert(newAtom.permissions() == DefinedAtom::permR__);
   AtomContentSet::iterator pos = _contentTable.find(&newAtom);
   if (pos == _contentTable.end()) {
     _contentTable.insert(&newAtom);

Modified: lld/trunk/lib/ReaderWriter/MachO/Atoms.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/Atoms.h?rev=209704&r1=209703&r2=209704&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/Atoms.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/Atoms.h Tue May 27 20:16:35 2014
@@ -17,16 +17,18 @@ namespace mach_o {
 class MachODefinedAtom : public SimpleDefinedAtom {
 public:
   MachODefinedAtom(const File &f, const StringRef name, Scope scope,
-                   ContentType type, const ArrayRef<uint8_t> content)
+                   ContentType type, Merge merge,
+                   const ArrayRef<uint8_t> content)
       : SimpleDefinedAtom(f), _name(name), _content(content),
-        _contentType(type), _scope(scope) {}
+        _contentType(type), _scope(scope), _merge(merge) {}
 
   // Constructor for zero-fill content
   MachODefinedAtom(const File &f, const StringRef name, Scope scope,
                    uint64_t size)
       : SimpleDefinedAtom(f), _name(name),
         _content(ArrayRef<uint8_t>(nullptr, size)),
-        _contentType(DefinedAtom::typeZeroFill), _scope(scope) {}
+        _contentType(DefinedAtom::typeZeroFill),
+        _scope(scope), _merge(mergeNo) {}
 
   uint64_t size() const override { return _content.size(); }
 
@@ -36,6 +38,8 @@ public:
 
   Scope scope() const override { return _scope; }
 
+  Merge merge() const override { return _merge; }
+
   DeadStripKind deadStrip() const override {
     if (_contentType == DefinedAtom::typeInitializerPtr)
       return deadStripNever;
@@ -55,6 +59,7 @@ private:
   const ArrayRef<uint8_t> _content;
   const ContentType _contentType;
   const Scope _scope;
+  const Merge _merge;
 };
 
 

Modified: lld/trunk/lib/ReaderWriter/MachO/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/File.h?rev=209704&r1=209703&r2=209704&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/File.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/File.h Tue May 27 20:16:35 2014
@@ -22,7 +22,7 @@ public:
   MachOFile(StringRef path) : SimpleFile(path) {}
 
   void addDefinedAtom(StringRef name, Atom::Scope scope,
-                      DefinedAtom::ContentType type,
+                      DefinedAtom::ContentType type, DefinedAtom::Merge merge,
                       ArrayRef<uint8_t> content, bool copyRefs) {
     if (copyRefs) {
       // Make a copy of the atom's name and content that is owned by this file.
@@ -30,7 +30,8 @@ public:
       content = content.copy(_allocator);
     }
     MachODefinedAtom *atom =
-        new (_allocator) MachODefinedAtom(*this, name, scope, type, content);
+        new (_allocator) MachODefinedAtom(*this, name, scope, type, merge,
+                                          content);
     addAtom(*atom);
   }
 

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp?rev=209704&r1=209703&r2=209704&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp Tue May 27 20:16:35 2014
@@ -91,6 +91,24 @@ appendRelocations(Relocations &relocs, S
   return error_code::success();
 }
 
+static error_code
+appendIndirectSymbols(IndirectSymbols &isyms, StringRef buffer, bool swap,
+                      bool bigEndian, uint32_t istOffset, uint32_t istCount,
+                      uint32_t startIndex, uint32_t count) {
+  if ((istOffset + istCount*4) > buffer.size())
+    return llvm::make_error_code(llvm::errc::executable_format_error);
+  if (startIndex+count  > istCount)
+    return llvm::make_error_code(llvm::errc::executable_format_error);
+  const uint32_t *indirectSymbolArray =
+            reinterpret_cast<const uint32_t*>(buffer.begin()+istOffset);
+
+  for(uint32_t i=0; i < count; ++i) {
+    isyms.push_back(read32(swap, indirectSymbolArray[startIndex+i]));
+  }
+  return error_code::success();
+}
+
+
 template <typename T> static T readBigEndian(T t) {
   if (llvm::sys::IsLittleEndianHost)
     return SwapByteOrder(t);
@@ -185,9 +203,25 @@ readBinary(std::unique_ptr<MemoryBuffer>
   f->flags = smh->flags;
 
 
-  // Walk load commands looking for segments/sections and the symbol table.
+  // Pre-scan load commands looking for indirect symbol table.
+  uint32_t indirectSymbolTableOffset = 0;
+  uint32_t indirectSymbolTableCount = 0;
   error_code ec = forEachLoadCommand(lcRange, lcCount, swap, is64,
                     [&] (uint32_t cmd, uint32_t size, const char* lc) -> bool {
+    if (cmd == LC_DYSYMTAB) {
+      const dysymtab_command *d = reinterpret_cast<const dysymtab_command*>(lc);
+      indirectSymbolTableOffset = read32(swap, d->indirectsymoff);
+      indirectSymbolTableCount = read32(swap, d->nindirectsyms);
+      return true;
+    }
+    return false;
+  });
+  if (ec)
+    return ec;
+
+  // Walk load commands looking for segments/sections and the symbol table.
+  ec = forEachLoadCommand(lcRange, lcCount, swap, is64,
+                    [&] (uint32_t cmd, uint32_t size, const char* lc) -> bool {
     if (is64) {
       if (cmd == LC_SEGMENT_64) {
         const segment_command_64 *seg =
@@ -220,6 +254,13 @@ readBinary(std::unique_ptr<MemoryBuffer>
           appendRelocations(section.relocations, mb->getBuffer(),
                             swap, isBigEndianArch, read32(swap, sect->reloff),
                                                    read32(swap, sect->nreloc));
+          if (section.type == S_NON_LAZY_SYMBOL_POINTERS) {
+            appendIndirectSymbols(section.indirectSymbols, mb->getBuffer(),
+                                  swap, isBigEndianArch,
+                                  indirectSymbolTableOffset,
+                                  indirectSymbolTableCount,
+                                  read32(swap, sect->reserved1), contentSize/4);
+          }
           f->sections.push_back(section);
         }
       }
@@ -255,6 +296,13 @@ readBinary(std::unique_ptr<MemoryBuffer>
           appendRelocations(section.relocations, mb->getBuffer(),
                             swap, isBigEndianArch, read32(swap, sect->reloff),
                                                    read32(swap, sect->nreloc));
+          if (section.type == S_NON_LAZY_SYMBOL_POINTERS) {
+            appendIndirectSymbols(section.indirectSymbols, mb->getBuffer(),
+                                  swap, isBigEndianArch,
+                                  indirectSymbolTableOffset,
+                                  indirectSymbolTableCount,
+                                  read32(swap, sect->reserved1), contentSize/4);
+          }
           f->sections.push_back(section);
         }
       }
@@ -328,10 +376,7 @@ readBinary(std::unique_ptr<MemoryBuffer>
             f->localSymbols.push_back(sout);
         }
       }
-    } else if (cmd == LC_DYSYMTAB) {
-      // TODO: indirect symbols
     }
-
     return false;
   });
   if (ec)

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp?rev=209704&r1=209703&r2=209704&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp Tue May 27 20:16:35 2014
@@ -92,7 +92,8 @@ static void processSymbol(const Normaliz
   } else {
     ArrayRef<uint8_t> atomContent = section.content.slice(offset, size);
     file.addDefinedAtom(sym.name, atomScope(sym.scope),
-                        atomTypeFromSection(section), atomContent, copyRefs);
+                        atomTypeFromSection(section), DefinedAtom::mergeNo,
+                        atomContent, copyRefs);
   }
 }
 
@@ -125,7 +126,8 @@ static error_code processSection(MachOFi
           unsigned size = i - offset + 2;
           ArrayRef<uint8_t> utf16Content = section.content.slice(offset, size);
           file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit,
-                              DefinedAtom::typeUTF16String, utf16Content, 
+                              DefinedAtom::typeUTF16String,
+                              DefinedAtom::mergeByContent, utf16Content,
                               copyRefs);
           offset = i + 2;
         }
@@ -139,9 +141,10 @@ static error_code processSection(MachOFi
                                        "terminated."); 
       }
     }
+    break;
   case llvm::MachO::S_COALESCED:
   case llvm::MachO::S_ZEROFILL:
-    // These sections are broken in to atoms based on symbols.
+    // These sections are broken into atoms based on symbols.
     break;
   case S_MOD_INIT_FUNC_POINTERS:
     if ((section.content.size() % pointerSize) != 0) {
@@ -156,7 +159,8 @@ static error_code processSection(MachOFi
     for (size_t i = 0, e = section.content.size(); i != e; i += pointerSize) {
       ArrayRef<uint8_t> bytes = section.content.slice(offset, pointerSize);
       file.addDefinedAtom(StringRef(), DefinedAtom::scopeTranslationUnit,
-                          DefinedAtom::typeInitializerPtr, bytes, copyRefs);
+                          DefinedAtom::typeInitializerPtr, DefinedAtom::mergeNo,
+                          bytes, copyRefs);
       offset += pointerSize;
     }
     break;
@@ -173,7 +177,26 @@ static error_code processSection(MachOFi
     for (size_t i = 0, e = section.content.size(); i != e; i += pointerSize) {
       ArrayRef<uint8_t> bytes = section.content.slice(offset, pointerSize);
       file.addDefinedAtom(StringRef(), DefinedAtom::scopeTranslationUnit,
-                          DefinedAtom::typeTerminatorPtr, bytes, copyRefs);
+                          DefinedAtom::typeTerminatorPtr, DefinedAtom::mergeNo,
+                          bytes, copyRefs);
+      offset += pointerSize;
+    }
+    break;
+  case S_NON_LAZY_SYMBOL_POINTERS:
+    if ((section.content.size() % pointerSize) != 0) {
+      return make_dynamic_error_code(Twine("Section ") + section.segmentName
+                                     + "/" + section.sectionName
+                                     + " has type S_NON_LAZY_SYMBOL_POINTERS "
+                                     "but its size ("
+                                     + Twine(section.content.size())
+                                     + ") is not a multiple of "
+                                     + Twine(pointerSize));
+    }
+    for (size_t i = 0, e = section.content.size(); i != e; i += pointerSize) {
+      ArrayRef<uint8_t> bytes = section.content.slice(offset, pointerSize);
+      file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit,
+                          DefinedAtom::typeGOT, DefinedAtom::mergeByContent,
+                          bytes, copyRefs);
       offset += pointerSize;
     }
     break;
@@ -183,7 +206,8 @@ static error_code processSection(MachOFi
         unsigned size = i - offset + 1;
         ArrayRef<uint8_t> strContent = section.content.slice(offset, size);
         file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit,
-                            DefinedAtom::typeCString, strContent, copyRefs);
+                            DefinedAtom::typeCString,
+                            DefinedAtom::mergeByContent, strContent, copyRefs);
         offset = i + 1;
       }
     }
@@ -205,7 +229,8 @@ static error_code processSection(MachOFi
     for (size_t i = 0, e = section.content.size(); i != e; i += 4) {
       ArrayRef<uint8_t> byteContent = section.content.slice(offset, 4);
       file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit,
-                          DefinedAtom::typeLiteral4, byteContent, copyRefs);
+                          DefinedAtom::typeLiteral4,
+                          DefinedAtom::mergeByContent, byteContent, copyRefs);
       offset += 4;
     }
     break;
@@ -219,7 +244,8 @@ static error_code processSection(MachOFi
     for (size_t i = 0, e = section.content.size(); i != e; i += 8) {
       ArrayRef<uint8_t> byteContent = section.content.slice(offset, 8);
       file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit,
-                          DefinedAtom::typeLiteral8, byteContent, copyRefs);
+                          DefinedAtom::typeLiteral8,
+                          DefinedAtom::mergeByContent, byteContent, copyRefs);
       offset += 8;
     }
     break;
@@ -233,7 +259,8 @@ static error_code processSection(MachOFi
     for (size_t i = 0, e = section.content.size(); i != e; i += 16) {
       ArrayRef<uint8_t> byteContent = section.content.slice(offset, 16);
       file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit,
-                          DefinedAtom::typeLiteral16, byteContent, copyRefs);
+                          DefinedAtom::typeLiteral16,
+                          DefinedAtom::mergeByContent, byteContent, copyRefs);
       offset += 16;
     }
     break;
@@ -248,7 +275,7 @@ static ErrorOr<std::unique_ptr<lld::File
 normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
                         bool copyRefs) {
   std::unique_ptr<MachOFile> file(new MachOFile(path));
-  
+
   // Create atoms from global symbols.
   for (const Symbol &sym : normalizedFile.globalSymbols) {
     processSymbol(normalizedFile, *file, sym, copyRefs);

Added: lld/trunk/test/mach-o/parse-non-lazy-pointers.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/parse-non-lazy-pointers.yaml?rev=209704&view=auto
==============================================================================
--- lld/trunk/test/mach-o/parse-non-lazy-pointers.yaml (added)
+++ lld/trunk/test/mach-o/parse-non-lazy-pointers.yaml Tue May 27 20:16:35 2014
@@ -0,0 +1,89 @@
+# RUN: lld -flavor darwin -arch i386 -r -print_atoms %s -o %t  | FileCheck %s
+#
+# Test parsing of non-lazy-pointer sections.
+#
+
+--- !mach-o
+arch:            x86
+file-type:       MH_OBJECT
+flags:           [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+has-UUID:        false
+OS:              unknown
+sections:
+  - segment:         __TEXT
+    section:         __text
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+    address:         0x0000000000000000
+    content:         [ 0x55, 0x89, 0xE5, 0xE8, 0x00, 0x00, 0x00, 0x00,
+                       0x59, 0x8D, 0x81, 0x14, 0x00, 0x00, 0x00, 0x8D,
+                       0x81, 0x18, 0x00, 0x00, 0x00, 0x5D, 0xC3, 0x55,
+                       0x89, 0xE5, 0x5D, 0xC3 ]
+    relocations:
+      - offset:          0x00000011
+        scattered:       true
+        type:            GENERIC_RELOC_LOCAL_SECTDIFF
+        length:          2
+        pc-rel:          false
+        value:           0x00000020
+      - offset:          0x00000000
+        scattered:       true
+        type:            GENERIC_RELOC_PAIR
+        length:          2
+        pc-rel:          false
+        value:           0x00000008
+      - offset:          0x0000000B
+        scattered:       true
+        type:            GENERIC_RELOC_LOCAL_SECTDIFF
+        length:          2
+        pc-rel:          false
+        value:           0x0000001C
+      - offset:          0x00000000
+        scattered:       true
+        type:            GENERIC_RELOC_PAIR
+        length:          2
+        pc-rel:          false
+        value:           0x00000008
+  - segment:         __IMPORT
+    section:         __pointers
+    type:            S_NON_LAZY_SYMBOL_POINTERS
+    attributes:      [  ]
+    address:         0x000000000000001C
+    content:         [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+    indirect-syms:   [ 2, 2147483648 ]
+local-symbols:
+  - name:            _foo
+    type:            N_SECT
+    sect:            1
+    value:           0x0000000000000017
+global-symbols:
+  - name:            _get
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000000
+undefined-symbols:
+  - name:            _bar
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+...
+
+
+# CHECK:defined-atoms:
+# CHECK:  - scope:           hidden
+# CHECK:    type:            got
+# CHECK:    content:         [ 00, 00, 00, 00 ]
+# CHECK:    merge:           by-content
+# CHECK:  - scope:           hidden
+# CHECK:    type:            got
+# CHECK:    content:         [ 00, 00, 00, 00 ]
+# CHECK:    merge:           by-content
+# CHECK:  - name:            _get
+# CHECK:    scope:           global
+# CHECK:    content:         [ 55, 89, E5, E8, 00, 00, 00, 00, 59, 8D, 81, 14,
+# CHECK:                       00, 00, 00, 8D, 81, 18, 00, 00, 00, 5D, C3 ]
+# CHECK:  - name:            _foo
+# CHECK:    content:         [ 55, 89, E5, 5D, C3 ]
+
+





More information about the llvm-commits mailing list