[llvm] r271611 - [yaml2obj] Sort MachO LinkEdit write operations based on offset

Chris Bieneman via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 2 16:54:20 PDT 2016


Author: cbieneman
Date: Thu Jun  2 18:52:08 2016
New Revision: 271611

URL: http://llvm.org/viewvc/llvm-project?rev=271611&view=rev
Log:
[yaml2obj] Sort MachO LinkEdit write operations based on offset

Although ld64 always outputs linkedit data in the same order, it isn't actually required to. This change makes yaml2obj resilient if the offsets are in arbitrary order.

Added:
    llvm/trunk/test/ObjectYAML/MachO/out_of_order_linkedit.yaml
Modified:
    llvm/trunk/tools/yaml2obj/yaml2macho.cpp

Added: llvm/trunk/test/ObjectYAML/MachO/out_of_order_linkedit.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/MachO/out_of_order_linkedit.yaml?rev=271611&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/MachO/out_of_order_linkedit.yaml (added)
+++ llvm/trunk/test/ObjectYAML/MachO/out_of_order_linkedit.yaml Thu Jun  2 18:52:08 2016
@@ -0,0 +1,266 @@
+# RUN: yaml2obj -format=macho %s | obj2yaml | FileCheck %s
+
+--- !mach-o
+FileHeader:      
+  magic:           0xFEEDFACF
+  cputype:         0x01000007
+  cpusubtype:      0x80000003
+  filetype:        0x00000002
+  ncmds:           16
+  sizeofcmds:      1408
+  flags:           0x00218085
+  reserved:        0x00000000
+LoadCommands:    
+  - 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:         552
+    segname:         __TEXT
+    vmaddr:          4294967296
+    vmsize:          8192
+    fileoff:         0
+    filesize:        8192
+    maxprot:         7
+    initprot:        5
+    nsects:          6
+    flags:           0
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         312
+    segname:         __DATA
+    vmaddr:          4294975488
+    vmsize:          4096
+    fileoff:         8192
+    filesize:        4096
+    maxprot:         7
+    initprot:        3
+    nsects:          3
+    flags:           0
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         72
+    segname:         __LINKEDIT
+    vmaddr:          4294979584
+    vmsize:          4096
+    fileoff:         12288
+    filesize:        2508
+    maxprot:         7
+    initprot:        1
+    nsects:          0
+    flags:           0
+  - cmd:             LC_DYLD_INFO_ONLY
+    cmdsize:         48
+    rebase_off:      12384
+    rebase_size:     8
+    bind_off:        12288
+    bind_size:       96
+    weak_bind_off:   0
+    weak_bind_size:  0
+    lazy_bind_off:   12392
+    lazy_bind_size:  624
+    export_off:      13016
+    export_size:     48
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          13080
+    nsyms:           30
+    stroff:          13700
+    strsize:         1096
+  - cmd:             LC_DYSYMTAB
+    cmdsize:         80
+    ilocalsym:       0
+    nlocalsym:       9
+    iextdefsym:      9
+    nextdefsym:      2
+    iundefsym:       11
+    nundefsym:       19
+    tocoff:          0
+    ntoc:            0
+    modtaboff:       0
+    nmodtab:         0
+    extrefsymoff:    0
+    nextrefsyms:     0
+    indirectsymoff:  13560
+    nindirectsyms:   35
+    extreloff:       0
+    nextrel:         0
+    locreloff:       0
+    nlocrel:         0
+  - cmd:             LC_LOAD_DYLINKER
+    cmdsize:         32
+    name:            12
+    PayloadString:   /usr/lib/dyld
+    ZeroPadBytes:    7
+  - cmd:             LC_UUID
+    cmdsize:         24
+    uuid:            461A1B28-822F-3F38-B670-645419E636F5
+  - cmd:             LC_VERSION_MIN_MACOSX
+    cmdsize:         16
+    version:         658176
+    sdk:             658176
+  - cmd:             LC_SOURCE_VERSION
+    cmdsize:         16
+    version:         0
+  - cmd:             LC_MAIN
+    cmdsize:         24
+    entryoff:        4448
+    stacksize:       0
+  - cmd:             LC_LOAD_DYLIB
+    cmdsize:         48
+    dylib:           
+      name:            24
+      timestamp:       2
+      current_version: 7864576
+      compatibility_version: 65536
+    PayloadString:   '/usr/lib/libc++.1.dylib'
+    ZeroPadBytes:    1
+  - cmd:             LC_LOAD_DYLIB
+    cmdsize:         56
+    dylib:           
+      name:            24
+      timestamp:       2
+      current_version: 80349697
+      compatibility_version: 65536
+    PayloadString:   /usr/lib/libSystem.B.dylib
+    ZeroPadBytes:    6
+  - cmd:             LC_FUNCTION_STARTS
+    cmdsize:         16
+    dataoff:         13064
+    datasize:        16
+  - cmd:             LC_DATA_IN_CODE
+    cmdsize:         16
+    dataoff:         13080
+    datasize:        0
+LinkEditData:    
+  RebaseOpcodes:   
+    - Opcode:          REBASE_OPCODE_SET_TYPE_IMM
+      Imm:             1
+    - Opcode:          REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
+      Imm:             2
+      ExtraData:       
+        - 0x0000000000000028
+    - Opcode:          REBASE_OPCODE_DO_REBASE_ULEB_TIMES
+      Imm:             0
+      ExtraData:       
+        - 0x000000000000000F
+    - Opcode:          REBASE_OPCODE_DONE
+      Imm:             0
+  BindOpcodes:     
+    - Opcode:          BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
+      Imm:             1
+      Symbol:          ''
+    - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
+      Imm:             0
+      Symbol:          __ZNSt3__14coutE
+    - Opcode:          BIND_OPCODE_SET_TYPE_IMM
+      Imm:             1
+      Symbol:          ''
+    - Opcode:          BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
+      Imm:             2
+      ULEBExtraData:   
+        - 0x0000000000000000
+      Symbol:          ''
+    - Opcode:          BIND_OPCODE_DO_BIND
+      Imm:             0
+      Symbol:          ''
+    - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
+      Imm:             0
+      Symbol:          __ZNSt3__15ctypeIcE2idE
+    - Opcode:          BIND_OPCODE_DO_BIND
+      Imm:             0
+      Symbol:          ''
+    - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
+      Imm:             0
+      Symbol:          ___gxx_personality_v0
+    - Opcode:          BIND_OPCODE_DO_BIND
+      Imm:             0
+      Symbol:          ''
+    - Opcode:          BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
+      Imm:             2
+      Symbol:          ''
+    - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
+      Imm:             0
+      Symbol:          dyld_stub_binder
+    - Opcode:          BIND_OPCODE_DO_BIND
+      Imm:             0
+      Symbol:          ''
+    - Opcode:          BIND_OPCODE_DONE
+      Imm:             0
+      Symbol:          ''
+...
+
+#CHECK:   - cmd:             LC_DYLD_INFO_ONLY
+#CHECK:     cmdsize:         48
+#CHECK:     rebase_off:      12384
+#CHECK:     rebase_size:     8
+#CHECK:     bind_off:        12288
+#CHECK:     bind_size:       96
+#CHECK:     weak_bind_off:   0
+#CHECK:     weak_bind_size:  0
+#CHECK:     lazy_bind_off:   12392
+#CHECK:     lazy_bind_size:  624
+#CHECK:     export_off:      13016
+#CHECK:     export_size:     48
+#CHECK: LinkEditData:    
+#CHECK:   RebaseOpcodes:   
+#CHECK:     - Opcode:          REBASE_OPCODE_SET_TYPE_IMM
+#CHECK:       Imm:             1
+#CHECK:     - Opcode:          REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
+#CHECK:       Imm:             2
+#CHECK:       ExtraData:       
+#CHECK:         - 0x0000000000000028
+#CHECK:     - Opcode:          REBASE_OPCODE_DO_REBASE_ULEB_TIMES
+#CHECK:       Imm:             0
+#CHECK:       ExtraData:       
+#CHECK:         - 0x000000000000000F
+#CHECK:     - Opcode:          REBASE_OPCODE_DONE
+#CHECK:       Imm:             0
+#CHECK:   BindOpcodes:     
+#CHECK:     - Opcode:          BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
+#CHECK:       Imm:             1
+#CHECK:       Symbol:          ''
+#CHECK:     - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
+#CHECK:       Imm:             0
+#CHECK:       Symbol:          __ZNSt3__14coutE
+#CHECK:     - Opcode:          BIND_OPCODE_SET_TYPE_IMM
+#CHECK:       Imm:             1
+#CHECK:       Symbol:          ''
+#CHECK:     - Opcode:          BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
+#CHECK:       Imm:             2
+#CHECK:       ULEBExtraData:   
+#CHECK:         - 0x0000000000000000
+#CHECK:       Symbol:          ''
+#CHECK:     - Opcode:          BIND_OPCODE_DO_BIND
+#CHECK:       Imm:             0
+#CHECK:       Symbol:          ''
+#CHECK:     - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
+#CHECK:       Imm:             0
+#CHECK:       Symbol:          __ZNSt3__15ctypeIcE2idE
+#CHECK:     - Opcode:          BIND_OPCODE_DO_BIND
+#CHECK:       Imm:             0
+#CHECK:       Symbol:          ''
+#CHECK:     - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
+#CHECK:       Imm:             0
+#CHECK:       Symbol:          ___gxx_personality_v0
+#CHECK:     - Opcode:          BIND_OPCODE_DO_BIND
+#CHECK:       Imm:             0
+#CHECK:       Symbol:          ''
+#CHECK:     - Opcode:          BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
+#CHECK:       Imm:             2
+#CHECK:       Symbol:          ''
+#CHECK:     - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
+#CHECK:       Imm:             0
+#CHECK:       Symbol:          dyld_stub_binder
+#CHECK:     - Opcode:          BIND_OPCODE_DO_BIND
+#CHECK:       Imm:             0
+#CHECK:       Symbol:          ''
+#CHECK:     - Opcode:          BIND_OPCODE_DONE
+#CHECK:       Imm:             0
+#CHECK:       Symbol:          ''

