[llvm] r270901 - [obj2yaml][yaml2obj] Support for MachO bind opcodes

Chris Bieneman via llvm-commits llvm-commits at lists.llvm.org
Thu May 26 13:06:18 PDT 2016


Author: cbieneman
Date: Thu May 26 15:06:14 2016
New Revision: 270901

URL: http://llvm.org/viewvc/llvm-project?rev=270901&view=rev
Log:
[obj2yaml][yaml2obj] Support for MachO bind opcodes

This adds support for YAML round tripping dyld info bind opcodes. Bind opcodes can have signed or unsigned LEB128 data, and they can have symbols associated with them.

Added:
    llvm/trunk/test/ObjectYAML/MachO/bind_opcode.yaml
Modified:
    llvm/trunk/include/llvm/ObjectYAML/MachOYAML.h
    llvm/trunk/lib/ObjectYAML/MachOYAML.cpp
    llvm/trunk/tools/obj2yaml/macho2yaml.cpp
    llvm/trunk/tools/yaml2obj/yaml2macho.cpp

Modified: llvm/trunk/include/llvm/ObjectYAML/MachOYAML.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/MachOYAML.h?rev=270901&r1=270900&r2=270901&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ObjectYAML/MachOYAML.h (original)
+++ llvm/trunk/include/llvm/ObjectYAML/MachOYAML.h Thu May 26 15:06:14 2016
@@ -63,8 +63,17 @@ struct RebaseOpcode {
   std::vector<yaml::Hex64> ExtraData;
 };
 
