1 //===- Relocations.h --------------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLD_MACHO_RELOCATIONS_H
10 #define LLD_MACHO_RELOCATIONS_H
12 #include "llvm/ADT/BitmaskEnum.h"
13 #include "llvm/ADT/PointerUnion.h"
14 #include "llvm/BinaryFormat/MachO.h"
15 #include "llvm/Support/Endian.h"
20 namespace lld::macho
{
21 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
26 enum class RelocAttrBits
{
28 PCREL
= 1 << 0, // Value is PC-relative offset
29 ABSOLUTE
= 1 << 1, // Value is an absolute address or fixed offset
30 BYTE4
= 1 << 2, // 4 byte datum
31 BYTE8
= 1 << 3, // 8 byte datum
32 EXTERN
= 1 << 4, // Can have an external symbol
33 LOCAL
= 1 << 5, // Can have a local symbol
34 ADDEND
= 1 << 6, // *_ADDEND paired prefix reloc
35 SUBTRAHEND
= 1 << 7, // *_SUBTRACTOR paired prefix reloc
36 BRANCH
= 1 << 8, // Value is branch target
37 GOT
= 1 << 9, // References a symbol in the Global Offset Table
38 TLV
= 1 << 10, // References a thread-local symbol
39 LOAD
= 1 << 11, // Relaxable indirect load
40 POINTER
= 1 << 12, // Non-relaxable indirect load (pointer is taken)
41 UNSIGNED
= 1 << 13, // *_UNSIGNED relocs
42 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ (1 << 14) - 1),
44 // Note: SUBTRACTOR always pairs with UNSIGNED (a delta between two symbols).
49 bool hasAttr(RelocAttrBits b
) const { return (bits
& b
) == b
; }
53 uint8_t type
= llvm::MachO::GENERIC_RELOC_INVALID
;
56 // The offset from the start of the subsection that this relocation belongs
59 // Adding this offset to the address of the referent symbol or subsection
60 // gives the destination that this relocation refers to.
62 llvm::PointerUnion
<Symbol
*, InputSection
*> referent
= nullptr;
66 Reloc(uint8_t type
, bool pcrel
, uint8_t length
, uint32_t offset
,
67 int64_t addend
, llvm::PointerUnion
<Symbol
*, InputSection
*> referent
)
68 : type(type
), pcrel(pcrel
), length(length
), offset(offset
),
69 addend(addend
), referent(referent
) {}
72 struct OptimizationHint
{
73 // Offset of the first address within the containing InputSection.
75 // Offset of the other addresses relative to the first one.
80 bool validateSymbolRelocation(const Symbol
*, const InputSection
*,
84 * v: The value the relocation is attempting to encode
85 * bits: The number of bits actually available to encode this relocation
87 void reportRangeError(void *loc
, const Reloc
&, const llvm::Twine
&v
,
88 uint8_t bits
, int64_t min
, uint64_t max
);
90 struct SymbolDiagnostic
{
92 llvm::StringRef reason
;
95 void reportRangeError(void *loc
, SymbolDiagnostic
, const llvm::Twine
&v
,
96 uint8_t bits
, int64_t min
, uint64_t max
);
98 template <typename Diagnostic
>
99 inline void checkInt(void *loc
, Diagnostic d
, int64_t v
, int bits
) {
100 if (v
!= llvm::SignExtend64(v
, bits
))
101 reportRangeError(loc
, d
, llvm::Twine(v
), bits
, llvm::minIntN(bits
),
102 llvm::maxIntN(bits
));
105 template <typename Diagnostic
>
106 inline void checkUInt(void *loc
, Diagnostic d
, uint64_t v
, int bits
) {
107 if ((v
>> bits
) != 0)
108 reportRangeError(loc
, d
, llvm::Twine(v
), bits
, 0, llvm::maxUIntN(bits
));
111 inline void writeAddress(uint8_t *loc
, uint64_t addr
, uint8_t length
) {
114 llvm::support::endian::write32le(loc
, addr
);
117 llvm::support::endian::write64le(loc
, addr
);
120 llvm_unreachable("invalid r_length");
124 extern const RelocAttrs invalidRelocAttrs
;
126 } // namespace lld::Macho