Modified: llvm/trunk/tools/yaml2obj/yaml2macho.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/yaml2obj/yaml2macho.cpp?rev=271611&r1=271610&r2=271611&view=diff
==============================================================================
--- llvm/trunk/tools/yaml2obj/yaml2macho.cpp (original)
+++ llvm/trunk/tools/yaml2obj/yaml2macho.cpp Thu Jun  2 18:52:08 2016
@@ -46,8 +46,15 @@ private:
   Error writeLoadCommands(raw_ostream &OS);
   Error writeSectionData(raw_ostream &OS);
   Error writeLinkEditData(raw_ostream &OS);
-  void writeBindOpcodes(raw_ostream &OS, uint64_t offset,
+  void writeBindOpcodes(raw_ostream &OS,
                         std::vector<MachOYAML::BindOpcode> &BindOpcodes);
+  // LinkEdit writers
+  Error writeRebaseOpcodes(raw_ostream &OS);
+  Error writeBasicBindOpcodes(raw_ostream &OS);
+  Error writeWeakBindOpcodes(raw_ostream &OS);
+  Error writeLazyBindOpcodes(raw_ostream &OS);
+  Error writeNameList(raw_ostream &OS);
+  Error writeStringTable(raw_ostream &OS);
   Error writeExportTrie(raw_ostream &OS);
 
   void dumpExportEntry(raw_ostream &OS, MachOYAML::ExportEntry &Entry);
@@ -275,9 +282,7 @@ Error MachOWriter::writeSectionData(raw_
 }
 
 void MachOWriter::writeBindOpcodes(
-    raw_ostream &OS, uint64_t offset,
-    std::vector<MachOYAML::BindOpcode> &BindOpcodes) {
-  ZeroToOffset(OS, offset);
+    raw_ostream &OS, std::vector<MachOYAML::BindOpcode> &BindOpcodes) {
 
   for (auto Opcode : BindOpcodes) {
     uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
@@ -337,21 +342,55 @@ void writeNListEntry(MachOYAML::NListEnt
 }
 
 Error MachOWriter::writeLinkEditData(raw_ostream &OS) {
-  MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit;
+  typedef Error (MachOWriter::*writeHandler)(raw_ostream &);
+  typedef std::pair<uint64_t, writeHandler> writeOperation;
+  std::vector<writeOperation> WriteQueue;
+
   MachO::dyld_info_command *DyldInfoOnlyCmd = 0;
   MachO::symtab_command *SymtabCmd = 0;
   for (auto &LC : Obj.LoadCommands) {
     switch (LC.Data.load_command_data.cmd) {
     case MachO::LC_SYMTAB:
       SymtabCmd = &LC.Data.symtab_command_data;
+      WriteQueue.push_back(
+          std::make_pair(SymtabCmd->symoff, &MachOWriter::writeNameList));
+      WriteQueue.push_back(
+          std::make_pair(SymtabCmd->stroff, &MachOWriter::writeStringTable));
       break;
     case MachO::LC_DYLD_INFO_ONLY:
       DyldInfoOnlyCmd = &LC.Data.dyld_info_command_data;
+      WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->rebase_off,
+                                          &MachOWriter::writeRebaseOpcodes));
+      WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->bind_off,
+                                          &MachOWriter::writeBasicBindOpcodes));
+      WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->weak_bind_off,
+                                          &MachOWriter::writeWeakBindOpcodes));
+      WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->lazy_bind_off,
+                                          &MachOWriter::writeLazyBindOpcodes));
+      WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->export_off,
+                                          &MachOWriter::writeExportTrie));
       break;
     }
   }
 
