[ELF] Convert {read,write}*be to endianness-aware read/write.

Subscribers: emaste, nemanjai, arichardson, kbarton, llvm-commits

Differential Revision: https://reviews.llvm.org/D44227

llvm-svn: 327156
This commit is contained in:
Fangrui Song 2018-03-09 18:03:22 +00:00
parent bc94b98c44
commit 0c483024e4
4 changed files with 66 additions and 45 deletions

View File

@ -14,7 +14,6 @@
#include "llvm/Support/Endian.h"
using namespace llvm;
using namespace llvm::support::endian;
using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf;
@ -112,14 +111,14 @@ void PPC64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
// be a pointer to the function descriptor in the .opd section. Using
// this scheme is simpler, but requires an extra indirection per PLT dispatch.
write32be(Buf, 0xf8410028); // std %r2, 40(%r1)
write32be(Buf + 4, 0x3d620000 | applyPPCHa(Off)); // addis %r11, %r2, X@ha
write32be(Buf + 8, 0xe98b0000 | applyPPCLo(Off)); // ld %r12, X@l(%r11)
write32be(Buf + 12, 0xe96c0000); // ld %r11,0(%r12)
write32be(Buf + 16, 0x7d6903a6); // mtctr %r11
write32be(Buf + 20, 0xe84c0008); // ld %r2,8(%r12)
write32be(Buf + 24, 0xe96c0010); // ld %r11,16(%r12)
write32be(Buf + 28, 0x4e800420); // bctr
write32(Buf, 0xf8410028); // std %r2, 40(%r1)
write32(Buf + 4, 0x3d620000 | applyPPCHa(Off)); // addis %r11, %r2, X@ha
write32(Buf + 8, 0xe98b0000 | applyPPCLo(Off)); // ld %r12, X@l(%r11)
write32(Buf + 12, 0xe96c0000); // ld %r11,0(%r12)
write32(Buf + 16, 0x7d6903a6); // mtctr %r11
write32(Buf + 20, 0xe84c0008); // ld %r2,8(%r12)
write32(Buf + 24, 0xe96c0010); // ld %r11,16(%r12)
write32(Buf + 28, 0x4e800420); // bctr
}
static std::pair<RelType, uint64_t> toAddr16Rel(RelType Type, uint64_t Val) {
@ -152,58 +151,58 @@ void PPC64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
checkAlignment<4>(Loc, Val, Type);
// Preserve the AA/LK bits in the branch instruction
uint8_t AALK = Loc[3];
write16be(Loc + 2, (AALK & 3) | (Val & 0xfffc));
write16(Loc + 2, (AALK & 3) | (Val & 0xfffc));
break;
}
case R_PPC64_ADDR16:
checkInt<16>(Loc, Val, Type);
write16be(Loc, Val);
write16(Loc, Val);
break;
case R_PPC64_ADDR16_DS:
checkInt<16>(Loc, Val, Type);
write16be(Loc, (read16be(Loc) & 3) | (Val & ~3));
write16(Loc, (read16(Loc) & 3) | (Val & ~3));
break;
case R_PPC64_ADDR16_HA:
case R_PPC64_REL16_HA:
write16be(Loc, applyPPCHa(Val));
write16(Loc, applyPPCHa(Val));
break;
case R_PPC64_ADDR16_HI:
case R_PPC64_REL16_HI:
write16be(Loc, applyPPCHi(Val));
write16(Loc, applyPPCHi(Val));
break;
case R_PPC64_ADDR16_HIGHER:
write16be(Loc, applyPPCHigher(Val));
write16(Loc, applyPPCHigher(Val));
break;
case R_PPC64_ADDR16_HIGHERA:
write16be(Loc, applyPPCHighera(Val));
write16(Loc, applyPPCHighera(Val));
break;
case R_PPC64_ADDR16_HIGHEST:
write16be(Loc, applyPPCHighest(Val));
write16(Loc, applyPPCHighest(Val));
break;
case R_PPC64_ADDR16_HIGHESTA:
write16be(Loc, applyPPCHighesta(Val));
write16(Loc, applyPPCHighesta(Val));
break;
case R_PPC64_ADDR16_LO:
write16be(Loc, applyPPCLo(Val));
write16(Loc, applyPPCLo(Val));
break;
case R_PPC64_ADDR16_LO_DS:
case R_PPC64_REL16_LO:
write16be(Loc, (read16be(Loc) & 3) | (applyPPCLo(Val) & ~3));
write16(Loc, (read16(Loc) & 3) | (applyPPCLo(Val) & ~3));
break;
case R_PPC64_ADDR32:
case R_PPC64_REL32:
checkInt<32>(Loc, Val, Type);
write32be(Loc, Val);
write32(Loc, Val);
break;
case R_PPC64_ADDR64:
case R_PPC64_REL64:
case R_PPC64_TOC:
write64be(Loc, Val);
write64(Loc, Val);
break;
case R_PPC64_REL24: {
uint32_t Mask = 0x03FFFFFC;
checkInt<24>(Loc, Val, Type);
write32be(Loc, (read32be(Loc) & ~Mask) | (Val & Mask));
write32(Loc, (read32(Loc) & ~Mask) | (Val & Mask));
break;
}
default:

