[lld] [WIP][lld] Support thumb PLTs for cortex-M (PR #86223)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 21 17:35:24 PDT 2024
github-actions[bot] wrote:
<!--LLVM CODE FORMAT COMMENT: {clang-format}-->
:warning: C/C++ code formatter, clang-format found issues in your code. :warning:
<details>
<summary>
You can test this locally with the following command:
</summary>
``````````bash
git-clang-format --diff 7564566779eb07e9daf41a351b09cf7607871845 4f19a8313b03124a1f3c5ba96df283be4882c7de -- lld/ELF/Arch/ARM.cpp lld/ELF/Config.h lld/ELF/InputFiles.cpp
``````````
</details>
<details>
<summary>
View the diff from clang-format here.
</summary>
``````````diff
diff --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp
index 4a0cee6ba5..8e130fe4de 100644
--- a/lld/ELF/Arch/ARM.cpp
+++ b/lld/ELF/Arch/ARM.cpp
@@ -232,10 +232,10 @@ static void writePltHeaderLong(uint8_t *buf) {
// .plt in the positive direction.
void ARM::writePltHeader(uint8_t *buf) const {
if (!config->armAlwaysThumb) {
- // Use a similar sequence to that in writePlt(), the difference is the calling
- // conventions mean we use lr instead of ip. The PLT entry is responsible for
- // saving lr on the stack, the dynamic loader is responsible for reloading
- // it.
+ // Use a similar sequence to that in writePlt(), the difference is the
+ // calling conventions mean we use lr instead of ip. The PLT entry is
+ // responsible for saving lr on the stack, the dynamic loader is responsible
+ // for reloading it.
const uint32_t pltData[] = {
0xe52de004, // L1: str lr, [sp,#-4]!
0xe28fe600, // add lr, pc, #0x0NN00000 &(.got.plt - L1 - 4)
@@ -278,7 +278,7 @@ void ARM::writePltHeader(uint8_t *buf) const {
buf[14] = (offset >> 16) & 0xff;
buf[15] = (offset >> 24) & 0xff;
- memcpy(buf + 16, trapInstr.data(), 4); // Pad to 32-byte boundary
+ memcpy(buf + 16, trapInstr.data(), 4); // Pad to 32-byte boundary
memcpy(buf + 20, trapInstr.data(), 4);
memcpy(buf + 24, trapInstr.data(), 4);
memcpy(buf + 28, trapInstr.data(), 4);
@@ -314,8 +314,8 @@ void ARM::writePlt(uint8_t *buf, const Symbol &sym,
if (!config->armAlwaysThumb) {
uint64_t offset = sym.getGotPltVA() - pltEntryAddr - 8;
- //llvm::errs() << "sym: " << sym.getName() << "\n";
- //llvm::errs() << "offset: " << (void*)offset << "\n";
+ // llvm::errs() << "sym: " << sym.getName() << "\n";
+ // llvm::errs() << "offset: " << (void*)offset << "\n";
// The PLT entry is similar to the example given in Appendix A of ELF for
// the Arm Architecture. Instead of using the Group Relocations to find the
@@ -338,15 +338,17 @@ void ARM::writePlt(uint8_t *buf, const Symbol &sym,
memcpy(buf + 12, trapInstr.data(), 4); // Pad to 16-byte boundary
} else {
uint64_t offset = sym.getGotPltVA() - pltEntryAddr - 12;
- //llvm::errs() << "sym: " << sym.getName() << "\n";
- //llvm::errs() << "offset: " << (void*)offset << "\n";
+ // llvm::errs() << "sym: " << sym.getName() << "\n";
+ // llvm::errs() << "offset: " << (void*)offset << "\n";
if (!llvm::isUInt<32>(offset)) {
llvm::errs() << "TODO: Implement long thumb plt?\n";
__builtin_trap();
}
- // MOVW: https://developer.arm.com/documentation/ddi0308/d/Thumb-Instructions/Alphabetical-list-of-Thumb-instructions/MOV--immediate-
- // MOVT: https://developer.arm.com/documentation/ddi0308/d/Thumb-Instructions/Alphabetical-list-of-Thumb-instructions/MOVT
+ // MOVW:
+ // https://developer.arm.com/documentation/ddi0308/d/Thumb-Instructions/Alphabetical-list-of-Thumb-instructions/MOV--immediate-
+ // MOVT:
+ // https://developer.arm.com/documentation/ddi0308/d/Thumb-Instructions/Alphabetical-list-of-Thumb-instructions/MOVT
// Emit
//
// movw ip, #<lower 16 bits>
@@ -371,14 +373,16 @@ void ARM::writePlt(uint8_t *buf, const Symbol &sym,
// imm16 = imm4:i:imm3:imm8, i = bit 11
//
uint16_t offset_lower = offset & 0xffff;
- //llvm::errs() << "offset_lower: " << format_hex(offset_lower, 4) << "\n";
+ // llvm::errs() << "offset_lower: " << format_hex(offset_lower, 4) << "\n";
uint32_t movwImm8 = offset_lower & 0xff;
uint32_t movwImm3 = (offset_lower >> 8) & 0x7;
uint32_t movwI = (offset_lower >> 11) & 0x1;
uint32_t movwImm4 = (offset_lower >> 12) & 0xf;
- uint32_t movwBits = (movwI << 10) | (movwImm4 << 0) | (movwImm3 << 28) | (movwImm8 << 16);
- //uint32_t movwBits = (movwI << 26) | (movwImm4 << 16) | (movwImm3 << 12) | movwImm8;
- //llvm::errs() << "movwBits: " << format_hex(movwBits, 4) << "\n";
+ uint32_t movwBits =
+ (movwI << 10) | (movwImm4 << 0) | (movwImm3 << 28) | (movwImm8 << 16);
+ // uint32_t movwBits = (movwI << 26) | (movwImm4 << 16) | (movwImm3 << 12) |
+ // movwImm8; llvm::errs() << "movwBits: " << format_hex(movwBits, 4) <<
+ // "\n";
write32(buf + 0, pltData[0] | movwBits);
// movt encoding:
@@ -392,23 +396,26 @@ void ARM::writePlt(uint8_t *buf, const Symbol &sym,
// imm16 = imm4:i:imm3:imm8, i = bit 11
//
uint16_t offset_upper = static_cast<uint16_t>(offset >> 16);
- //llvm::errs() << "offset_upper: " << format_hex(offset_upper, 4) << "\n";
+ // llvm::errs() << "offset_upper: " << format_hex(offset_upper, 4) << "\n";
uint32_t movtImm8 = offset_upper & 0xff;
uint32_t movtImm3 = (offset_upper >> 8) & 0x7;
uint32_t movtI = (offset_upper >> 11) & 0x1;
uint32_t movtImm4 = (offset_upper >> 12) & 0xf;
- //uint32_t movtBits = (movtI << 26) | (movtImm4 << 16) | (movtImm3 << 12) | movtImm8;
- uint32_t movtBits = (movtI << 10) | (movtImm4 << 0) | (movtImm3 << 28) | (movtImm8 << 16);
- //llvm::errs() << "movtBits: " << format_hex(movtBits, 4) << "\n";
+ // uint32_t movtBits = (movtI << 26) | (movtImm4 << 16) | (movtImm3 << 12) |
+ // movtImm8;
+ uint32_t movtBits =
+ (movtI << 10) | (movtImm4 << 0) | (movtImm3 << 28) | (movtImm8 << 16);
+ // llvm::errs() << "movtBits: " << format_hex(movtBits, 4) << "\n";
write32(buf + 4, pltData[1] | movtBits);
- write16(buf + 8, 0x44fc); // add ip, pc
- write32(buf + 10, 0xf000f8dc); // ldr.w pc, [ip]
- //write32(buf + 10, 0xf8dcf000); // ldr.w pc, [ip]
- write16(buf + 14, 0xe7fc); // Branch to the previous instruction.
- //memcpy(buf + 14, trapInstr.data(), 2); // Pad to 16-byte boundary
+ write16(buf + 8, 0x44fc); // add ip, pc
+ write32(buf + 10, 0xf000f8dc); // ldr.w pc, [ip]
+ // write32(buf + 10, 0xf8dcf000); // ldr.w pc, [ip]
+ write16(buf + 14, 0xe7fc); // Branch to the previous instruction.
+ // memcpy(buf + 14, trapInstr.data(), 2); // Pad to 16-byte boundary
- // The PLT size for ARM is 16 bytes and the above sequence is 14 bytes so we could potentially fit one more instruction.
+ // The PLT size for ARM is 16 bytes and the above sequence is 14 bytes so we
+ // could potentially fit one more instruction.
}
}
@@ -451,7 +458,8 @@ bool ARM::needsThunk(RelExpr expr, RelType type, const InputFile *file,
case R_ARM_THM_JUMP24:
// Source is Thumb, all PLT entries are ARM so interworking is required.
// Otherwise we need to interwork if STT_FUNC Symbol has bit 0 clear (ARM).
- if ((expr == R_PLT_PC && !config->armAlwaysThumb) || (s.isFunc() && (s.getVA() & 1) == 0))
+ if ((expr == R_PLT_PC && !config->armAlwaysThumb) ||
+ (s.isFunc() && (s.getVA() & 1) == 0))
return true;
[[fallthrough]];
case R_ARM_THM_CALL: {
``````````
</details>
https://github.com/llvm/llvm-project/pull/86223
More information about the llvm-commits
mailing list