+struct BindOpcode {
+  MachO::BindOpcode Opcode;
+  uint8_t Imm;
+  std::vector<yaml::Hex64> ULEBExtraData;
+  std::vector<int64_t> SLEBExtraData;
+  StringRef Symbol;
+};
+
 struct LinkEditData {
   std::vector<MachOYAML::RebaseOpcode> RebaseOpcodes;
+  std::vector<MachOYAML::BindOpcode> BindOpcodes;
 };
 
 struct Object {
@@ -81,7 +90,9 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachO
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::Section)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::Hex8)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::Hex64)
+LLVM_YAML_IS_SEQUENCE_VECTOR(int64_t)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::RebaseOpcode)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::BindOpcode)
 
 namespace llvm {
 namespace yaml {
@@ -106,6 +117,10 @@ template <> struct MappingTraits<MachOYA
   static void mapping(IO &IO, MachOYAML::RebaseOpcode &RebaseOpcode);
 };
 
+template <> struct MappingTraits<MachOYAML::BindOpcode> {
+  static void mapping(IO &IO, MachOYAML::BindOpcode &BindOpcode);
+};
+
 template <> struct MappingTraits<MachOYAML::Section> {
   static void mapping(IO &IO, MachOYAML::Section &Section);
 };
@@ -116,25 +131,43 @@ template <> struct MappingTraits<MachOYA
 template <> struct ScalarEnumerationTraits<MachO::LoadCommandType> {
   static void enumeration(IO &io, MachO::LoadCommandType &value) {
 #include "llvm/Support/MachO.def"
-  io.enumFallback<Hex32>(value);
+    io.enumFallback<Hex32>(value);
   }
 };
 
-#define ENUM_CASE(Enum)                                                 \
-  io.enumCase(value, #Enum, MachO::Enum);
+#define ENUM_CASE(Enum) io.enumCase(value, #Enum, MachO::Enum);
 
 template <> struct ScalarEnumerationTraits<MachO::RebaseOpcode> {
   static void enumeration(IO &io, MachO::RebaseOpcode &value) {
-  ENUM_CASE(REBASE_OPCODE_DONE)
-  ENUM_CASE(REBASE_OPCODE_SET_TYPE_IMM)
-  ENUM_CASE(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB)
-  ENUM_CASE(REBASE_OPCODE_ADD_ADDR_ULEB)
-  ENUM_CASE(REBASE_OPCODE_ADD_ADDR_IMM_SCALED)
-  ENUM_CASE(REBASE_OPCODE_DO_REBASE_IMM_TIMES)
-  ENUM_CASE(REBASE_OPCODE_DO_REBASE_ULEB_TIMES)
-  ENUM_CASE(REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB)
-  ENUM_CASE(REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB)
-  io.enumFallback<Hex8>(value);
+    ENUM_CASE(REBASE_OPCODE_DONE)
+    ENUM_CASE(REBASE_OPCODE_SET_TYPE_IMM)
+    ENUM_CASE(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB)
+    ENUM_CASE(REBASE_OPCODE_ADD_ADDR_ULEB)
+    ENUM_CASE(REBASE_OPCODE_ADD_ADDR_IMM_SCALED)
+    ENUM_CASE(REBASE_OPCODE_DO_REBASE_IMM_TIMES)
+    ENUM_CASE(REBASE_OPCODE_DO_REBASE_ULEB_TIMES)
+    ENUM_CASE(REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB)
+    ENUM_CASE(REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB)
+    io.enumFallback<Hex8>(value);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<MachO::BindOpcode> {
+  static void enumeration(IO &io, MachO::BindOpcode &value) {
+    ENUM_CASE(BIND_OPCODE_DONE)
+    ENUM_CASE(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM)
+    ENUM_CASE(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB)
+    ENUM_CASE(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM)
+    ENUM_CASE(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM)
+    ENUM_CASE(BIND_OPCODE_SET_TYPE_IMM)
+    ENUM_CASE(BIND_OPCODE_SET_ADDEND_SLEB)
+    ENUM_CASE(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB)
+    ENUM_CASE(BIND_OPCODE_ADD_ADDR_ULEB)
+    ENUM_CASE(BIND_OPCODE_DO_BIND)
+    ENUM_CASE(BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
+    ENUM_CASE(BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED)
+    ENUM_CASE(BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB)
+    io.enumFallback<Hex8>(value);
   }
 };
 

Modified: llvm/trunk/lib/ObjectYAML/MachOYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/MachOYAML.cpp?rev=270901&r1=270900&r2=270901&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/MachOYAML.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/MachOYAML.cpp Thu May 26 15:06:14 2016
@@ -97,18 +97,28 @@ void MappingTraits<MachOYAML::Object>::m
   IO.setContext(nullptr);
 }
 
-void MappingTraits<MachOYAML::LinkEditData>::mapping(IO &IO,
-                                               MachOYAML::LinkEditData &LinkEditData) {
+void MappingTraits<MachOYAML::LinkEditData>::mapping(
+    IO &IO, MachOYAML::LinkEditData &LinkEditData) {
   IO.mapOptional("RebaseOpcodes", LinkEditData.RebaseOpcodes);
+  IO.mapOptional("BindOpcodes", LinkEditData.BindOpcodes);
 }
 
-void MappingTraits<MachOYAML::RebaseOpcode>::mapping(IO &IO,
-                                               MachOYAML::RebaseOpcode &RebaseOpcode) {
+void MappingTraits<MachOYAML::RebaseOpcode>::mapping(
+    IO &IO, MachOYAML::RebaseOpcode &RebaseOpcode) {
   IO.mapRequired("Opcode", RebaseOpcode.Opcode);
   IO.mapRequired("Imm", RebaseOpcode.Imm);
   IO.mapOptional("ExtraData", RebaseOpcode.ExtraData);
 }
 
+void MappingTraits<MachOYAML::BindOpcode>::mapping(
+    IO &IO, MachOYAML::BindOpcode &BindOpcode) {
+  IO.mapRequired("Opcode", BindOpcode.Opcode);
+  IO.mapRequired("Imm", BindOpcode.Imm);
+  IO.mapOptional("ULEBExtraData", BindOpcode.ULEBExtraData);
+  IO.mapOptional("SLEBExtraData", BindOpcode.SLEBExtraData);
+  IO.mapOptional("Symbol", BindOpcode.Symbol);
+}
+
 template <typename StructType>
 void mapLoadCommandData(IO &IO, MachOYAML::LoadCommand &LoadCommand) {}
 

Added: llvm/trunk/test/ObjectYAML/MachO/bind_opcode.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/MachO/bind_opcode.yaml?rev=270901&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/MachO/bind_opcode.yaml (added)
+++ llvm/trunk/test/ObjectYAML/MachO/bind_opcode.yaml Thu May 26 15:06:14 2016
@@ -0,0 +1,133 @@
+# RUN: yaml2obj -format=macho %s | obj2yaml | FileCheck %s
+
+--- !mach-o
+FileHeader:      
+  magic:           0xFEEDFACF
+  cputype:         0x01000007
+  cpusubtype:      0x80000003
+  filetype:        0x00000002
+  ncmds:           4
+  sizeofcmds:      224
+  flags:           0x00218085
+  reserved:        0x00000000
+LoadCommands:    
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         72
+    segname:         __LINKEDIT
+    vmaddr:          4294979584
+    vmsize:          4096
+    fileoff:         1024
+    filesize:        2508
+    maxprot:         7
+    initprot:        1
+    nsects:          0
+    flags:           0
+  - cmd:             LC_DYLD_INFO_ONLY
+    cmdsize:         48
+    rebase_off:      1024
+    rebase_size:     8
+    bind_off:        1032
+    bind_size:       96
+    weak_bind_off:   0
+    weak_bind_size:  0
+    lazy_bind_off:   1128
+    lazy_bind_size:  624
+    export_off:      1752
+    export_size:     48
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          1816
+    nsyms:           30
+    stroff:          2436
+    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:  2296
+    nindirectsyms:   35
+    extreloff:       0
+    nextrel:         0
+    locreloff:       0
+    nlocrel:         0
+LinkEditData:    
+  BindOpcodes:     
+    - Opcode:          BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
+      Imm:             1
+    - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
+      Imm:             0
+      Symbol:          __ZNSt3__14coutE
+    - Opcode:          BIND_OPCODE_SET_TYPE_IMM
+      Imm:             1
+    - Opcode:          BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
+      Imm:             2
+      ULEBExtraData:   
+        - 0x0000000000000000
+    - Opcode:          BIND_OPCODE_DO_BIND
+      Imm:             0
+    - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
+      Imm:             0
+      Symbol:          __ZNSt3__15ctypeIcE2idE
+    - Opcode:          BIND_OPCODE_DO_BIND
+      Imm:             0
+    - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
+      Imm:             0
+      Symbol:          ___gxx_personality_v0
+    - Opcode:          BIND_OPCODE_DO_BIND
+      Imm:             0
+    - Opcode:          BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
+      Imm:             2
+    - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
+      Imm:             0
+      Symbol:          dyld_stub_binder
+    - Opcode:          BIND_OPCODE_DO_BIND
+      Imm:             0
+    - Opcode:          BIND_OPCODE_DONE
+      Imm:             0
+...
+
+#CHECK: LinkEditData:    
+#CHECK:   BindOpcodes:     
+#CHECK:     - Opcode:          BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
+#CHECK:       Imm:             1
+#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:     - Opcode:          BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
+#CHECK:       Imm:             2
+#CHECK:       ULEBExtraData:   
+#CHECK:         - 0x0000000000000000
+#CHECK:     - Opcode:          BIND_OPCODE_DO_BIND
+#CHECK:       Imm:             0
+#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:     - 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:     - Opcode:          BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
+#CHECK:       Imm:             2
+#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:     - Opcode:          BIND_OPCODE_DONE
+#CHECK:       Imm:             0
+

Modified: llvm/trunk/tools/obj2yaml/macho2yaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/obj2yaml/macho2yaml.cpp?rev=270901&r1=270900&r2=270901&view=diff
==============================================================================
--- llvm/trunk/tools/obj2yaml/macho2yaml.cpp (original)
+++ llvm/trunk/tools/obj2yaml/macho2yaml.cpp Thu May 26 15:06:14 2016
@@ -29,6 +29,9 @@ class MachODumper {
   void dumpHeader(std::unique_ptr<MachOYAML::Object> &Y);
   void dumpLoadCommands(std::unique_ptr<MachOYAML::Object> &Y);
   void dumpLinkEdit(std::unique_ptr<MachOYAML::Object> &Y);
+  void dumpRebaseOpcodes(std::unique_ptr<MachOYAML::Object> &Y);
+  void dumpBindOpcodes(std::vector<MachOYAML::BindOpcode> &BindOpcodes,
+                       ArrayRef<uint8_t> OpcodeBuffer, bool Lazy = false);
 
 public:
   MachODumper(const object::MachOObjectFile &O) : Obj(O) {}
@@ -192,6 +195,11 @@ void MachODumper::dumpLoadCommands(std::
 }
 
 void MachODumper::dumpLinkEdit(std::unique_ptr<MachOYAML::Object> &Y) {
+  dumpRebaseOpcodes(Y);
+  dumpBindOpcodes(Y->LinkEdit.BindOpcodes, Obj.getDyldInfoBindOpcodes());
+}
+
+void MachODumper::dumpRebaseOpcodes(std::unique_ptr<MachOYAML::Object> &Y) {
   MachOYAML::LinkEditData &LEData = Y->LinkEdit;
 
   auto RebaseOpcodes = Obj.getDyldInfoRebaseOpcodes();
@@ -231,6 +239,64 @@ void MachODumper::dumpLinkEdit(std::uniq
       break;
   }
 }
+
+void MachODumper::dumpBindOpcodes(
+    std::vector<MachOYAML::BindOpcode> &BindOpcodes,
+    ArrayRef<uint8_t> OpcodeBuffer, bool Lazy) {
+  for (auto OpCode = OpcodeBuffer.begin(); OpCode != OpcodeBuffer.end();
+       ++OpCode) {
+    MachOYAML::BindOpcode BindOp;
+    BindOp.Opcode =
+        static_cast<MachO::BindOpcode>(*OpCode & MachO::BIND_OPCODE_MASK);
+    BindOp.Imm = *OpCode & MachO::BIND_IMMEDIATE_MASK;
+
+    unsigned Count;
+    uint64_t ULEB = 0;
+    int64_t SLEB = 0;
+    const uint8_t *SymStart;
+
+    switch (BindOp.Opcode) {
+    case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
+      ULEB = decodeULEB128(OpCode + 1, &Count);
+      BindOp.ULEBExtraData.push_back(ULEB);
+      OpCode += Count;
+    // Intentionally no break here -- this opcode has two ULEB values
+
+    case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
+    case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
+    case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
+    case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
+      ULEB = decodeULEB128(OpCode + 1, &Count);
+      BindOp.ULEBExtraData.push_back(ULEB);
+      OpCode += Count;
+      break;
+
+    case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
+      SLEB = decodeSLEB128(OpCode + 1, &Count);
+      BindOp.SLEBExtraData.push_back(SLEB);
+      OpCode += Count;
+      break;
+
+    case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
+      SymStart = ++OpCode;
+      while (*OpCode) {
+        ++OpCode;
+      }
+      BindOp.Symbol = StringRef(reinterpret_cast<const char *>(SymStart),
+                                OpCode - SymStart);
+      break;
+    default:
+      break;
+    }
+
+    BindOpcodes.push_back(BindOp);
+
+    // Lazy bindings have DONE opcodes between operations, so we need to keep
+    // processing after a DONE.
+    if (!Lazy && BindOp.Opcode == MachO::BIND_OPCODE_DONE)
+      break;
+  }
+}
 
 Error macho2yaml(raw_ostream &Out, const object::MachOObjectFile &Obj) {
   MachODumper Dumper(Obj);

Modified: llvm/trunk/tools/yaml2obj/yaml2macho.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/yaml2obj/yaml2macho.cpp?rev=270901&r1=270900&r2=270901&view=diff
==============================================================================
--- llvm/trunk/tools/yaml2obj/yaml2macho.cpp (original)
+++ llvm/trunk/tools/yaml2obj/yaml2macho.cpp Thu May 26 15:06:14 2016
@@ -289,6 +289,23 @@ Error MachOWriter::writeLinkEditData(raw
     }
   }
 
+  ZeroToOffset(OS, DyldInfoOnlyCmd->bind_off);
+
+  for (auto Opcode : LinkEdit.BindOpcodes) {
+    uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
+    OS.write(reinterpret_cast<char *>(&OpByte), 1);
+    for (auto Data : Opcode.ULEBExtraData) {
+      encodeULEB128(Data, OS);
+    }
+    for (auto Data : Opcode.SLEBExtraData) {
+      encodeSLEB128(Data, OS);
+    }
+    if(!Opcode.Symbol.empty()) {
+      OS.write(Opcode.Symbol.data(), Opcode.Symbol.size());
+      OS.write("\0", 1);
+    }
+  }
+
   // Fill to the end of the string table
   ZeroToOffset(OS, SymtabCmd->stroff + SymtabCmd->strsize);
 




More information about the llvm-commits mailing list