From 524243d61e9ed6f99be875cdc63071ff86b3a4a1 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Thu, 26 May 2016 20:06:14 +0000 Subject: [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. llvm-svn: 270901 --- llvm/tools/obj2yaml/macho2yaml.cpp | 66 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'llvm/tools/obj2yaml/macho2yaml.cpp') diff --git a/llvm/tools/obj2yaml/macho2yaml.cpp b/llvm/tools/obj2yaml/macho2yaml.cpp index d3dfdbbf8da..7aca3fd82f0 100644 --- a/llvm/tools/obj2yaml/macho2yaml.cpp +++ b/llvm/tools/obj2yaml/macho2yaml.cpp @@ -29,6 +29,9 @@ class MachODumper { void dumpHeader(std::unique_ptr &Y); void dumpLoadCommands(std::unique_ptr &Y); void dumpLinkEdit(std::unique_ptr &Y); + void dumpRebaseOpcodes(std::unique_ptr &Y); + void dumpBindOpcodes(std::vector &BindOpcodes, + ArrayRef OpcodeBuffer, bool Lazy = false); public: MachODumper(const object::MachOObjectFile &O) : Obj(O) {} @@ -192,6 +195,11 @@ void MachODumper::dumpLoadCommands(std::unique_ptr &Y) { } void MachODumper::dumpLinkEdit(std::unique_ptr &Y) { + dumpRebaseOpcodes(Y); + dumpBindOpcodes(Y->LinkEdit.BindOpcodes, Obj.getDyldInfoBindOpcodes()); +} + +void MachODumper::dumpRebaseOpcodes(std::unique_ptr &Y) { MachOYAML::LinkEditData &LEData = Y->LinkEdit; auto RebaseOpcodes = Obj.getDyldInfoRebaseOpcodes(); @@ -232,6 +240,64 @@ void MachODumper::dumpLinkEdit(std::unique_ptr &Y) { } } +void MachODumper::dumpBindOpcodes( + std::vector &BindOpcodes, + ArrayRef OpcodeBuffer, bool Lazy) { + for (auto OpCode = OpcodeBuffer.begin(); OpCode != OpcodeBuffer.end(); + ++OpCode) { + MachOYAML::BindOpcode BindOp; + BindOp.Opcode = + static_cast(*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(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); Expected> YAML = Dumper.dump(); -- cgit v1.2.3