Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -591,45 +591,33 @@ } } -static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, - uint64_t P, const Symbol &Sym, RelExpr Expr) { +static uint64_t calcAArch64ExprVA(const InputFile *File, RelType Type, + int64_t A, uint64_t P, const Symbol &Sym, + RelExpr Expr) { switch (Expr) { - case R_INVALID: - return 0; - case R_ABS: - case R_RELAX_TLS_LD_TO_LE_ABS: - case R_RELAX_GOT_PC_NOPIC: - return Sym.getVA(A); - case R_ADDEND: - return A; - case R_ARM_SBREL: - return Sym.getVA(A) - getARMStaticBase(Sym); - case R_GOT: - case R_RELAX_TLS_GD_TO_IE_ABS: - return Sym.getGotVA() + A; - case R_GOTONLY_PC: - return In.Got->getVA() + A - P; - case R_GOTONLY_PC_FROM_END: - return In.Got->getVA() + A - P + In.Got->getSize(); - case R_GOTREL: - return Sym.getVA(A) - In.Got->getVA(); - case R_GOTREL_FROM_END: - return Sym.getVA(A) - In.Got->getVA() - In.Got->getSize(); - case R_GOT_FROM_END: - case R_RELAX_TLS_GD_TO_IE_END: - return Sym.getGotOffset() + A - In.Got->getSize(); - case R_TLSLD_GOT_OFF: - case R_GOT_OFF: - case R_RELAX_TLS_GD_TO_IE_GOT_OFF: - return Sym.getGotOffset() + A; case R_AARCH64_GOT_PAGE_PC: case R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC: return getAArch64Page(Sym.getGotVA() + A) - getAArch64Page(P); - case R_GOT_PC: - case R_RELAX_TLS_GD_TO_IE: - return Sym.getGotVA() + A - P; - case R_HEXAGON_GOT: - return Sym.getGotVA() - In.GotPlt->getVA(); + case R_AARCH64_PAGE_PC: { + uint64_t Val = Sym.isUndefWeak() ? A : Sym.getVA(A); + return getAArch64Page(Val) - getAArch64Page(P); + } + case R_AARCH64_PLT_PAGE_PC: { + uint64_t Val = Sym.isUndefWeak() ? A : Sym.getPltVA() + A; + return getAArch64Page(Val) - getAArch64Page(P); + } + case R_AARCH64_TLSDESC_PAGE: + return getAArch64Page(In.Got->getGlobalDynAddr(Sym) + A) - + getAArch64Page(P); + + default: + llvm_unreachable("invalid expression"); + } +} + +static uint64_t calcMipsExprVA(const InputFile *File, RelType Type, int64_t A, + uint64_t P, const Symbol &Sym, RelExpr Expr) { + switch (Expr) { case R_MIPS_GOTREL: return Sym.getVA(A) - In.MipsGot->getGp(File); case R_MIPS_GOT_GP: @@ -668,40 +656,14 @@ case R_MIPS_TLSLD: return In.MipsGot->getVA() + In.MipsGot->getTlsIndexOffset(File) - In.MipsGot->getGp(File); - case R_AARCH64_PAGE_PC: { - uint64_t Val = Sym.isUndefWeak() ? A : Sym.getVA(A); - return getAArch64Page(Val) - getAArch64Page(P); - } - case R_AARCH64_PLT_PAGE_PC: { - uint64_t Val = Sym.isUndefWeak() ? A : Sym.getPltVA() + A; - return getAArch64Page(Val) - getAArch64Page(P); - } - case R_RISCV_PC_INDIRECT: { - const Relocation *HiRel = getRISCVPCRelHi20(&Sym, A); - if (!HiRel) - return 0; - return getRelocTargetVA(File, HiRel->Type, HiRel->Addend, Sym.getVA(), - *HiRel->Sym, HiRel->Expr); - } - case R_PC: { - uint64_t Dest; - if (Sym.isUndefWeak()) { - // On ARM and AArch64 a branch to an undefined weak resolves to the - // next instruction, otherwise the place. - if (Config->EMachine == EM_ARM) - Dest = getARMUndefinedRelativeWeakVA(Type, A, P); - else if (Config->EMachine == EM_AARCH64) - Dest = getAArch64UndefinedRelativeWeakVA(Type, A, P); - else - Dest = Sym.getVA(A); - } else { - Dest = Sym.getVA(A); - } - return Dest - P; + default: + llvm_unreachable("invalid expression"); } - case R_PLT: - return Sym.getPltVA() + A; - case R_PLT_PC: +} + +static uint64_t calcPPCExprVA(const InputFile *File, RelType Type, int64_t A, + uint64_t P, const Symbol &Sym, RelExpr Expr) { + switch (Expr) { case R_PPC_CALL_PLT: return Sym.getPltVA() + A - P; case R_PPC_CALL: { @@ -722,6 +684,57 @@ } case R_PPC_TOC: return getPPC64TocBase() + A; + default: + llvm_unreachable("invalid expression"); + } +} + +static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, + uint64_t P, const Symbol &Sym, RelExpr Expr) { + switch (Expr) { + case R_INVALID: + return 0; + case R_ABS: + case R_RELAX_TLS_LD_TO_LE_ABS: + case R_RELAX_GOT_PC_NOPIC: + return Sym.getVA(A); + case R_ADDEND: + return A; + case R_GOT: + case R_RELAX_TLS_GD_TO_IE_ABS: + return Sym.getGotVA() + A; + case R_GOTONLY_PC: + return In.Got->getVA() + A - P; + case R_GOTONLY_PC_FROM_END: + return In.Got->getVA() + A - P + In.Got->getSize(); + case R_GOTREL: + return Sym.getVA(A) - In.Got->getVA(); + case R_GOTREL_FROM_END: + return Sym.getVA(A) - In.Got->getVA() - In.Got->getSize(); + case R_GOT_FROM_END: + case R_RELAX_TLS_GD_TO_IE_END: + return Sym.getGotOffset() + A - In.Got->getSize(); + case R_TLSLD_GOT_OFF: + case R_GOT_OFF: + case R_RELAX_TLS_GD_TO_IE_GOT_OFF: + return Sym.getGotOffset() + A; + case R_GOT_PC: + case R_RELAX_TLS_GD_TO_IE: + return Sym.getGotVA() + A - P; + case R_PC: + if (Sym.isUndefWeak()) { + // On ARM and AArch64 a branch to an undefined weak resolves to the + // next instruction, otherwise the place. + if (Config->EMachine == EM_ARM) + return getARMUndefinedRelativeWeakVA(Type, A, P) - P; + if (Config->EMachine == EM_AARCH64) + return getAArch64UndefinedRelativeWeakVA(Type, A, P) - P; + } + return Sym.getVA(A) - P; + case R_PLT: + return Sym.getPltVA() + A; + case R_PLT_PC: + return Sym.getPltVA() + A - P; case R_RELAX_GOT_PC: return Sym.getVA(A) - P; case R_RELAX_TLS_GD_TO_LE: @@ -743,9 +756,6 @@ return Sym.getSize() + A; case R_TLSDESC: return In.Got->getGlobalDynAddr(Sym) + A; - case R_AARCH64_TLSDESC_PAGE: - return getAArch64Page(In.Got->getGlobalDynAddr(Sym) + A) - - getAArch64Page(P); case R_TLSGD_GOT: return In.Got->getGlobalDynOffset(Sym) + A; case R_TLSGD_GOT_FROM_END: @@ -759,8 +769,36 @@ case R_TLSLD_PC: return In.Got->getTlsIndexVA() + A - P; default: - llvm_unreachable("invalid expression"); + break; + } + + switch (Config->EMachine) { + case EM_AARCH64: + return calcAArch64ExprVA(File, Type, A, P, Sym, Expr); + case EM_ARM: + if (Expr == R_ARM_SBREL) + return Sym.getVA(A) - getARMStaticBase(Sym); + break; + case EM_MIPS: + return calcMipsExprVA(File, Type, A, P, Sym, Expr); + case EM_HEXAGON: + if (Expr == R_HEXAGON_GOT) + return Sym.getGotVA() - In.GotPlt->getVA(); + break; + case EM_PPC: + case EM_PPC64: + return calcPPCExprVA(File, Type, A, P, Sym, Expr); + case EM_RISCV: + if (Expr == R_RISCV_PC_INDIRECT) { + if (const Relocation *HiRel = getRISCVPCRelHi20(&Sym, A)) + return getRelocTargetVA(File, HiRel->Type, HiRel->Addend, Sym.getVA(), + *HiRel->Sym, HiRel->Expr); + return 0; + } + break; } + + llvm_unreachable("invalid expression"); } // This function applies relocations to sections without SHF_ALLOC bit.