Problems generating Mach-O File (x86_64 , osx 10.12)

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:

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). I’m yet not familiarized with the code , so i can’t fix it right now , Im unable to find the information of the symbols that MachONormalizedFileBinaryWrite::buildLazyBindInfo has ,since is generated after the pass.

I’ll be glad to receive guidance so i can fix it myself and familiarize myself with the code.

LLD Mach-O support was experimental and AFAIK it is unmaintained. It lacks a lots of features to be usable. The only supported linker on macOS is ld64.

Surely this is not the end-game?

Patricio has submitted a patch to fix this particular issue. Please let us move LLD forward enough in the meantime until llvm devs consider mach-o a first class target of LLD.