Skip to content

Commit b327810

Browse files
author
Shankar Easwaran
committedMar 8, 2013
[ELF] Create baseclass for all ELF writers
llvm-svn: 176724
1 parent a88c55b commit b327810

File tree

3 files changed

+389
-587
lines changed

3 files changed

+389
-587
lines changed
 

‎lld/lib/ReaderWriter/ELF/DynamicLibraryWriter.h

Lines changed: 11 additions & 292 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,7 @@
99
#ifndef LLD_READER_WRITER_ELF_DYNAMIC_LIBRARY_WRITER_H
1010
#define LLD_READER_WRITER_ELF_DYNAMIC_LIBRARY_WRITER_H
1111

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"
2113

2214
namespace lld {
2315
namespace elf {
@@ -31,326 +23,53 @@ class DynamicLibraryWriter;
3123
// DynamicLibraryWriter Class
3224
//===----------------------------------------------------------------------===//
3325
template<class ELFT>
34-
class DynamicLibraryWriter : public ELFWriter {
26+
class DynamicLibraryWriter : public OutputELFWriter<ELFT> {
3527
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-
DynamicLibraryWriter(const ELFTargetInfo &ti);
28+
DynamicLibraryWriter(const ELFTargetInfo &ti):OutputELFWriter<ELFT>(ti)
29+
{}
4130

4231
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);
4832
void buildDynamicSymbolTable(const File &file);
49-
void buildSectionHeaderTable();
50-
void assignSectionsWithNoSegments();
5133
void addDefaultAtoms();
5234
void addFiles(InputFiles&);
5335
void finalizeDefaultAtomValues();
5436

55-
uint64_t addressOfAtom(const Atom *atom) {
56-
return _atomToAddressMap[atom];
57-
}
58-
59-
void createDefaultSections();
60-
61-
void createDefaultDynamicEntries() {}
62-
6337
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-
CRuntimeFile<ELFT> _runtimeFile;
8738
};
8839

8940
//===----------------------------------------------------------------------===//
9041
// DynamicLibraryWriter
9142
//===----------------------------------------------------------------------===//
92-
template <class ELFT>
93-
DynamicLibraryWriter<ELFT>::DynamicLibraryWriter(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 DynamicLibraryWriter<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 DynamicLibraryWriter<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-
12043
template <class ELFT>
12144
void DynamicLibraryWriter<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-
}
12645
// Add all the defined symbols to the dynamic symbol table
12746
// we need hooks into the Atom to find out which atoms need
12847
// to be exported
129-
for (auto sec : _layout->sections())
48+
for (auto sec : this->_layout->sections())
13049
if (auto section = dyn_cast<AtomSection<ELFT>>(sec))
13150
for (const auto &atom : section->atoms()) {
13251
const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom->_atom);
13352
if (da && (da->scope() != DefinedAtom::scopeTranslationUnit))
134-
_dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(),
135-
atom->_virtualAddr, atom);
53+
this->_dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(),
54+
atom->_virtualAddr, atom);
13655
}
137-
for (const auto &loadName : _soNeeded) {
138-
Elf_Dyn dyn;
139-
dyn.d_tag = DT_NEEDED;
140-
dyn.d_un.d_val = _dynamicStringTable->addString(loadName.getKey());
141-
_dynamicTable->addEntry(dyn);
142-
}
143-
}
144-
145-
template <class ELFT> void DynamicLibraryWriter<ELFT>::buildAtomToAddressMap() {
146-
for (auto sec : _layout->sections())
147-
if (auto section = dyn_cast<AtomSection<ELFT>>(sec))
148-
for (const auto &atom : section->atoms())
149-
_atomToAddressMap[atom->_atom] = atom->_virtualAddr;
150-
// build the atomToAddressMap that contains absolute symbols too
151-
for (auto &atom : _layout->absoluteAtoms())
152-
_atomToAddressMap[atom->_atom] = atom->_virtualAddr;
153-
}
15456

155-
template<class ELFT>
156-
void DynamicLibraryWriter<ELFT>::buildSectionHeaderTable() {
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-
}
57+
OutputELFWriter<ELFT>::buildDynamicSymbolTable(file);
16458
}
16559

