[obj2yaml][yaml2obj] Support for MachO weak bindings

This adds support for YAML round tripping dyld info weak bindings. The storage and format of these is the same as regular bind opcodes, they are just interpreted differently by dyld.

llvm-svn: 270911
This commit is contained in:
Chris Bieneman 2016-05-26 20:50:05 +00:00
parent 84bb355c3a
commit 659b35a5d8
5 changed files with 163 additions and 16 deletions

View File

@ -74,6 +74,7 @@ struct BindOpcode {
struct LinkEditData { struct LinkEditData {
std::vector<MachOYAML::RebaseOpcode> RebaseOpcodes; std::vector<MachOYAML::RebaseOpcode> RebaseOpcodes;
std::vector<MachOYAML::BindOpcode> BindOpcodes; std::vector<MachOYAML::BindOpcode> BindOpcodes;
std::vector<MachOYAML::BindOpcode> WeakBindOpcodes;
}; };
struct Object { struct Object {

View File

@ -101,6 +101,7 @@ void MappingTraits<MachOYAML::LinkEditData>::mapping(
IO &IO, MachOYAML::LinkEditData &LinkEditData) { IO &IO, MachOYAML::LinkEditData &LinkEditData) {
IO.mapOptional("RebaseOpcodes", LinkEditData.RebaseOpcodes); IO.mapOptional("RebaseOpcodes", LinkEditData.RebaseOpcodes);
IO.mapOptional("BindOpcodes", LinkEditData.BindOpcodes); IO.mapOptional("BindOpcodes", LinkEditData.BindOpcodes);
IO.mapOptional("WeakBindOpcodes", LinkEditData.WeakBindOpcodes);
} }
void MappingTraits<MachOYAML::RebaseOpcode>::mapping( void MappingTraits<MachOYAML::RebaseOpcode>::mapping(

View File

@ -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: 0
bind_size: 0
weak_bind_off: 1032
weak_bind_size: 96
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:
WeakBindOpcodes:
- 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: WeakBindOpcodes:
#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

View File

@ -197,6 +197,8 @@ void MachODumper::dumpLoadCommands(std::unique_ptr<MachOYAML::Object> &Y) {
void MachODumper::dumpLinkEdit(std::unique_ptr<MachOYAML::Object> &Y) { void MachODumper::dumpLinkEdit(std::unique_ptr<MachOYAML::Object> &Y) {
dumpRebaseOpcodes(Y); dumpRebaseOpcodes(Y);
dumpBindOpcodes(Y->LinkEdit.BindOpcodes, Obj.getDyldInfoBindOpcodes()); dumpBindOpcodes(Y->LinkEdit.BindOpcodes, Obj.getDyldInfoBindOpcodes());
dumpBindOpcodes(Y->LinkEdit.WeakBindOpcodes,
Obj.getDyldInfoWeakBindOpcodes());
} }
void MachODumper::dumpRebaseOpcodes(std::unique_ptr<MachOYAML::Object> &Y) { void MachODumper::dumpRebaseOpcodes(std::unique_ptr<MachOYAML::Object> &Y) {

View File

@ -46,6 +46,8 @@ private:
Error writeLoadCommands(raw_ostream &OS); Error writeLoadCommands(raw_ostream &OS);
Error writeSectionData(raw_ostream &OS); Error writeSectionData(raw_ostream &OS);
Error writeLinkEditData(raw_ostream &OS); Error writeLinkEditData(raw_ostream &OS);
void writeBindOpcodes(raw_ostream &OS, uint64_t offset,
std::vector<MachOYAML::BindOpcode> &BindOpcodes);
void ZeroToOffset(raw_ostream &OS, size_t offset); void ZeroToOffset(raw_ostream &OS, size_t offset);
@ -264,6 +266,27 @@ Error MachOWriter::writeSectionData(raw_ostream &OS) {
return Error::success(); return Error::success();
} }
void MachOWriter::writeBindOpcodes(
raw_ostream &OS, uint64_t offset,
std::vector<MachOYAML::BindOpcode> &BindOpcodes) {
ZeroToOffset(OS, offset);
for (auto Opcode : 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);
}
}
}
Error MachOWriter::writeLinkEditData(raw_ostream &OS) { Error MachOWriter::writeLinkEditData(raw_ostream &OS) {
MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit; MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit;
MachO::dyld_info_command *DyldInfoOnlyCmd = 0; MachO::dyld_info_command *DyldInfoOnlyCmd = 0;
@ -289,22 +312,9 @@ Error MachOWriter::writeLinkEditData(raw_ostream &OS) {
} }
} }
ZeroToOffset(OS, DyldInfoOnlyCmd->bind_off); writeBindOpcodes(OS, DyldInfoOnlyCmd->bind_off, LinkEdit.BindOpcodes);
writeBindOpcodes(OS, DyldInfoOnlyCmd->weak_bind_off,
for (auto Opcode : LinkEdit.BindOpcodes) { LinkEdit.WeakBindOpcodes);
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 // Fill to the end of the string table
ZeroToOffset(OS, SymtabCmd->stroff + SymtabCmd->strsize); ZeroToOffset(OS, SymtabCmd->stroff + SymtabCmd->strsize);