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
//===------ lib/ReaderWriter/MachO/LayoutPass.h - Handles Layout of atoms -===//
//
// 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_READER_WRITER_MACHO_LAYOUT_PASS_H
#define LLD_READER_WRITER_MACHO_LAYOUT_PASS_H

#include "lld/Core/File.h"
#include "lld/Core/Pass.h"
#include "lld/Core/Reader.h"
#include "lld/Core/Simple.h"
#include "llvm/ADT/DenseMap.h"
#include <map>
#include <string>
#include <vector>

namespace lld {
class DefinedAtom;
class SimpleFile;

namespace mach_o {

/// This linker pass does the layout of the atoms. The pass is done after the
/// order their .o files were found on the command line, then by order of the
/// atoms (address) in the .o file.  But some atoms have a preferred location
/// in their section (such as pinned to the start or end of the section), so
/// the sort must take that into account too.
class LayoutPass : public Pass {
public:
  struct SortKey {
    SortKey(OwningAtomPtr<DefinedAtom> &&atom,
            const DefinedAtom *root, uint64_t override)
    : _atom(std::move(atom)), _root(root), _override(override) {}
    OwningAtomPtr<DefinedAtom> _atom;
    const DefinedAtom *_root;
    uint64_t _override;

    // Note, these are only here to appease MSVC bots which didn't like
    // the same methods being implemented/deleted in OwningAtomPtr.
    SortKey(SortKey &&key) : _atom(std::move(key._atom)), _root(key._root),
                             _override(key._override) {
      key._root = nullptr;
    }

    SortKey &operator=(SortKey &&key) {
      _atom = std::move(key._atom);
      _root = key._root;
      key._root = nullptr;
      _override = key._override;
      return *this;
    }

  private:
    SortKey(const SortKey &) = delete;
    void operator=(const SortKey&) = delete;
  };

  typedef std::function<bool (const DefinedAtom *left, const DefinedAtom *right,
                              bool &leftBeforeRight)> SortOverride;

  LayoutPass(const Registry &registry, SortOverride sorter);

  /// Sorts atoms in mergedFile by content type then by command line order.
  llvm::Error perform(SimpleFile &mergedFile) override;

  ~LayoutPass() override = default;

private:
  // Build the followOn atoms chain as specified by the kindLayoutAfter
  // reference type
  void buildFollowOnTable(const File::AtomRange<DefinedAtom> &range);

  // Build a map of Atoms to ordinals for sorting the atoms
  void buildOrdinalOverrideMap(const File::AtomRange<DefinedAtom> &range);

  const Registry &_registry;
  SortOverride _customSorter;

  typedef llvm::DenseMap<const DefinedAtom *, const DefinedAtom *> AtomToAtomT;
  typedef llvm::DenseMap<const DefinedAtom *, uint64_t> AtomToOrdinalT;

  // A map to be used to sort atoms. It represents the order of atoms in the
  // result; if Atom X is mapped to atom Y in this map, X will be located
  // immediately before Y in the output file. Y might be mapped to another
  // atom, constructing a follow-on chain. An atom cannot be mapped to more
  // than one atom unless all but one atom are of size zero.
  AtomToAtomT _followOnNexts;

  // A map to be used to sort atoms. It's a map from an atom to its root of
  // follow-on chain. A root atom is mapped to itself. If an atom is not in
  // _followOnNexts, the atom is not in this map, and vice versa.
  AtomToAtomT _followOnRoots;

  AtomToOrdinalT _ordinalOverrideMap;

  // Helper methods for buildFollowOnTable().
  const DefinedAtom *findAtomFollowedBy(const DefinedAtom *targetAtom);
  bool checkAllPrevAtomsZeroSize(const DefinedAtom *targetAtom);

  void setChainRoot(const DefinedAtom *targetAtom, const DefinedAtom *root);

  std::vector<SortKey> decorate(File::AtomRange<DefinedAtom> &atomRange) const;

  void undecorate(File::AtomRange<DefinedAtom> &atomRange,
                  std::vector<SortKey> &keys) const;

  // Check if the follow-on graph is a correct structure. For debugging only.
  void checkFollowonChain(const File::AtomRange<DefinedAtom> &range);
};

} // namespace mach_o
} // namespace lld

#endif // LLD_READER_WRITER_MACHO_LAYOUT_PASS_H