diff options
-rw-r--r-- | lld/ELF/Writer.cpp | 95 |
1 files changed, 48 insertions, 47 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index d4bfc639195..44fa72ee354 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -505,54 +505,55 @@ RelExpr Writer<ELFT>::adjustExpr(SymbolBody &Body, bool IsWrite, RelExpr Expr, return fromPlt(Expr); } - if (!IsWrite && !refersToGotEntry(Expr) && !needsPlt(Expr) && Preemptible) { - // This relocation would require the dynamic linker to write a value - // to read only memory. We can hack around it if we are producing an - // executable and the refered symbol can be preemepted to refer to the - // executable. - if (Config->Shared) { - StringRef S = getELFRelocationTypeName(Config->EMachine, Type); - error("relocation " + S + " cannot be used when making a shared " - "object; recompile with -fPIC."); - return Expr; - } - if (Body.getVisibility() != STV_DEFAULT) { - error("Cannot preempt symbol"); - return Expr; - } - if (Body.isObject()) { - // Produce a copy relocation. - auto *B = cast<SharedSymbol<ELFT>>(&Body); - if (!B->needsCopy()) - addCopyRelSymbol(B); - return Expr; - } - if (Body.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). - Body.NeedsCopyOrPltAddr = true; - return toPlt(Expr); - } - error("Symbol is missing type"); + if (IsWrite || refersToGotEntry(Expr) || needsPlt(Expr) || !Preemptible) + return Expr; + + // This relocation would require the dynamic linker to write a value to read + // only memory. We can hack around it if we are producing an executable and + // the refered symbol can be preemepted to refer to the executable. + if (Config->Shared) { + StringRef S = getELFRelocationTypeName(Config->EMachine, Type); + error("relocation " + S + " cannot be used when making a shared " + "object; recompile with -fPIC."); + return Expr; + } + if (Body.getVisibility() != STV_DEFAULT) { + error("Cannot preempt symbol"); + return Expr; + } + if (Body.isObject()) { + // Produce a copy relocation. + auto *B = cast<SharedSymbol<ELFT>>(&Body); + if (!B->needsCopy()) + addCopyRelSymbol(B); + return Expr; } + if (Body.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). + Body.NeedsCopyOrPltAddr = true; + return toPlt(Expr); + } + error("Symbol is missing type"); + return Expr; } |