Reference.h revision 314564
1314564Sdim//===- Core/References.h - A Reference to Another Atom ----------*- C++ -*-===// 2280461Sdim// 3280461Sdim// The LLVM Linker 4280461Sdim// 5280461Sdim// This file is distributed under the University of Illinois Open Source 6280461Sdim// License. See LICENSE.TXT for details. 7280461Sdim// 8280461Sdim//===----------------------------------------------------------------------===// 9280461Sdim 10280461Sdim#ifndef LLD_CORE_REFERENCES_H 11280461Sdim#define LLD_CORE_REFERENCES_H 12280461Sdim 13314564Sdim#include <cstdint> 14280461Sdim 15280461Sdimnamespace lld { 16314564Sdim 17280461Sdimclass Atom; 18280461Sdim 19280461Sdim/// 20280461Sdim/// The linker has a Graph Theory model of linking. An object file is seen 21280461Sdim/// as a set of Atoms with References to other Atoms. Each Atom is a node 22280461Sdim/// and each Reference is an edge. 23280461Sdim/// 24280461Sdim/// For example if a function contains a call site to "malloc" 40 bytes into 25280461Sdim/// the Atom, then the function Atom will have a Reference of: offsetInAtom=40, 26280461Sdim/// kind=callsite, target=malloc, addend=0. 27280461Sdim/// 28303239Sdim/// Besides supporting traditional "relocations", references are also used 29303239Sdim/// forcing layout (one atom must follow another), marking data-in-code 30303239Sdim/// (jump tables or ARM constants), etc. 31280461Sdim/// 32280461Sdim/// The "kind" of a reference is a tuple of <namespace, arch, value>. This 33280461Sdim/// enable us to re-use existing relocation types definded for various 34303239Sdim/// file formats and architectures. 35280461Sdim/// 36280461Sdim/// References and atoms form a directed graph. The dead-stripping pass 37280461Sdim/// traverses them starting from dead-strip root atoms to garbage collect 38280461Sdim/// unreachable ones. 39280461Sdim/// 40280461Sdim/// References of any kind are considered as directed edges. In addition to 41280461Sdim/// that, references of some kind is considered as bidirected edges. 42280461Sdimclass Reference { 43280461Sdimpublic: 44280461Sdim /// Which universe defines the kindValue(). 45280461Sdim enum class KindNamespace { 46280461Sdim all = 0, 47280461Sdim testing = 1, 48303239Sdim mach_o = 2, 49280461Sdim }; 50280461Sdim 51280461Sdim KindNamespace kindNamespace() const { return (KindNamespace)_kindNamespace; } 52280461Sdim void setKindNamespace(KindNamespace ns) { _kindNamespace = (uint8_t)ns; } 53280461Sdim 54280461Sdim // Which architecture the kind value is for. 55303239Sdim enum class KindArch { all, AArch64, ARM, x86, x86_64}; 56280461Sdim 57280461Sdim KindArch kindArch() const { return (KindArch)_kindArch; } 58280461Sdim void setKindArch(KindArch a) { _kindArch = (uint8_t)a; } 59280461Sdim 60280461Sdim typedef uint16_t KindValue; 61280461Sdim 62280461Sdim KindValue kindValue() const { return _kindValue; } 63280461Sdim 64280461Sdim /// setKindValue() is needed because during linking, some optimizations may 65280461Sdim /// change the codegen and hence the reference kind. 66280461Sdim void setKindValue(KindValue value) { 67280461Sdim _kindValue = value; 68280461Sdim } 69280461Sdim 70280461Sdim /// KindValues used with KindNamespace::all and KindArch::all. 71280461Sdim enum { 72280461Sdim // kindLayoutAfter is treated as a bidirected edge by the dead-stripping 73280461Sdim // pass. 74280461Sdim kindLayoutAfter = 1, 75280461Sdim kindAssociate, 76280461Sdim }; 77280461Sdim 78280461Sdim // A value to be added to the value of a target 79280461Sdim typedef int64_t Addend; 80280461Sdim 81280461Sdim /// If the reference is a fixup in the Atom, then this returns the 82280461Sdim /// byte offset into the Atom's content to do the fix up. 83280461Sdim virtual uint64_t offsetInAtom() const = 0; 84280461Sdim 85280461Sdim /// Returns the atom this reference refers to. 86280461Sdim virtual const Atom *target() const = 0; 87280461Sdim 88280461Sdim /// During linking, the linker may merge graphs which coalesces some nodes 89280461Sdim /// (i.e. Atoms). To switch the target of a reference, this method is called. 90280461Sdim virtual void setTarget(const Atom *) = 0; 91280461Sdim 92280461Sdim /// Some relocations require a symbol and a value (e.g. foo + 4). 93280461Sdim virtual Addend addend() const = 0; 94280461Sdim 95280461Sdim /// During linking, some optimzations may change addend value. 96280461Sdim virtual void setAddend(Addend) = 0; 97280461Sdim 98280461Sdim /// Returns target specific attributes of the reference. 99280461Sdim virtual uint32_t tag() const { return 0; } 100280461Sdim 101280461Sdimprotected: 102280461Sdim /// Reference is an abstract base class. Only subclasses can use constructor. 103280461Sdim Reference(KindNamespace ns, KindArch a, KindValue value) 104280461Sdim : _kindValue(value), _kindNamespace((uint8_t)ns), _kindArch((uint8_t)a) {} 105280461Sdim 106280461Sdim /// The memory for Reference objects is always managed by the owning File 107280461Sdim /// object. Therefore, no one but the owning File object should call 108280461Sdim /// delete on an Reference. In fact, some File objects may bulk allocate 109280461Sdim /// an array of References, so they cannot be individually deleted by anyone. 110314564Sdim virtual ~Reference() = default; 111280461Sdim 112280461Sdim KindValue _kindValue; 113280461Sdim uint8_t _kindNamespace; 114280461Sdim uint8_t _kindArch; 115280461Sdim}; 116280461Sdim 117314564Sdim} // end namespace lld 118280461Sdim 119280461Sdim#endif // LLD_CORE_REFERENCES_H 120