diff options
-rw-r--r-- | lld/ELF/Relocations.cpp | 57 |
1 files changed, 26 insertions, 31 deletions
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 8106868..ae045ee 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -541,35 +541,6 @@ static void errorOrWarn(const Twine &Msg) { warn(Msg); } -// Returns PLT relocation expression. -// -// 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). -static RelExpr getPltExpr(Symbol &Sym, RelExpr Expr, bool &IsConstant) { - Sym.NeedsPltAddr = true; - Sym.IsPreemptible = false; - IsConstant = true; - return toPlt(Expr); -} - // This modifies the expression if we can use a copy relocation or point the // symbol to the PLT. template <class ELFT> @@ -637,8 +608,32 @@ static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type, return Expr; } - if (Sym.isFunc()) - return getPltExpr(Sym, Expr, IsConstant); + 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)); |