reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
//===- Core/References.h - A Reference to Another Atom ----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLD_CORE_REFERENCES_H
#define LLD_CORE_REFERENCES_H

#include <cstdint>

namespace lld {

class Atom;

///
/// The linker has a Graph Theory model of linking. An object file is seen
/// as a set of Atoms with References to other Atoms.  Each Atom is a node
/// and each Reference is an edge.
///
/// For example if a function contains a call site to "malloc" 40 bytes into
/// the Atom, then the function Atom will have a Reference of: offsetInAtom=40,
/// kind=callsite, target=malloc, addend=0.
///
/// Besides supporting traditional "relocations", references are also used
/// forcing layout (one atom must follow another), marking data-in-code
/// (jump tables or ARM constants), etc.
///
/// The "kind" of a reference is a tuple of <namespace, arch, value>.  This
/// enable us to re-use existing relocation types definded for various
/// file formats and architectures.
///
/// References and atoms form a directed graph. The dead-stripping pass
/// traverses them starting from dead-strip root atoms to garbage collect
/// unreachable ones.
///
/// References of any kind are considered as directed edges. In addition to
/// that, references of some kind is considered as bidirected edges.
class Reference {
public:
  /// Which universe defines the kindValue().
  enum class KindNamespace {
    all     = 0,
    testing = 1,
    mach_o  = 2,
  };

  KindNamespace kindNamespace() const { return (KindNamespace)_kindNamespace; }
  void setKindNamespace(KindNamespace ns) { _kindNamespace = (uint8_t)ns; }

  // Which architecture the kind value is for.
  enum class KindArch { all, AArch64, ARM, x86, x86_64};

  KindArch kindArch() const { return (KindArch)_kindArch; }
  void setKindArch(KindArch a) { _kindArch = (uint8_t)a; }

  typedef uint16_t KindValue;

  KindValue kindValue() const { return _kindValue; }

  /// setKindValue() is needed because during linking, some optimizations may
  /// change the codegen and hence the reference kind.
  void setKindValue(KindValue value) {
    _kindValue = value;
  }

  /// KindValues used with KindNamespace::all and KindArch::all.
  enum {
    // kindLayoutAfter is treated as a bidirected edge by the dead-stripping
    // pass.
    kindLayoutAfter = 1,
    kindAssociate,
  };

  // A value to be added to the value of a target
  typedef int64_t Addend;

  /// If the reference is a fixup in the Atom, then this returns the
  /// byte offset into the Atom's content to do the fix up.
  virtual uint64_t offsetInAtom() const = 0;

  /// Returns the atom this reference refers to.
  virtual const Atom *target() const = 0;

  /// During linking, the linker may merge graphs which coalesces some nodes
  /// (i.e. Atoms).  To switch the target of a reference, this method is called.
  virtual void setTarget(const Atom *) = 0;

  /// Some relocations require a symbol and a value (e.g. foo + 4).
  virtual Addend addend() const = 0;

  /// During linking, some optimzations may change addend value.
  virtual void setAddend(Addend) = 0;

  /// Returns target specific attributes of the reference.
  virtual uint32_t tag() const { return 0; }

protected:
  /// Reference is an abstract base class.  Only subclasses can use constructor.
  Reference(KindNamespace ns, KindArch a, KindValue value)
      : _kindValue(value), _kindNamespace((uint8_t)ns), _kindArch((uint8_t)a) {}

  /// The memory for Reference objects is always managed by the owning File
  /// object.  Therefore, no one but the owning File object should call
  /// delete on an Reference.  In fact, some File objects may bulk allocate
  /// an array of References, so they cannot be individually deleted by anyone.
  virtual ~Reference() = default;

  KindValue  _kindValue;
  uint8_t    _kindNamespace;
  uint8_t    _kindArch;
};

} // end namespace lld

#endif // LLD_CORE_REFERENCES_H