Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -42,6 +42,25 @@ static void add32le(uint8_t *P, int32_t V) { add32(P, V); } static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); } +template static void checkIsInt(int64_t Val, uint32_t Type) { + if (!isInt(Val)) + error("Relocation " + getELFRelocationTypeName(Config->EMachine, Type) + + " out of range"); +} + +template static void checkIsUInt(uint64_t Val, uint32_t Type) { + if (!isUInt(Val)) + error("Relocation " + getELFRelocationTypeName(Config->EMachine, Type) + + " out of range"); +} + +template static void checkAlignment(uint64_t Val, uint32_t Type) { + uint64_t Mask = (1 << N) - 1; + if ((Val & Mask) != 0) + error("Improper alignment for relocation " + + getELFRelocationTypeName(Config->EMachine, Type)); +} + namespace { class X86TargetInfo final : public TargetInfo { public: @@ -360,11 +379,11 @@ write64le(Loc, SA); break; case R_X86_64_32: + checkIsUInt<32>(SA, Type); + write32le(Loc, SA); + break; case R_X86_64_32S: - if (Type == R_X86_64_32 && !isUInt<32>(SA)) - error("R_X86_64_32 out of range"); - else if (!isInt<32>(SA)) - error("R_X86_64_32S out of range"); + checkIsInt<32>(SA, Type); write32le(Loc, SA); break; case R_X86_64_DTPOFF32: @@ -372,8 +391,7 @@ break; case R_X86_64_TPOFF32: { uint64_t Val = SA - Out::TlsPhdr->p_memsz; - if (!isInt<32>(Val)) - error("R_X86_64_TPOFF32 out of range"); + checkIsInt<32>(Val, Type); write32le(Loc, Val); break; } @@ -505,13 +523,11 @@ switch (Type) { case R_PPC64_ADDR16: - if (!isInt<16>(SA)) - error("Relocation R_PPC64_ADDR16 overflow"); + checkIsInt<16>(SA, Type); write16be(Loc, SA); break; case R_PPC64_ADDR16_DS: - if (!isInt<16>(SA)) - error("Relocation R_PPC64_ADDR16_DS overflow"); + checkIsInt<16>(SA, Type); write16be(Loc, (read16be(Loc) & 3) | (SA & ~3)); break; case R_PPC64_ADDR16_LO: @@ -539,9 +555,7 @@ write16be(Loc, applyPPCHighesta(SA)); break; case R_PPC64_ADDR14: { - if ((SA & 3) != 0) - error("Improper alignment for relocation R_PPC64_ADDR14"); - + checkAlignment<2>(SA, Type); // Preserve the AA/LK bits in the branch instruction uint8_t AALK = Loc[3]; write16be(Loc + 2, (AALK & 3) | (SA & 0xfffc)); @@ -557,8 +571,7 @@ write16be(Loc, applyPPCHa(SA - P)); break; case R_PPC64_ADDR32: - if (!isInt<32>(SA)) - error("Relocation R_PPC64_ADDR32 overflow"); + checkIsInt<32>(SA, Type); write32be(Loc, SA); break; case R_PPC64_REL24: { @@ -584,8 +597,7 @@ } uint32_t Mask = 0x03FFFFFC; - if (!isInt<24>(SA - P)) - error("Relocation R_PPC64_REL24 overflow"); + checkIsInt<24>(SA - P, Type); write32be(Loc, (read32be(Loc) & ~Mask) | ((SA - P) & Mask)); uint32_t Nop = 0x60000000; @@ -594,8 +606,7 @@ break; } case R_PPC64_REL32: - if (!isInt<32>(SA - P)) - error("Relocation R_PPC64_REL32 overflow"); + checkIsInt<32>(SA - P, Type); write32be(Loc, SA - P); break; case R_PPC64_REL64: @@ -698,23 +709,16 @@ return Expr & (~static_cast(0xFFF)); } -template -static void checkAArch64OutOfRange(int64_t X, uint32_t Type) { - if (!isInt(X)) - error("Relocation " + getELFRelocationTypeName(EM_AARCH64, Type) + - " out of range"); -} - void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA) const { switch (Type) { case R_AARCH64_ABS16: - checkAArch64OutOfRange<16>(SA, Type); + checkIsInt<16>(SA, Type); write16le(Loc, SA); break; case R_AARCH64_ABS32: - checkAArch64OutOfRange<32>(SA, Type); + checkIsInt<32>(SA, Type); write32le(Loc, SA); break; case R_AARCH64_ABS64: @@ -731,21 +735,21 @@ break; case R_AARCH64_ADR_PREL_LO21: { uint64_t X = SA - P; - checkAArch64OutOfRange<21>(X, Type); + checkIsInt<21>(X, Type); updateAArch64Adr(Loc, X & 0x1FFFFF); break; } case R_AARCH64_ADR_GOT_PAGE: case R_AARCH64_ADR_PREL_PG_HI21: { uint64_t X = getAArch64Page(SA) - getAArch64Page(P); - checkAArch64OutOfRange<33>(X, Type); + checkIsInt<33>(X, Type); updateAArch64Adr(Loc, (X >> 12) & 0x1FFFFF); // X[32:12] break; } case R_AARCH64_JUMP26: case R_AARCH64_CALL26: { uint64_t X = SA - P; - checkAArch64OutOfRange<28>(X, Type); + checkIsInt<28>(X, Type); or32le(Loc, (X & 0x0FFFFFFC) >> 2); break; } @@ -754,8 +758,7 @@ or32le(Loc, (SA & 0xFFC) << 8); break; case R_AARCH64_LD64_GOT_LO12_NC: - if (SA & 0x7) - error("Relocation R_AARCH64_LD64_GOT_LO12_NC not aligned"); + checkAlignment<3>(SA, Type); // No overflow check needed. or32le(Loc, (SA & 0xFF8) << 7); break; @@ -768,11 +771,11 @@ or32le(Loc, (SA & 0xFFF) << 10); break; case R_AARCH64_PREL16: - checkAArch64OutOfRange<16>(SA - P, Type); + checkIsInt<16>(SA - P, Type); write16le(Loc, SA - P); break; case R_AARCH64_PREL32: - checkAArch64OutOfRange<32>(SA - P, Type); + checkIsInt<32>(SA - P, Type); write32le(Loc, SA - P); break; case R_AARCH64_PREL64: @@ -830,8 +833,7 @@ break; case R_MIPS_GOT16: { int64_t V = SA - getMipsGpAddr(); - if (!isInt<16>(V)) - error("Relocation R_MIPS_GOT16 out of range"); + checkIsInt<16>(V, Type); write32(Loc, (read32(Loc) & 0xffff0000) | (V & 0xffff)); break; } Index: test/ELF/ppc64-addr16-error.s =================================================================== --- test/ELF/ppc64-addr16-error.s +++ test/ELF/ppc64-addr16-error.s @@ -4,4 +4,4 @@ .short sym+65539 -// CHECK: Relocation R_PPC64_ADDR16 overflow +// CHECK: Relocation R_PPC64_ADDR16 out of range