[llvm] r271611 - [yaml2obj] Sort MachO LinkEdit write operations based on offset
Chris Bieneman via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 2 16:54:20 PDT 2016
Author: cbieneman
Date: Thu Jun 2 18:52:08 2016
New Revision: 271611
URL: http://llvm.org/viewvc/llvm-project?rev=271611&view=rev
Log:
[yaml2obj] Sort MachO LinkEdit write operations based on offset
Although ld64 always outputs linkedit data in the same order, it isn't actually required to. This change makes yaml2obj resilient if the offsets are in arbitrary order.
Added:
llvm/trunk/test/ObjectYAML/MachO/out_of_order_linkedit.yaml
Modified:
llvm/trunk/tools/yaml2obj/yaml2macho.cpp
Added: llvm/trunk/test/ObjectYAML/MachO/out_of_order_linkedit.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/MachO/out_of_order_linkedit.yaml?rev=271611&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/MachO/out_of_order_linkedit.yaml (added)
+++ llvm/trunk/test/ObjectYAML/MachO/out_of_order_linkedit.yaml Thu Jun 2 18:52:08 2016
@@ -0,0 +1,266 @@
+# RUN: yaml2obj -format=macho %s | obj2yaml | FileCheck %s
+
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x01000007
+ cpusubtype: 0x80000003
+ filetype: 0x00000002
+ ncmds: 16
+ sizeofcmds: 1408
+ flags: 0x00218085
+ reserved: 0x00000000
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 72
+ segname: __PAGEZERO
+ vmaddr: 0
+ vmsize: 4294967296
+ fileoff: 0
+ filesize: 0
+ maxprot: 0
+ initprot: 0
+ nsects: 0
+ flags: 0
+ - cmd: LC_SEGMENT_64
+ cmdsize: 552
+ segname: __TEXT
+ vmaddr: 4294967296
+ vmsize: 8192
+ fileoff: 0
+ filesize: 8192
+ maxprot: 7
+ initprot: 5
+ nsects: 6
+ flags: 0
+ - cmd: LC_SEGMENT_64
+ cmdsize: 312
+ segname: __DATA
+ vmaddr: 4294975488
+ vmsize: 4096
+ fileoff: 8192
+ filesize: 4096
+ maxprot: 7
+ initprot: 3
+ nsects: 3
+ flags: 0
+ - cmd: LC_SEGMENT_64
+ cmdsize: 72
+ segname: __LINKEDIT
+ vmaddr: 4294979584
+ vmsize: 4096
+ fileoff: 12288
+ filesize: 2508
+ maxprot: 7
+ initprot: 1
+ nsects: 0
+ flags: 0
+ - cmd: LC_DYLD_INFO_ONLY
+ cmdsize: 48
+ rebase_off: 12384
+ rebase_size: 8
+ bind_off: 12288
+ bind_size: 96
+ weak_bind_off: 0
+ weak_bind_size: 0
+ lazy_bind_off: 12392
+ lazy_bind_size: 624
+ export_off: 13016
+ export_size: 48
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 13080
+ nsyms: 30
+ stroff: 13700
+ 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: 13560
+ nindirectsyms: 35
+ extreloff: 0
+ nextrel: 0
+ locreloff: 0
+ nlocrel: 0
+ - cmd: LC_LOAD_DYLINKER
+ cmdsize: 32
+ name: 12
+ PayloadString: /usr/lib/dyld
+ ZeroPadBytes: 7
+ - cmd: LC_UUID
+ cmdsize: 24
+ uuid: 461A1B28-822F-3F38-B670-645419E636F5
+ - cmd: LC_VERSION_MIN_MACOSX
+ cmdsize: 16
+ version: 658176
+ sdk: 658176
+ - cmd: LC_SOURCE_VERSION
+ cmdsize: 16
+ version: 0
+ - cmd: LC_MAIN
+ cmdsize: 24
+ entryoff: 4448
+ stacksize: 0
+ - cmd: LC_LOAD_DYLIB
+ cmdsize: 48
+ dylib:
+ name: 24
+ timestamp: 2
+ current_version: 7864576
+ compatibility_version: 65536
+ PayloadString: '/usr/lib/libc++.1.dylib'
+ ZeroPadBytes: 1
+ - cmd: LC_LOAD_DYLIB
+ cmdsize: 56
+ dylib:
+ name: 24
+ timestamp: 2
+ current_version: 80349697
+ compatibility_version: 65536
+ PayloadString: /usr/lib/libSystem.B.dylib
+ ZeroPadBytes: 6
+ - cmd: LC_FUNCTION_STARTS
+ cmdsize: 16
+ dataoff: 13064
+ datasize: 16
+ - cmd: LC_DATA_IN_CODE
+ cmdsize: 16
+ dataoff: 13080
+ datasize: 0
+LinkEditData:
+ RebaseOpcodes:
+ - Opcode: REBASE_OPCODE_SET_TYPE_IMM
+ Imm: 1
+ - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
+ Imm: 2
+ ExtraData:
+ - 0x0000000000000028
+ - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES
+ Imm: 0
+ ExtraData:
+ - 0x000000000000000F
+ - Opcode: REBASE_OPCODE_DONE
+ Imm: 0
+ BindOpcodes:
+ - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
+ Imm: 1
+ Symbol: ''
+ - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
+ Imm: 0
+ Symbol: __ZNSt3__14coutE
+ - Opcode: BIND_OPCODE_SET_TYPE_IMM
+ Imm: 1
+ Symbol: ''
+ - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
+ Imm: 2
+ ULEBExtraData:
+ - 0x0000000000000000
+ Symbol: ''
+ - Opcode: BIND_OPCODE_DO_BIND
+ Imm: 0
+ Symbol: ''
+ - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
+ Imm: 0
+ Symbol: __ZNSt3__15ctypeIcE2idE
+ - Opcode: BIND_OPCODE_DO_BIND
+ Imm: 0
+ Symbol: ''
+ - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
+ Imm: 0
+ Symbol: ___gxx_personality_v0
+ - Opcode: BIND_OPCODE_DO_BIND
+ Imm: 0
+ Symbol: ''
+ - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
+ Imm: 2
+ Symbol: ''
+ - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
+ Imm: 0
+ Symbol: dyld_stub_binder
+ - Opcode: BIND_OPCODE_DO_BIND
+ Imm: 0
+ Symbol: ''
+ - Opcode: BIND_OPCODE_DONE
+ Imm: 0
+ Symbol: ''
+...
+
+#CHECK: - cmd: LC_DYLD_INFO_ONLY
+#CHECK: cmdsize: 48
+#CHECK: rebase_off: 12384
+#CHECK: rebase_size: 8
+#CHECK: bind_off: 12288
+#CHECK: bind_size: 96
+#CHECK: weak_bind_off: 0
+#CHECK: weak_bind_size: 0
+#CHECK: lazy_bind_off: 12392
+#CHECK: lazy_bind_size: 624
+#CHECK: export_off: 13016
+#CHECK: export_size: 48
+#CHECK: LinkEditData:
+#CHECK: RebaseOpcodes:
+#CHECK: - Opcode: REBASE_OPCODE_SET_TYPE_IMM
+#CHECK: Imm: 1
+#CHECK: - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
+#CHECK: Imm: 2
+#CHECK: ExtraData:
+#CHECK: - 0x0000000000000028
+#CHECK: - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES
+#CHECK: Imm: 0
+#CHECK: ExtraData:
+#CHECK: - 0x000000000000000F
+#CHECK: - Opcode: REBASE_OPCODE_DONE
+#CHECK: Imm: 0
+#CHECK: BindOpcodes:
+#CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
+#CHECK: Imm: 1
+#CHECK: Symbol: ''
+#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: Symbol: ''
+#CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
+#CHECK: Imm: 2
+#CHECK: ULEBExtraData:
+#CHECK: - 0x0000000000000000
+#CHECK: Symbol: ''
+#CHECK: - Opcode: BIND_OPCODE_DO_BIND
+#CHECK: Imm: 0
+#CHECK: Symbol: ''
+#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: Symbol: ''
+#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: Symbol: ''
+#CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
+#CHECK: Imm: 2
+#CHECK: Symbol: ''
+#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: Symbol: ''
+#CHECK: - Opcode: BIND_OPCODE_DONE
+#CHECK: Imm: 0
+#CHECK: Symbol: ''
Modified: llvm/trunk/tools/yaml2obj/yaml2macho.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/yaml2obj/yaml2macho.cpp?rev=271611&r1=271610&r2=271611&view=diff
==============================================================================
--- llvm/trunk/tools/yaml2obj/yaml2macho.cpp (original)
+++ llvm/trunk/tools/yaml2obj/yaml2macho.cpp Thu Jun 2 18:52:08 2016
@@ -46,8 +46,15 @@ private:
Error writeLoadCommands(raw_ostream &OS);
Error writeSectionData(raw_ostream &OS);
Error writeLinkEditData(raw_ostream &OS);
- void writeBindOpcodes(raw_ostream &OS, uint64_t offset,
+ void writeBindOpcodes(raw_ostream &OS,
std::vector<MachOYAML::BindOpcode> &BindOpcodes);
+ // LinkEdit writers
+ Error writeRebaseOpcodes(raw_ostream &OS);
+ Error writeBasicBindOpcodes(raw_ostream &OS);
+ Error writeWeakBindOpcodes(raw_ostream &OS);
+ Error writeLazyBindOpcodes(raw_ostream &OS);
+ Error writeNameList(raw_ostream &OS);
+ Error writeStringTable(raw_ostream &OS);
Error writeExportTrie(raw_ostream &OS);
void dumpExportEntry(raw_ostream &OS, MachOYAML::ExportEntry &Entry);
@@ -275,9 +282,7 @@ Error MachOWriter::writeSectionData(raw_
}
void MachOWriter::writeBindOpcodes(
- raw_ostream &OS, uint64_t offset,
- std::vector<MachOYAML::BindOpcode> &BindOpcodes) {
- ZeroToOffset(OS, offset);
+ raw_ostream &OS, std::vector<MachOYAML::BindOpcode> &BindOpcodes) {
for (auto Opcode : BindOpcodes) {
uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
@@ -337,21 +342,55 @@ void writeNListEntry(MachOYAML::NListEnt
}
Error MachOWriter::writeLinkEditData(raw_ostream &OS) {
- MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit;
+ typedef Error (MachOWriter::*writeHandler)(raw_ostream &);
+ typedef std::pair<uint64_t, writeHandler> writeOperation;
+ std::vector<writeOperation> WriteQueue;
+
MachO::dyld_info_command *DyldInfoOnlyCmd = 0;
MachO::symtab_command *SymtabCmd = 0;
for (auto &LC : Obj.LoadCommands) {
switch (LC.Data.load_command_data.cmd) {
case MachO::LC_SYMTAB:
SymtabCmd = &LC.Data.symtab_command_data;
+ WriteQueue.push_back(
+ std::make_pair(SymtabCmd->symoff, &MachOWriter::writeNameList));
+ WriteQueue.push_back(
+ std::make_pair(SymtabCmd->stroff, &MachOWriter::writeStringTable));
break;
case MachO::LC_DYLD_INFO_ONLY:
DyldInfoOnlyCmd = &LC.Data.dyld_info_command_data;
+ WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->rebase_off,
+ &MachOWriter::writeRebaseOpcodes));
+ WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->bind_off,
+ &MachOWriter::writeBasicBindOpcodes));
+ WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->weak_bind_off,
+ &MachOWriter::writeWeakBindOpcodes));
+ WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->lazy_bind_off,
+ &MachOWriter::writeLazyBindOpcodes));
+ WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->export_off,
+ &MachOWriter::writeExportTrie));
break;
}
}
- ZeroToOffset(OS, DyldInfoOnlyCmd->rebase_off);
+ std::sort(
+ WriteQueue.begin(), WriteQueue.end(),
+ [](writeOperation &a, writeOperation &b) { return a.first < b.first; });
+
+ for (auto writeOp : WriteQueue) {
+ ZeroToOffset(OS, writeOp.first);
+ if (auto Err = (this->*writeOp.second)(OS))
+ return Err;
+ }
+
+ // Fill to the end of the string table
+ ZeroToOffset(OS, SymtabCmd->stroff + SymtabCmd->strsize);
+
+ return Error::success();
+}
+
+Error MachOWriter::writeRebaseOpcodes(raw_ostream &OS) {
+ MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit;
for (auto Opcode : LinkEdit.RebaseOpcodes) {
uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
@@ -360,38 +399,39 @@ Error MachOWriter::writeLinkEditData(raw
encodeULEB128(Data, OS);
}
}
+ return Error::success();
+}
- writeBindOpcodes(OS, DyldInfoOnlyCmd->bind_off, LinkEdit.BindOpcodes);
- writeBindOpcodes(OS, DyldInfoOnlyCmd->weak_bind_off,
- LinkEdit.WeakBindOpcodes);
- writeBindOpcodes(OS, DyldInfoOnlyCmd->lazy_bind_off,
- LinkEdit.LazyBindOpcodes);
+Error MachOWriter::writeBasicBindOpcodes(raw_ostream &OS) {
+ writeBindOpcodes(OS, Obj.LinkEdit.BindOpcodes);
+ return Error::success();
+}
- ZeroToOffset(OS, DyldInfoOnlyCmd->export_off);
- if (auto Err = writeExportTrie(OS))
- return Err;
+Error MachOWriter::writeWeakBindOpcodes(raw_ostream &OS) {
+ writeBindOpcodes(OS, Obj.LinkEdit.WeakBindOpcodes);
+ return Error::success();
+}
- ZeroToOffset(OS, SymtabCmd->symoff);
-
- for (auto NLE : LinkEdit.NameList) {
+Error MachOWriter::writeLazyBindOpcodes(raw_ostream &OS) {
+ writeBindOpcodes(OS, Obj.LinkEdit.LazyBindOpcodes);
+ return Error::success();
+}
+
+Error MachOWriter::writeNameList(raw_ostream &OS) {
+ for (auto NLE : Obj.LinkEdit.NameList) {
if (is64Bit)
writeNListEntry<MachO::nlist_64>(NLE, OS);
else
writeNListEntry<MachO::nlist>(NLE, OS);
}
+ return Error::success();
+}
- auto currOffset = OS.tell() - fileStart;
- if (currOffset < SymtabCmd->stroff)
- Fill(OS, SymtabCmd->stroff - currOffset, 0xDEADBEEFu);
-
- for (auto Str : LinkEdit.StringTable) {
+Error MachOWriter::writeStringTable(raw_ostream &OS) {
+ for (auto Str : Obj.LinkEdit.StringTable) {
OS.write(Str.data(), Str.size());
OS.write('\0');
}
-
- // Fill to the end of the string table
- ZeroToOffset(OS, SymtabCmd->stroff + SymtabCmd->strsize);
-
return Error::success();
}
More information about the llvm-commits
mailing list