View File

@ -47,16 +47,14 @@ using namespace llvm::dwarf;
using namespace llvm::ELF;
using namespace llvm::object;
using namespace llvm::support;
using namespace llvm::support::endian;
using namespace lld;
using namespace lld::elf;
constexpr size_t MergeNoTailSection::NumShards;
using llvm::support::endian::write32le;
using llvm::support::endian::write64le;
static void write32(void *Buf, uint32_t Val) {
endian::write32(Buf, Val, Config->Endianness);
}
constexpr size_t MergeNoTailSection::NumShards;
uint64_t SyntheticSection::getVA() const {
if (OutputSection *Sec = getParent())
@ -381,7 +379,7 @@ EhFrameSection::EhFrameSection()
template <class ELFT, class RelTy>
CieRecord *EhFrameSection::addCie(EhSectionPiece &Cie, ArrayRef<RelTy> Rels) {
auto *Sec = cast<EhInputSection>(Cie.Sec);
if (read32(Cie.data().data() + 4, Config->Endianness) != 0)
if (read32(Cie.data().data() + 4) != 0)
fatal(toString(Sec) + ": CIE expected at beginning of .eh_frame");
Symbol *Personality = nullptr;
@ -440,7 +438,7 @@ void EhFrameSection::addSectionAux(EhInputSection *Sec, ArrayRef<RelTy> Rels) {
return;
size_t Offset = Piece.InputOff;
uint32_t ID = read32(Piece.data().data() + 4, Config->Endianness);
uint32_t ID = read32(Piece.data().data() + 4);
if (ID == 0) {
OffsetToCie[Offset] = addCie<ELFT>(Piece, Rels);
continue;
@ -538,11 +536,11 @@ std::vector<EhFrameSection::FdeData> EhFrameSection::getFdeData() const {
static uint64_t readFdeAddr(uint8_t *Buf, int Size) {
switch (Size) {
case DW_EH_PE_udata2:
return read16(Buf, Config->Endianness);
return read16(Buf);
case DW_EH_PE_udata4:
return read32(Buf, Config->Endianness);
return read32(Buf);
case DW_EH_PE_udata8:
return read64(Buf, Config->Endianness);
return read64(Buf);
case DW_EH_PE_absptr:
return readUint(Buf);
}

View File

@ -179,6 +179,31 @@ static void checkAlignment(uint8_t *Loc, uint64_t V, RelType Type) {
lld::toString(Type) + ": 0x" + llvm::utohexstr(V) +
" is not aligned to " + Twine(N) + " bytes");
}
// Endianness-aware read/write.
inline uint16_t read16(const void *P) {
return llvm::support::endian::read16(P, Config->Endianness);
}
inline uint32_t read32(const void *P) {
return llvm::support::endian::read32(P, Config->Endianness);
}
inline uint64_t read64(const void *P) {
return llvm::support::endian::read64(P, Config->Endianness);
}
inline void write16(void *P, uint16_t V) {
llvm::support::endian::write16(P, V, Config->Endianness);
}
inline void write32(void *P, uint32_t V) {
llvm::support::endian::write32(P, V, Config->Endianness);
}
inline void write64(void *P, uint64_t V) {
llvm::support::endian::write64(P, V, Config->Endianness);
}
} // namespace elf
} // namespace lld

View File

@ -40,7 +40,6 @@
using namespace llvm;
using namespace llvm::object;
using namespace llvm::support::endian;
using namespace llvm::ELF;
namespace lld {
@ -307,10 +306,10 @@ bool ThumbV7PILongThunk::isCompatibleWith(RelType Type) const {
// Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
void MipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const {
uint64_t S = Destination.getVA();
write32(Buf, 0x3c190000, Config->Endianness); // lui $25, %hi(func)
write32(Buf + 4, 0x08000000 | (S >> 2), Config->Endianness); // j func
write32(Buf + 8, 0x27390000, Config->Endianness); // addiu $25, $25, %lo(func)
write32(Buf + 12, 0x00000000, Config->Endianness); // nop
write32(Buf, 0x3c190000); // lui $25, %hi(func)
write32(Buf + 4, 0x08000000 | (S >> 2)); // j func
write32(Buf + 8, 0x27390000); // addiu $25, $25, %lo(func)
write32(Buf + 12, 0x00000000); // nop
Target->relocateOne(Buf, R_MIPS_HI16, S);
Target->relocateOne(Buf + 8, R_MIPS_LO16, S);
}
@ -330,10 +329,10 @@ InputSection *MipsThunk::getTargetInputSection() const {
// to call PIC function from the non-PIC one.
void MicroMipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const {
uint64_t S = Destination.getVA() | 1;
write16(Buf, 0x41b9, Config->Endianness); // lui $25, %hi(func)
write16(Buf + 4, 0xd400, Config->Endianness); // j func
write16(Buf + 8, 0x3339, Config->Endianness); // addiu $25, $25, %lo(func)
write16(Buf + 12, 0x0c00, Config->Endianness); // nop
write16(Buf, 0x41b9); // lui $25, %hi(func)
write16(Buf + 4, 0xd400); // j func
write16(Buf + 8, 0x3339); // addiu $25, $25, %lo(func)
write16(Buf + 12, 0x0c00); // nop
Target->relocateOne(Buf, R_MICROMIPS_HI16, S);
Target->relocateOne(Buf + 4, R_MICROMIPS_26_S1, S);
Target->relocateOne(Buf + 8, R_MICROMIPS_LO16, S);
@ -356,9 +355,9 @@ InputSection *MicroMipsThunk::getTargetInputSection() const {
void MicroMipsR6Thunk::writeTo(uint8_t *Buf, ThunkSection &) const {
uint64_t S = Destination.getVA() | 1;
uint64_t P = ThunkSym->getVA();
write16(Buf, 0x1320, Config->Endianness); // lui $25, %hi(func)
write16(Buf + 4, 0x3339, Config->Endianness); // addiu $25, $25, %lo(func)
write16(Buf + 8, 0x9400, Config->Endianness); // bc func
write16(Buf, 0x1320); // lui $25, %hi(func)
write16(Buf + 4, 0x3339); // addiu $25, $25, %lo(func)
write16(Buf + 8, 0x9400); // bc func
Target->relocateOne(Buf, R_MICROMIPS_HI16, S);
Target->relocateOne(Buf + 4, R_MICROMIPS_LO16, S);
Target->relocateOne(Buf + 8, R_MICROMIPS_PC26_S1, S - P - 12);