Path: blob/main/contrib/llvm-project/lld/MachO/Relocations.h
34878 views
//===- Relocations.h --------------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLD_MACHO_RELOCATIONS_H9#define LLD_MACHO_RELOCATIONS_H1011#include "llvm/ADT/BitmaskEnum.h"12#include "llvm/ADT/PointerUnion.h"13#include "llvm/BinaryFormat/MachO.h"14#include "llvm/Support/Endian.h"1516#include <cstddef>17#include <cstdint>1819namespace lld::macho {20LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();2122class Symbol;23class InputSection;2425enum class RelocAttrBits {26_0 = 0, // invalid27PCREL = 1 << 0, // Value is PC-relative offset28ABSOLUTE = 1 << 1, // Value is an absolute address or fixed offset29BYTE4 = 1 << 2, // 4 byte datum30BYTE8 = 1 << 3, // 8 byte datum31EXTERN = 1 << 4, // Can have an external symbol32LOCAL = 1 << 5, // Can have a local symbol33ADDEND = 1 << 6, // *_ADDEND paired prefix reloc34SUBTRAHEND = 1 << 7, // *_SUBTRACTOR paired prefix reloc35BRANCH = 1 << 8, // Value is branch target36GOT = 1 << 9, // References a symbol in the Global Offset Table37TLV = 1 << 10, // References a thread-local symbol38LOAD = 1 << 11, // Relaxable indirect load39POINTER = 1 << 12, // Non-relaxable indirect load (pointer is taken)40UNSIGNED = 1 << 13, // *_UNSIGNED relocs41LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ (1 << 14) - 1),42};43// Note: SUBTRACTOR always pairs with UNSIGNED (a delta between two symbols).4445struct RelocAttrs {46llvm::StringRef name;47RelocAttrBits bits;48bool hasAttr(RelocAttrBits b) const { return (bits & b) == b; }49};5051struct Reloc {52uint8_t type = llvm::MachO::GENERIC_RELOC_INVALID;53bool pcrel = false;54uint8_t length = 0;55// The offset from the start of the subsection that this relocation belongs56// to.57uint32_t offset = 0;58// Adding this offset to the address of the referent symbol or subsection59// gives the destination that this relocation refers to.60int64_t addend = 0;61llvm::PointerUnion<Symbol *, InputSection *> referent = nullptr;6263Reloc() = default;6465Reloc(uint8_t type, bool pcrel, uint8_t length, uint32_t offset,66int64_t addend, llvm::PointerUnion<Symbol *, InputSection *> referent)67: type(type), pcrel(pcrel), length(length), offset(offset),68addend(addend), referent(referent) {}6970InputSection *getReferentInputSection() const;71};7273bool validateSymbolRelocation(const Symbol *, const InputSection *,74const Reloc &);7576/*77* v: The value the relocation is attempting to encode78* bits: The number of bits actually available to encode this relocation79*/80void reportRangeError(void *loc, const Reloc &, const llvm::Twine &v,81uint8_t bits, int64_t min, uint64_t max);8283struct SymbolDiagnostic {84const Symbol *symbol;85llvm::StringRef reason;86};8788void reportRangeError(void *loc, SymbolDiagnostic, const llvm::Twine &v,89uint8_t bits, int64_t min, uint64_t max);9091template <typename Diagnostic>92inline void checkInt(void *loc, Diagnostic d, int64_t v, int bits) {93if (v != llvm::SignExtend64(v, bits))94reportRangeError(loc, d, llvm::Twine(v), bits, llvm::minIntN(bits),95llvm::maxIntN(bits));96}9798template <typename Diagnostic>99inline void checkUInt(void *loc, Diagnostic d, uint64_t v, int bits) {100if ((v >> bits) != 0)101reportRangeError(loc, d, llvm::Twine(v), bits, 0, llvm::maxUIntN(bits));102}103104inline void writeAddress(uint8_t *loc, uint64_t addr, uint8_t length) {105switch (length) {106case 2:107llvm::support::endian::write32le(loc, addr);108break;109case 3:110llvm::support::endian::write64le(loc, addr);111break;112default:113llvm_unreachable("invalid r_length");114}115}116117InputSection *offsetToInputSection(uint64_t *);118119extern const RelocAttrs invalidRelocAttrs;120121} // namespace lld::Macho122123#endif124125126