[lld] r254144 - [ELF] Factor out relocation checks into separate functions.
Igor Kudrin via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 26 01:49:44 PST 2015
Author: ikudrin
Date: Thu Nov 26 03:49:44 2015
New Revision: 254144
URL: http://llvm.org/viewvc/llvm-project?rev=254144&view=rev
Log:
[ELF] Factor out relocation checks into separate functions.
It helps to standardize common checks and unify error messages.
Differential revision: http://reviews.llvm.org/D14943
Modified:
lld/trunk/ELF/Target.cpp
lld/trunk/test/ELF/ppc64-addr16-error.s
Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=254144&r1=254143&r2=254144&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Thu Nov 26 03:49:44 2015
@@ -42,6 +42,27 @@ template <endianness E> static void add3
static void add32le(uint8_t *P, int32_t V) { add32<support::little>(P, V); }
static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); }
+template <unsigned N> static void checkInt(int64_t V, uint32_t Type) {
+ if (isInt<N>(V))
+ return;
+ StringRef S = getELFRelocationTypeName(Config->EMachine, Type);
+ error("Relocation " + S + " out of range");
+}
+
+template <unsigned N> static void checkUInt(uint64_t V, uint32_t Type) {
+ if (isUInt<N>(V))
+ return;
+ StringRef S = getELFRelocationTypeName(Config->EMachine, Type);
+ error("Relocation " + S + " out of range");
+}
+
+template <unsigned N> static void checkAlignment(uint64_t V, uint32_t Type) {
+ if ((V & (N - 1)) == 0)
+ return;
+ StringRef S = getELFRelocationTypeName(Config->EMachine, Type);
+ error("Improper alignment for relocation " + S);
+}
+
namespace {
class X86TargetInfo final : public TargetInfo {
public:
@@ -574,11 +595,11 @@ void X86_64TargetInfo::relocateOne(uint8
write64le(Loc, SA);
break;
case R_X86_64_32:
+ checkUInt<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");
+ checkInt<32>(SA, Type);
write32le(Loc, SA);
break;
case R_X86_64_DTPOFF32:
@@ -586,8 +607,7 @@ void X86_64TargetInfo::relocateOne(uint8
break;
case R_X86_64_TPOFF32: {
uint64_t Val = SA - Out<ELF64LE>::TlsPhdr->p_memsz;
- if (!isInt<32>(Val))
- error("R_X86_64_TPOFF32 out of range");
+ checkInt<32>(Val, Type);
write32le(Loc, Val);
break;
}
@@ -721,13 +741,11 @@ void PPC64TargetInfo::relocateOne(uint8_
switch (Type) {
case R_PPC64_ADDR16:
- if (!isInt<16>(SA))
- error("Relocation R_PPC64_ADDR16 overflow");
+ checkInt<16>(SA, Type);
write16be(Loc, SA);
break;
case R_PPC64_ADDR16_DS:
- if (!isInt<16>(SA))
- error("Relocation R_PPC64_ADDR16_DS overflow");
+ checkInt<16>(SA, Type);
write16be(Loc, (read16be(Loc) & 3) | (SA & ~3));
break;
case R_PPC64_ADDR16_LO:
@@ -755,9 +773,7 @@ void PPC64TargetInfo::relocateOne(uint8_
write16be(Loc, applyPPCHighesta(SA));
break;
case R_PPC64_ADDR14: {
- if ((SA & 3) != 0)
- error("Improper alignment for relocation R_PPC64_ADDR14");
-
+ checkAlignment<4>(SA, Type);
// Preserve the AA/LK bits in the branch instruction
uint8_t AALK = Loc[3];
write16be(Loc + 2, (AALK & 3) | (SA & 0xfffc));
@@ -773,8 +789,7 @@ void PPC64TargetInfo::relocateOne(uint8_
write16be(Loc, applyPPCHa(SA - P));
break;
case R_PPC64_ADDR32:
- if (!isInt<32>(SA))
- error("Relocation R_PPC64_ADDR32 overflow");
+ checkInt<32>(SA, Type);
write32be(Loc, SA);
break;
case R_PPC64_REL24: {
@@ -800,8 +815,7 @@ void PPC64TargetInfo::relocateOne(uint8_
}
uint32_t Mask = 0x03FFFFFC;
- if (!isInt<24>(SA - P))
- error("Relocation R_PPC64_REL24 overflow");
+ checkInt<24>(SA - P, Type);
write32be(Loc, (read32be(Loc) & ~Mask) | ((SA - P) & Mask));
uint32_t Nop = 0x60000000;
@@ -810,8 +824,7 @@ void PPC64TargetInfo::relocateOne(uint8_
break;
}
case R_PPC64_REL32:
- if (!isInt<32>(SA - P))
- error("Relocation R_PPC64_REL32 overflow");
+ checkInt<32>(SA - P, Type);
write32be(Loc, SA - P);
break;
case R_PPC64_REL64:
@@ -915,23 +928,16 @@ static uint64_t getAArch64Page(uint64_t
return Expr & (~static_cast<uint64_t>(0xFFF));
}
-template <unsigned N>
-static void checkAArch64OutOfRange(int64_t X, uint32_t Type) {
- if (!isInt<N>(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);
+ checkInt<16>(SA, Type);
write16le(Loc, SA);
break;
case R_AARCH64_ABS32:
- checkAArch64OutOfRange<32>(SA, Type);
+ checkInt<32>(SA, Type);
write32le(Loc, SA);
break;
case R_AARCH64_ABS64:
@@ -948,21 +954,21 @@ void AArch64TargetInfo::relocateOne(uint
break;
case R_AARCH64_ADR_PREL_LO21: {
uint64_t X = SA - P;
- checkAArch64OutOfRange<21>(X, Type);
+ checkInt<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);
+ checkInt<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);
+ checkInt<28>(X, Type);
or32le(Loc, (X & 0x0FFFFFFC) >> 2);
break;
}
@@ -971,8 +977,7 @@ void AArch64TargetInfo::relocateOne(uint
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<8>(SA, Type);
// No overflow check needed.
or32le(Loc, (SA & 0xFF8) << 7);
break;
@@ -985,11 +990,11 @@ void AArch64TargetInfo::relocateOne(uint
or32le(Loc, (SA & 0xFFF) << 10);
break;
case R_AARCH64_PREL16:
- checkAArch64OutOfRange<16>(SA - P, Type);
+ checkInt<16>(SA - P, Type);
write16le(Loc, SA - P);
break;
case R_AARCH64_PREL32:
- checkAArch64OutOfRange<32>(SA - P, Type);
+ checkInt<32>(SA - P, Type);
write32le(Loc, SA - P);
break;
case R_AARCH64_PREL64:
@@ -1055,8 +1060,8 @@ void MipsTargetInfo<ELFT>::relocateOne(u
case R_MIPS_CALL16:
case R_MIPS_GOT16: {
int64_t V = SA - getMipsGpAddr<ELFT>();
- if (Type == R_MIPS_GOT16 && !isInt<16>(V))
- error("Relocation R_MIPS_GOT16 out of range");
+ if (Type == R_MIPS_GOT16)
+ checkInt<16>(V, Type);
write32<E>(Loc, (read32<E>(Loc) & 0xffff0000) | (V & 0xffff));
break;
}
Modified: lld/trunk/test/ELF/ppc64-addr16-error.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc64-addr16-error.s?rev=254144&r1=254143&r2=254144&view=diff
==============================================================================
--- lld/trunk/test/ELF/ppc64-addr16-error.s (original)
+++ lld/trunk/test/ELF/ppc64-addr16-error.s Thu Nov 26 03:49:44 2015
@@ -4,4 +4,4 @@
.short sym+65539
-// CHECK: Relocation R_PPC64_ADDR16 overflow
+// CHECK: Relocation R_PPC64_ADDR16 out of range
More information about the llvm-commits
mailing list