• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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