Commit d5cd8bc9 authored by Tom Stellard's avatar Tom Stellard
Browse files

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
parent 170dfab4
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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;

+4 −0
Original line number Diff line number Diff line
@@ -67,6 +67,10 @@ public:
    return invalid;
  }

  Reference::KindValue lazyImmediateLocationKind() override {
    return lazyImmediateLocation;
  }

  Reference::KindValue pointerKind() override {
    return invalid;
  }
+4 −0
Original line number Diff line number Diff line
@@ -127,6 +127,10 @@ public:
    return pointer64;
  }

  Reference::KindValue lazyImmediateLocationKind() override {
    return lazyImmediateLocation;
  }

  uint32_t dwarfCompactUnwindType() override {
    return 0x03000000;
  }
+4 −0
Original line number Diff line number Diff line
@@ -70,6 +70,10 @@ public:
    return delta32;
  }

  Reference::KindValue lazyImmediateLocationKind() override {
    return lazyImmediateLocation;
  }

  Reference::KindValue unwindRefToEhFrameKind() override {
    return invalid;
  }
+4 −0
Original line number Diff line number Diff line
@@ -116,6 +116,10 @@ public:
    return unwindFDEToFunction;
  }

  Reference::KindValue lazyImmediateLocationKind() override {
    return lazyImmediateLocation;
  }

  Reference::KindValue unwindRefToEhFrameKind() override {
    return unwindInfoToEhFrame;
  }
Loading