Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -338,30 +338,9 @@ bool AbsVal = isAbsoluteValue(Body); bool RelE = isRelExpr(E); - if (AbsVal && !RelE) - return true; - if (!AbsVal && RelE) + if (AbsVal || RelE) return true; - // Relative relocation to an absolute value. This is normally unrepresentable, - // but if the relocation refers to a weak undefined symbol, we allow it to - // resolve to the image base. This is a little strange, but it allows us to - // link function calls to such symbols. Normally such a call will be guarded - // with a comparison, which will load a zero from the GOT. - // Another special case is MIPS _gp_disp symbol which represents offset - // between start of a function and '_gp' value and defined as absolute just - // to simplify the code. - if (AbsVal && RelE) { - if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak()) - return true; - if (&Body == ElfSym::MipsGpDisp) - return true; - error(S.getLocation(RelOff) + ": relocation " + toString(Type) + - " cannot refer to absolute symbol '" + toString(Body) + - "' defined in " + toString(Body.File)); - return true; - } - return Target->usesOnlyLowPageBits(Type); } @@ -442,8 +421,11 @@ if (Body.isGnuIFunc()) { Expr = toPlt(Expr); } else if (!Preemptible) { - if (needsPlt(Expr)) + if (needsPlt(Expr)) { + if (isAbsoluteValue(Body)) + return Expr; Expr = fromPlt(Expr); + } if (Expr == R_GOT_PC && !isAbsoluteValue(Body)) Expr = Target->adjustRelaxExpr(Type, Data, Expr); } Index: test/ELF/linkerscript/symbol-absolute.s =================================================================== --- /dev/null +++ test/ELF/linkerscript/symbol-absolute.s @@ -0,0 +1,12 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "PROVIDE_HIDDEN(base = 0);" > %t.script +# RUN: ld.lld -shared --gc-sections --script %t.script -o %t1 %t +# RUN: llvm-readobj --elf-output-style=GNU --file-headers --symbols %t1 | FileCheck %s +# CHECK: 0000000000000000 0 NOTYPE LOCAL HIDDEN ABS base + +.text +.globl _start +_start: + lea base(%rip),%rax Index: test/ELF/relocation-relative-absolute.s =================================================================== --- test/ELF/relocation-relative-absolute.s +++ test/ELF/relocation-relative-absolute.s @@ -2,11 +2,14 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %tinput1.o # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux \ # RUN: %S/Inputs/relocation-relative-absolute.s -o %tinput2.o -# RUN: not ld.lld %tinput1.o %tinput2.o -o %t -pie 2>&1 | FileCheck %s +# RUN: ld.lld %tinput1.o %tinput2.o -o %t -pie +# RUN: llvm-readobj -dyn-relocations %t | FileCheck %s + +# CHECK: Dynamic Relocations { +# CHECK-NEXT: 0x3018 R_X86_64_JUMP_SLOT - 0x2A +# CHECK-NEXT: } .globl _start _start: -# CHECK: {{.*}}input1.o:(.text+0x1): relocation R_X86_64_PLT32 cannot refer to absolute symbol 'answer' defined in {{.*}}input2.o - call answer@PLT Index: test/ELF/relocation-relative-weak.s =================================================================== --- test/ELF/relocation-relative-weak.s +++ test/ELF/relocation-relative-weak.s @@ -4,6 +4,7 @@ # RUN: llvm-readobj -dyn-relocations %t | FileCheck %s # CHECK: Dynamic Relocations { +# CHECK-NEXT: 0x3018 R_X86_64_JUMP_SLOT - 0x0 # CHECK-NEXT: } .globl _start