Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:13

0001 //===- MCELFExtras.h - Extra functions for ELF ------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_MC_MCELFEXTRAS_H
0010 #define LLVM_MC_MCELFEXTRAS_H
0011 
0012 #include "llvm/ADT/STLExtras.h"
0013 #include "llvm/ADT/bit.h"
0014 #include "llvm/BinaryFormat/ELF.h"
0015 #include "llvm/Support/LEB128.h"
0016 #include "llvm/Support/raw_ostream.h"
0017 
0018 #include <cstdint>
0019 #include <type_traits>
0020 
0021 namespace llvm::ELF {
0022 // Encode relocations as CREL to OS. ToCrel is responsible for converting a
0023 // const RelocsTy & to an Elf_Crel.
0024 template <bool Is64, class RelocsTy, class F>
0025 void encodeCrel(raw_ostream &OS, RelocsTy Relocs, F ToCrel) {
0026   using uint = std::conditional_t<Is64, uint64_t, uint32_t>;
0027   uint OffsetMask = 8, Offset = 0, Addend = 0;
0028   uint32_t SymIdx = 0, Type = 0;
0029   for (const auto &R : Relocs)
0030     OffsetMask |= ToCrel(R).r_offset;
0031   const int Shift = llvm::countr_zero(OffsetMask);
0032   encodeULEB128(Relocs.size() * 8 + ELF::CREL_HDR_ADDEND + Shift, OS);
0033   for (const auto &R : Relocs) {
0034     auto CR = ToCrel(R);
0035     auto DeltaOffset = static_cast<uint>((CR.r_offset - Offset) >> Shift);
0036     Offset = CR.r_offset;
0037     uint8_t B = (DeltaOffset << 3) + (SymIdx != CR.r_symidx) +
0038                 (Type != CR.r_type ? 2 : 0) +
0039                 (Addend != uint(CR.r_addend) ? 4 : 0);
0040     if (DeltaOffset < 0x10) {
0041       OS << char(B);
0042     } else {
0043       OS << char(B | 0x80);
0044       encodeULEB128(DeltaOffset >> 4, OS);
0045     }
0046     // Delta symidx/type/addend members (SLEB128).
0047     if (B & 1) {
0048       encodeSLEB128(static_cast<int32_t>(CR.r_symidx - SymIdx), OS);
0049       SymIdx = CR.r_symidx;
0050     }
0051     if (B & 2) {
0052       encodeSLEB128(static_cast<int32_t>(CR.r_type - Type), OS);
0053       Type = CR.r_type;
0054     }
0055     if (B & 4) {
0056       encodeSLEB128(std::make_signed_t<uint>(CR.r_addend - Addend), OS);
0057       Addend = CR.r_addend;
0058     }
0059   }
0060 }
0061 } // namespace llvm::ELF
0062 
0063 #endif