summaryrefslogtreecommitdiffstats
path: root/llvm/tools/obj2yaml/macho2yaml.cpp
diff options
context:
space:
mode:
authorChris Bieneman <beanz@apple.com>2016-05-26 20:06:14 +0000
committerChris Bieneman <beanz@apple.com>2016-05-26 20:06:14 +0000
commit524243d61e9ed6f99be875cdc63071ff86b3a4a1 (patch)
tree6c6132369f2687f5bd68039f86303a7cf7b3b50b /llvm/tools/obj2yaml/macho2yaml.cpp
parentf1f3f93c9efe6a409bc79d17cd8be1f860a758b4 (diff)
downloadbcm5719-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.cpp66
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();
OpenPOWER on IntegriCloud