-  ZeroToOffset(OS, DyldInfoOnlyCmd->rebase_off);
+  std::sort(
+      WriteQueue.begin(), WriteQueue.end(),
+      [](writeOperation &a, writeOperation &b) { return a.first < b.first; });
+
+  for (auto writeOp : WriteQueue) {
+    ZeroToOffset(OS, writeOp.first);
+    if (auto Err = (this->*writeOp.second)(OS))
+      return Err;
+  }
+
+  // Fill to the end of the string table
+  ZeroToOffset(OS, SymtabCmd->stroff + SymtabCmd->strsize);
+
+  return Error::success();
+}
+
+Error MachOWriter::writeRebaseOpcodes(raw_ostream &OS) {
+  MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit;
 
   for (auto Opcode : LinkEdit.RebaseOpcodes) {
     uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
@@ -360,38 +399,39 @@ Error MachOWriter::writeLinkEditData(raw
       encodeULEB128(Data, OS);
     }
   }
+  return Error::success();
+}
 
-  writeBindOpcodes(OS, DyldInfoOnlyCmd->bind_off, LinkEdit.BindOpcodes);
-  writeBindOpcodes(OS, DyldInfoOnlyCmd->weak_bind_off,
-                   LinkEdit.WeakBindOpcodes);
-  writeBindOpcodes(OS, DyldInfoOnlyCmd->lazy_bind_off,
-                   LinkEdit.LazyBindOpcodes);
+Error MachOWriter::writeBasicBindOpcodes(raw_ostream &OS) {
+  writeBindOpcodes(OS, Obj.LinkEdit.BindOpcodes);
+  return Error::success();
+}
 
