[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