diff --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp index 180b522b8e5f0..64fc24c49fb91 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 5964196a1bae2..8238b15bcf56b 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); }