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
) {}
71 InputSection
*getReferentInputSection() const;
73 // Must point to an offset within a CStringInputSection or a
74 // ConcatInputSection.
75 llvm::StringRef
getReferentString() const;
78 bool validateSymbolRelocation(const Symbol
*, const InputSection
*,
82 * v: The value the relocation is attempting to encode
83 * bits: The number of bits actually available to encode this relocation
85 void reportRangeError(void *loc
, const Reloc
&, const llvm::Twine
&v
,
86 uint8_t bits
, int64_t min
, uint64_t max
);
88 struct SymbolDiagnostic
{
90 llvm::StringRef reason
;
93 void reportRangeError(void *loc
, SymbolDiagnostic
, const llvm::Twine
&v
,
94 uint8_t bits
, int64_t min
, uint64_t max
);
96 template <typename Diagnostic
>
97 inline void checkInt(void *loc
, Diagnostic d
, int64_t v
, int bits
) {
98 if (v
!= llvm::SignExtend64(v
, bits
))
99 reportRangeError(loc
, d
, llvm::Twine(v
), bits
, llvm::minIntN(bits
),
100 llvm::maxIntN(bits
));
103 template <typename Diagnostic
>
104 inline void checkUInt(void *loc
, Diagnostic d
, uint64_t v
, int bits
) {
105 if ((v
>> bits
) != 0)
106 reportRangeError(loc
, d
, llvm::Twine(v
), bits
, 0, llvm::maxUIntN(bits
));
109 inline void writeAddress(uint8_t *loc
, uint64_t addr
, uint8_t length
) {
112 llvm::support::endian::write32le(loc
, addr
);
115 llvm::support::endian::write64le(loc
, addr
);
118 llvm_unreachable("invalid r_length");
122 InputSection
*offsetToInputSection(uint64_t *);
124 extern const RelocAttrs invalidRelocAttrs
;
126 } // namespace lld::Macho