From f373c77f50451ff585b507cce05705632553d13a Mon Sep 17 00:00:00 2001 From: Nick Kledzik Date: Tue, 11 Nov 2014 01:31:18 +0000 Subject: [mach-o] Fix lazy binding offsets The way lazy binding works in mach-o is that the linker generates a helper function and has the stub (PLT) initially jump to it. The helper function pushes an extra parameter then jumps into dyld. The extra parameter is an offset into the lazy binding info where dyld will find the information about which symbol to bind and way lazy binding pointer to update. llvm-svn: 221654 --- .../ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp') diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp index 543b60fe8bc..102b185df52 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp @@ -125,6 +125,12 @@ private: void append_uleb128(uint64_t value) { llvm::encodeULEB128(value, _ostream); } + void append_uleb128Fixed(uint64_t value, unsigned byteCount) { + unsigned min = llvm::getULEB128Size(value); + assert(min <= byteCount); + unsigned pad = byteCount - min; + llvm::encodeULEB128(value, _ostream, pad); + } void append_sleb128(int64_t value) { llvm::encodeSLEB128(value, _ostream); } @@ -999,6 +1005,7 @@ void MachOFileLayout::buildRebaseInfo() { void MachOFileLayout::buildBindInfo() { // TODO: compress bind info. + uint64_t lastAddend = 0; for (const BindLocation& entry : _file.bindingInfo) { _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind); _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB @@ -1007,9 +1014,10 @@ void MachOFileLayout::buildBindInfo() { _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal); _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM); _bindingInfo.append_string(entry.symbolName); - if (entry.addend != 0) { + if (entry.addend != lastAddend) { _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB); _bindingInfo.append_sleb128(entry.addend); + lastAddend = entry.addend; } _bindingInfo.append_byte(BIND_OPCODE_DO_BIND); } @@ -1022,11 +1030,12 @@ void MachOFileLayout::buildLazyBindInfo() { _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind); _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | entry.segIndex); - _lazyBindingInfo.append_uleb128(entry.segOffset); + _lazyBindingInfo.append_uleb128Fixed(entry.segOffset, 5); _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal); _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM); _lazyBindingInfo.append_string(entry.symbolName); _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND); + _lazyBindingInfo.append_byte(BIND_OPCODE_DONE); } _lazyBindingInfo.append_byte(BIND_OPCODE_DONE); _lazyBindingInfo.align(_is64 ? 8 : 4); -- cgit v1.2.3