Home | History | Annotate | Download | only in Core
      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