summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--llvm/include/llvm/ObjectYAML/MachOYAML.h59
-rw-r--r--llvm/lib/ObjectYAML/MachOYAML.cpp18
-rw-r--r--llvm/test/ObjectYAML/MachO/bind_opcode.yaml133
-rw-r--r--llvm/tools/obj2yaml/macho2yaml.cpp66
-rw-r--r--llvm/tools/yaml2obj/yaml2macho.cpp17
5 files changed, 276 insertions, 17 deletions
diff --git a/llvm/include/llvm/ObjectYAML/MachOYAML.h b/llvm/include/llvm/ObjectYAML/MachOYAML.h
index d86589cb5e9..185afdcdd50 100644
--- a/llvm/include/llvm/ObjectYAML/MachOYAML.h
+++ b/llvm/include/llvm/ObjectYAML/MachOYAML.h
@@ -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::MachOYAML::LoadCommand)
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<MachOYAML::RebaseOpcode> {
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<MachOYAML::Section> {
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);
}
};
diff --git a/llvm/lib/ObjectYAML/MachOYAML.cpp b/llvm/lib/ObjectYAML/MachOYAML.cpp
index 641e27e43f7..48217af54b7 100644
--- a/llvm/lib/ObjectYAML/MachOYAML.cpp
+++ b/llvm/lib/ObjectYAML/MachOYAML.cpp
@@ -97,18 +97,28 @@ void MappingTraits<MachOYAML::Object>::mapping(IO &IO,
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) {}
diff --git a/llvm/test/ObjectYAML/MachO/bind_opcode.yaml b/llvm/test/ObjectYAML/MachO/bind_opcode.yaml
new file mode 100644
index 00000000000..4c010b4cd48
--- /dev/null
+++ b/llvm/test/ObjectYAML/MachO/bind_opcode.yaml
@@ -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
+
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();
diff --git a/llvm/tools/yaml2obj/yaml2macho.cpp b/llvm/tools/yaml2obj/yaml2macho.cpp
index d24a08c6e54..a1f5dda9d9d 100644
--- a/llvm/tools/yaml2obj/yaml2macho.cpp
+++ b/llvm/tools/yaml2obj/yaml2macho.cpp
@@ -289,6 +289,23 @@ Error MachOWriter::writeLinkEditData(raw_ostream &OS) {
}
}
+ 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);
OpenPOWER on IntegriCloud