1 //===- bolt/Core/Relocation.h - Object file relocations ---------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains the declaration of Relocation class, which represents a 10 // relocation in an object or a binary file. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef BOLT_CORE_RELOCATION_H 15 #define BOLT_CORE_RELOCATION_H 16 17 #include "llvm/ADT/Triple.h" 18 19 namespace llvm { 20 class MCStreamer; 21 class MCSymbol; 22 class raw_ostream; 23 24 namespace ELF { 25 /// Relocation type mask that was accidentally output by bfd 2.30 linker. 26 enum { R_X86_64_converted_reloc_bit = 0x80 }; 27 } // namespace ELF 28 29 namespace bolt { 30 31 /// Relocation class. 32 struct Relocation { 33 static Triple::ArchType Arch; /// set by BinaryContext ctor. 34 35 /// The offset of this relocation in the object it is contained in. 36 uint64_t Offset; 37 38 /// The symbol this relocation is referring to. 39 MCSymbol *Symbol; 40 41 /// Relocation type. 42 uint64_t Type; 43 44 /// The offset from the \p Symbol base used to compute the final 45 /// value of this relocation. 46 uint64_t Addend; 47 48 /// The computed relocation value extracted from the binary file. 49 /// Used to validate relocation correctness. 50 uint64_t Value; 51 52 /// Return size in bytes of the given relocation \p Type. 53 static size_t getSizeForType(uint64_t Type); 54 55 /// Return size of this relocation. getSizeRelocation56 size_t getSize() const { return getSizeForType(Type); } 57 58 /// Skip relocations that we don't want to handle in BOLT 59 static bool skipRelocationType(uint64_t Type); 60 61 /// Handle special cases when relocation should not be processed by BOLT 62 static bool skipRelocationProcess(uint64_t Type, uint64_t Contents); 63 64 // Adjust value depending on relocation type (make it PC relative or not) 65 static uint64_t adjustValue(uint64_t Type, uint64_t Value, 66 uint64_t PC); 67 68 /// Extract current relocated value from binary contents. This is used for 69 /// RISC architectures where values are encoded in specific bits depending 70 /// on the relocation value. For X86, we limit to sign extending the value 71 /// if necessary. 72 static uint64_t extractValue(uint64_t Type, uint64_t Contents, uint64_t PC); 73 74 /// Return true if relocation type is PC-relative. Return false otherwise. 75 static bool isPCRelative(uint64_t Type); 76 77 /// Check if \p Type is a supported relocation type. 78 static bool isSupported(uint64_t Type); 79 80 /// Return true if relocation type implies the creation of a GOT entry 81 static bool isGOT(uint64_t Type); 82 83 /// Special relocation type that allows the linker to modify the instruction. 84 static bool isX86GOTPCRELX(uint64_t Type); 85 86 /// Return true if relocation type is NONE 87 static bool isNone(uint64_t Type); 88 89 /// Return true if relocation type is RELATIVE 90 static bool isRelative(uint64_t Type); 91 92 /// Return true if relocation type is IRELATIVE 93 static bool isIRelative(uint64_t Type); 94 95 /// Return true if relocation type is for thread local storage. 96 static bool isTLS(uint64_t Type); 97 98 /// Return code for a NONE relocation 99 static uint64_t getNone(); 100 101 /// Return code for a PC-relative 4-byte relocation 102 static uint64_t getPC32(); 103 104 /// Return code for a PC-relative 8-byte relocation 105 static uint64_t getPC64(); 106 107 /// Return true if this relocation is PC-relative. Return false otherwise. isPCRelativeRelocation108 bool isPCRelative() const { return isPCRelative(Type); } 109 110 /// Return true if this relocation is R_*_RELATIVE type. Return false 111 /// otherwise. isRelativeRelocation112 bool isRelative() const { return isRelative(Type); } 113 114 /// Emit relocation at a current \p Streamer' position. The caller is 115 /// responsible for setting the position correctly. 116 size_t emit(MCStreamer *Streamer) const; 117 118 /// Print a relocation to \p OS. 119 void print(raw_ostream &OS) const; 120 }; 121 122 /// Relocation ordering by offset. 123 inline bool operator<(const Relocation &A, const Relocation &B) { 124 return A.Offset < B.Offset; 125 } 126 127 inline bool operator<(const Relocation &A, uint64_t B) { return A.Offset < B; } 128 129 inline bool operator<(uint64_t A, const Relocation &B) { return A < B.Offset; } 130 131 inline raw_ostream &operator<<(raw_ostream &OS, const Relocation &Rel) { 132 Rel.print(OS); 133 return OS; 134 } 135 136 } // namespace bolt 137 } // namespace llvm 138 139 #endif 140