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