]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h
Vendor import of lld trunk r233088:
[FreeBSD/FreeBSD.git] / lib / ReaderWriter / ELF / ARM / ARMExecutableWriter.h
1 //===--------- lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h -------------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #ifndef LLD_READER_WRITER_ELF_ARM_ARM_EXECUTABLE_WRITER_H
10 #define LLD_READER_WRITER_ELF_ARM_ARM_EXECUTABLE_WRITER_H
11
12 #include "ExecutableWriter.h"
13 #include "ARMLinkingContext.h"
14 #include "ARMTargetHandler.h"
15 #include "ARMSymbolTable.h"
16
17 namespace {
18 const char *gotSymbol = "_GLOBAL_OFFSET_TABLE_";
19 }
20
21 namespace lld {
22 namespace elf {
23
24 template <class ELFT>
25 class ARMExecutableWriter : public ExecutableWriter<ELFT> {
26 public:
27   ARMExecutableWriter(ARMLinkingContext &context,
28                       ARMTargetLayout<ELFT> &layout);
29
30 protected:
31   // Add any runtime files and their atoms to the output
32   bool createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
33
34   void finalizeDefaultAtomValues() override;
35
36   void addDefaultAtoms() override {
37     ExecutableWriter<ELFT>::addDefaultAtoms();
38   }
39
40   /// \brief Create symbol table.
41   unique_bump_ptr<SymbolTable<ELFT>> createSymbolTable() override;
42
43   void processUndefinedSymbol(StringRef symName,
44                               RuntimeFile<ELFT> &file) const override;
45
46   // Setup the ELF header.
47   std::error_code setELFHeader() override;
48
49 private:
50   ARMLinkingContext &_context;
51   ARMTargetLayout<ELFT> &_armLayout;
52 };
53
54 template <class ELFT>
55 ARMExecutableWriter<ELFT>::ARMExecutableWriter(ARMLinkingContext &context,
56                                                ARMTargetLayout<ELFT> &layout)
57     : ExecutableWriter<ELFT>(context, layout), _context(context),
58       _armLayout(layout) {}
59
60 template <class ELFT>
61 bool ARMExecutableWriter<ELFT>::createImplicitFiles(
62     std::vector<std::unique_ptr<File>> &result) {
63   ExecutableWriter<ELFT>::createImplicitFiles(result);
64   return true;
65 }
66
67 template <class ELFT>
68 void ARMExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
69   // Finalize the atom values that are part of the parent.
70   ExecutableWriter<ELFT>::finalizeDefaultAtomValues();
71   auto gotAtomIter = _armLayout.findAbsoluteAtom(gotSymbol);
72   if (gotAtomIter != _armLayout.absoluteAtoms().end()) {
73     auto *gotAtom = *gotAtomIter;
74     if (auto gotpltSection = _armLayout.findOutputSection(".got.plt"))
75       gotAtom->_virtualAddr = gotpltSection->virtualAddr();
76     else if (auto gotSection = _armLayout.findOutputSection(".got"))
77       gotAtom->_virtualAddr = gotSection->virtualAddr();
78     else
79       gotAtom->_virtualAddr = 0;
80   }
81   // TODO: resolve addresses of __exidx_start/_end atoms
82 }
83
84 template <class ELFT>
85 unique_bump_ptr<SymbolTable<ELFT>>
86     ARMExecutableWriter<ELFT>::createSymbolTable() {
87   return unique_bump_ptr<SymbolTable<ELFT>>(
88       new (this->_alloc) ARMSymbolTable<ELFT>(this->_context));
89 }
90
91 template <class ELFT>
92 void ARMExecutableWriter<ELFT>::processUndefinedSymbol(
93     StringRef symName, RuntimeFile<ELFT> &file) const {
94   if (symName == gotSymbol) {
95     file.addAbsoluteAtom(gotSymbol);
96   } else if (symName.startswith("__exidx")) {
97     file.addAbsoluteAtom("__exidx_start");
98     file.addAbsoluteAtom("__exidx_end");
99   }
100 }
101
102 template <class ELFT>
103 std::error_code ARMExecutableWriter<ELFT>::setELFHeader() {
104   if (std::error_code ec = ExecutableWriter<ELFT>::setELFHeader())
105     return ec;
106
107   // Fixup entry point for Thumb code.
108   StringRef entryName = _context.entrySymbolName();
109   if (const AtomLayout *al = _armLayout.findAtomLayoutByName(entryName)) {
110     const auto *ea = dyn_cast<DefinedAtom>(al->_atom);
111     if (ea && ea->codeModel() == DefinedAtom::codeARMThumb)
112       this->_elfHeader->e_entry(al->_virtualAddr | 0x1);
113   }
114
115   return std::error_code();
116 }
117
118 } // namespace elf
119 } // namespace lld
120
121 #endif // LLD_READER_WRITER_ELF_ARM_ARM_EXECUTABLE_WRITER_H