diff options
| author | Martin Storsjo <martin@martin.st> | 2018-05-04 06:06:27 +0000 |
|---|---|---|
| committer | Martin Storsjo <martin@martin.st> | 2018-05-04 06:06:27 +0000 |
| commit | cc80776effccf0854c66ec9b0b5d4fd73892539a (patch) | |
| tree | e34f339186ed826db943f2cb64e48155603ff20d /lld/COFF/Chunks.cpp | |
| parent | 665c7a44798435daa239984db552d9941e8dbdc3 (diff) | |
| download | bcm5719-llvm-cc80776effccf0854c66ec9b0b5d4fd73892539a.tar.gz bcm5719-llvm-cc80776effccf0854c66ec9b0b5d4fd73892539a.zip | |
[COFF] Implement the remaining ARM64 relocations
Now only IMAGE_REL_ARM64_ABSOLUTE and IMAGE_REL_ARM64_TOKEN
are unhandled.
Also add range checks for the existing BRANCH26 relocation.
Differential Revision: https://reviews.llvm.org/D46354
llvm-svn: 331505
Diffstat (limited to 'lld/COFF/Chunks.cpp')
| -rw-r--r-- | lld/COFF/Chunks.cpp | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp index 6d8a0c7c1f4..5f673f8f3eb 100644 --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -181,11 +181,11 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS, // Interpret the existing immediate value as a byte offset to the // target symbol, then update the instruction with the immediate as // the page offset from the current instruction to the target. -static void applyArm64Addr(uint8_t *Off, uint64_t S, uint64_t P) { +static void applyArm64Addr(uint8_t *Off, uint64_t S, uint64_t P, int Shift) { uint32_t Orig = read32le(Off); uint64_t Imm = ((Orig >> 29) & 0x3) | ((Orig >> 3) & 0x1FFFFC); S += Imm; - Imm = (S >> 12) - (P >> 12); + Imm = (S >> Shift) - (P >> Shift); uint32_t ImmLo = (Imm & 0x3) << 29; uint32_t ImmHi = (Imm & 0x1FFFFC) << 3; uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3); @@ -247,13 +247,34 @@ static void applySecRelLdr(const SectionChunk *Sec, uint8_t *Off, applyArm64Ldr(Off, (S - OS->getRVA()) & 0xfff); } +static void applyArm64Branch26(uint8_t *Off, int64_t V) { + if (!isInt<28>(V)) + fatal("relocation out of range"); + or32(Off, (V & 0x0FFFFFFC) >> 2); +} + +static void applyArm64Branch19(uint8_t *Off, int64_t V) { + if (!isInt<21>(V)) + fatal("relocation out of range"); + or32(Off, (V & 0x001FFFFC) << 3); +} + +static void applyArm64Branch14(uint8_t *Off, int64_t V) { + if (!isInt<16>(V)) + fatal("relocation out of range"); + or32(Off, (V & 0x0000FFFC) << 3); +} + void SectionChunk::applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S, uint64_t P) const { switch (Type) { - case IMAGE_REL_ARM64_PAGEBASE_REL21: applyArm64Addr(Off, S, P); break; + case IMAGE_REL_ARM64_PAGEBASE_REL21: applyArm64Addr(Off, S, P, 12); break; + case IMAGE_REL_ARM64_REL21: applyArm64Addr(Off, S, P, 0); break; case IMAGE_REL_ARM64_PAGEOFFSET_12A: applyArm64Imm(Off, S & 0xfff, 0); break; case IMAGE_REL_ARM64_PAGEOFFSET_12L: applyArm64Ldr(Off, S & 0xfff); break; - case IMAGE_REL_ARM64_BRANCH26: or32(Off, ((S - P) & 0x0FFFFFFC) >> 2); break; + case IMAGE_REL_ARM64_BRANCH26: applyArm64Branch26(Off, S - P); break; + case IMAGE_REL_ARM64_BRANCH19: applyArm64Branch19(Off, S - P); break; + case IMAGE_REL_ARM64_BRANCH14: applyArm64Branch14(Off, S - P); break; case IMAGE_REL_ARM64_ADDR32: add32(Off, S + Config->ImageBase); break; case IMAGE_REL_ARM64_ADDR32NB: add32(Off, S); break; case IMAGE_REL_ARM64_ADDR64: add64(Off, S + Config->ImageBase); break; @@ -261,6 +282,7 @@ void SectionChunk::applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS, case IMAGE_REL_ARM64_SECREL_LOW12A: applySecRelLow12A(this, Off, OS, S); break; case IMAGE_REL_ARM64_SECREL_HIGH12A: applySecRelHigh12A(this, Off, OS, S); break; case IMAGE_REL_ARM64_SECREL_LOW12L: applySecRelLdr(this, Off, OS, S); break; + case IMAGE_REL_ARM64_SECTION: applySecIdx(Off, OS); break; default: fatal("unsupported relocation type 0x" + Twine::utohexstr(Type)); } @@ -471,7 +493,7 @@ void ImportThunkChunkARM::writeTo(uint8_t *Buf) const { void ImportThunkChunkARM64::writeTo(uint8_t *Buf) const { int64_t Off = ImpSymbol->getRVA() & 0xfff; memcpy(Buf + OutputSectionOff, ImportThunkARM64, sizeof(ImportThunkARM64)); - applyArm64Addr(Buf + OutputSectionOff, ImpSymbol->getRVA(), RVA); + applyArm64Addr(Buf + OutputSectionOff, ImpSymbol->getRVA(), RVA, 12); applyArm64Ldr(Buf + OutputSectionOff + 4, Off); } |

