Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -347,10 +347,11 @@ InputSectionBase &S, uint64_t RelOff) { // These expressions always compute a constant if (isRelExprOneOf(E)) + R_MIPS_GOTREL, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, + R_MIPS_GOT_GP_PC, R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, + R_GOTONLY_PC, R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_PC, + R_TLSGD, R_PPC_PLT_OPD, R_TLSDESC_CALL, R_TLSDESC_PAGE, + R_HINT>(E)) return true; // These never do, except if the entire file is position dependent or if @@ -526,7 +527,6 @@ // interpose any aliases. for (SharedSymbol *Sym : getSymbolsAt(SS)) { Sym->CopyRelSec = Sec; - Sym->IsPreemptible = false; Sym->IsUsedInRegularObj = true; Sym->Used = true; } @@ -541,105 +541,6 @@ warn(Msg); } -// This modifies the expression if we can use a copy relocation or point the -// symbol to the PLT. -template -static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type, - InputSectionBase &S, uint64_t RelOff, - bool &IsConstant) { - // If a relocation can be applied at link-time, we don't need to - // create a dynamic relocation in the first place. - if (IsConstant) - return Expr; - - // We can create any dynamic relocation supported by the dynamic linker if a - // section is writable or we are passed -z notext. - bool CanWrite = (S.Flags & SHF_WRITE) || !Config->ZText; - if (CanWrite && Target->isPicRel(Type)) - return Expr; - - // If the relocation is to a weak undef, and we are producing - // executable, give up on it and produce a non preemptible 0. - if (!Config->Shared && Sym.isUndefWeak()) { - Sym.IsPreemptible = false; - IsConstant = true; - return Expr; - } - - // If we got here we know that this relocation would require the dynamic - // linker to write a value to read only memory or use an unsupported - // relocation. - - // We can hack around it if we are producing an executable and - // the refered symbol can be preemepted to refer to the executable. - if (!CanWrite && (Config->Shared || (Config->Pic && !isRelExpr(Expr)))) { - error( - "can't create dynamic relocation " + toString(Type) + " against " + - (Sym.getName().empty() ? "local symbol" : "symbol: " + toString(Sym)) + - " in readonly segment; recompile object files with -fPIC" + - getLocation(S, Sym, RelOff)); - return Expr; - } - - // Copy relocations are only possible if we are creating an executable and the - // symbol is shared. - if (!Sym.isShared() || Config->Shared) - return Expr; - - if (Sym.getVisibility() != STV_DEFAULT) { - error("cannot preempt symbol: " + toString(Sym) + - getLocation(S, Sym, RelOff)); - return Expr; - } - - if (Sym.isObject()) { - // Produce a copy relocation. - auto *B = dyn_cast(&Sym); - if (B && !B->CopyRelSec) { - if (Config->ZNocopyreloc) - error("unresolvable relocation " + toString(Type) + - " against symbol '" + toString(*B) + - "'; recompile with -fPIC or remove '-z nocopyreloc'" + - getLocation(S, Sym, RelOff)); - - addCopyRelSymbol(*B); - } - IsConstant = true; - return Expr; - } - - if (Sym.isFunc()) { - // This handles a non PIC program call to function in a shared library. In - // an ideal world, we could just report an error saying the relocation can - // overflow at runtime. In the real world with glibc, crt1.o has a - // R_X86_64_PC32 pointing to libc.so. - // - // The general idea on how to handle such cases is to create a PLT entry and - // use that as the function value. - // - // For the static linking part, we just return a plt expr and everything - // else will use the the PLT entry as the address. - // - // The remaining problem is making sure pointer equality still works. We - // need the help of the dynamic linker for that. We let it know that we have - // a direct reference to a so symbol by creating an undefined symbol with a - // non zero st_value. Seeing that, the dynamic linker resolves the symbol to - // the value of the symbol we created. This is true even for got entries, so - // pointer equality is maintained. To avoid an infinite loop, the only entry - // that points to the real function is a dedicated got entry used by the - // plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT, - // R_386_JMP_SLOT, etc). - Sym.NeedsPltAddr = true; - Sym.IsPreemptible = false; - IsConstant = true; - return toPlt(Expr); - } - - errorOrWarn("symbol '" + toString(Sym) + "' has no type" + - getLocation(S, Sym, RelOff)); - return Expr; -} - // MIPS has an odd notion of "paired" relocations to calculate addends. // For example, if a relocation is of R_MIPS_HI16, there must be a // R_MIPS_LO16 relocation after that, and an addend is calculated using @@ -797,14 +698,14 @@ template static void addPltEntry(PltSection *Plt, GotPltSection *GotPlt, - RelocationBaseSection *Rel, RelType Type, Symbol &Sym, - bool UseSymVA) { + RelocationBaseSection *Rel, RelType Type, Symbol &Sym) { Plt->addEntry(Sym); GotPlt->addEntry(Sym); - Rel->addReloc({Type, GotPlt, Sym.getGotPltOffset(), UseSymVA, &Sym, 0}); + Rel->addReloc( + {Type, GotPlt, Sym.getGotPltOffset(), !Sym.IsPreemptible, &Sym, 0}); } -template static void addGotEntry(Symbol &Sym, bool Preemptible) { +template static void addGotEntry(Symbol &Sym) { InX::Got->addEntry(Sym); RelExpr Expr = Sym.isTls() ? R_TLS : R_ABS; @@ -817,7 +718,8 @@ // add a static relocation to a Relocations vector so that // InputSection::relocate will do the work for us. We may be able // to just write a value now, but it is a TODO.) - bool IsLinkTimeConstant = !Preemptible && (!Config->Pic || isAbsolute(Sym)); + bool IsLinkTimeConstant = + !Sym.IsPreemptible && (!Config->Pic || isAbsolute(Sym)); if (IsLinkTimeConstant) { InX::Got->Relocations.push_back({Expr, Target->GotRel, Off, 0, &Sym}); return; @@ -828,12 +730,12 @@ RelType Type; if (Sym.isTls()) Type = Target->TlsGotRel; - else if (!Preemptible && Config->Pic && !isAbsolute(Sym)) + else if (!Sym.IsPreemptible && Config->Pic && !isAbsolute(Sym)) Type = Target->RelativeRel; else Type = Target->GotRel; - InX::RelaDyn->addReloc(Type, InX::Got, Off, !Preemptible, &Sym, 0, R_ABS, - Target->GotRel); + InX::RelaDyn->addReloc(Type, InX::Got, Off, !Sym.IsPreemptible, &Sym, 0, + R_ABS, Target->GotRel); } // The reason we have to do this early scan is as follows @@ -849,6 +751,131 @@ // sections. Given that it is ro, we will need an extra PT_LOAD. This // complicates things for the dynamic linker and means we would have to reserve // space for the extra PT_LOAD even if we end up not using it. +template +static RelExpr processRelocAux(InputSectionBase &Sec, RelExpr Expr, + RelType Type, uint64_t Offset, Symbol &Sym, + const RelTy &Rel, int64_t Addend) { + if (isStaticLinkTimeConstant(Expr, Type, Sym, Sec, Offset)) { + Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); + return Expr; + } + bool CanWrite = (Sec.Flags & SHF_WRITE) || !Config->ZText; + if (CanWrite) { + // R_GOT refers to a position in the got, even if the symbol is preemptible. + bool IsPreemptibleValue = Sym.IsPreemptible && Expr != R_GOT; + + if (!IsPreemptibleValue) { + InX::RelaDyn->addReloc(Target->RelativeRel, &Sec, Offset, true, &Sym, + Addend, Expr, Type); + return Expr; + } else if (Target->isPicRel(Type)) { + InX::RelaDyn->addReloc( + {Target->getDynRel(Type), &Sec, Offset, false, &Sym, Addend}); + + // MIPS ABI turns using of GOT and dynamic relocations inside out. + // While regular ABI uses dynamic relocations to fill up GOT entries + // MIPS ABI requires dynamic linker to fills up GOT entries using + // specially sorted dynamic symbol table. This affects even dynamic + // relocations against symbols which do not require GOT entries + // creation explicitly, i.e. do not have any GOT-relocations. So if + // a preemptible symbol has a dynamic relocation we anyway have + // to create a GOT entry for it. + // If a non-preemptible symbol has a dynamic relocation against it, + // dynamic linker takes it st_value, adds offset and writes down + // result of the dynamic relocation. In case of preemptible symbol + // dynamic linker performs symbol resolution, writes the symbol value + // to the GOT entry and reads the GOT entry when it needs to perform + // a dynamic relocation. + // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf p.4-19 + if (Config->EMachine == EM_MIPS) + InX::MipsGot->addEntry(Sym, Addend, Expr); + return Expr; + } + } + + // If the relocation is to a weak undef, and we are producing + // executable, give up on it and produce a non preemptible 0. + if (!Config->Shared && Sym.isUndefWeak()) { + Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); + return Expr; + } + + if (!CanWrite && (Config->Pic && !isRelExpr(Expr))) { + error( + "can't create dynamic relocation " + toString(Type) + " against " + + (Sym.getName().empty() ? "local symbol" : "symbol: " + toString(Sym)) + + " in readonly segment; recompile object files with -fPIC" + + getLocation(Sec, Sym, Offset)); + return Expr; + } + + // Copy relocations are only possible if we are creating an executable. + if (Config->Shared) { + errorOrWarn("relocation " + toString(Type) + + " cannot be used against symbol " + toString(Sym) + + "; recompile with -fPIC" + getLocation(Sec, Sym, Offset)); + return Expr; + } + + // If the symbol is undefined we already reported any relevant errors. + if (!Sym.isShared()) { + assert(Sym.isUndefined()); + return Expr; + } + + if (Sym.getVisibility() != STV_DEFAULT) { + error("cannot preempt symbol: " + toString(Sym) + + getLocation(Sec, Sym, Offset)); + return Expr; + } + + if (Sym.isObject()) { + // Produce a copy relocation. + auto &SS = cast(Sym); + if (!SS.CopyRelSec) { + if (Config->ZNocopyreloc) + error("unresolvable relocation " + toString(Type) + + " against symbol '" + toString(SS) + + "'; recompile with -fPIC or remove '-z nocopyreloc'" + + getLocation(Sec, Sym, Offset)); + addCopyRelSymbol(SS); + } + Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); + return Expr; + } + + if (Sym.isFunc()) { + // This handles a non PIC program call to function in a shared library. In + // an ideal world, we could just report an error saying the relocation can + // overflow at runtime. In the real world with glibc, crt1.o has a + // R_X86_64_PC32 pointing to libc.so. + // + // The general idea on how to handle such cases is to create a PLT entry and + // use that as the function value. + // + // For the static linking part, we just return a plt expr and everything + // else will use the the PLT entry as the address. + // + // The remaining problem is making sure pointer equality still works. We + // need the help of the dynamic linker for that. We let it know that we have + // a direct reference to a so symbol by creating an undefined symbol with a + // non zero st_value. Seeing that, the dynamic linker resolves the symbol to + // the value of the symbol we created. This is true even for got entries, so + // pointer equality is maintained. To avoid an infinite loop, the only entry + // that points to the real function is a dedicated got entry used by the + // plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT, + // R_386_JMP_SLOT, etc). + Sym.NeedsPltAddr = true; + Expr = toPlt(Expr); + Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); + return Expr; + } + + errorOrWarn("symbol '" + toString(Sym) + "' has no type" + + getLocation(Sec, Sym, Offset)); + return Expr; +} + template static void scanReloc(InputSectionBase &Sec, OffsetGetter &GetOffset, RelTy *&I, RelTy *End) { @@ -881,20 +908,6 @@ if (isRelExprOneOf(Expr)) return; - // In case of MIPS GP-relative relocations always resolve to a definition - // in a regular input file, ignoring the one-definition rule. So we, - // for example, should not attempt to create a dynamic relocation even - // if the target symbol is preemptible. There are two two MIPS GP-relative - // relocations R_MIPS_GPREL16 and R_MIPS_GPREL32. But only R_MIPS_GPREL16 - // can be against a preemptible symbol. - if (Expr == R_MIPS_GOTREL) { - int64_t Addend = computeAddend(Rel, End, Sec, Expr, Sym.isLocal()); - Sec.Relocations.push_back({R_MIPS_GOTREL, Type, Offset, Addend, &Sym}); - return; - } - - bool Preemptible = Sym.IsPreemptible; - // Strenghten or relax relocations. // // GNU ifunc symbols must be accessed via PLT because their addresses @@ -908,18 +921,11 @@ // is always at the beginning of a search list. We can leverage that fact. if (Sym.isGnuIFunc()) Expr = toPlt(Expr); - else if (!Preemptible && Expr == R_GOT_PC && !isAbsoluteValue(Sym)) + else if (!Sym.IsPreemptible && Expr == R_GOT_PC && !isAbsoluteValue(Sym)) Expr = Target->adjustRelaxExpr(Type, RelocatedAddr, Expr); - else if (!Preemptible) + else if (!Sym.IsPreemptible) Expr = fromPlt(Expr); - bool IsConstant = - isStaticLinkTimeConstant(Expr, Type, Sym, Sec, Rel.r_offset); - - Expr = adjustExpr(Sym, Expr, Type, Sec, Rel.r_offset, IsConstant); - if (errorCount()) - return; - // This relocation does not require got entry, but it is relative to got and // needs it to be created. Here we request for that. if (isRelExprOneOf(Sec, Expr, Type, Offset, Sym, Rel, Addend); // If a relocation needs PLT, we create PLT and GOTPLT slots for the symbol. if (needsPlt(Expr) && !Sym.isInPlt()) { - if (Sym.isGnuIFunc() && !Preemptible) + if (Sym.isGnuIFunc() && !Sym.IsPreemptible) addPltEntry(InX::Iplt, InX::IgotPlt, InX::RelaIplt, - Target->IRelativeRel, Sym, true); + Target->IRelativeRel, Sym); else addPltEntry(InX::Plt, InX::GotPlt, InX::RelaPlt, Target->PltRel, - Sym, !Preemptible); + Sym); } // Create a GOT slot if a relocation needs GOT. @@ -962,56 +969,9 @@ InX::RelaDyn->addReloc({Target->TlsGotRel, InX::MipsGot, Sym.getGotOffset(), false, &Sym, 0}); } else if (!Sym.isInGot()) { - addGotEntry(Sym, Preemptible); + addGotEntry(Sym); } } - - if (!needsPlt(Expr) && !needsGot(Expr) && Sym.IsPreemptible) { - // We don't know anything about the finaly symbol. Just ask the dynamic - // linker to handle the relocation for us. - if (!Target->isPicRel(Type)) - errorOrWarn("relocation " + toString(Type) + - " cannot be used against symbol " + toString(Sym) + - "; recompile with -fPIC" + getLocation(Sec, Sym, Offset)); - - InX::RelaDyn->addReloc( - {Target->getDynRel(Type), &Sec, Offset, false, &Sym, Addend}); - - // MIPS ABI turns using of GOT and dynamic relocations inside out. - // While regular ABI uses dynamic relocations to fill up GOT entries - // MIPS ABI requires dynamic linker to fills up GOT entries using - // specially sorted dynamic symbol table. This affects even dynamic - // relocations against symbols which do not require GOT entries - // creation explicitly, i.e. do not have any GOT-relocations. So if - // a preemptible symbol has a dynamic relocation we anyway have - // to create a GOT entry for it. - // If a non-preemptible symbol has a dynamic relocation against it, - // dynamic linker takes it st_value, adds offset and writes down - // result of the dynamic relocation. In case of preemptible symbol - // dynamic linker performs symbol resolution, writes the symbol value - // to the GOT entry and reads the GOT entry when it needs to perform - // a dynamic relocation. - // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf p.4-19 - if (Config->EMachine == EM_MIPS) - InX::MipsGot->addEntry(Sym, Addend, Expr); - return; - } - - // If the produced value is a constant, we just remember to write it - // when outputting this section. We also have to do it if the format - // uses Elf_Rel, since in that case the written value is the addend. - if (IsConstant) { - Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); - return; - } - - // If the output being produced is position independent, the final value - // is still not known. In that case we still need some help from the - // dynamic linker. We can however do better than just copying the incoming - // relocation. We can process some of it and and just ask the dynamic - // linker to add the load address. - InX::RelaDyn->addReloc(Target->RelativeRel, &Sec, Offset, true, &Sym, Addend, - Expr, Type); } template Index: test/ELF/aarch64-fpic-adr_prel_lo21.s =================================================================== --- test/ELF/aarch64-fpic-adr_prel_lo21.s +++ test/ELF/aarch64-fpic-adr_prel_lo21.s @@ -1,7 +1,7 @@ // REQUIRES: aarch64 // RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o // RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s -// CHECK: can't create dynamic relocation R_AARCH64_ADR_PREL_LO21 against symbol: dat +// CHECK: relocation R_AARCH64_ADR_PREL_LO21 cannot be used against symbol dat; recompile with -fPIC // CHECK: >>> defined in {{.*}}.o // CHECK: >>> referenced by {{.*}}.o:(.text+0x0) Index: test/ELF/aarch64-fpic-adr_prel_pg_hi21.s =================================================================== --- test/ELF/aarch64-fpic-adr_prel_pg_hi21.s +++ test/ELF/aarch64-fpic-adr_prel_pg_hi21.s @@ -1,7 +1,7 @@ // REQUIRES: aarch64 // RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o // RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s -// CHECK: can't create dynamic relocation R_AARCH64_ADR_PREL_PG_HI21 against symbol: dat +// CHECK: relocation R_AARCH64_ADR_PREL_PG_HI21 cannot be used against symbol dat; recompile with -fPIC // CHECK: >>> defined in {{.*}}.o // CHECK: >>> referenced by {{.*}}.o:(.text+0x0) Index: test/ELF/got32-i386-pie-rw.s =================================================================== --- test/ELF/got32-i386-pie-rw.s +++ test/ELF/got32-i386-pie-rw.s @@ -7,8 +7,8 @@ # CHECK: .foobar PROGBITS 00001000 # CHECK: .got PROGBITS [[GOT:[0-9a-z]*]] -# CHECK: [[GOT]] 00000008 R_386_RELATIVE # CHECK: 00001002 00000008 R_386_RELATIVE +# CHECK: [[GOT]] 00000008 R_386_RELATIVE foo: .section .foobar, "awx" Index: test/ELF/i386-got-and-copy.s =================================================================== --- test/ELF/i386-got-and-copy.s +++ test/ELF/i386-got-and-copy.s @@ -15,6 +15,7 @@ # CHECK: Relocations [ # CHECK-NEXT: Section (4) .rel.dyn { # CHECK-NEXT: 0x{{[0-9A-F]+}} R_386_COPY foo +# CHECK-NEXT: 0x{{[0-9A-F]+}} R_386_GLOB_DAT foo # CHECK-NEXT: } # CHECK-NEXT: ] Index: test/ELF/mips-got-and-copy.s =================================================================== --- test/ELF/mips-got-and-copy.s +++ test/ELF/mips-got-and-copy.s @@ -23,13 +23,17 @@ # CHECK-NEXT: Reserved entries [ # CHECK: ] # CHECK-NEXT: Local entries [ +# CHECK-NEXT: ] +# CHECK-NEXT: Global entries [ # CHECK-NEXT: Entry { # CHECK-NEXT: Address: # CHECK-NEXT: Access: -32744 # CHECK-NEXT: Initial: 0x[[DATA0]] +# CHECK-NEXT: Value: 0x[[DATA0]] +# CHECK-NEXT: Type: Object +# CHECK-NEXT: Section: .bss +# CHECK-NEXT: Name: data0@ # CHECK-NEXT: } -# CHECK-NEXT: ] -# CHECK-NEXT: Global entries [ # CHECK-NEXT: Entry { # CHECK-NEXT: Address: # CHECK-NEXT: Access: -32740 Index: test/ELF/x86-64-dyn-rel-error.s =================================================================== --- test/ELF/x86-64-dyn-rel-error.s +++ test/ELF/x86-64-dyn-rel-error.s @@ -11,4 +11,6 @@ // CHECK: relocation R_X86_64_32 cannot be used against symbol zed; recompile with -fPIC -// RUN: ld.lld --noinhibit-exec %t.o %t2.so -o %t 2>&1 | FileCheck %s +// RUN: ld.lld --noinhibit-exec %t.o %t2.so -o %t 2>&1 | FileCheck --check-prefix=WARN %s + +// WARN: symbol 'zed' has no type