summaryrefslogtreecommitdiff
path: root/lld/ELF
diff options
context:
space:
mode:
authorSimi Pallipurath <simi.pallipurath@arm.com>2023-02-15 11:06:04 +0000
committerSimi Pallipurath <simi.pallipurath@arm.com>2023-02-15 11:42:49 +0000
commit674f094d852b773d35e9face1b504ab68473dc86 (patch)
treefde6c66db2c43e41583887141ea0b9aa8fd39a9c /lld/ELF
parent5bb8ead4e9dc4a03bddae1f7d3419e97eac37426 (diff)
downloadllvm-674f094d852b773d35e9face1b504ab68473dc86.tar.gz
[lld][ARM][NFCI][1/3]Big Endian support - Removing assumptions
Change: - Replacing the memcpy that assume little endian with the endian-aware write. Shouldn't affect the output for now, just a prerequisite for the next patches. Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D140201
Diffstat (limited to 'lld/ELF')
-rw-r--r--lld/ELF/Arch/ARM.cpp30
-rw-r--r--lld/ELF/Thunks.cpp172
2 files changed, 77 insertions, 125 deletions
diff --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp
index 180b522b8e5f..64fc24c49fb9 100644
--- a/lld/ELF/Arch/ARM.cpp
+++ b/lld/ELF/Arch/ARM.cpp
@@ -15,6 +15,7 @@
using namespace llvm;
using namespace llvm::support::endian;
+using namespace llvm::support;
using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf;
@@ -194,16 +195,14 @@ void ARM::writeIgotPlt(uint8_t *buf, const Symbol &s) const {
// Long form PLT Header that does not have any restrictions on the displacement
// of the .plt from the .got.plt.
static void writePltHeaderLong(uint8_t *buf) {
- const uint8_t pltData[] = {
- 0x04, 0xe0, 0x2d, 0xe5, // str lr, [sp,#-4]!
- 0x04, 0xe0, 0x9f, 0xe5, // ldr lr, L2
- 0x0e, 0xe0, 0x8f, 0xe0, // L1: add lr, pc, lr
- 0x08, 0xf0, 0xbe, 0xe5, // ldr pc, [lr, #8]
- 0x00, 0x00, 0x00, 0x00, // L2: .word &(.got.plt) - L1 - 8
- 0xd4, 0xd4, 0xd4, 0xd4, // Pad to 32-byte boundary
- 0xd4, 0xd4, 0xd4, 0xd4, // Pad to 32-byte boundary
- 0xd4, 0xd4, 0xd4, 0xd4};
- memcpy(buf, pltData, sizeof(pltData));
+ write32(buf + 0, 0xe52de004); // str lr, [sp,#-4]!
+ write32(buf + 4, 0xe59fe004); // ldr lr, L2
+ write32(buf + 8, 0xe08fe00e); // L1: add lr, pc, lr
+ write32(buf + 12, 0xe5bef008); // ldr pc, [lr, #8]
+ write32(buf + 16, 0x00000000); // L2: .word &(.got.plt) - L1 - 8
+ write32(buf + 20, 0xd4d4d4d4); // Pad to 32-byte boundary
+ write32(buf + 24, 0xd4d4d4d4); // Pad to 32-byte boundary
+ write32(buf + 28, 0xd4d4d4d4);
uint64_t gotPlt = in.gotPlt->getVA();
uint64_t l1 = in.plt->getVA() + 8;
write32le(buf + 16, gotPlt - l1 - 8);
@@ -248,13 +247,10 @@ void ARM::addPltHeaderSymbols(InputSection &isec) const {
// of the .plt from the .got.plt.
static void writePltLong(uint8_t *buf, uint64_t gotPltEntryAddr,
uint64_t pltEntryAddr) {
- const uint8_t pltData[] = {
- 0x04, 0xc0, 0x9f, 0xe5, // ldr ip, L2
- 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc
- 0x00, 0xf0, 0x9c, 0xe5, // ldr pc, [ip]
- 0x00, 0x00, 0x00, 0x00, // L2: .word Offset(&(.got.plt) - L1 - 8
- };
- memcpy(buf, pltData, sizeof(pltData));
+ write32(buf + 0, 0xe59fc004); // ldr ip, L2
+ write32(buf + 4, 0xe08cc00f); // L1: add ip, ip, pc
+ write32(buf + 8, 0xe59cf000); // ldr pc, [ip]
+ write32(buf + 12, 0x00000000); // L2: .word Offset(&(.got.plt) - L1 - 8
uint64_t l1 = pltEntryAddr + 4;
write32le(buf + 12, gotPltEntryAddr - l1 - 8);
}
diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp
index 5964196a1bae..8238b15bcf56 100644
--- a/lld/ELF/Thunks.cpp
+++ b/lld/ELF/Thunks.cpp
@@ -554,10 +554,7 @@ void ARMThunk::writeTo(uint8_t *buf) {
uint64_t s = getARMThunkDestVA(destination);
uint64_t p = getThunkTargetSym()->getVA();
int64_t offset = s - p - 8;
- const uint8_t data[] = {
- 0x00, 0x00, 0x00, 0xea, // b S
- };
- memcpy(buf, data, sizeof(data));
+ write32(buf, 0xea000000); // b S
target->relocateNoSym(buf, R_ARM_JUMP24, offset);
}
@@ -600,10 +597,7 @@ void ThumbThunk::writeTo(uint8_t *buf) {
uint64_t s = getARMThunkDestVA(destination);
uint64_t p = getThunkTargetSym()->getVA();
int64_t offset = s - p - 4;
- const uint8_t data[] = {
- 0x00, 0xf0, 0x00, 0xb0, // b.w S
- };
- memcpy(buf, data, sizeof(data));
+ write32(buf, 0xb000f000); // b.w S
target->relocateNoSym(buf, R_ARM_THM_JUMP24, offset);
}
@@ -618,13 +612,10 @@ bool ThumbThunk::isCompatibleWith(const InputSection &isec,
}
void ARMV7ABSLongThunk::writeLong(uint8_t *buf) {
- const uint8_t data[] = {
- 0x00, 0xc0, 0x00, 0xe3, // movw ip,:lower16:S
- 0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S
- 0x1c, 0xff, 0x2f, 0xe1, // bx ip
- };
+ write32(buf + 0, 0xe300c000); // movw ip,:lower16:S
+ write32(buf + 4, 0xe340c000); // movt ip,:upper16:S
+ write32(buf + 8, 0xe12fff1c); // bx ip
uint64_t s = getARMThunkDestVA(destination);
- memcpy(buf, data, sizeof(data));
target->relocateNoSym(buf, R_ARM_MOVW_ABS_NC, s);
target->relocateNoSym(buf + 4, R_ARM_MOVT_ABS, s);
}
@@ -636,13 +627,12 @@ void ARMV7ABSLongThunk::addSymbols(ThunkSection &isec) {
}
void ThumbV7ABSLongThunk::writeLong(uint8_t *buf) {
- const uint8_t data[] = {
- 0x40, 0xf2, 0x00, 0x0c, // movw ip, :lower16:S
- 0xc0, 0xf2, 0x00, 0x0c, // movt ip, :upper16:S
- 0x60, 0x47, // bx ip
- };
+ write16(buf + 0, 0xf240); // movw ip, :lower16:S
+ write16(buf + 2, 0x0c00);
+ write16(buf + 4, 0xf2c0); // movt ip, :upper16:S
+ write16(buf + 6, 0x0c00);
+ write16(buf + 8, 0x4760); // bx ip
uint64_t s = getARMThunkDestVA(destination);
- memcpy(buf, data, sizeof(data));
target->relocateNoSym(buf, R_ARM_THM_MOVW_ABS_NC, s);
target->relocateNoSym(buf + 4, R_ARM_THM_MOVT_ABS, s);
}
@@ -654,16 +644,13 @@ void ThumbV7ABSLongThunk::addSymbols(ThunkSection &isec) {
}
void ARMV7PILongThunk::writeLong(uint8_t *buf) {
- const uint8_t data[] = {
- 0xf0, 0xcf, 0x0f, 0xe3, // P: movw ip,:lower16:S - (P + (L1-P) + 8)
- 0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S - (P + (L1-P) + 8)
- 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc
- 0x1c, 0xff, 0x2f, 0xe1, // bx ip
- };
+ write32(buf + 0, 0xe30fcff0); // P: movw ip,:lower16:S - (P + (L1-P) + 8)
+ write32(buf + 4, 0xe340c000); // movt ip,:upper16:S - (P + (L1-P) + 8)
+ write32(buf + 8, 0xe08cc00f); // L1: add ip, ip, pc
+ write32(buf + 12, 0xe12fff1c); // bx ip
uint64_t s = getARMThunkDestVA(destination);
uint64_t p = getThunkTargetSym()->getVA();
int64_t offset = s - p - 16;
- memcpy(buf, data, sizeof(data));
target->relocateNoSym(buf, R_ARM_MOVW_PREL_NC, offset);
target->relocateNoSym(buf + 4, R_ARM_MOVT_PREL, offset);
}
@@ -675,16 +662,15 @@ void ARMV7PILongThunk::addSymbols(ThunkSection &isec) {
}
void ThumbV7PILongThunk::writeLong(uint8_t *buf) {
- const uint8_t data[] = {
- 0x4f, 0xf6, 0xf4, 0x7c, // P: movw ip,:lower16:S - (P + (L1-P) + 4)
- 0xc0, 0xf2, 0x00, 0x0c, // movt ip,:upper16:S - (P + (L1-P) + 4)
- 0xfc, 0x44, // L1: add ip, pc
- 0x60, 0x47, // bx ip
- };
+ write16(buf + 0, 0xf64f); // P: movw ip,:lower16:S - (P + (L1-P) + 4)
+ write16(buf + 2, 0x7cf4);
+ write16(buf + 4, 0xf2c0); // movt ip,:upper16:S - (P + (L1-P) + 4)
+ write16(buf + 6, 0x0c00);
+ write16(buf + 8, 0x44fc); // L1: add ip, pc
+ write16(buf + 10, 0x4760); // bx ip
uint64_t s = getARMThunkDestVA(destination);
uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
int64_t offset = s - p - 12;
- memcpy(buf, data, sizeof(data));
target->relocateNoSym(buf, R_ARM_THM_MOVW_PREL_NC, offset);
target->relocateNoSym(buf + 4, R_ARM_THM_MOVT_PREL, offset);
}
@@ -700,15 +686,12 @@ void ThumbV6MABSLongThunk::writeLong(uint8_t *buf) {
// only register we can corrupt is r12 we must instead spill a low register
// to the stack to use as a scratch register. We push r1 even though we
// don't need to get some space to use for the return address.
- const uint8_t data[] = {
- 0x03, 0xb4, // push {r0, r1} ; Obtain scratch registers
- 0x01, 0x48, // ldr r0, [pc, #4] ; L1
- 0x01, 0x90, // str r0, [sp, #4] ; SP + 4 = S
- 0x01, 0xbd, // pop {r0, pc} ; restore r0 and branch to dest
- 0x00, 0x00, 0x00, 0x00 // L1: .word S
- };
+ write16(buf + 0, 0xb403); // push {r0, r1} ; Obtain scratch registers
+ write16(buf + 2, 0x4801); // ldr r0, [pc, #4] ; L1
+ write16(buf + 4, 0x9001); // str r0, [sp, #4] ; SP + 4 = S
+ write16(buf + 6, 0xbd01); // pop {r0, pc} ; restore r0 and branch to dest
+ write32(buf + 8, 0x00000000); // L1: .word S
uint64_t s = getARMThunkDestVA(destination);
- memcpy(buf, data, sizeof(data));
target->relocateNoSym(buf + 8, R_ARM_ABS32, s);
}
@@ -723,18 +706,15 @@ void ThumbV6MPILongThunk::writeLong(uint8_t *buf) {
// Most Thumb instructions cannot access the high registers r8 - r15. As the
// only register we can corrupt is ip (r12) we must instead spill a low
// register to the stack to use as a scratch register.
- const uint8_t data[] = {
- 0x01, 0xb4, // P: push {r0} ; Obtain scratch register
- 0x02, 0x48, // ldr r0, [pc, #8] ; L2
- 0x84, 0x46, // mov ip, r0 ; high to low register
- 0x01, 0xbc, // pop {r0} ; restore scratch register
- 0xe7, 0x44, // L1: add pc, ip ; transfer control
- 0xc0, 0x46, // nop ; pad to 4-byte boundary
- 0x00, 0x00, 0x00, 0x00, // L2: .word S - (P + (L1 - P) + 4)
- };
+ write16(buf + 0, 0xb401); // P: push {r0} ; Obtain scratch register
+ write16(buf + 2, 0x4802); // ldr r0, [pc, #8] ; L2
+ write16(buf + 4, 0x4684); // mov ip, r0 ; high to low register
+ write16(buf + 6, 0xbc01); // pop {r0} ; restore scratch register
+ write16(buf + 8, 0x44e7); // L1: add pc, ip ; transfer control
+ write16(buf + 10, 0x46c0); // nop ; pad to 4-byte boundary
+ write32(buf + 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 4)
uint64_t s = getARMThunkDestVA(destination);
uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
- memcpy(buf, data, sizeof(data));
target->relocateNoSym(buf + 12, R_ARM_REL32, s - p - 12);
}
@@ -746,11 +726,8 @@ void ThumbV6MPILongThunk::addSymbols(ThunkSection &isec) {
}
void ARMV5LongLdrPcThunk::writeLong(uint8_t *buf) {
- const uint8_t data[] = {
- 0x04, 0xf0, 0x1f, 0xe5, // ldr pc, [pc,#-4] ; L1
- 0x00, 0x00, 0x00, 0x00, // L1: .word S
- };
- memcpy(buf, data, sizeof(data));
+ write32(buf + 0, 0xe51ff004); // ldr pc, [pc,#-4] ; L1
+ write32(buf + 4, 0x00000000); // L1: .word S
target->relocateNoSym(buf + 4, R_ARM_ABS32, getARMThunkDestVA(destination));
}
@@ -762,12 +739,9 @@ void ARMV5LongLdrPcThunk::addSymbols(ThunkSection &isec) {
}
void ARMV4ABSLongBXThunk::writeLong(uint8_t *buf) {
- const uint8_t data[] = {
- 0x00, 0xc0, 0x9f, 0xe5, // ldr r12, [pc] ; L1
- 0x1c, 0xff, 0x2f, 0xe1, // bx r12
- 0x00, 0x00, 0x00, 0x00, // L1: .word S
- };
- memcpy(buf, data, sizeof(data));
+ write32(buf + 0, 0xe59fc000); // ldr r12, [pc] ; L1
+ write32(buf + 4, 0xe12fff1c); // bx r12
+ write32(buf + 8, 0x00000000); // L1: .word S
target->relocateNoSym(buf + 8, R_ARM_ABS32, getARMThunkDestVA(destination));
}
@@ -779,13 +753,10 @@ void ARMV4ABSLongBXThunk::addSymbols(ThunkSection &isec) {
}
void ThumbV4ABSLongBXThunk::writeLong(uint8_t *buf) {
- const uint8_t data[] = {
- 0x78, 0x47, // bx pc
- 0xfd, 0xe7, // b #-6 ; Arm recommended sequence to follow bx pc
- 0x04, 0xf0, 0x1f, 0xe5, // ldr pc, [pc, #-4] ; L1
- 0x00, 0x00, 0x00, 0x00, // L1: .word S
- };
- memcpy(buf, data, sizeof(data));
+ write16(buf + 0, 0x4778); // bx pc
+ write16(buf + 2, 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc
+ write32(buf + 4, 0xe51ff004); // ldr pc, [pc, #-4] ; L1
+ write32(buf + 8, 0x00000000); // L1: .word S
target->relocateNoSym(buf + 8, R_ARM_ABS32, getARMThunkDestVA(destination));
}
@@ -798,14 +769,11 @@ void ThumbV4ABSLongBXThunk::addSymbols(ThunkSection &isec) {
}
void ThumbV4ABSLongThunk::writeLong(uint8_t *buf) {
- const uint8_t data[] = {
- 0x78, 0x47, // bx pc
- 0xfd, 0xe7, // b #-6 ; Arm recommended sequence to follow bx pc
- 0x00, 0xc0, 0x9f, 0xe5, // ldr r12, [pc] ; L1
- 0x1c, 0xff, 0x2f, 0xe1, // bx r12
- 0x00, 0x00, 0x00, 0x00, // L1: .word S
- };
- memcpy(buf, data, sizeof(data));
+ write16(buf + 0, 0x4778); // bx pc
+ write16(buf + 2, 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc
+ write32(buf + 4, 0xe59fc000); // ldr r12, [pc] ; L1
+ write32(buf + 8, 0xe12fff1c); // bx r12
+ write32(buf + 12, 0x00000000); // L1: .word S
target->relocateNoSym(buf + 12, R_ARM_ABS32, getARMThunkDestVA(destination));
}
@@ -818,15 +786,12 @@ void ThumbV4ABSLongThunk::addSymbols(ThunkSection &isec) {
}
void ARMV4PILongBXThunk::writeLong(uint8_t *buf) {
- const uint8_t data[] = {
- 0x04, 0xc0, 0x9f, 0xe5, // P: ldr ip, [pc,#4] ; L2
- 0x0c, 0xc0, 0x8f, 0xe0, // L1: add ip, pc, ip
- 0x1c, 0xff, 0x2f, 0xe1, // bx ip
- 0x00, 0x00, 0x00, 0x00, // L2: .word S - (P + (L1 - P) + 8)
- };
+ write32(buf + 0, 0xe59fc004); // P: ldr ip, [pc,#4] ; L2
+ write32(buf + 4, 0xe08fc00c); // L1: add ip, pc, ip
+ write32(buf + 8, 0xe12fff1c); // bx ip
+ write32(buf + 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
uint64_t s = getARMThunkDestVA(destination);
uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
- memcpy(buf, data, sizeof(data));
target->relocateNoSym(buf + 12, R_ARM_REL32, s - p - 12);
}
@@ -838,14 +803,11 @@ void ARMV4PILongBXThunk::addSymbols(ThunkSection &isec) {
}
void ARMV4PILongThunk::writeLong(uint8_t *buf) {
- const uint8_t data[] = {
- 0x00, 0xc0, 0x9f, 0xe5, // P: ldr ip, [pc] ; L2
- 0x0c, 0xf0, 0x8f, 0xe0, // L1: add pc, pc, r12
- 0x00, 0x00, 0x00, 0x00, // L2: .word S - (P + (L1 - P) + 8)
- };
+ write32(buf + 0, 0xe59fc000); // P: ldr ip, [pc] ; L2
+ write32(buf + 4, 0xe08ff00c); // L1: add pc, pc, r12
+ write32(buf + 8, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
uint64_t s = getARMThunkDestVA(destination);
uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
- memcpy(buf, data, sizeof(data));
target->relocateNoSym(buf + 8, R_ARM_REL32, s - p - 12);
}
@@ -857,16 +819,13 @@ void ARMV4PILongThunk::addSymbols(ThunkSection &isec) {
}
void ThumbV4PILongBXThunk::writeLong(uint8_t *buf) {
- const uint8_t data[] = {
- 0x78, 0x47, // P: bx pc
- 0xfd, 0xe7, // b #-6 ; Arm recommended sequence to follow bx pc
- 0x00, 0xc0, 0x9f, 0xe5, // ldr r12, [pc] ; L2
- 0x0f, 0xf0, 0x8c, 0xe0, // L1: add pc, r12, pc
- 0x00, 0x00, 0x00, 0x00, // L2: .word S - (P + (L1 - P) + 8)
- };
+ write16(buf + 0, 0x4778); // P: bx pc
+ write16(buf + 2, 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc
+ write32(buf + 4, 0xe59fc000); // ldr r12, [pc] ; L2
+ write32(buf + 8, 0xe08cf00f); // L1: add pc, r12, pc
+ write32(buf + 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
uint64_t s = getARMThunkDestVA(destination);
uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
- memcpy(buf, data, sizeof(data));
target->relocateNoSym(buf + 12, R_ARM_REL32, s - p - 16);
}
@@ -879,17 +838,14 @@ void ThumbV4PILongBXThunk::addSymbols(ThunkSection &isec) {
}
void ThumbV4PILongThunk::writeLong(uint8_t *buf) {
- const uint8_t data[] = {
- 0x78, 0x47, // P: bx pc
- 0xfd, 0xe7, // b #-6 ; Arm recommended sequence to follow bx pc
- 0x04, 0xc0, 0x9f, 0xe5, // ldr ip, [pc,#4] ; L2
- 0x0c, 0xc0, 0x8f, 0xe0, // L1: add ip, pc, ip
- 0x1c, 0xff, 0x2f, 0xe1, // bx ip
- 0x00, 0x00, 0x00, 0x00, // L2: .word S - (P + (L1 - P) + 8)
- };
+ write16(buf + 0, 0x4778); // P: bx pc
+ write16(buf + 2, 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc
+ write32(buf + 4, 0xe59fc004); // ldr ip, [pc,#4] ; L2
+ write32(buf + 8, 0xe08fc00c); // L1: add ip, pc, ip
+ write32(buf + 12, 0xe12fff1c); // bx ip
+ write32(buf + 16, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
uint64_t s = getARMThunkDestVA(destination);
uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
- memcpy(buf, data, sizeof(data));
target->relocateNoSym(buf + 16, R_ARM_REL32, s - p - 16);
}