diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -134,6 +134,7 @@ for (const section_64 &sec : sections) { InputSection *isec = make(); isec->file = this; + isec->header = &sec; isec->name = StringRef(sec.sectname, strnlen(sec.sectname, 16)); isec->segname = StringRef(sec.segname, strnlen(sec.segname, 16)); isec->data = {buf + sec.offset, static_cast(sec.size)}; diff --git a/lld/MachO/InputSection.h b/lld/MachO/InputSection.h --- a/lld/MachO/InputSection.h +++ b/lld/MachO/InputSection.h @@ -40,6 +40,8 @@ StringRef name; StringRef segname; + // This provides access to the address of the section in the input file. + const llvm::MachO::section_64 *header; ArrayRef data; // TODO these properties ought to live in an OutputSection class. diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp --- a/lld/MachO/InputSection.cpp +++ b/lld/MachO/InputSection.cpp @@ -47,7 +47,16 @@ else va = s->getVA(); } else { - fatal("TODO: Non-extern relocations are not supported"); + uint32_t sectIdx = rel.r_symbolnum - 1; + if (sectIdx > file->sections.size()) + fatal("Relocation section index is greater than number of sections"); + InputSection *isec = file->sections[sectIdx]; + va = isec->addr; + // The implicit addend for pcrel section relocations is the pcrel offset + // in terms of the addresses in the input file. Here we adjust it so that + // it describes the offset from the start of the relocated section. + // TODO: Figure out what to do for non-pcrel section relocations. + addend -= isec->header->addr - (rel.r_address + 4); } uint64_t val = va + addend; diff --git a/lld/test/MachO/relocations.s b/lld/test/MachO/relocations.s --- a/lld/test/MachO/relocations.s +++ b/lld/test/MachO/relocations.s @@ -12,9 +12,12 @@ # CHECK-LABEL: <_main>: ## Test X86_64_RELOC_BRANCH # CHECK: callq 0x[[#%x, F_ADDR]] <_f> -## Test X86_64_RELOC_SIGNED +## Test extern (symbol) X86_64_RELOC_SIGNED # CHECK: leaq [[#%u, STR_OFF:]](%rip), %rsi # CHECK-NEXT: [[#%x, CSTRING_ADDR - STR_OFF]] +## Test non-extern (section) X86_64_RELOC_SIGNED +# CHECK: leaq [[#%u, LSTR_OFF:]](%rip), %rsi +# CHECK-NEXT: [[#%x, CSTRING_ADDR + 22 - LSTR_OFF]] .section __TEXT,__text .globl _main, _f @@ -26,11 +29,21 @@ _f: movl $0x2000004, %eax # write() syscall mov $1, %rdi # stdout - leaq str(%rip), %rsi - mov $13, %rdx # length of str + leaq _str(%rip), %rsi + mov $21, %rdx # length of str + syscall + + movl $0x2000004, %eax # write() syscall + mov $1, %rdi # stdout + leaq L_.str(%rip), %rsi + mov $15, %rdx # length of str syscall ret .section __TEXT,__cstring -str: - .asciz "Hello world!\n" +## References to this generate a symbol relocation +_str: + .asciz "Local defined symbol\n" +## References to this generate a section relocation +L_.str: + .asciz "Private symbol\n"