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,18 @@ 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 @@ -29,13 +29,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_to_str(%rip), %rsi mov $15, %rdx # length of str syscall ret @@ -47,3 +53,8 @@ ## References to this generate a section relocation L_.str: .asciz "Private symbol\n" + +.section __DATA,__const +L_.ptr_to_str: +## This generates a non-pcrel section relocation + .quad L_.str