1 //===- Core/References.h - A Reference to Another Atom ----------*- 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 #ifndef LLD_CORE_REFERENCES_H 10 #define LLD_CORE_REFERENCES_H 11 12 #include <cstdint> 13 14 namespace lld { 15 16 class Atom; 17 18 /// 19 /// The linker has a Graph Theory model of linking. An object file is seen 20 /// as a set of Atoms with References to other Atoms. Each Atom is a node 21 /// and each Reference is an edge. 22 /// 23 /// For example if a function contains a call site to "malloc" 40 bytes into 24 /// the Atom, then the function Atom will have a Reference of: offsetInAtom=40, 25 /// kind=callsite, target=malloc, addend=0. 26 /// 27 /// Besides supporting traditional "relocations", references are also used 28 /// forcing layout (one atom must follow another), marking data-in-code 29 /// (jump tables or ARM constants), etc. 30 /// 31 /// The "kind" of a reference is a tuple of <namespace, arch, value>. This 32 /// enable us to re-use existing relocation types definded for various 33 /// file formats and architectures. 34 /// 35 /// References and atoms form a directed graph. The dead-stripping pass 36 /// traverses them starting from dead-strip root atoms to garbage collect 37 /// unreachable ones. 38 /// 39 /// References of any kind are considered as directed edges. In addition to 40 /// that, references of some kind is considered as bidirected edges. 41 class Reference { 42 public: 43 /// Which universe defines the kindValue(). 44 enum class KindNamespace { 45 all = 0, 46 testing = 1, 47 mach_o = 2, 48 }; 49 kindNamespace()50 KindNamespace kindNamespace() const { return (KindNamespace)_kindNamespace; } setKindNamespace(KindNamespace ns)51 void setKindNamespace(KindNamespace ns) { _kindNamespace = (uint8_t)ns; } 52 53 // Which architecture the kind value is for. 54 enum class KindArch { all, AArch64, ARM, x86, x86_64}; 55 kindArch()56 KindArch kindArch() const { return (KindArch)_kindArch; } setKindArch(KindArch a)57 void setKindArch(KindArch a) { _kindArch = (uint8_t)a; } 58 59 typedef uint16_t KindValue; 60 kindValue()61 KindValue kindValue() const { return _kindValue; } 62 63 /// setKindValue() is needed because during linking, some optimizations may 64 /// change the codegen and hence the reference kind. setKindValue(KindValue value)65 void setKindValue(KindValue value) { 66 _kindValue = value; 67 } 68 69 /// KindValues used with KindNamespace::all and KindArch::all. 70 enum { 71 // kindLayoutAfter is treated as a bidirected edge by the dead-stripping 72 // pass. 73 kindLayoutAfter = 1, 74 kindAssociate, 75 }; 76 77 // A value to be added to the value of a target 78 typedef int64_t Addend; 79 80 /// If the reference is a fixup in the Atom, then this returns the 81 /// byte offset into the Atom's content to do the fix up. 82 virtual uint64_t offsetInAtom() const = 0; 83 84 /// Returns the atom this reference refers to. 85 virtual const Atom *target() const = 0; 86 87 /// During linking, the linker may merge graphs which coalesces some nodes 88 /// (i.e. Atoms). To switch the target of a reference, this method is called. 89 virtual void setTarget(const Atom *) = 0; 90 91 /// Some relocations require a symbol and a value (e.g. foo + 4). 92 virtual Addend addend() const = 0; 93 94 /// During linking, some optimizations may change addend value. 95 virtual void setAddend(Addend) = 0; 96 97 /// Returns target specific attributes of the reference. tag()98 virtual uint32_t tag() const { return 0; } 99 100 protected: 101 /// Reference is an abstract base class. Only subclasses can use constructor. Reference(KindNamespace ns,KindArch a,KindValue value)102 Reference(KindNamespace ns, KindArch a, KindValue value) 103 : _kindValue(value), _kindNamespace((uint8_t)ns), _kindArch((uint8_t)a) {} 104 105 /// The memory for Reference objects is always managed by the owning File 106 /// object. Therefore, no one but the owning File object should call 107 /// delete on a Reference. In fact, some File objects may bulk allocate 108 /// an array of References, so they cannot be individually deleted by anyone. 109 virtual ~Reference() = default; 110 111 KindValue _kindValue; 112 uint8_t _kindNamespace; 113 uint8_t _kindArch; 114 }; 115 116 } // end namespace lld 117 118 #endif // LLD_CORE_REFERENCES_H 119