aboutsummaryrefslogtreecommitdiff
path: root/lib/ReaderWriter/ELF/OutputELFWriter.h
blob: bb3901010634f7c6d449a2aa6a41e7f2a357e1c7 (plain) (blame)
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
//===- lib/ReaderWriter/ELF/OutputELFWriter.h ----------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLD_READER_WRITER_ELF_OUTPUT_WRITER_H
#define LLD_READER_WRITER_ELF_OUTPUT_WRITER_H

#include "ELFFile.h"
#include "TargetLayout.h"
#include "lld/Core/Writer.h"
#include "llvm/ADT/StringSet.h"

namespace lld {
class ELFLinkingContext;

namespace elf {
using namespace llvm;
using namespace llvm::object;

//  OutputELFWriter Class
//
/// \brief This acts as the base class for all the ELF writers that are output
/// for emitting an ELF output file. This class also acts as a common class for
/// creating static and dynamic executables. All the function in this class
/// can be overridden and an appropriate writer be created
template<class ELFT>
class OutputELFWriter : public ELFWriter {
public:
  typedef Elf_Shdr_Impl<ELFT> Elf_Shdr;
  typedef Elf_Sym_Impl<ELFT> Elf_Sym;
  typedef Elf_Dyn_Impl<ELFT> Elf_Dyn;

  OutputELFWriter(ELFLinkingContext &ctx, TargetLayout<ELFT> &layout);

protected:
  // build the sections that need to be created
  virtual void createDefaultSections();

  // Build all the output sections
  void buildChunks(const File &file) override;

  // Build the output file
  virtual std::error_code buildOutput(const File &file);

  // Setup the ELF header.
  virtual std::error_code setELFHeader();

  // Write the file to the path specified
  std::error_code writeFile(const File &File, StringRef path) override;

  // Write to the output file.
  virtual std::error_code writeOutput(const File &file, StringRef path);

  // Get the size of the output file that the linker would emit.
  virtual uint64_t outputFileSize() const;

  // Build the atom to address map, this has to be called
  // before applying relocations
  virtual void buildAtomToAddressMap(const File &file);

  // Build the symbol table for static linking
  virtual void buildStaticSymbolTable(const File &file);

  // Build the dynamic symbol table for dynamic linking
  virtual void buildDynamicSymbolTable(const File &file);

  // Build the section header table
  virtual void buildSectionHeaderTable();

  // Assign sections that have no segments such as the symbol table,
  // section header table, string table etc
  virtual void assignSectionsWithNoSegments();

  // Add any runtime files and their atoms to the output
  void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;

  // Finalize the default atom values
  virtual void finalizeDefaultAtomValues();

  // This is called by the write section to apply relocations
  uint64_t addressOfAtom(const Atom *atom) override {
    auto addr = _atomToAddressMap.find(atom);
    return addr == _atomToAddressMap.end() ? 0 : addr->second;
  }

  // This is a hook for creating default dynamic entries
  virtual void createDefaultDynamicEntries() {}

  /// \brief Create symbol table.
  virtual unique_bump_ptr<SymbolTable<ELFT>> createSymbolTable();

  /// \brief create dynamic table.
  virtual unique_bump_ptr<DynamicTable<ELFT>> createDynamicTable();

  /// \brief create dynamic symbol table.
  virtual unique_bump_ptr<DynamicSymbolTable<ELFT>>
      createDynamicSymbolTable();

  /// \brief Create entry in the dynamic symbols table for this atom.
  virtual bool isDynSymEntryRequired(const SharedLibraryAtom *sla) const {
    return _layout.isReferencedByDefinedAtom(sla);
  }

  /// \brief Create DT_NEEDED dynamic tage for the shared library.
  virtual bool isNeededTagRequired(const SharedLibraryAtom *sla) const {
    return false;
  }

  /// \brief Process undefined symbols that left after resolution step.
  virtual void processUndefinedSymbol(StringRef symName,
                                      RuntimeFile<ELFT> &file) const;

  /// \brief Assign addresses to atoms marking section's start and end.
  void updateScopeAtomValues(StringRef sym, StringRef sec);

  llvm::BumpPtrAllocator _alloc;

  ELFLinkingContext &_ctx;
  TargetHandler &_targetHandler;

  typedef llvm::DenseMap<const Atom *, uint64_t> AtomToAddress;
  AtomToAddress _atomToAddressMap;
  TargetLayout<ELFT> &_layout;
  unique_bump_ptr<ELFHeader<ELFT>> _elfHeader;
  unique_bump_ptr<ProgramHeader<ELFT>> _programHeader;
  unique_bump_ptr<SymbolTable<ELFT>> _symtab;
  unique_bump_ptr<StringTable<ELFT>> _strtab;
  unique_bump_ptr<StringTable<ELFT>> _shstrtab;
  unique_bump_ptr<SectionHeader<ELFT>> _shdrtab;
  unique_bump_ptr<EHFrameHeader<ELFT>> _ehFrameHeader;
  /// \name Dynamic sections.
  /// @{
  unique_bump_ptr<DynamicTable<ELFT>> _dynamicTable;
  unique_bump_ptr<DynamicSymbolTable<ELFT>> _dynamicSymbolTable;
  unique_bump_ptr<StringTable<ELFT>> _dynamicStringTable;
  unique_bump_ptr<HashSection<ELFT>> _hashTable;
  llvm::StringSet<> _soNeeded;
  /// @}

private:
  static StringRef maybeGetSOName(Node *node);
  void updateScopeAtomValues(StringRef start, StringRef end, StringRef sec);
};

} // namespace elf
} // namespace lld

#endif // LLD_READER_WRITER_ELF_OUTPUT_WRITER_H