summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Stellard <tstellar@redhat.com>2017-12-05 20:25:50 +0000
committerTom Stellard <tstellar@redhat.com>2017-12-05 20:25:50 +0000
commitd5cd8bc98b6e3d9f58031e1ad3c983955ec9a179 (patch)
tree23fe6f2563615e57c1518905ec5093bc86d66bf3
parent170dfab48d7741847180760e8ac42308e08ee2db (diff)
downloadllvm-d5cd8bc98b6e3d9f58031e1ad3c983955ec9a179.tar.gz
Merging r311734:
------------------------------------------------------------------------ r311734 | ruiu | 2017-08-24 16:51:40 -0700 (Thu, 24 Aug 2017) | 44 lines [MACH-O] Fix the ASM code generated for __stub_helpers section Patch by Patricio Villalobos. I discovered that lld for darwin is generating the wrong code for lazy bindings in the __stub_helper section (at least for osx 10.12). This is the way i can reproduce this problem, using this program: #include <stdio.h> int main(int argc, char **argv) { printf("C: printf!\n"); puts("C: puts!\n"); return 0; } Then I link it using i have tested it in 3.9, 4.0 and 4.1 versions: $ clang -c hello.c $ lld -flavor darwin hello.o -o h1 -lc When i execute the binary h1 the system gives me the following error: C: printf! dyld: lazy symbol binding failed: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB has segment 4 which is too large (0..3) dyld: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB has segment 4 which is too large (0..3) Trace/BPT trap: 5 Investigating the code, it seems that the problem is that the asm code generated in the file StubPass.cpp, specifically in the line 323,when it adds, what it seems an arbitrary number (12) to the offset into the lazy bind opcodes section, but it should be calculated depending on the MachONormalizedFileBinaryWrite::lazyBindingInfo result. I confirmed this bug by patching the code manually in the binary and writing the right offset in the asm code (__stub_helper). This patch fixes the content of the atom that contains the assembly code when the offset is known. Differential Revision: https://reviews.llvm.org/D35387 ------------------------------------------------------------------------ llvm-svn: 319825
-rw-r--r--lld/lib/ReaderWriter/MachO/ArchHandler.h4
-rw-r--r--lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp4
-rw-r--r--lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp4
-rw-r--r--lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp4
-rw-r--r--lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp4
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp57
-rw-r--r--lld/test/mach-o/lazy-bind-x86_64.yaml4
7 files changed, 79 insertions, 2 deletions
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler.h b/lld/lib/ReaderWriter/MachO/ArchHandler.h
index 70a63bd1004b..6028006ca9d9 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler.h
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler.h
@@ -112,6 +112,10 @@ public:
/// info in final executables.
virtual bool isLazyPointer(const Reference &);
+ /// Reference from an __stub_helper entry to the required offset of the
+ /// lazy bind commands.
+ virtual Reference::KindValue lazyImmediateLocationKind() = 0;
+
/// Returns true if the specified relocation is paired to the next relocation.
virtual bool isPairedReloc(const normalized::Relocation &) = 0;
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
index 7d1544854cf1..2f663c660f5c 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
@@ -67,6 +67,10 @@ public:
return invalid;
}
+ Reference::KindValue lazyImmediateLocationKind() override {
+ return lazyImmediateLocation;
+ }
+
Reference::KindValue pointerKind() override {
return invalid;
}
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
index 10360b5c6dda..b9c815c5a320 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
@@ -127,6 +127,10 @@ public:
return pointer64;
}
+ Reference::KindValue lazyImmediateLocationKind() override {
+ return lazyImmediateLocation;
+ }
+
uint32_t dwarfCompactUnwindType() override {
return 0x03000000;
}
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
index 2272bff65ccb..a2c68092724d 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
@@ -70,6 +70,10 @@ public:
return delta32;
}
+ Reference::KindValue lazyImmediateLocationKind() override {
+ return lazyImmediateLocation;
+ }
+
Reference::KindValue unwindRefToEhFrameKind() override {
return invalid;
}
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
index d687ca5de5b4..aee9959ca6b8 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
@@ -116,6 +116,10 @@ public:
return unwindFDEToFunction;
}
+ Reference::KindValue lazyImmediateLocationKind() override {
+ return lazyImmediateLocation;
+ }
+
Reference::KindValue unwindRefToEhFrameKind() override {
return unwindInfoToEhFrame;
}
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
index e58e3d2e7a4b..f2e5ed781678 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
@@ -172,6 +172,8 @@ private:
SymbolScope &symbolScope);
void appendSection(SectionInfo *si, NormalizedFile &file);
uint32_t sectionIndexForAtom(const Atom *atom);
+ void fixLazyReferenceImm(const DefinedAtom *atom, uint32_t offset,
+ NormalizedFile &file);
typedef llvm::DenseMap<const Atom*, uint32_t> AtomToIndex;
struct AtomAndIndex { const Atom *atom; uint32_t index; SymbolScope scope; };
@@ -1423,6 +1425,8 @@ void Util::addRebaseAndBindingInfo(const lld::File &atomFile,
uint8_t segmentIndex;
uint64_t segmentStartAddr;
+ uint32_t offsetInBindInfo = 0;
+
for (SectionInfo *sect : _sectionInfos) {
segIndexForSection(sect, segmentIndex, segmentStartAddr);
for (const AtomInfo &info : sect->atomsAndOffsets) {
@@ -1467,6 +1471,59 @@ void Util::addRebaseAndBindingInfo(const lld::File &atomFile,
bind.symbolName = targ->name();
bind.addend = ref->addend();
nFile.lazyBindingInfo.push_back(bind);
+
+ // Now that we know the segmentOffset and the ordinal attribute,
+ // we can fix the helper's code
+
+ fixLazyReferenceImm(atom, offsetInBindInfo, nFile);
+
+ // 5 bytes for opcodes + variable sizes (target name + \0 and offset
+ // encode's size)
+ offsetInBindInfo +=
+ 6 + targ->name().size() + llvm::getULEB128Size(bind.segOffset);
+ if (bind.ordinal > BIND_IMMEDIATE_MASK)
+ offsetInBindInfo += llvm::getULEB128Size(bind.ordinal);
+ }
+ }
+ }
+ }
+}
+
+void Util::fixLazyReferenceImm(const DefinedAtom *atom, uint32_t offset,
+ NormalizedFile &file) {
+ for (const auto &ref : *atom) {
+ const DefinedAtom *da = dyn_cast<DefinedAtom>(ref->target());
+ if (da == nullptr)
+ return;
+
+ const Reference *helperRef = nullptr;
+ for (const Reference *hr : *da) {
+ if (hr->kindValue() == _archHandler.lazyImmediateLocationKind()) {
+ helperRef = hr;
+ break;
+ }
+ }
+ if (helperRef == nullptr)
+ continue;
+
+ // TODO: maybe get the fixed atom content from _archHandler ?
+ for (SectionInfo *sectInfo : _sectionInfos) {
+ for (const AtomInfo &atomInfo : sectInfo->atomsAndOffsets) {
+ if (atomInfo.atom == helperRef->target()) {
+ auto sectionContent =
+ file.sections[sectInfo->normalizedSectionIndex].content;
+ uint8_t *rawb =
+ file.ownedAllocations.Allocate<uint8_t>(sectionContent.size());
+ llvm::MutableArrayRef<uint8_t> newContent{rawb,
+ sectionContent.size()};
+ std::copy(sectionContent.begin(), sectionContent.end(),
+ newContent.begin());
+ llvm::support::ulittle32_t *loc =
+ reinterpret_cast<llvm::support::ulittle32_t *>(
+ &newContent[atomInfo.offsetInSection +
+ helperRef->offsetInAtom()]);
+ *loc = offset;
+ file.sections[sectInfo->normalizedSectionIndex].content = newContent;
}
}
}
diff --git a/lld/test/mach-o/lazy-bind-x86_64.yaml b/lld/test/mach-o/lazy-bind-x86_64.yaml
index 5c588c571952..1322719e5f65 100644
--- a/lld/test/mach-o/lazy-bind-x86_64.yaml
+++ b/lld/test/mach-o/lazy-bind-x86_64.yaml
@@ -80,8 +80,8 @@ undefined-symbols:
# CHECK-HELPERS:Disassembly of section __TEXT,__stub_helper:
# CHECK-HELPERS: 68 00 00 00 00 pushq $0
-# CHECK-HELPERS: 68 10 00 00 00 pushq $16
-# CHECK-HELPERS: 68 20 00 00 00 pushq $32
+# CHECK-HELPERS: 68 0b 00 00 00 pushq $11
+# CHECK-HELPERS: 68 16 00 00 00 pushq $22
# Make sure the stub helper is correctly aligned
# CHECK-DYLIBS: sectname __stub_helper