16660
template<class ELFT>
167-
void DynamicLibraryWriter<ELFT>::assignSectionsWithNoSegments() {
168-
for (auto mergedSec : _layout->mergedSections()) {
169-
if (mergedSec->kind() != Chunk<ELFT>::K_ELFSection &&
170-
mergedSec->kind() != Chunk<ELFT>::K_AtomSection)
171-
continue;
172-
if (!mergedSec->hasSegment())
173-
_shdrtab->appendSection(mergedSec);
174-
}
175-
_layout->assignOffsetsForMiscSections();
176-
for (auto sec : _layout->sections())
177-
if (auto section = dyn_cast<Section<ELFT>>(sec))
178-
if (!DefaultLayout<ELFT>::hasOutputSegment(section))
179-
_shdrtab->updateSection(section);
180-
}
61+
void DynamicLibraryWriter<ELFT>::addDefaultAtoms() { }
18162

182-
/// \brief Add absolute symbols by default. These are linker added
183-
/// absolute symbols
184-
template<class ELFT>
185-
void DynamicLibraryWriter<ELFT>::addDefaultAtoms() {
186-
_runtimeFile.addAbsoluteAtom("__bss_start");
187-
}
188-
189-
/// \brief Hook in lld to add CRuntime file
19063
template <class ELFT>
19164
void DynamicLibraryWriter<ELFT>::addFiles(InputFiles &inputFiles) {
192-
addDefaultAtoms();
193-
inputFiles.prependFile(_runtimeFile);
194-
// Give a chance for the target to add atoms
195-
_targetHandler.addFiles(inputFiles);
65+
this->_targetHandler.addFiles(inputFiles);
19666
}
19767

198-
/// Finalize the value of all the absolute symbols that we
199-
/// created
20068
template<class ELFT>
20169
void DynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues() {
202-
auto bssStartAtomIter = _layout->findAbsoluteAtom("__bss_start");
203-
204-
assert(!(bssStartAtomIter == _layout->absoluteAtoms().end()) &&
205-
"Unable to find the absolute atoms that have been added by lld");
206-
207-
auto phe = _programHeader->findProgramHeader(
208-
llvm::ELF::PT_LOAD, llvm::ELF::PF_W, llvm::ELF::PF_X);
209-
210-
(*bssStartAtomIter)->_virtualAddr = (*phe)->p_vaddr + (*phe)->p_filesz;
211-
212-
// Give a chance for the target to finalize its atom values
213-
_targetHandler.finalizeSymbolValues();
70+
this->_targetHandler.finalizeSymbolValues();
21471
}
21572