-  ZeroToOffset(OS, DyldInfoOnlyCmd->export_off);
-  if (auto Err = writeExportTrie(OS))
-    return Err;
+Error MachOWriter::writeWeakBindOpcodes(raw_ostream &OS) {
+  writeBindOpcodes(OS, Obj.LinkEdit.WeakBindOpcodes);
+  return Error::success();
+}
 
-  ZeroToOffset(OS, SymtabCmd->symoff);
-  
-  for (auto NLE : LinkEdit.NameList) {
+Error MachOWriter::writeLazyBindOpcodes(raw_ostream &OS) {
+  writeBindOpcodes(OS, Obj.LinkEdit.LazyBindOpcodes);
+  return Error::success();
+}
+
+Error MachOWriter::writeNameList(raw_ostream &OS) {
+  for (auto NLE : Obj.LinkEdit.NameList) {
     if (is64Bit)
       writeNListEntry<MachO::nlist_64>(NLE, OS);
     else
       writeNListEntry<MachO::nlist>(NLE, OS);
   }
+  return Error::success();
+}
 
-  auto currOffset = OS.tell() - fileStart;
-  if (currOffset < SymtabCmd->stroff)
-    Fill(OS, SymtabCmd->stroff - currOffset, 0xDEADBEEFu);
-
-  for (auto Str : LinkEdit.StringTable) {
+Error MachOWriter::writeStringTable(raw_ostream &OS) {
+  for (auto Str : Obj.LinkEdit.StringTable) {
     OS.write(Str.data(), Str.size());
     OS.write('\0');
   }
-
-  // Fill to the end of the string table
-  ZeroToOffset(OS, SymtabCmd->stroff + SymtabCmd->strsize);
-
   return Error::success();
 }
 




More information about the llvm-commits mailing list