[PATCH] D142880: [RISCV][LLD] Support R_RISCV_SET_ULEB128 and R_RISCV_SUB_ULEB128

Kito Cheng via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 30 02:53:30 PST 2023


kito-cheng created this revision.
kito-cheng added reviewers: asb, jrtc27, MaskRay.
Herald added subscribers: luke, VincentWu, vkmr, frasercrmck, evandro, luismarques, apazos, sameer.abuasal, s.egerton, Jim, benna, psnobl, jocewei, PkmX, the_o, brucehoult, MartinMosbeck, rogfer01, edward-jones, zzheng, shiva0217, niosHD, sabuasal, simoncook, johnrusso, rbar, arichardson, emaste.
Herald added a project: All.
kito-cheng requested review of this revision.
Herald added subscribers: llvm-commits, pcwang-thead, eopXD.
Herald added a project: LLVM.

Support for the uleb128 related relocation[1].

R_RISCV_SET_ULEB128 should defer the relocation until
R_RISCV_SUB_ULEB128 appear since the symbol address of
R_RISCV_SET_ULEB128 might not fit the space of the current ULEB128
value, e.g. current ULEB128 value occupy 2 byte only, but the address of symbol
might not fit in 2 byte, it only fit for the address difference of
R_RISCV_SET_ULEB128 and R_RISCV_SUB_ULEB128.

R_RISCV_SUB_ULEB128 must come after R_RISCV_SET_ULEB128, and rely value
of previous R_RISCV_SET_ULEB128 relocation.

NOTE: DO NOT merge this until corresponding psABI PR has merged.

[1] https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/361


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D142880

Files:
  lld/ELF/Arch/RISCV.cpp


Index: lld/ELF/Arch/RISCV.cpp
===================================================================
--- lld/ELF/Arch/RISCV.cpp
+++ lld/ELF/Arch/RISCV.cpp
@@ -41,6 +41,7 @@
   RelType getDynRel(RelType type) const override;
   RelExpr getRelExpr(RelType type, const Symbol &s,
                      const uint8_t *loc) const override;
+  void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override;
   void relocate(uint8_t *loc, const Relocation &rel,
                 uint64_t val) const override;
   bool relaxOnce(int pass) const override;
@@ -95,6 +96,17 @@
          (extractBits(imm, 4, 0) << 7);
 }
 
+static void checkULEB128LengthNoExtend(uint8_t *loc, const RelType type,
+                                       unsigned oldLength, unsigned newLength) {
+  if (newLength <= oldLength)
+    return;
+
+  ErrorPlace errPlace = getErrorPlace(loc);
+  error(errPlace.loc + " ULEB128 value has extended the length by " +
+        toString(type) + "relocation from " + Twine(oldLength) + " byte to " +
+        Twine(newLength) + " byte");
+}
+
 RISCV::RISCV() {
   copyRel = R_RISCV_COPY;
   pltRel = R_RISCV_JUMP_SLOT;
@@ -270,6 +282,8 @@
   case R_RISCV_SUB16:
   case R_RISCV_SUB32:
   case R_RISCV_SUB64:
+  case R_RISCV_SET_ULEB128:
+  case R_RISCV_SUB_ULEB128:
     return R_RISCV_ADD;
   case R_RISCV_JAL:
   case R_RISCV_BRANCH:
@@ -306,6 +320,60 @@
   }
 }
 
+void RISCV::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
+  const unsigned bits = config->is64 ? 64 : 32;
+  uint64_t secAddr = sec.getOutputSection()->addr;
+  if (auto *s = dyn_cast<InputSection>(&sec))
+    secAddr += s->outSecOff;
+
+  uint8_t *lastULEB128SetLoc = nullptr;
+  uint64_t lastULEB128SetVal = 0;
+  for (const Relocation &rel : sec.relocs()) {
+    uint8_t *loc = buf + rel.offset;
+    const uint64_t val = SignExtend64(
+        sec.getRelocTargetVA(sec.file, rel.type, rel.addend,
+                             secAddr + rel.offset, *rel.sym, rel.expr),
+        bits);
+
+    if (rel.expr == R_RELAX_HINT)
+      continue;
+
+    switch (rel.type) {
+    case R_RISCV_SET_ULEB128: {
+      if (lastULEB128SetLoc != nullptr) {
+        ErrorPlace errPlace = getErrorPlace(loc);
+        error(errPlace.loc +
+              " More than one R_RISCV_SET_ULEB128 in same location");
+      }
+      lastULEB128SetLoc = loc;
+      lastULEB128SetVal = val;
+      break;
+    }
+    case R_RISCV_SUB_ULEB128: {
+      if (loc != lastULEB128SetLoc) {
+        ErrorPlace errPlace = getErrorPlace(loc);
+        error(errPlace.loc +
+              " R_RISCV_SUB_ULEB128 must come after R_RISCV_SET_ULEB128");
+        break;
+      }
+      unsigned oldLength;
+      decodeULEB128(loc, &oldLength);
+      uint64_t newVal = lastULEB128SetVal - val;
+      unsigned newLength = encodeULEB128(newVal, loc, /*PadTo*/ oldLength);
+      checkULEB128LengthNoExtend(loc, rel.type, oldLength, newLength);
+      lastULEB128SetLoc = nullptr;
+      break;
+    }
+    default:
+      relocate(loc, rel, val);
+    }
+  }
+  if (lastULEB128SetLoc != nullptr) {
+    ErrorPlace errPlace = getErrorPlace(lastULEB128SetLoc);
+    error(errPlace.loc + " Orphan R_RISCV_SET_ULEB128");
+  }
+}
+
 void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   const unsigned bits = config->wordsize * 8;
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D142880.493260.patch
Type: text/x-patch
Size: 3322 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230130/81a942c5/attachment.bin>


More information about the llvm-commits mailing list