216-
template <class ELFT>
217-
error_code DynamicLibraryWriter<ELFT>::writeFile(const File &file, StringRef path) {
218-
buildChunks(file);
219-
220-
// Call the preFlight callbacks to modify the sections and the atoms
221-
// contained in them, in anyway the targets may want
222-
_layout->doPreFlight();
223-
224-
// Create the default sections like the symbol table, string table, and the
225-
// section string table
226-
createDefaultSections();
227-
228-
_dynamicTable->createDefaultEntries();
229-
buildDynamicSymbolTable(file);
230-
231-
// Set the Layout
232-
_layout->assignSectionsToSegments();
233-
_layout->assignFileOffsets();
234-
_layout->assignVirtualAddress();
235-
236-
// Finalize the default value of symbols that the linker adds
237-
finalizeDefaultAtomValues();
238-
239-
// Build the Atom To Address map for applying relocations
240-
buildAtomToAddressMap();
241-
242-
// Create symbol table and section string table
243-
buildStaticSymbolTable(file);
244-
245-
// Finalize the layout by calling the finalize() functions
246-
_layout->finalize();
247-
248-
// build Section Header table
249-
buildSectionHeaderTable();
250-
251-
// assign Offsets and virtual addresses
252-
// for sections with no segments
253-
assignSectionsWithNoSegments();
254-
255-
_dynamicTable->updateDynamicTable(_hashTable.get(),
256-
_dynamicSymbolTable.get());
257-
258-
uint64_t totalSize = _shdrtab->fileOffset() + _shdrtab->fileSize();
259-
260-
OwningPtr<FileOutputBuffer> buffer;
261-
error_code ec = FileOutputBuffer::create(path,
262-
totalSize, buffer,
263-
FileOutputBuffer::F_executable);
264-
if (ec)
265-
return ec;
266-
267-
_Header->e_ident(ELF::EI_CLASS, _targetInfo.is64Bits() ? ELF::ELFCLASS64 :
268-
ELF::ELFCLASS32);
269-
_Header->e_ident(ELF::EI_DATA, _targetInfo.isLittleEndian() ?
270-
ELF::ELFDATA2LSB : ELF::ELFDATA2MSB);
271-
_Header->e_type(_targetInfo.getOutputType());
272-
_Header->e_machine(_targetInfo.getOutputMachine());
273-
274-
if (!_targetHandler.doesOverrideHeader()) {
275-
_Header->e_ident(ELF::EI_VERSION, 1);
276-
_Header->e_ident(ELF::EI_OSABI, 0);
277-
_Header->e_version(1);
278-
} else {
279-
// override the contents of the ELF Header
280-
_targetHandler.setHeaderInfo(_Header.get());
281-
}
282-
_Header->e_phoff(_programHeader->fileOffset());
283-
_Header->e_shoff(_shdrtab->fileOffset());
284-
_Header->e_phentsize(_programHeader->entsize());
285-
_Header->e_phnum(_programHeader->numHeaders());
286-
_Header->e_shentsize(_shdrtab->entsize());
287-
_Header->e_shnum(_shdrtab->numHeaders());
288-
_Header->e_shstrndx(_shstrtab->ordinal());
289-
uint64_t virtualAddr = 0;
290-
_layout->findAtomAddrByName(_targetInfo.getEntry(), virtualAddr);
291-
292-
// HACK: We have to write out the header and program header here even though
293-
// they are a member of a segment because only sections are written in the
294-
// following loop.
295-
_Header->write(this, *buffer);
296-
_programHeader->write(this, *buffer);
297-
298-
for (auto section : _layout->sections())
299-
section->write(this, *buffer);
300-
301-
return buffer->commit();
302-
}
303-
304-
template<class ELFT>
305-
void DynamicLibraryWriter<ELFT>::createDefaultSections() {
306-
_Header.reset(new (_alloc) Header<ELFT>(_targetInfo));
307-
_programHeader.reset(new (_alloc) ProgramHeader<ELFT>(_targetInfo));
308-
_layout->setHeader(_Header.get());
309-
_layout->setProgramHeader(_programHeader.get());
310-
311-
_symtab.reset(new (_alloc) SymbolTable<ELFT>(
312-
_targetInfo, ".symtab", DefaultLayout<ELFT>::ORDER_SYMBOL_TABLE));
313-
_strtab.reset(new (_alloc) StringTable<ELFT>(
314-
_targetInfo, ".strtab", DefaultLayout<ELFT>::ORDER_STRING_TABLE));
315-
_shstrtab.reset(new (_alloc) StringTable<ELFT>(
316-
_targetInfo, ".shstrtab", DefaultLayout<ELFT>::ORDER_SECTION_STRINGS));
317-
_shdrtab.reset(new (_alloc) SectionHeader<ELFT>(
318-
_targetInfo, DefaultLayout<ELFT>::ORDER_SECTION_HEADERS));
319-
_layout->addSection(_symtab.get());
320-
_layout->addSection(_strtab.get());
321-
_layout->addSection(_shstrtab.get());
322-
_shdrtab->setStringSection(_shstrtab.get());
323-
_symtab->setStringSection(_strtab.get());
324-
_layout->addSection(_shdrtab.get());
325-
326-
_dynamicTable.reset(new (_alloc) DynamicTable<ELFT>(
327-
_targetInfo, ".dynamic", DefaultLayout<ELFT>::ORDER_DYNAMIC));
328-
_dynamicStringTable.reset(new (_alloc) StringTable<ELFT>(
329-
_targetInfo, ".dynstr", DefaultLayout<ELFT>::ORDER_DYNAMIC_STRINGS,
330-
true));
331-
_dynamicSymbolTable.reset(new (_alloc) DynamicSymbolTable<ELFT>(
332-
_targetInfo, ".dynsym", DefaultLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS));
333-
_interpSection.reset(new (_alloc) InterpSection<ELFT>(
334-
_targetInfo, ".interp", DefaultLayout<ELFT>::ORDER_INTERP,
335-
_targetInfo.getInterpreter()));
336-
_hashTable.reset(new (_alloc) HashSection<ELFT>(
337-
_targetInfo, ".hash", DefaultLayout<ELFT>::ORDER_HASH));
338-
_layout->addSection(_dynamicTable.get());
339-
_layout->addSection(_dynamicStringTable.get());
340-
_layout->addSection(_dynamicSymbolTable.get());
341-
_layout->addSection(_interpSection.get());
342-
_layout->addSection(_hashTable.get());
343-
_dynamicSymbolTable->setStringSection(_dynamicStringTable.get());
344-
if (_layout->hasDynamicRelocationTable())
345-
_layout->getDynamicRelocationTable()->setSymbolTable(
346-
_dynamicSymbolTable.get());
347-
if (_layout->hasPLTRelocationTable())
348-
_layout->getPLTRelocationTable()->setSymbolTable(
349-
_dynamicSymbolTable.get());
350-
351-
// give a chance for the target to add sections
352-
_targetHandler.createDefaultSections();
353-
}
35473
} // namespace elf
35574
} // namespace lld
35675

