diff --git a/lld/MachO/Arch/X86_64.cpp b/lld/MachO/Arch/X86_64.cpp --- a/lld/MachO/Arch/X86_64.cpp +++ b/lld/MachO/Arch/X86_64.cpp @@ -47,6 +47,8 @@ case X86_64_RELOC_SIGNED_4: case X86_64_RELOC_GOT_LOAD: return read32le(loc); + case X86_64_RELOC_UNSIGNED: + return read64le(loc); default: error("TODO: Unhandled relocation type " + std::to_string(type)); return 0; @@ -65,6 +67,9 @@ // since the RIP has advanced by 4 at this point. write32le(loc, val - 4); break; + case X86_64_RELOC_UNSIGNED: + write64le(loc, val); + break; default: llvm_unreachable( "getImplicitAddend should have flagged all unhandled relocation types"); diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -173,11 +173,10 @@ fatal("TODO: Scattered relocations not supported"); auto rel = reinterpret_cast(anyRel); - if (!rel.r_pcrel) - fatal("TODO: Only pcrel relocations are supported"); Reloc r; r.type = rel.r_type; + r.pcrel = rel.r_pcrel; uint32_t secRelOffset = rel.r_address; uint64_t rawAddend = target->getImplicitAddend(buf + sec.offset + secRelOffset, r.type); @@ -186,6 +185,9 @@ 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 + diff --git a/lld/MachO/InputSection.h b/lld/MachO/InputSection.h --- a/lld/MachO/InputSection.h +++ b/lld/MachO/InputSection.h @@ -24,12 +24,13 @@ struct Reloc { uint8_t type; - // Adding this offset to the address of the target symbol or subsection gives - // the destination that this relocation refers to. - uint32_t addend; + bool pcrel; // The offset from the start of the subsection that this relocation belongs // to. uint32_t offset; + // Adding this offset to the address of the target symbol or subsection gives + // the destination that this relocation refers to. + uint64_t addend; llvm::PointerUnion target; }; diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp --- a/lld/MachO/InputSection.cpp +++ b/lld/MachO/InputSection.cpp @@ -43,7 +43,7 @@ } uint64_t val = va + r.addend; - if (1) // TODO: handle non-pcrel relocations + if (r.pcrel) val -= getVA() + r.offset; target->relocateOne(buf + r.offset, r.type, val); } diff --git a/lld/MachO/Target.h b/lld/MachO/Target.h --- a/lld/MachO/Target.h +++ b/lld/MachO/Target.h @@ -29,6 +29,7 @@ class TargetInfo { public: virtual ~TargetInfo() = default; + virtual uint64_t getImplicitAddend(const uint8_t *loc, uint8_t type) const = 0; virtual void relocateOne(uint8_t *loc, uint8_t type, uint64_t val) const = 0; diff --git a/lld/test/MachO/x86-64-reloc-unsigned.s b/lld/test/MachO/x86-64-reloc-unsigned.s new file mode 100644 --- /dev/null +++ b/lld/test/MachO/x86-64-reloc-unsigned.s @@ -0,0 +1,24 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o +# RUN: lld -flavor darwinnew -o %t %t.o +# RUN: llvm-objdump --full-contents %t | FileCheck %s +# CHECK: Contents of section foo: +# CHECK: 2000 08200000 00000000 +# CHECK: Contents of section bar: +# CHECK: 2008 11311111 01000000 + +.globl _main, _foo, _bar + +.section __DATA,foo +_foo: +.quad _bar + +.section __DATA,bar +_bar: +## The unsigned relocation should support 64-bit addends +.quad _foo + 0x111111111 + +.text +_main: + mov $0, %rax + ret