9
9
#ifndef LLD_READER_WRITER_ELF_EXECUTABLE_WRITER_H
10
10
#define LLD_READER_WRITER_ELF_EXECUTABLE_WRITER_H
11
11
12
- #include " lld/ReaderWriter/Writer.h"
13
-
14
- #include " DefaultLayout.h"
15
- #include " TargetLayout.h"
16
- #include " ExecutableAtoms.h"
17
-
18
- #include " lld/ReaderWriter/ELFTargetInfo.h"
19
-
20
- #include " llvm/ADT/StringSet.h"
12
+ #include " OutputELFWriter.h"
21
13
22
14
namespace lld {
23
15
namespace elf {
@@ -31,148 +23,29 @@ class ExecutableWriter;
31
23
// ExecutableWriter Class
32
24
// ===----------------------------------------------------------------------===//
33
25
template <class ELFT >
34
- class ExecutableWriter : public ELFWriter {
26
+ class ExecutableWriter : public OutputELFWriter <ELFT> {
35
27
public:
36
- typedef Elf_Shdr_Impl<ELFT> Elf_Shdr;
37
- typedef Elf_Sym_Impl<ELFT> Elf_Sym;
38
- typedef Elf_Dyn_Impl<ELFT> Elf_Dyn;
39
-
40
- ExecutableWriter (const ELFTargetInfo &ti);
28
+ ExecutableWriter (const ELFTargetInfo &ti)
29
+ : OutputELFWriter<ELFT>(ti), _runtimeFile(ti)
30
+ {}
41
31
42
32
private:
43
- // build the sections that need to be created
44
- void buildChunks (const File &file);
45
- virtual error_code writeFile (const File &File, StringRef path);
46
- void buildAtomToAddressMap ();
47
- void buildStaticSymbolTable (const File &file);
48
- void buildDynamicSymbolTable (const File &file);
49
- void buildSectionHeaderTable ();
50
- void assignSectionsWithNoSegments ();
51
- void addDefaultAtoms ();
52
- void addFiles (InputFiles&);
53
- void finalizeDefaultAtomValues ();
54
-
55
- uint64_t addressOfAtom (const Atom *atom) {
56
- return _atomToAddressMap[atom];
57
- }
58
-
59
- void createDefaultSections ();
60
-
61
- void createDefaultDynamicEntries () {}
33
+ virtual void addDefaultAtoms ();
34
+ virtual void addFiles (InputFiles&);
35
+ virtual void finalizeDefaultAtomValues ();
62
36
63
- llvm::BumpPtrAllocator _alloc;
64
-
65
- const ELFTargetInfo &_targetInfo;
66
- TargetHandler<ELFT> &_targetHandler;
67
-
68
- typedef llvm::DenseMap<const Atom *, uint64_t > AtomToAddress;
69
- AtomToAddress _atomToAddressMap;
70
- TargetLayout<ELFT> *_layout;
71
- LLD_UNIQUE_BUMP_PTR (Header<ELFT>) _Header;
72
- LLD_UNIQUE_BUMP_PTR (ProgramHeader<ELFT>) _programHeader;
73
- LLD_UNIQUE_BUMP_PTR (SymbolTable<ELFT>) _symtab;
74
- LLD_UNIQUE_BUMP_PTR (StringTable<ELFT>) _strtab;
75
- LLD_UNIQUE_BUMP_PTR (StringTable<ELFT>) _shstrtab;
76
- LLD_UNIQUE_BUMP_PTR (SectionHeader<ELFT>) _shdrtab;
77
- // / \name Dynamic sections.
78
- // / @{
79
- LLD_UNIQUE_BUMP_PTR (DynamicTable<ELFT>) _dynamicTable;
80
- LLD_UNIQUE_BUMP_PTR (DynamicSymbolTable<ELFT>) _dynamicSymbolTable;
81
- LLD_UNIQUE_BUMP_PTR (StringTable<ELFT>) _dynamicStringTable;
82
- LLD_UNIQUE_BUMP_PTR (InterpSection<ELFT>) _interpSection;
83
- LLD_UNIQUE_BUMP_PTR (HashSection<ELFT>) _hashTable;
84
- llvm::StringSet<> _soNeeded;
85
- // / @}
86
37
CRuntimeFile<ELFT> _runtimeFile;
87
38
};
88
39
89
40
// ===----------------------------------------------------------------------===//
90
41
// ExecutableWriter
91
42
// ===----------------------------------------------------------------------===//
92
- template <class ELFT >
93
- ExecutableWriter<ELFT>::ExecutableWriter(const ELFTargetInfo &ti)
94
- : _targetInfo(ti), _targetHandler(ti.getTargetHandler<ELFT>()),
95
- _runtimeFile (ti) {
96
- _layout = &_targetHandler.targetLayout ();
97
- }
98
-
99
- template <class ELFT >
100
- void ExecutableWriter<ELFT>::buildChunks(const File &file) {
101
- for (const DefinedAtom *definedAtom : file.defined ()) {
102
- _layout->addAtom (definedAtom);
103
- }
104
- for (const AbsoluteAtom *absoluteAtom : file.absolute ())
105
- _layout->addAtom (absoluteAtom);
106
- }
107
-
108
- template <class ELFT >
109
- void ExecutableWriter<ELFT>::buildStaticSymbolTable(const File &file) {
110
- for (auto sec : _layout->sections ())
111
- if (auto section = dyn_cast<AtomSection<ELFT>>(sec))
112
- for (const auto &atom : section->atoms ())
113
- _symtab->addSymbol (atom->_atom , section->ordinal (), atom->_virtualAddr );
114
- for (auto &atom : _layout->absoluteAtoms ())
115
- _symtab->addSymbol (atom->_atom , ELF::SHN_ABS, atom->_virtualAddr );
116
- for (const UndefinedAtom *a : file.undefined ())
117
- _symtab->addSymbol (a, ELF::SHN_UNDEF);
118
- }
119
-
120
- template <class ELFT >
121
- void ExecutableWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
122
- for (const auto sla : file.sharedLibrary ()) {
123
- _dynamicSymbolTable->addSymbol (sla, ELF::SHN_UNDEF);
124
- _soNeeded.insert (sla->loadName ());
125
- }
126
- for (const auto &loadName : _soNeeded) {
127
- Elf_Dyn dyn;
128
- dyn.d_tag = DT_NEEDED;
129
- dyn.d_un .d_val = _dynamicStringTable->addString (loadName.getKey ());
130
- _dynamicTable->addEntry (dyn);
131
- }
132
- }
133
-
134
- template <class ELFT > void ExecutableWriter<ELFT>::buildAtomToAddressMap() {
135
- for (auto sec : _layout->sections ())
136
- if (auto section = dyn_cast<AtomSection<ELFT>>(sec))
137
- for (const auto &atom : section->atoms ())
138
- _atomToAddressMap[atom->_atom ] = atom->_virtualAddr ;
139
- // build the atomToAddressMap that contains absolute symbols too
140
- for (auto &atom : _layout->absoluteAtoms ())
141
- _atomToAddressMap[atom->_atom ] = atom->_virtualAddr ;
142
- }
143
-
144
- template <class ELFT >
145
- void ExecutableWriter<ELFT>::buildSectionHeaderTable() {
146
- for (auto mergedSec : _layout->mergedSections ()) {
147
- if (mergedSec->kind () != Chunk<ELFT>::K_ELFSection &&
148
- mergedSec->kind () != Chunk<ELFT>::K_AtomSection)
149
- continue ;
150
- if (mergedSec->hasSegment ())
151
- _shdrtab->appendSection (mergedSec);
152
- }
153
- }
154
-
155
- template <class ELFT >
156
- void ExecutableWriter<ELFT>::assignSectionsWithNoSegments() {
157
- for (auto mergedSec : _layout->mergedSections ()) {
158
- if (mergedSec->kind () != Chunk<ELFT>::K_ELFSection &&
159
- mergedSec->kind () != Chunk<ELFT>::K_AtomSection)
160
- continue ;
161
- if (!mergedSec->hasSegment ())
162
- _shdrtab->appendSection (mergedSec);
163
- }
164
- _layout->assignOffsetsForMiscSections ();
165
- for (auto sec : _layout->sections ())
166
- if (auto section = dyn_cast<Section<ELFT>>(sec))
167
- if (!DefaultLayout<ELFT>::hasOutputSegment (section))
168
- _shdrtab->updateSection (section);
169
- }
170
43
171
44
// / \brief Add absolute symbols by default. These are linker added
172
45
// / absolute symbols
173
46
template <class ELFT >
174
47
void ExecutableWriter<ELFT>::addDefaultAtoms() {
175
- _runtimeFile.addUndefinedAtom (_targetInfo.getEntry ());
48
+ _runtimeFile.addUndefinedAtom (this -> _targetInfo .getEntry ());
176
49
_runtimeFile.addAbsoluteAtom (" __bss_start" );
177
50
_runtimeFile.addAbsoluteAtom (" __bss_end" );
178
51
_runtimeFile.addAbsoluteAtom (" _end" );
@@ -193,17 +66,17 @@ void ExecutableWriter<ELFT>::addFiles(InputFiles &inputFiles) {
193
66
addDefaultAtoms ();
194
67
inputFiles.prependFile (_runtimeFile);
195
68
// Give a chance for the target to add atoms
196
- _targetHandler.addFiles (inputFiles);
69
+ this -> _targetHandler .addFiles (inputFiles);
197
70
}
198
71
199
72
// / Finalize the value of all the absolute symbols that we
200
73
// / created
201
74
template <class ELFT >
202
75
void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
203
- auto bssStartAtomIter = _layout->findAbsoluteAtom (" __bss_start" );
204
- auto bssEndAtomIter = _layout->findAbsoluteAtom (" __bss_end" );
205
- auto underScoreEndAtomIter = _layout->findAbsoluteAtom (" _end" );
206
- auto endAtomIter = _layout->findAbsoluteAtom (" end" );
76
+ auto bssStartAtomIter = this -> _layout ->findAbsoluteAtom (" __bss_start" );
77
+ auto bssEndAtomIter = this -> _layout ->findAbsoluteAtom (" __bss_end" );
78
+ auto underScoreEndAtomIter = this -> _layout ->findAbsoluteAtom (" _end" );
79
+ auto endAtomIter = this -> _layout ->findAbsoluteAtom (" end" );
207
80
208
81
auto startEnd = [&](StringRef sym, StringRef sec) -> void {
209
82
// TODO: This looks like a good place to use Twine...
@@ -212,9 +85,9 @@ void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
212
85
start += " _start" ;
213
86
end += sym;
214
87
end += " _end" ;
215
- auto s = _layout->findAbsoluteAtom (start);
216
- auto e = _layout->findAbsoluteAtom (end);
217
- auto section = _layout->findOutputSection (sec);
88
+ auto s = this -> _layout ->findAbsoluteAtom (start);
89
+ auto e = this -> _layout ->findAbsoluteAtom (end);
90
+ auto section = this -> _layout ->findOutputSection (sec);
218
91
if (section) {
219
92
(*s)->_virtualAddr = section->virtualAddr ();
220
93
(*e)->_virtualAddr = section->virtualAddr () + section->memSize ();
@@ -229,16 +102,16 @@ void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
229
102
startEnd (" rela_iplt" , " .rela.plt" );
230
103
startEnd (" fini_array" , " .fini_array" );
231
104
232
- assert (!(bssStartAtomIter == _layout->absoluteAtoms ().end () ||
233
- bssEndAtomIter == _layout->absoluteAtoms ().end () ||
234
- underScoreEndAtomIter == _layout->absoluteAtoms ().end () ||
235
- endAtomIter == _layout->absoluteAtoms ().end ()) &&
105
+ assert (!(bssStartAtomIter == this -> _layout ->absoluteAtoms ().end () ||
106
+ bssEndAtomIter == this -> _layout ->absoluteAtoms ().end () ||
107
+ underScoreEndAtomIter == this -> _layout ->absoluteAtoms ().end () ||
108
+ endAtomIter == this -> _layout ->absoluteAtoms ().end ()) &&
236
109
" Unable to find the absolute atoms that have been added by lld" );
237
110
238
- auto phe = _programHeader->findProgramHeader (
111
+ auto phe = this -> _programHeader ->findProgramHeader (
239
112
llvm::ELF::PT_LOAD, llvm::ELF::PF_W, llvm::ELF::PF_X);
240
113
241
- assert (!(phe == _programHeader->end ()) &&
114
+ assert (!(phe == this -> _programHeader ->end ()) &&
242
115
" Can't find a data segment in the program header!" );
243
116
244
117
(*bssStartAtomIter)->_virtualAddr = (*phe)->p_vaddr + (*phe)->p_filesz ;
@@ -247,153 +120,9 @@ void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
247
120
(*endAtomIter)->_virtualAddr = (*phe)->p_vaddr + (*phe)->p_memsz ;
248
121
249
122
// Give a chance for the target to finalize its atom values
250
- _targetHandler.finalizeSymbolValues ();
123
+ this -> _targetHandler .finalizeSymbolValues ();
251
124
}
252
125
253
- template <class ELFT >
254
- error_code ExecutableWriter<ELFT>::writeFile(const File &file, StringRef path) {
255
- buildChunks (file);
256
-
257
- // Call the preFlight callbacks to modify the sections and the atoms
258
- // contained in them, in anyway the targets may want
259
- _layout->doPreFlight ();
260
-
261
- // Create the default sections like the symbol table, string table, and the
262
- // section string table
263
- createDefaultSections ();
264
-
265
- if (_targetInfo.isDynamic ()) {
266
- _dynamicTable->createDefaultEntries ();
267
- buildDynamicSymbolTable (file);
268
- }
269
-
270
- // Set the Layout
271
- _layout->assignSectionsToSegments ();
272
- _layout->assignFileOffsets ();
273
- _layout->assignVirtualAddress ();
274
-
275
- // Finalize the default value of symbols that the linker adds
276
- finalizeDefaultAtomValues ();
277
-
278
- // Build the Atom To Address map for applying relocations
279
- buildAtomToAddressMap ();
280
-
281
- // Create symbol table and section string table
282
- buildStaticSymbolTable (file);
283
-
284
- // Finalize the layout by calling the finalize() functions
285
- _layout->finalize ();
286
-
287
- // build Section Header table
288
- buildSectionHeaderTable ();
289
-
290
- // assign Offsets and virtual addresses
291
- // for sections with no segments
292
- assignSectionsWithNoSegments ();
293
-
294
- if (_targetInfo.isDynamic ())
295
- _dynamicTable->updateDynamicTable (_hashTable.get (),
296
- _dynamicSymbolTable.get ());
297
-
298
- uint64_t totalSize = _shdrtab->fileOffset () + _shdrtab->fileSize ();
299
-
300
- OwningPtr<FileOutputBuffer> buffer;
301
- error_code ec = FileOutputBuffer::create (path,
302
- totalSize, buffer,
303
- FileOutputBuffer::F_executable);
304
- if (ec)
305
- return ec;
306
-
307
- _Header->e_ident (ELF::EI_CLASS, _targetInfo.is64Bits () ? ELF::ELFCLASS64 :
308
- ELF::ELFCLASS32);
309
- _Header->e_ident (ELF::EI_DATA, _targetInfo.isLittleEndian () ?
310
- ELF::ELFDATA2LSB : ELF::ELFDATA2MSB);
311
- _Header->e_type (_targetInfo.getOutputType ());
312
- _Header->e_machine (_targetInfo.getOutputMachine ());
313
-
314
- if (!_targetHandler.doesOverrideHeader ()) {
315
- _Header->e_ident (ELF::EI_VERSION, 1 );
316
- _Header->e_ident (ELF::EI_OSABI, 0 );
317
- _Header->e_version (1 );
318
- } else {
319
- // override the contents of the ELF Header
320
- _targetHandler.setHeaderInfo (_Header.get ());
321
- }
322
- _Header->e_phoff (_programHeader->fileOffset ());
323
- _Header->e_shoff (_shdrtab->fileOffset ());
324
- _Header->e_phentsize (_programHeader->entsize ());
325
- _Header->e_phnum (_programHeader->numHeaders ());
326
- _Header->e_shentsize (_shdrtab->entsize ());
327
- _Header->e_shnum (_shdrtab->numHeaders ());
328
- _Header->e_shstrndx (_shstrtab->ordinal ());
329
- uint64_t virtualAddr = 0 ;
330
- _layout->findAtomAddrByName (_targetInfo.getEntry (), virtualAddr);
331
- _Header->e_entry (virtualAddr);
332
-
333
- // HACK: We have to write out the header and program header here even though
334
- // they are a member of a segment because only sections are written in the
335
- // following loop.
336
- _Header->write (this , *buffer);
337
- _programHeader->write (this , *buffer);
338
-
339
- for (auto section : _layout->sections ())
340
- section->write (this , *buffer);
341
-
342
- return buffer->commit ();
343
- }
344
-
345
- template <class ELFT >
346
- void ExecutableWriter<ELFT>::createDefaultSections() {
347
- _Header.reset (new (_alloc) Header<ELFT>(_targetInfo));
348
- _programHeader.reset (new (_alloc) ProgramHeader<ELFT>(_targetInfo));
349
- _layout->setHeader (_Header.get ());
350
- _layout->setProgramHeader (_programHeader.get ());
351
-
352
- _symtab.reset (new (_alloc) SymbolTable<ELFT>(
353
- _targetInfo, " .symtab" , DefaultLayout<ELFT>::ORDER_SYMBOL_TABLE));
354
- _strtab.reset (new (_alloc) StringTable<ELFT>(
355
- _targetInfo, " .strtab" , DefaultLayout<ELFT>::ORDER_STRING_TABLE));
356
- _shstrtab.reset (new (_alloc) StringTable<ELFT>(
357
- _targetInfo, " .shstrtab" , DefaultLayout<ELFT>::ORDER_SECTION_STRINGS));
358
- _shdrtab.reset (new (_alloc) SectionHeader<ELFT>(
359
- _targetInfo, DefaultLayout<ELFT>::ORDER_SECTION_HEADERS));
360
- _layout->addSection (_symtab.get ());
361
- _layout->addSection (_strtab.get ());
362
- _layout->addSection (_shstrtab.get ());
363
- _shdrtab->setStringSection (_shstrtab.get ());
364
- _symtab->setStringSection (_strtab.get ());
365
- _layout->addSection (_shdrtab.get ());
366
-
367
- if (_targetInfo.isDynamic ()) {
368
- _dynamicTable.reset (new (_alloc) DynamicTable<ELFT>(
369
- _targetInfo, " .dynamic" , DefaultLayout<ELFT>::ORDER_DYNAMIC));
370
- _dynamicStringTable.reset (new (_alloc) StringTable<ELFT>(
371
- _targetInfo, " .dynstr" , DefaultLayout<ELFT>::ORDER_DYNAMIC_STRINGS,
372
- true ));
373
- _dynamicSymbolTable.reset (new (_alloc) DynamicSymbolTable<ELFT>(
374
- _targetInfo, " .dynsym" , DefaultLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS));
375
- _interpSection.reset (new (_alloc) InterpSection<ELFT>(
376
- _targetInfo, " .interp" , DefaultLayout<ELFT>::ORDER_INTERP,
377
- _targetInfo.getInterpreter ()));
378
- _hashTable.reset (new (_alloc) HashSection<ELFT>(
379
- _targetInfo, " .hash" , DefaultLayout<ELFT>::ORDER_HASH));
380
- _layout->addSection (_dynamicTable.get ());
381
- _layout->addSection (_dynamicStringTable.get ());
382
- _layout->addSection (_dynamicSymbolTable.get ());
383
- _layout->addSection (_interpSection.get ());
384
- _layout->addSection (_hashTable.get ());
385
- _dynamicSymbolTable->setStringSection (_dynamicStringTable.get ());
386
- if (_layout->hasDynamicRelocationTable ())
387
- _layout->getDynamicRelocationTable ()->setSymbolTable (
388
- _dynamicSymbolTable.get ());
389
- if (_layout->hasPLTRelocationTable ())
390
- _layout->getPLTRelocationTable ()->setSymbolTable (
391
- _dynamicSymbolTable.get ());
392
- }
393
-
394
- // give a chance for the target to add sections
395
- _targetHandler.createDefaultSections ();
396
- }
397
126
} // namespace elf
398
127
} // namespace lld
399
128
0 commit comments