diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -185,9 +185,6 @@ r.target = symbols[rel.r_symbolnum]; r.addend = rawAddend; } else { - if (!rel.r_pcrel) - fatal("TODO: Only pcrel section relocations are supported"); - if (rel.r_symbolnum == 0 || rel.r_symbolnum > subsections.size()) fatal("invalid section index in relocation for offset " + std::to_string(r.offset) + " in section " + sec.sectname + @@ -195,14 +192,19 @@ SubsectionMap &targetSubsecMap = subsections[rel.r_symbolnum - 1]; const section_64 &targetSec = sectionHeaders[rel.r_symbolnum - 1]; - // 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 target section. - // TODO: Figure out what to do for non-pcrel section relocations. - // TODO: The offset of 4 is probably not right for ARM64, nor for - // relocations with r_length != 2. - uint32_t targetOffset = - sec.addr + rel.r_address + 4 + rawAddend - targetSec.addr; + uint32_t targetOffset; + if (rel.r_pcrel) { + // 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 target section. + // TODO: The offset of 4 is probably not right for ARM64, nor for + // relocations with r_length != 2. + targetOffset = + sec.addr + rel.r_address + 4 + rawAddend - targetSec.addr; + } else { + // The addend for a non-pcrel relocation is its absolute address. + targetOffset = rawAddend - targetSec.addr; + } r.target = findContainingSubsection(targetSubsecMap, &targetOffset); r.addend = targetOffset; } 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 @@ -19,6 +19,10 @@ # CHECK: leaq [[#%u, LSTR_OFF:]](%rip), %rsi # CHECK-NEXT: [[#%x, CSTRING_ADDR + 22 - LSTR_OFF]] +# RUN: llvm-objdump --section=__const --full-contents -d %t | FileCheck %s --check-prefix=NONPCREL +# NONPCREL: Contents of section __const: +# NONPCREL-NEXT: 100001000 b0030000 01000000 b0030000 01000000 + .section __TEXT,__text .globl _main, _f _main: @@ -29,13 +33,19 @@ _f: movl $0x2000004, %eax # write() syscall mov $1, %rdi # stdout - leaq _str(%rip), %rsi + leaq _str(%rip), %rsi # This generates a pcrel symbol relocation mov $21, %rdx # length of str syscall movl $0x2000004, %eax # write() syscall mov $1, %rdi # stdout - leaq L_.str(%rip), %rsi + leaq L_.str(%rip), %rsi # This generates a pcrel section relocation + mov $15, %rdx # length of str + syscall + + movl $0x2000004, %eax # write() syscall + mov $1, %rdi # stdout + movq L_.ptr_1_to_str(%rip), %rsi mov $15, %rdx # length of str syscall ret @@ -47,3 +57,10 @@ ## References to this generate a section relocation L_.str: .asciz "Private symbol\n" + +.section __DATA,__const +## These generate non-pcrel section relocations +L_.ptr_1_to_str: + .quad L_.str +L_.ptr_2_to_str: + .quad L_.str