diff options
author | Chris Bieneman <beanz@apple.com> | 2016-05-26 20:06:14 +0000 |
---|---|---|
committer | Chris Bieneman <beanz@apple.com> | 2016-05-26 20:06:14 +0000 |
commit | 524243d61e9ed6f99be875cdc63071ff86b3a4a1 (patch) | |
tree | 6c6132369f2687f5bd68039f86303a7cf7b3b50b /llvm/tools/obj2yaml/macho2yaml.cpp | |
parent | f1f3f93c9efe6a409bc79d17cd8be1f860a758b4 (diff) | |
download | bcm5719-llvm-524243d61e9ed6f99be875cdc63071ff86b3a4a1.tar.gz bcm5719-llvm-524243d61e9ed6f99be875cdc63071ff86b3a4a1.zip |
[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
Diffstat (limited to 'llvm/tools/obj2yaml/macho2yaml.cpp')
-rw-r--r-- | llvm/tools/obj2yaml/macho2yaml.cpp | 66 |
1 files changed, 66 insertions, 0 deletions
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<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::unique_ptr<MachOYAML::Object> &Y) { } 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(); @@ -232,6 +240,64 @@ void MachODumper::dumpLinkEdit(std::unique_ptr<MachOYAML::Object> &Y) { } } +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); Expected<std::unique_ptr<MachOYAML::Object>> YAML = Dumper.dump(); |