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:
parent
6e8ea28227
commit
73cc17e63a
266
test/ObjectYAML/MachO/out_of_order_linkedit.yaml
Normal file
266
test/ObjectYAML/MachO/out_of_order_linkedit.yaml
Normal 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: ''
|
@ -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();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user