‎lld/lib/ReaderWriter/ELF/ExecutableWriter.h

Lines changed: 24 additions & 295 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,7 @@
99
#ifndef LLD_READER_WRITER_ELF_EXECUTABLE_WRITER_H
1010
#define LLD_READER_WRITER_ELF_EXECUTABLE_WRITER_H
1111

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"
2113

2214
namespace lld {
2315
namespace elf {
@@ -31,148 +23,29 @@ class ExecutableWriter;
3123
// ExecutableWriter Class
3224
//===----------------------------------------------------------------------===//
3325
template<class ELFT>
34-
class ExecutableWriter : public ELFWriter {
26+
class ExecutableWriter : public OutputELFWriter<ELFT> {
3527
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+
{}
4131

4232
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();
6236

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-
/// @}
8637
CRuntimeFile<ELFT> _runtimeFile;
8738
};
8839

8940
//===----------------------------------------------------------------------===//
9041
// ExecutableWriter
9142
//===----------------------------------------------------------------------===//
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-
}
17043

17144
/// \brief Add absolute symbols by default. These are linker added
17245
/// absolute symbols
17346
template<class ELFT>
17447
void ExecutableWriter<ELFT>::addDefaultAtoms() {
175-
_runtimeFile.addUndefinedAtom(_targetInfo.getEntry());
48+
_runtimeFile.addUndefinedAtom(this->_targetInfo.getEntry());
17649
_runtimeFile.addAbsoluteAtom("__bss_start");
17750
_runtimeFile.addAbsoluteAtom("__bss_end");
17851
_runtimeFile.addAbsoluteAtom("_end");
@@ -193,17 +66,17 @@ void ExecutableWriter<ELFT>::addFiles(InputFiles &inputFiles) {
19366
addDefaultAtoms();
19467
inputFiles.prependFile(_runtimeFile);
19568
// Give a chance for the target to add atoms
196-
_targetHandler.addFiles(inputFiles);
69+
this->_targetHandler.addFiles(inputFiles);
19770
}
19871

19972
/// Finalize the value of all the absolute symbols that we
20073
/// created
20174
template<class ELFT>
20275
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");
20780

20881
auto startEnd = [&](StringRef sym, StringRef sec) -> void {
20982
// TODO: This looks like a good place to use Twine...
@@ -212,9 +85,9 @@ void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
21285
start += "_start";
21386
end += sym;
21487
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);
21891
if (section) {
21992
(*s)->_virtualAddr = section->virtualAddr();
22093
(*e)->_virtualAddr = section->virtualAddr() + section->memSize();
@@ -229,16 +102,16 @@ void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
229102
startEnd("rela_iplt", ".rela.plt");
230103
startEnd("fini_array", ".fini_array");
231104

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()) &&
236109
"Unable to find the absolute atoms that have been added by lld");
237110

238-
auto phe = _programHeader->findProgramHeader(
111+
auto phe = this->_programHeader->findProgramHeader(
239112
llvm::ELF::PT_LOAD, llvm::ELF::PF_W, llvm::ELF::PF_X);
240113

241-
assert(!(phe == _programHeader->end()) &&
114+
assert(!(phe == this->_programHeader->end()) &&
242115
"Can't find a data segment in the program header!");
243116

244117
(*bssStartAtomIter)->_virtualAddr = (*phe)->p_vaddr + (*phe)->p_filesz;
@@ -247,153 +120,9 @@ void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
247120
(*endAtomIter)->_virtualAddr = (*phe)->p_vaddr + (*phe)->p_memsz;
248121

249122
// Give a chance for the target to finalize its atom values
250-
_targetHandler.finalizeSymbolValues();
123+
this->_targetHandler.finalizeSymbolValues();
251124
}
252125

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-
}
397126
} // namespace elf
398127
} // namespace lld
399128

