summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/ELFTargetHandler.h
blob: 196f143fb7402ce6de98da9423b79986dedb752a (plain)
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//===- lib/ReaderWriter/ELF/ELFTargetHandler.h -----------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief These interfaces provide target specific hooks to change the linker's
/// behaivor.
///
//===----------------------------------------------------------------------===//

#ifndef LLD_READER_WRITER_ELF_TARGETHANDLER_H
#define LLD_READER_WRITER_ELF_TARGETHANDLER_H

#include "lld/Core/InputFiles.h"
#include "lld/Core/LinkerOptions.h"
#include "lld/Core/LLVM.h"
#include "lld/Core/TargetInfo.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"

#include "llvm/ADT/Hashing.h"

#include <memory>
#include <vector>
#include <unordered_map>

namespace lld {
template <class ELFT> class ELFDefinedAtom;
namespace elf {
template <class ELFT> class ELFTargetLayout;
template <class ELFT> class ELFHeader;
template <class ELFT> class Section;

/// \brief The target registers a set of handlers for overriding target specific
/// attributes for a DefinedAtom. The Reader uses this class to query for the
/// type of atom and its permissions 
template <class ELFT> class ELFTargetAtomHandler {
public:
  typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;

  virtual DefinedAtom::ContentType contentType(
      const lld::ELFDefinedAtom<ELFT> *atom) const {
    return atom->contentType();
  }

  virtual DefinedAtom::ContentType contentType(const Elf_Sym *sym) const {
    return DefinedAtom::typeZeroFill;
  }

  virtual DefinedAtom::ContentPermissions contentPermissions(
      const lld::ELFDefinedAtom<ELFT> *atom) const {
    return atom->permissions();
  }
};

/// \brief An interface to override functions that are provided by the 
/// the default ELF Layout
template <class ELFT> class ELFTargetHandler : public ELFTargetHandlerBase {

public:
  ELFTargetHandler(ELFTargetInfo &targetInfo) : _targetInfo(targetInfo) {}

  /// Register a Target, so that the target backend may choose on how to merge
  /// individual atoms within the section, this is a way to control output order
  /// of atoms that is determined by the target
  void registerTargetSection(StringRef name,
                             DefinedAtom::ContentPermissions perm) {
    const TargetSectionKey targetSection(name, perm);
    if (_registeredTargetSections.find(targetSection) ==
        _registeredTargetSections.end())
      _registeredTargetSections.insert(std::make_pair(targetSection, true));
  }

  /// Check if the section is registered given the section name and its
  /// contentType, if they are registered the target would need to 
  /// create a section so that atoms insert, atom virtual address assignment
  /// could be overridden and controlled by the Target
  bool isSectionRegisteredByTarget(StringRef name,
                                   DefinedAtom::ContentPermissions perm) {
    const TargetSectionKey targetSection(name, perm);
    if (_registeredTargetSections.find(targetSection) ==
        _registeredTargetSections.end())
      return false;
    return true;
  }

  /// If the target overrides ELF header information, this API would
  /// return true, so that the target can set all fields specific to
  /// that target
  virtual bool doesOverrideELFHeader() = 0;

  /// Set the ELF Header information 
  virtual void setELFHeaderInfo(ELFHeader<ELFT> *elfHeader) = 0;

  /// ELFTargetLayout 
  virtual ELFTargetLayout<ELFT> &targetLayout() = 0;

  /// ELFTargetAtomHandler
  virtual ELFTargetAtomHandler<ELFT> &targetAtomHandler() = 0;

  /// Create a set of Default target sections that a target might needj
  virtual void createDefaultSections() = 0;

  /// \brief Add a section to the current Layout
  virtual void addSection(Section<ELFT> *section) = 0;

  /// \brief add new symbol file 
  virtual void addFiles(InputFiles &) = 0;

  /// \brief Finalize the symbol values
  virtual void finalizeSymbolValues() = 0;

  /// \brief allocate Commons, some architectures may move small common
  /// symbols over to small data, this would also be used 
  virtual void allocateCommons() = 0;

private:
  struct TargetSectionKey {
    TargetSectionKey(StringRef name, DefinedAtom::ContentPermissions perm)
        : _name(name), _perm(perm) {
    }

    // Data members
    const StringRef _name;
    DefinedAtom::ContentPermissions _perm;
  };

  struct TargetSectionKeyHash {
    int64_t operator()(const TargetSectionKey &k) const {
      return llvm::hash_combine(k._name, k._perm);
    }
  };

  struct TargetSectionKeyEq {
    bool operator()(const TargetSectionKey &lhs,
                    const TargetSectionKey &rhs) const {
      return ((lhs._name == rhs._name) && (lhs._perm == rhs._perm));
    }
  };

  typedef std::unordered_map<TargetSectionKey, bool, TargetSectionKeyHash,
                             TargetSectionKeyEq> RegisteredTargetSectionMapT;
  typedef typename RegisteredTargetSectionMapT::iterator RegisteredTargetSectionMapIterT;

protected:
  const ELFTargetInfo &_targetInfo;
  RegisteredTargetSectionMapT _registeredTargetSections;
};

} // elf
} // lld

#endif // LLD_READER_WRITER_ELF_TARGETHANDLER_H
OpenPOWER on IntegriCloud