1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[yaml2obj] Sort MachO LinkEdit write operations based on offset

This re-applies r271611, and hopefully the bots won't break this time.

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.

llvm-svn: 271687
This commit is contained in:
Chris Bieneman 2016-06-03 16:58:05 +00:00
parent 6e8ea28227
commit 73cc17e63a
2 changed files with 330 additions and 26 deletions

View File

@ -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: ''

View File

@ -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_ostream &OS) {
}
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,53 @@ void writeNListEntry(MachOYAML::NListEntry &NLE, raw_ostream &OS) {
}
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(),
[](const writeOperation &a, const writeOperation &b) {
return a.first < b.first;
});
for (auto writeOp : WriteQueue) {
ZeroToOffset(OS, writeOp.first);
if (auto Err = (this->*writeOp.second)(OS))
return Err;
}
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 +397,39 @@ Error MachOWriter::writeLinkEditData(raw_ostream &OS) {
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();
}