Lines changed: 354 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,354 @@
1+
//===- lib/ReaderWriter/ELF/OutputELFWriter.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_OUTPUT_ELF_WRITER_H
10+
#define LLD_READER_WRITER_OUTPUT_ELF_WRITER_H
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"
21+
22+
namespace lld {
23+
namespace elf {
24+
using namespace llvm;
25+
using namespace llvm::object;
26+
27+
template<class ELFT>
28+
class OutputELFWriter;
29+
30+
//===----------------------------------------------------------------------===//
31+
// OutputELFWriter Class
32+
//===----------------------------------------------------------------------===//
33+
/// \brief This acts as the base class for all the ELF writers that are output
34+
/// for emitting an ELF output file. This class also acts as a common class for
35+
/// creating static and dynamic executables. All the function in this class
36+
/// can be overridden and an appropriate writer be created
37+
template<class ELFT>
38+
class OutputELFWriter : public ELFWriter {
39+
public:
40+
typedef Elf_Shdr_Impl<ELFT> Elf_Shdr;
41+
typedef Elf_Sym_Impl<ELFT> Elf_Sym;
42+
typedef Elf_Dyn_Impl<ELFT> Elf_Dyn;
43+
44+
OutputELFWriter(const ELFTargetInfo &ti);
45+
46+
protected:
47+
// build the sections that need to be created
48+
virtual void createDefaultSections();
49+
50+
// Build all the output sections
51+
virtual void buildChunks(const File &file);
52+
53+
// Build the output file
54+
virtual error_code buildOutput(const File &file);
55+
56+
// Write the file to the path specified
57+
virtual error_code writeFile(const File &File, StringRef path);
58+
59+
// Build the atom to address map, this has to be called
60+
// before applying relocations
61+
virtual void buildAtomToAddressMap();
62+
63+
// Build the symbol table for static linking
64+
virtual void buildStaticSymbolTable(const File &file);
65+
66+
// Build the dynamic symbol table for dynamic linking
67+
virtual void buildDynamicSymbolTable(const File &file);
68+
69+
// Build the section header table
70+
virtual void buildSectionHeaderTable();
71+
72+
// Assign sections that have no segments such as the symbol table,
73+
// section header table, string table etc
74+
virtual void assignSectionsWithNoSegments();
75+
76+
// Add default atoms that need to be present in the output file
77+
virtual void addDefaultAtoms() = 0;
78+
79+
// Add any runtime files and their atoms to the output
80+
virtual void addFiles(InputFiles&) = 0;
81+
82+
// Finalize the default atom values
83+
virtual void finalizeDefaultAtomValues() = 0;
84+
85+
// This is called by the write section to apply relocations
86+
virtual uint64_t addressOfAtom(const Atom *atom) {
87+
return _atomToAddressMap[atom];
88+
}
89+
90+
// This is a hook for creating default dynamic entries
91+
virtual void createDefaultDynamicEntries() {}
92+
93+
llvm::BumpPtrAllocator _alloc;
94+
95+
const ELFTargetInfo &_targetInfo;
96+
TargetHandler<ELFT> &_targetHandler;
97+
98+
typedef llvm::DenseMap<const Atom *, uint64_t> AtomToAddress;
99+
AtomToAddress _atomToAddressMap;
100+
TargetLayout<ELFT> *_layout;
101+
LLD_UNIQUE_BUMP_PTR(Header<ELFT>) _Header;
102+
LLD_UNIQUE_BUMP_PTR(ProgramHeader<ELFT>) _programHeader;
103+
LLD_UNIQUE_BUMP_PTR(SymbolTable<ELFT>) _symtab;
104+
LLD_UNIQUE_BUMP_PTR(StringTable<ELFT>) _strtab;
105+
LLD_UNIQUE_BUMP_PTR(StringTable<ELFT>) _shstrtab;
106+
LLD_UNIQUE_BUMP_PTR(SectionHeader<ELFT>) _shdrtab;
107+
/// \name Dynamic sections.
108+
/// @{
109+
LLD_UNIQUE_BUMP_PTR(DynamicTable<ELFT>) _dynamicTable;
110+
LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>) _dynamicSymbolTable;
111+
LLD_UNIQUE_BUMP_PTR(StringTable<ELFT>) _dynamicStringTable;
112+
LLD_UNIQUE_BUMP_PTR(InterpSection<ELFT>) _interpSection;
113+
LLD_UNIQUE_BUMP_PTR(HashSection<ELFT>) _hashTable;
114+
llvm::StringSet<> _soNeeded;
115+
/// @}
116+
};
117+
118+
//===----------------------------------------------------------------------===//
119+
// OutputELFWriter
120+
//===----------------------------------------------------------------------===//
121+
template <class ELFT>
122+
OutputELFWriter<ELFT>::OutputELFWriter(const ELFTargetInfo &ti)
123+
: _targetInfo(ti), _targetHandler(ti.getTargetHandler<ELFT>()) {
124+
_layout = &_targetHandler.targetLayout();
125+
}
126+
127+
template <class ELFT>
128+
void OutputELFWriter<ELFT>::buildChunks(const File &file) {
129+
for (const DefinedAtom *definedAtom : file.defined()) {
130+
_layout->addAtom(definedAtom);
131+
}
132+
for (const AbsoluteAtom *absoluteAtom : file.absolute())
133+
_layout->addAtom(absoluteAtom);
134+
}
135+
136+
template <class ELFT>
137+
void OutputELFWriter<ELFT>::buildStaticSymbolTable(const File &file) {
138+
for (auto sec : _layout->sections())
139+
if (auto section = dyn_cast<AtomSection<ELFT>>(sec))
140+
for (const auto &atom : section->atoms())
141+
_symtab->addSymbol(atom->_atom, section->ordinal(), atom->_virtualAddr);
142+
for (auto &atom : _layout->absoluteAtoms())
143+
_symtab->addSymbol(atom->_atom, ELF::SHN_ABS, atom->_virtualAddr);
144+
for (const UndefinedAtom *a : file.undefined())
145+
_symtab->addSymbol(a, ELF::SHN_UNDEF);
146+
}
147+
148+
template <class ELFT>
149+
void OutputELFWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
150+
for (const auto sla : file.sharedLibrary()) {
151+
_dynamicSymbolTable->addSymbol(sla, ELF::SHN_UNDEF);
152+
_soNeeded.insert(sla->loadName());
153+
}
154+
for (const auto &loadName : _soNeeded) {
155+
Elf_Dyn dyn;
156+
dyn.d_tag = DT_NEEDED;
157+
dyn.d_un.d_val = _dynamicStringTable->addString(loadName.getKey());
158+
_dynamicTable->addEntry(dyn);
159+
}
160+
}
161+
162+
template <class ELFT> void OutputELFWriter<ELFT>::buildAtomToAddressMap() {
163+
for (auto sec : _layout->sections())
164+
if (auto section = dyn_cast<AtomSection<ELFT>>(sec))
165+
for (const auto &atom : section->atoms())
166+
_atomToAddressMap[atom->_atom] = atom->_virtualAddr;
167+
// build the atomToAddressMap that contains absolute symbols too
168+
for (auto &atom : _layout->absoluteAtoms())
169+
_atomToAddressMap[atom->_atom] = atom->_virtualAddr;
170+
}
171+
172+
template<class ELFT>
173+
void OutputELFWriter<ELFT>::buildSectionHeaderTable() {
174+
for (auto mergedSec : _layout->mergedSections()) {
175+
if (mergedSec->kind() != Chunk<ELFT>::K_ELFSection &&
176+
mergedSec->kind() != Chunk<ELFT>::K_AtomSection)
177+
continue;
178+
if (mergedSec->hasSegment())
179+
_shdrtab->appendSection(mergedSec);
180+
}
181+
}
182+
183+
template<class ELFT>
184+
void OutputELFWriter<ELFT>::assignSectionsWithNoSegments() {
185+
for (auto mergedSec : _layout->mergedSections()) {
186+
if (mergedSec->kind() != Chunk<ELFT>::K_ELFSection &&
187+
mergedSec->kind() != Chunk<ELFT>::K_AtomSection)
188+
continue;
189+
if (!mergedSec->hasSegment())
190+
_shdrtab->appendSection(mergedSec);
191+
}
192+
_layout->assignOffsetsForMiscSections();
193+
for (auto sec : _layout->sections())
194+
if (auto section = dyn_cast<Section<ELFT>>(sec))
195+
if (!DefaultLayout<ELFT>::hasOutputSegment(section))
196+
_shdrtab->updateSection(section);
197+
}
198+
199+
template<class ELFT>
200+
void OutputELFWriter<ELFT>::createDefaultSections() {
201+
_Header.reset(new (_alloc) Header<ELFT>(_targetInfo));
202+
_programHeader.reset(new (_alloc) ProgramHeader<ELFT>(_targetInfo));
203+
_layout->setHeader(_Header.get());
204+
_layout->setProgramHeader(_programHeader.get());
205+
206+
_symtab.reset(new (_alloc) SymbolTable<ELFT>(
207+
_targetInfo, ".symtab", DefaultLayout<ELFT>::ORDER_SYMBOL_TABLE));
208+
_strtab.reset(new (_alloc) StringTable<ELFT>(
209+
_targetInfo, ".strtab", DefaultLayout<ELFT>::ORDER_STRING_TABLE));
210+
_shstrtab.reset(new (_alloc) StringTable<ELFT>(
211+
_targetInfo, ".shstrtab", DefaultLayout<ELFT>::ORDER_SECTION_STRINGS));
212+
_shdrtab.reset(new (_alloc) SectionHeader<ELFT>(
213+
_targetInfo, DefaultLayout<ELFT>::ORDER_SECTION_HEADERS));
214+
_layout->addSection(_symtab.get());
215+
_layout->addSection(_strtab.get());
216+
_layout->addSection(_shstrtab.get());
217+
_shdrtab->setStringSection(_shstrtab.get());
218+
_symtab->setStringSection(_strtab.get());
219+
_layout->addSection(_shdrtab.get());
220+
221+
if (_targetInfo.isDynamic()) {
222+
_dynamicTable.reset(new (_alloc) DynamicTable<ELFT>(
223+
_targetInfo, ".dynamic", DefaultLayout<ELFT>::ORDER_DYNAMIC));
224+
_dynamicStringTable.reset(new (_alloc) StringTable<ELFT>(
225+
_targetInfo, ".dynstr", DefaultLayout<ELFT>::ORDER_DYNAMIC_STRINGS,
226+
true));
227+
_dynamicSymbolTable.reset(new (_alloc) DynamicSymbolTable<ELFT>(
228+
_targetInfo, ".dynsym", DefaultLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS));
229+
_interpSection.reset(new (_alloc) InterpSection<ELFT>(
230+
_targetInfo, ".interp", DefaultLayout<ELFT>::ORDER_INTERP,
231+
_targetInfo.getInterpreter()));
232+
_hashTable.reset(new (_alloc) HashSection<ELFT>(
233+
_targetInfo, ".hash", DefaultLayout<ELFT>::ORDER_HASH));
234+
_layout->addSection(_dynamicTable.get());
235+
_layout->addSection(_dynamicStringTable.get());
236+
_layout->addSection(_dynamicSymbolTable.get());
237+
_layout->addSection(_interpSection.get());
238+
_layout->addSection(_hashTable.get());
239+
_dynamicSymbolTable->setStringSection(_dynamicStringTable.get());
240+
if (_layout->hasDynamicRelocationTable())
241+
_layout->getDynamicRelocationTable()->setSymbolTable(
242+
_dynamicSymbolTable.get());
243+
if (_layout->hasPLTRelocationTable())
244+
_layout->getPLTRelocationTable()->setSymbolTable(
245+
_dynamicSymbolTable.get());
246+
}
247+
248+
// give a chance for the target to add sections
249+
_targetHandler.createDefaultSections();
250+
}
251+
252+
template <class ELFT>
253+
error_code OutputELFWriter<ELFT>::buildOutput(const File &file) {
254+
buildChunks(file);
255+
256+
// Call the preFlight callbacks to modify the sections and the atoms
257+
// contained in them, in anyway the targets may want
258+
_layout->doPreFlight();
259+
260+
// Create the default sections like the symbol table, string table, and the
261+
// section string table
262+
createDefaultSections();
263+
264+
if (_targetInfo.isDynamic()) {
265+
_dynamicTable->createDefaultEntries();
266+
buildDynamicSymbolTable(file);
267+
}
268+
269+
// Set the Layout
270+
_layout->assignSectionsToSegments();
271+
_layout->assignFileOffsets();
272+
_layout->assignVirtualAddress();
273+
274+
// Finalize the default value of symbols that the linker adds
275+
finalizeDefaultAtomValues();
276+
277+
// Build the Atom To Address map for applying relocations
278+
buildAtomToAddressMap();
279+
280+
// Create symbol table and section string table
281+
buildStaticSymbolTable(file);
282+
283+
// Finalize the layout by calling the finalize() functions
284+
_layout->finalize();
285+
286+
// build Section Header table
287+
buildSectionHeaderTable();
288+
289+
// assign Offsets and virtual addresses
290+
// for sections with no segments
291+
assignSectionsWithNoSegments();
292+
293+
if (_targetInfo.isDynamic())
294+
_dynamicTable->updateDynamicTable(_hashTable.get(),
295+
_dynamicSymbolTable.get());
296+
297+
return error_code::success();
298+
}
299+
300+
template <class ELFT>
301+
error_code OutputELFWriter<ELFT>::writeFile(const File &file, StringRef path) {
302+
303+
buildOutput(file);
304+
305+
uint64_t totalSize = _shdrtab->fileOffset() + _shdrtab->fileSize();
306+
307+
OwningPtr<FileOutputBuffer> buffer;
308+
error_code ec = FileOutputBuffer::create(path,
309+
totalSize, buffer,
310+
FileOutputBuffer::F_executable);
311+
if (ec)
312+
return ec;
313+
314+
_Header->e_ident(ELF::EI_CLASS, _targetInfo.is64Bits() ? ELF::ELFCLASS64 :
315+
ELF::ELFCLASS32);
316+
_Header->e_ident(ELF::EI_DATA, _targetInfo.isLittleEndian() ?
317+
ELF::ELFDATA2LSB : ELF::ELFDATA2MSB);
318+
_Header->e_type(_targetInfo.getOutputType());
319+
_Header->e_machine(_targetInfo.getOutputMachine());
320+
321+
if (!_targetHandler.doesOverrideHeader()) {
322+
_Header->e_ident(ELF::EI_VERSION, 1);
323+
_Header->e_ident(ELF::EI_OSABI, 0);
324+
_Header->e_version(1);
325+
} else {
326+
// override the contents of the ELF Header
327+
_targetHandler.setHeaderInfo(_Header.get());
328+
}
329+
_Header->e_phoff(_programHeader->fileOffset());
330+
_Header->e_shoff(_shdrtab->fileOffset());
331+
_Header->e_phentsize(_programHeader->entsize());
332+
_Header->e_phnum(_programHeader->numHeaders());
333+
_Header->e_shentsize(_shdrtab->entsize());
334+
_Header->e_shnum(_shdrtab->numHeaders());
335+
_Header->e_shstrndx(_shstrtab->ordinal());
336+
uint64_t virtualAddr = 0;
337+
_layout->findAtomAddrByName(_targetInfo.getEntry(), virtualAddr);
338+
_Header->e_entry(virtualAddr);
339+
340+
// HACK: We have to write out the header and program header here even though
341+
// they are a member of a segment because only sections are written in the
342+
// following loop.
343+
_Header->write(this, *buffer);
344+
_programHeader->write(this, *buffer);
345+
346+
for (auto section : _layout->sections())
347+
section->write(this, *buffer);
348+
349+
return buffer->commit();
350+
}
351+
} // namespace elf
352+
} // namespace lld
353+
354+
#endif // LLD_READER_WRITER_OUTPUT_ELF_WRITER_H

0 commit comments

Comments
 (0)
Please sign in to comment.