[lld] [ELF] Support relocatable files using CREL (PR #98115)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 26 09:53:47 PDT 2024
================
@@ -205,6 +206,94 @@ class ThunkCreator {
uint32_t pass = 0;
};
+// Decode LEB128 without error checking. Only used by performance critical code
+// like RelocsCrel.
+inline uint64_t readLEB128(const uint8_t *&p, uint64_t leb) {
+ uint64_t acc = 0, shift = 0, byte;
+ do {
+ byte = *p++;
+ acc |= (byte - 128 * (byte >= leb)) << shift;
+ shift += 7;
+ } while (byte >= 128);
+ return acc;
+}
+inline uint64_t readULEB128(const uint8_t *&p) { return readLEB128(p, 128); }
+inline int64_t readSLEB128(const uint8_t *&p) { return readLEB128(p, 64); }
+
+// This class implements a CREL iterator that does not allocate extra memory.
+template <bool is64> struct RelocsCrel {
+ using uint = std::conditional_t<is64, uint64_t, uint32_t>;
+ struct const_iterator {
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = llvm::object::Elf_Crel_Impl<is64>;
+ using difference_type = ptrdiff_t;
+ using pointer = value_type *;
+ using reference = const value_type &;
+ uint32_t count;
+ uint8_t flagBits, shift;
+ const uint8_t *p;
+ llvm::object::Elf_Crel_Impl<is64> crel{};
+ const_iterator(size_t hdr, const uint8_t *p)
+ : count(hdr / 8), flagBits(hdr & 4 ? 3 : 2), shift(hdr % 4), p(p) {
+ if (count)
+ step();
+ }
+ void step() {
+ // See object::decodeCrel.
+ const uint8_t b = *p++;
+ crel.r_offset += b >> flagBits << shift;
+ if (b >= 0x80)
+ crel.r_offset +=
+ ((readULEB128(p) << (7 - flagBits)) - (0x80 >> flagBits)) << shift;
+ if (b & 1)
+ crel.r_symidx += readSLEB128(p);
+ if (b & 2)
+ crel.r_type += readSLEB128(p);
+ if (b & 4 && flagBits == 3)
+ crel.r_addend += static_cast<uint>(readSLEB128(p));
+ }
+ llvm::object::Elf_Crel_Impl<is64> operator*() const { return crel; };
+ const llvm::object::Elf_Crel_Impl<is64> *operator->() const {
+ return &crel;
+ }
+ bool operator==(const const_iterator &r) const { return count == r.count; }
+ bool operator!=(const const_iterator &r) const { return count != r.count; }
+ const_iterator &operator++() {
+ if (--count)
+ step();
+ return *this;
+ }
+ void operator+=(size_t n) {
+ for (; n; --n)
+ operator++();
+ }
+
+ // R_PPC64_REL24_NOTOC in Relocations.cpp
----------------
MaskRay wrote:
The commend `// R_PPC64_REL24_NOTOC in Relocations.cpp` can be expanded. The `operator*()` is used by
` end = static_cast<const void *>(rels.end()); ` in Relocations.cpp
https://github.com/llvm/llvm-project/pull/98115
More information about the llvm-commits
mailing list