blob: 6c1a633c9b0b699713f9ff6d5dc127d85b7df96b [file] [log] [blame]
Nick Kledzikabb69812012-05-31 22:34:00 +00001//===- lib/ReaderWriter/ELF/WriterELF.cpp ---------------------------------===//
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
10#include "lld/ReaderWriter/WriterELF.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000011#include "ReferenceKinds.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000012
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000013#include "lld/Core/DefinedAtom.h"
14#include "lld/Core/File.h"
15#include "lld/Core/InputFiles.h"
16#include "lld/Core/Reference.h"
17#include "lld/Core/SharedLibraryAtom.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000018#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/DenseMap.h"
Shankar Easwaran495d38b2012-12-27 02:26:30 +000020#include "llvm/ADT/Hashing.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000021#include "llvm/ADT/OwningPtr.h"
22#include "llvm/ADT/SmallVector.h"
Shankar Easwaran495d38b2012-12-27 02:26:30 +000023#include "llvm/ADT/StringExtras.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000024#include "llvm/ADT/StringMap.h"
25#include "llvm/ADT/StringRef.h"
Shankar Easwaran495d38b2012-12-27 02:26:30 +000026#include "llvm/ADT/StringSwitch.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000027#include "llvm/Object/ELF.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000028#include "llvm/Support/Allocator.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000029#include "llvm/Support/Debug.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000030#include "llvm/Support/ELF.h"
31#include "llvm/Support/ErrorHandling.h"
32#include "llvm/Support/FileOutputBuffer.h"
33#include "llvm/Support/Format.h"
34#include "llvm/Support/MathExtras.h"
35#include "llvm/Support/raw_ostream.h"
36#include "llvm/Support/system_error.h"
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +000037#include "ExecutableAtoms.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000038
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000039#include <map>
Shankar Easwaran495d38b2012-12-27 02:26:30 +000040#include <unordered_map>
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000041#include <tuple>
42#include <vector>
Nick Kledzikabb69812012-05-31 22:34:00 +000043
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000044using namespace llvm;
45using namespace llvm::object;
Nick Kledzikabb69812012-05-31 22:34:00 +000046namespace lld {
47namespace elf {
Michael J. Spencera2c97272013-01-04 21:09:21 +000048template<support::endianness target_endianness,
49 std::size_t max_align,
50 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +000051class ELFExecutableWriter;
Hemant Kulkarni87dbac02012-11-13 21:34:45 +000052
Shankar Easwaran495d38b2012-12-27 02:26:30 +000053/// \brief The ELFWriter class is a base class for the linker to write
54/// various kinds of ELF files.
55class ELFWriter : public Writer {
Michael J. Spencera2c97272013-01-04 21:09:21 +000056public:
57 ELFWriter() { }
Shankar Easwaran495d38b2012-12-27 02:26:30 +000058
Michael J. Spencera2c97272013-01-04 21:09:21 +000059public:
60 /// \brief builds the chunks that needs to be written to the output
61 /// ELF file
62 virtual void buildChunks(const lld::File &file) = 0;
Shankar Easwaran495d38b2012-12-27 02:26:30 +000063
Michael J. Spencera2c97272013-01-04 21:09:21 +000064 /// \brief Writes the chunks into the output file specified by path
65 virtual error_code writeFile(const lld::File &File, StringRef path) = 0;
Shankar Easwaran495d38b2012-12-27 02:26:30 +000066
Michael J. Spencera2c97272013-01-04 21:09:21 +000067 /// \brief Writes the chunks into the output file specified by path
68 virtual uint64_t addressOfAtom(const Atom *atom) = 0;
Shankar Easwaran495d38b2012-12-27 02:26:30 +000069
Michael J. Spencera2c97272013-01-04 21:09:21 +000070 /// \brief Return the processing function to apply Relocations
71 virtual KindHandler *kindHandler() = 0;
Hemant Kulkarni87dbac02012-11-13 21:34:45 +000072};
73
Shankar Easwaran495d38b2012-12-27 02:26:30 +000074/// \brief A chunk is a contiguous region of space
Michael J. Spencera2c97272013-01-04 21:09:21 +000075template<support::endianness target_endianness,
76 std::size_t max_align,
77 bool is64Bits>
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000078class Chunk {
79public:
Shankar Easwaran495d38b2012-12-27 02:26:30 +000080
81 /// \brief Describes the type of Chunk
82 enum Kind {
83 K_ELFHeader, // ELF Header
84 K_ELFProgramHeader, // Program Header
85 K_ELFSegment, // Segment
86 K_ELFSection, // Section
87 K_ELFSectionHeader // Section header
Hemant Kulkarni87dbac02012-11-13 21:34:45 +000088 };
Michael J. Spencera2c97272013-01-04 21:09:21 +000089 Chunk(StringRef name, Kind kind)
Shankar Easwaran495d38b2012-12-27 02:26:30 +000090 : _name(name)
91 , _kind(kind)
92 , _fsize(0)
93 , _msize(0)
94 , _align2(0)
95 , _order(0)
96 , _ordinal(1)
97 , _start(0)
98 , _fileoffset(0) {}
99 virtual ~Chunk() {}
Michael J. Spencera2c97272013-01-04 21:09:21 +0000100 // Does the chunk occupy disk space
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000101 virtual bool occupiesNoDiskSpace() const {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000102 return false;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000103 }
104 // The name of the chunk
105 StringRef name() const { return _name; }
106 // Kind of chunk
107 Kind kind() const { return _kind; }
108 uint64_t fileSize() const { return _fsize; }
109 uint64_t align2() const { return _align2; }
110 void appendAtom() const;
111
112 // The ordinal value of the chunk
113 uint64_t ordinal() const { return _ordinal;}
114 void setOrdinal(uint64_t newVal) { _ordinal = newVal;}
115 // The order in which the chunk would appear in the output file
116 uint64_t order() const { return _order; }
117 void setOrder(uint32_t order) { _order = order; }
118 // Output file offset of the chunk
119 uint64_t fileOffset() const { return _fileoffset; }
120 void setFileOffset(uint64_t offset) { _fileoffset = offset; }
121 // Output start address of the chunk
122 void setVAddr(uint64_t start) { _start = start; }
123 uint64_t virtualAddr() const { return _start; }
124 // Does the chunk occupy memory during execution ?
125 uint64_t memSize() const { return _msize; }
126 void setMemSize(uint64_t msize) { _msize = msize; }
Michael J. Spencera2c97272013-01-04 21:09:21 +0000127 // Writer the chunk
128 virtual void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000129 OwningPtr<FileOutputBuffer> &buffer) = 0;
130 // Finalize the chunk before writing
131 virtual void finalize() = 0;
132
Hemant Kulkarni927bbc22012-09-14 16:11:34 +0000133protected:
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000134 StringRef _name;
135 Kind _kind;
136 uint64_t _fsize;
137 uint64_t _msize;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +0000138 uint64_t _align2;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000139 uint32_t _order;
Hemant Kulkarni08e410292012-10-01 23:53:20 +0000140 uint64_t _ordinal;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000141 uint64_t _start;
142 uint64_t _fileoffset;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +0000143};
144
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000145/// \brief The ELFLayoutOptions encapsulates the options used by all Layouts
146/// Examples of the ELFLayoutOptions would be a script that would be used
Michael J. Spencera2c97272013-01-04 21:09:21 +0000147/// to drive the layout
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000148class ELFLayoutOptions {
Hemant Kulkarni927bbc22012-09-14 16:11:34 +0000149public:
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000150 ELFLayoutOptions() { }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +0000151
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000152 ELFLayoutOptions(StringRef &linker_script) : _script(linker_script)
153 {}
Hemant Kulkarni87dbac02012-11-13 21:34:45 +0000154
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000155 /// parse the linker script
156 error_code parseLinkerScript();
Hemant Kulkarni736f7fb2012-11-21 21:07:36 +0000157
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000158 /// Is the current section present in the linker script
159 bool isSectionPresent();
160
Hemant Kulkarni08e410292012-10-01 23:53:20 +0000161private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000162 StringRef _script;
Hemant Kulkarni08e410292012-10-01 23:53:20 +0000163};
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000164
Michael J. Spencera2c97272013-01-04 21:09:21 +0000165/// \brief The ELFLayout is an abstract class for managing the final layout for
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000166/// the kind of binaries(Shared Libraries / Relocatables / Executables 0
Michael J. Spencera2c97272013-01-04 21:09:21 +0000167/// Each architecture (Hexagon, PowerPC, MIPS) would have a concrete
168/// subclass derived from ELFLayout for generating each binary thats
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000169// needed by the lld linker
170class ELFLayout {
171public:
172 typedef uint32_t SectionOrder;
173 typedef uint32_t SegmentType;
174 typedef uint32_t Flags;
175
176public:
177 /// Return the order the section would appear in the output file
178 virtual SectionOrder getSectionOrder
179 (const StringRef name,
180 int32_t contentType,
181 int32_t contentPerm) = 0;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000182 /// append the Atom to the layout and create appropriate sections
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000183 virtual error_code addAtom(const Atom *atom) = 0;
184 /// find the Atom Address in the current layout
185 virtual bool findAtomAddrByName(const StringRef name, uint64_t &addr) = 0;
186 /// associates a section to a segment
187 virtual void assignSectionsToSegments() = 0;
188 /// associates a virtual address to the segment, section, and the atom
189 virtual void assignVirtualAddress() = 0;
190 /// associates a file offset to the segment, section and the atom
191 virtual void assignFileOffsets() = 0;
192
193public:
194 ELFLayout() {}
Michael J. Spencera2c97272013-01-04 21:09:21 +0000195 ELFLayout(WriterOptionsELF &writerOptions,
196 ELFLayoutOptions &layoutOptions)
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000197 : _writerOptions(writerOptions)
198 , _layoutOptions(layoutOptions) {}
199 virtual ~ELFLayout() { }
200
201private:
202 WriterOptionsELF _writerOptions;
203 ELFLayoutOptions _layoutOptions;
204};
205
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000206/// \brief A section contains a set of atoms that have similiar properties
207/// The atoms that have similiar properties are merged to form a section
Michael J. Spencera2c97272013-01-04 21:09:21 +0000208template<support::endianness target_endianness,
209 std::size_t max_align,
210 bool is64Bits>
211class Section : public Chunk<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000212public:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000213 // The Kind of section that the object represents
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000214 enum SectionKind {
215 K_Default,
216 K_SymbolTable,
217 K_StringTable,
218 };
219 // Create a section object, the section is set to the default type if the
220 // caller doesnot set it
Michael J. Spencera2c97272013-01-04 21:09:21 +0000221 Section(const StringRef sectionName,
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000222 const int32_t contentType,
223 const int32_t contentPermissions,
224 const int32_t order,
Michael J. Spencera2c97272013-01-04 21:09:21 +0000225 const SectionKind kind = K_Default)
226 : Chunk<target_endianness, max_align, is64Bits>(
227 sectionName, Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000228 , _contentType(contentType)
229 , _contentPermissions(contentPermissions)
230 , _sectionKind(kind)
231 , _entSize(0)
232 , _shInfo(0)
233 , _link(0) {
234 this->setOrder(order);
235 }
236
237 /// return the section kind
238 SectionKind sectionKind() const {
239 return _sectionKind;
240 }
241
242 /// Align the offset to the required modulus defined by the atom alignment
243 uint64_t alignOffset(uint64_t offset, DefinedAtom::Alignment &atomAlign) {
244 uint64_t requiredModulus = atomAlign.modulus;
245 uint64_t align2 = 1u << atomAlign.powerOf2;
246 uint64_t currentModulus = (offset % align2);
247 uint64_t retOffset = offset;
248 if (currentModulus != requiredModulus) {
249 if (requiredModulus > currentModulus)
250 retOffset += requiredModulus - currentModulus;
251 else
252 retOffset += align2 + requiredModulus - currentModulus;
253 }
254 return retOffset;
255 }
256
Michael J. Spencera2c97272013-01-04 21:09:21 +0000257 // \brief Append an atom to a Section. The atom gets pushed into a vector
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000258 // contains the atom, the atom file offset, the atom virtual address
259 // the atom file offset is aligned appropriately as set by the Reader
260 void appendAtom(const Atom *atom) {
261 Atom::Definition atomType = atom->definition();
262 const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom);
263 assert(atom != nullptr && "Expecting the atom to be a DefinedAtom");
264 DefinedAtom::Alignment atomAlign = definedAtom->alignment();
265 uint64_t align2 = 1u << atomAlign.powerOf2;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000266 // Align the atom to the required modulus/ align the file offset and the
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000267 // memory offset seperately this is required so that BSS symbols are handled
268 // properly as the BSS symbols only occupy memory size and not file size
269 uint64_t fOffset = alignOffset(this->fileSize(), atomAlign);
270 uint64_t mOffset = alignOffset(this->memSize(), atomAlign);
271 switch (atomType) {
272 case Atom::definitionRegular:
273 switch(definedAtom->contentType()) {
274 case DefinedAtom::typeCode:
275 case DefinedAtom::typeData:
Michael J. Spencer8de83642013-01-07 08:00:42 +0000276 case DefinedAtom::typeConstant:
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000277 _atoms.push_back(std::make_pair(atom, std::make_pair(fOffset, 0)));
278 this->_fsize = fOffset + definedAtom->size();
279 this->_msize = mOffset + definedAtom->size();
280 break;
281 case DefinedAtom::typeZeroFill:
282 _atoms.push_back(std::make_pair(atom, std::make_pair(mOffset, 0)));
283 this->_msize = mOffset + definedAtom->size();
284 break;
285 default:
286 this->_fsize = fOffset + definedAtom->size();
287 this->_msize = mOffset + definedAtom->size();
288 break;
289 }
290 break;
291 default:
292 llvm_unreachable("Expecting only definedAtoms being passed here");
293 break;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000294 }
295 // Set the section alignment to the largest alignment
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000296 // std::max doesnot support uint64_t
Michael J. Spencera2c97272013-01-04 21:09:21 +0000297 if (this->_align2 < align2)
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000298 this->_align2 = align2;
299 }
300
Michael J. Spencera2c97272013-01-04 21:09:21 +0000301 /// \brief Set the virtual address of each Atom in the Section. This
302 /// routine gets called after the linker fixes up the virtual address
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000303 /// of the section
304 void assignVirtualAddress(uint64_t &addr) {
305 for (auto &ai : _atoms) {
306 ai.second.second = addr + ai.second.first;
307 }
308 addr += this->memSize();
309 }
310
Michael J. Spencera2c97272013-01-04 21:09:21 +0000311 /// \brief Set the file offset of each Atom in the section. This routine
312 /// gets called after the linker fixes up the section offset
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000313 void assignOffsets(uint64_t offset) {
314 for (auto &ai : _atoms) {
315 ai.second.first = offset + ai.second.first;
316 }
317 }
318
Michael J. Spencera2c97272013-01-04 21:09:21 +0000319 /// \brief Find the Atom address given a name, this is needed to to properly
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000320 /// apply relocation. The section class calls this to find the atom address
321 /// to fix the relocation
322 bool findAtomAddrByName(const StringRef name, uint64_t &addr) {
323 for (auto ai : _atoms) {
324 if (ai.first->name() == name) {
325 addr = ai.second.second;
326 return true;
327 }
328 }
329 return false;
330 }
331
332 /// \brief Does the Atom occupy any disk space
333 bool occupiesNoDiskSpace() const {
334 return _contentType == DefinedAtom::typeZeroFill;
335 }
336
Michael J. Spencera2c97272013-01-04 21:09:21 +0000337 /// \brief The permission of the section is the most permissive permission
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000338 /// of all atoms that the section contains
339 void setContentPermissions(int32_t perm) {
340 _contentPermissions = std::max(perm, _contentPermissions);
341 }
342
343 /// \brief Get the section flags, defined by the permissions of the section
344 int64_t flags() {
345 switch (_contentPermissions) {
346 case DefinedAtom::perm___:
347 return 0;
348
349 case DefinedAtom::permR__:
350 return llvm::ELF::SHF_ALLOC;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000351
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000352 case DefinedAtom::permR_X:
353 return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000354
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000355 case DefinedAtom::permRW_:
356 case DefinedAtom::permRW_L:
357 return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000358
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000359 case DefinedAtom::permRWX:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000360 return llvm::ELF::SHF_ALLOC |
361 llvm::ELF::SHF_WRITE |
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000362 llvm::ELF::SHF_EXECINSTR;
363
364 default:
365 break;
366 }
367 return llvm::ELF::SHF_ALLOC;
368 }
369
370 /// \brief Return the raw flags, we need this to sort segments
371 int64_t atomflags() const {
372 return _contentPermissions;
373 }
374
Michael J. Spencera2c97272013-01-04 21:09:21 +0000375 /// \brief Return the section type, the returned value is recorded in the
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000376 /// sh_type field of the Section Header
377 int type() {
378 switch (_contentType) {
379 case DefinedAtom::typeCode:
380 case DefinedAtom::typeData:
381 case DefinedAtom::typeConstant:
382 return llvm::ELF::SHT_PROGBITS;
383
384 case DefinedAtom::typeZeroFill:
385 return llvm::ELF::SHT_NOBITS;
386
387 // Case to handle section types
388 // Symtab, String Table ...
389 default:
390 return _contentType;
391 }
392 }
393
Michael J. Spencera2c97272013-01-04 21:09:21 +0000394 /// \brief Returns the section link field, the returned value is
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000395 /// recorded in the sh_link field of the Section Header
396 int link() const {
397 return _link;
398 }
399
400 void setLink(int32_t link) {
401 _link = link;
402 }
403
Michael J. Spencera2c97272013-01-04 21:09:21 +0000404 /// \brief Returns the section entsize field, the returned value is
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000405 /// recorded in the sh_entsize field of the Section Header
406 int entsize() const {
407 return _entSize;
408 }
409
Michael J. Spencera2c97272013-01-04 21:09:21 +0000410 /// \brief Returns the shinfo field, the returned value is
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000411 /// recorded in the sh_info field of the Section Header
Michael J. Spencera2c97272013-01-04 21:09:21 +0000412 int shinfo() const {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000413 return _shInfo;
414 }
415
416 /// \brief Records the segmentType, that this section belongs to
417 void setSegment(const ELFLayout::SegmentType segmentType) {
418 _segmentType = segmentType;
419 }
420
421 /// \brief convert the segment type to a String for diagnostics
422 /// and printing purposes
423 StringRef segmentKindToStr() const {
424 switch(_segmentType) {
425 case llvm::ELF::PT_INTERP:
426 return "INTERP";
427 case llvm::ELF::PT_LOAD:
428 return "LOAD";
429 case llvm::ELF::PT_GNU_EH_FRAME:
430 return "EH_FRAME";
431 case llvm::ELF::PT_NOTE:
432 return "NOTE";
433 case llvm::ELF::PT_DYNAMIC:
434 return "DYNAMIC";
435 case llvm::ELF::PT_GNU_RELRO:
436 return "RELRO";
437 case llvm::ELF::PT_NULL:
438 return "NULL";
439 default:
440 return "UNKNOWN";
441 }
442 }
443
444 /// \brief for LLVM style RTTI information
Michael J. Spencera2c97272013-01-04 21:09:21 +0000445 static inline bool classof(
446 const Chunk<target_endianness, max_align, is64Bits> *c) {
447 return c->kind() ==
448 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000449 }
450
451 /// \brief Finalize the section contents before writing
452 void finalize() { }
453
Michael J. Spencera2c97272013-01-04 21:09:21 +0000454 /// \brief Write the section and the atom contents to the buffer
455 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000456 OwningPtr<FileOutputBuffer> &buffer) {
457 uint8_t *chunkBuffer = buffer->getBufferStart();
458 for (auto &ai : _atoms) {
459 const DefinedAtom *definedAtom = llvm::dyn_cast<DefinedAtom>(ai.first);
Michael J. Spencer8de83642013-01-07 08:00:42 +0000460 if (definedAtom->contentType() == DefinedAtom::typeZeroFill)
461 continue;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000462 // Copy raw content of atom to file buffer.
463 ArrayRef<uint8_t> content = definedAtom->rawContent();
464 uint64_t contentSize = content.size();
465 if (contentSize == 0)
466 continue;
467 uint8_t *atomContent = chunkBuffer + ai.second.first;
468 std::copy_n(content.data(), contentSize, atomContent);
469 for (auto ref = definedAtom->begin(); ref != definedAtom->end(); ++ref) {
470 uint32_t offset = ref->offsetInAtom();
471 uint64_t targetAddress = 0;
472 if (ref->target() != nullptr)
473 targetAddress = writer->addressOfAtom(ref->target());
474 else
475 assert(0 && "Found the target to be NULL");
476 uint64_t fixupAddress = writer->addressOfAtom(ai.first) + offset;
477 // apply the relocation
Michael J. Spencera2c97272013-01-04 21:09:21 +0000478 writer->kindHandler()->applyFixup(ref->kind(),
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000479 ref->addend(),
480 &atomContent[offset],
481 fixupAddress,
482 targetAddress);
483 }
484 }
485 }
486
487 /// Atom Iterators
Michael J. Spencera2c97272013-01-04 21:09:21 +0000488 typedef typename std::vector<std::pair<const Atom *,
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000489 std::pair<uint64_t, uint64_t>>>::iterator atom_iter;
490
491 atom_iter atoms_begin() { return _atoms.begin(); }
492
493 atom_iter atoms_end() { return _atoms.end(); }
494
495protected:
496 int32_t _contentType;
497 int32_t _contentPermissions;
498 SectionKind _sectionKind;
499 // An Atom is appended to the vector with the following fields
500 // field1 : Atom
501 // field2 : fileoffset (initially set with a base offset of 0)
502 // field3 : virtual address
503 std::vector<std::pair<const Atom *, std::pair<uint64_t, uint64_t>>> _atoms;
504 ELFLayout::SegmentType _segmentType;
505 int64_t _entSize;
506 int64_t _shInfo;
507 int64_t _link;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000508};
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000509
Michael J. Spencera2c97272013-01-04 21:09:21 +0000510/// \brief A MergedSections represents a set of sections grouped by the same
511/// name. The output file that gets written by the linker has sections grouped
512/// by similiar names
513template<support::endianness target_endianness,
514 std::size_t max_align,
515 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000516class MergedSections {
517public:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000518 MergedSections(StringRef name)
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000519 : _name(name)
520 ,_hasSegment(false)
521 ,_ordinal(0)
522 ,_flags(0)
523 ,_size(0)
524 ,_memSize(0)
525 ,_fileOffset(0)
526 ,_virtualAddr(0)
527 ,_shInfo(0)
528 ,_entSize(0)
529 ,_link(0)
530 ,_align2(0)
531 ,_kind(0)
532 ,_type(0) { }
Michael J. Spencera2c97272013-01-04 21:09:21 +0000533
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000534 // Set the MergedSections is associated with a segment
535 void setHasSegment() { _hasSegment = true; }
536
Michael J. Spencera2c97272013-01-04 21:09:21 +0000537 /// Sets the ordinal
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000538 void setOrdinal(uint64_t ordinal) {
539 _ordinal = ordinal;
540 }
541
Michael J. Spencera2c97272013-01-04 21:09:21 +0000542 /// Sets the Memory size
543 void setMemSize(uint64_t memsz) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000544 _memSize = memsz;
545 }
546
547 /// Sets the size fo the merged Section
548 void setSize(uint64_t fsiz) {
549 _size = fsiz;
550 }
551
Michael J. Spencera2c97272013-01-04 21:09:21 +0000552 // The offset of the first section contained in the merged section is
553 // contained here
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000554 void setFileOffset(uint64_t foffset) {
555 _fileOffset = foffset;
556 }
557
558 // Sets the starting address of the section
559 void setAddr(uint64_t addr) {
560 _virtualAddr = addr;
561 }
562
563 // Appends a section into the list of sections that are part of this Merged
564 // Section
Michael J. Spencera2c97272013-01-04 21:09:21 +0000565 void appendSection(Chunk<target_endianness, max_align, is64Bits> *c) {
566 if (c->align2() > _align2)
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000567 _align2 = c->align2();
Michael J. Spencera2c97272013-01-04 21:09:21 +0000568 if (c->kind() ==
569 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection) {
570 Section<target_endianness, max_align, is64Bits> *section;
571 section =
572 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(c);
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000573 _link = section->link();
574 _shInfo = section->shinfo();
575 _entSize = section->entsize();
576 _type = section->type();
577 if (_flags < section->flags())
578 _flags = section->flags();
579 }
580 _kind = c->kind();
581 _sections.push_back(c);
582 }
583
584 // Iterators
Michael J. Spencera2c97272013-01-04 21:09:21 +0000585 typedef typename std::vector<
586 Chunk<target_endianness, max_align, is64Bits> *>::iterator ChunkIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000587
588 ChunkIter begin_sections() { return _sections.begin(); }
589
590 ChunkIter end_sections() { return _sections.end(); }
591
592 // The below functions returns the properties of the MergeSection
593 bool hasSegment() const { return _hasSegment; }
594
595 StringRef name() const { return _name; }
596
597 int64_t shinfo() const { return _shInfo; }
598
599 uint64_t align2() const { return _align2; }
600
601 int64_t link() const { return _link; }
602
603 int64_t type() const { return _type; }
604
605 uint64_t virtualAddr() const { return _virtualAddr; }
606
607 int64_t ordinal() const { return _ordinal; }
608
609 int64_t kind() const { return _kind; }
610
611 uint64_t fileSize() const { return _size; }
612
613 int64_t entsize() const { return _entSize; }
614
615 uint64_t fileOffset() const { return _fileOffset; }
616
617 int64_t flags() const { return _flags; }
618
619 uint64_t memSize() { return _memSize; }
620
621private:
622 StringRef _name;
623 bool _hasSegment;
624 uint64_t _ordinal;
625 int64_t _flags;
626 uint64_t _size;
627 uint64_t _memSize;
628 uint64_t _fileOffset;
629 uint64_t _virtualAddr;
630 int64_t _shInfo;
631 int64_t _entSize;
632 int64_t _link;
633 uint64_t _align2;
634 int64_t _kind;
635 int64_t _type;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000636 std::vector<Chunk<target_endianness, max_align, is64Bits> *> _sections;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000637};
638
Michael J. Spencera2c97272013-01-04 21:09:21 +0000639/// \brief A segment can be divided into segment slices
640/// depending on how the segments can be split
641template<support::endianness target_endianness,
642 std::size_t max_align,
643 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000644class SegmentSlice {
645public:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000646 typedef typename std::vector<
Michael J. Spencer00b702c2013-01-07 07:59:46 +0000647 Chunk<target_endianness, max_align, is64Bits> *>::iterator sectionIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000648
649 SegmentSlice() { }
650
651 /// Set the segment slice so that it begins at the offset specified
Michael J. Spencera2c97272013-01-04 21:09:21 +0000652 /// by fileoffset and set the start of the slice to be s and the end
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000653 /// of the slice to be e
654 void set(uint64_t fileoffset, int32_t s, int e) {
655 _startSection = s;
656 _endSection = e+1;
657 _offset = fileoffset;
658 }
659
660 // Set the segment slice start and end iterators. This is used to walk through
661 // the sections that are part of the Segment slice
662 void setSections(sectionIter start, sectionIter end) {
663 _startSectionIter = start;
664 _endSectionIter = end;
665 }
666
667 // Return the fileOffset of the slice
668 uint64_t fileOffset() const { return _offset; }
669
670 // Return the size of the slice
671 uint64_t fileSize() const { return _size; }
672
673 // Return the start of the slice
674 int32_t startSection() const { return _startSection; }
675
676 // Return the start address of the slice
677 uint64_t virtualAddr() const { return _addr; }
678
679 // Return the memory size of the slice
680 uint64_t memSize() const { return _memSize; }
681
682 // Return the alignment of the slice
683 uint64_t align2() const { return _align2; }
684
685 void setSize(uint64_t sz) { _size = sz; }
686
687 void setMemSize(uint64_t memsz) { _memSize = memsz; }
688
689 void setVAddr(uint64_t addr) { _addr = addr; }
690
691 void setAlign(uint64_t align) { _align2 = align; }
692
Michael J. Spencera2c97272013-01-04 21:09:21 +0000693 static bool compare_slices(
694 SegmentSlice<target_endianness, max_align, is64Bits> *a,
695 SegmentSlice<target_endianness, max_align, is64Bits> *b) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000696 return (a->startSection() < b->startSection());
697 }
698
699 // Functions to run through the slice
700 sectionIter sections_begin() { return _startSectionIter; }
701
702 sectionIter sections_end() { return _endSectionIter; }
703
704private:
705 int32_t _startSection;
706 int32_t _endSection;
707 sectionIter _startSectionIter;
708 sectionIter _endSectionIter;
709 uint64_t _addr;
710 uint64_t _offset;
711 uint64_t _size;
712 uint64_t _align2;
713 uint64_t _memSize;
714};
715
716/// \brief A segment contains a set of sections, that have similiar properties
717// the sections are already seperated based on different flags and properties
718// the segment is just a way to concatenate sections to segments
Michael J. Spencera2c97272013-01-04 21:09:21 +0000719template<support::endianness target_endianness,
720 std::size_t max_align,
721 bool is64Bits>
722class Segment : public Chunk<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000723public:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000724 typedef typename std::vector<SegmentSlice<
725 target_endianness, max_align, is64Bits> *>::iterator slice_iter;
726 typedef typename std::vector<
Michael J. Spencer00b702c2013-01-07 07:59:46 +0000727 Chunk<target_endianness, max_align, is64Bits> *>::iterator SectionIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000728
729 Segment(const StringRef name,
730 const ELFLayout::SegmentType type,
731 const WriterOptionsELF &options)
Michael J. Spencera2c97272013-01-04 21:09:21 +0000732 : Chunk<target_endianness, max_align, is64Bits>(name,
733 Chunk<target_endianness, max_align, is64Bits>::K_ELFSegment)
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000734 , _segmentType(type)
735 , _flags(0)
736 , _atomflags(0)
737 , _options(options) {
738 this->_align2 = 0;
739 this->_fsize = 0;
740 }
741
742 /// append a section to a segment
Michael J. Spencera2c97272013-01-04 21:09:21 +0000743 void append(Section<target_endianness, max_align, is64Bits> *section) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000744 _sections.push_back(section);
745 if (_flags < section->flags())
746 _flags = section->flags();
747 if (_atomflags < section->atomflags())
748 _atomflags = section->atomflags();
749 if (this->_align2 < section->align2())
750 this->_align2 = section->align2();
751 }
752
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000753 /// Prepend a generic chunk to the segment.
754 void prepend(Chunk<target_endianness, max_align, is64Bits> *c) {
755 _sections.insert(_sections.begin(), c);
756 }
757
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000758 /// Sort segments depending on the property
759 /// If we have a Program Header segment, it should appear first
760 /// If we have a INTERP segment, that should appear after the Program Header
761 /// All Loadable segments appear next in this order
762 /// All Read Write Execute segments follow
763 /// All Read Execute segments appear next
764 /// All Read only segments appear first
Michael J. Spencera2c97272013-01-04 21:09:21 +0000765 /// All Write execute segments follow
766 static bool compareSegments(
767 Segment<target_endianness, max_align, is64Bits> *sega,
768 Segment<target_endianness, max_align, is64Bits> *segb) {
769 if (sega->atomflags() < segb->atomflags())
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000770 return false;
771 return true;
772 }
773
774 /// \brief Start assigning file offset to the segment chunks The fileoffset
775 /// needs to be page at the start of the segment and in addition the
776 /// fileoffset needs to be aligned to the max section alignment within the
777 /// segment. This is required so that the ELF property p_poffset % p_align =
778 /// p_vaddr mod p_align holds true.
779 /// The algorithm starts off by assigning the startOffset thats passed in as
780 /// parameter to the first section in the segment, if the difference between
781 /// the newly computed offset is greater than a page, then we create a segment
Michael J. Spencera2c97272013-01-04 21:09:21 +0000782 /// slice, as it would be a waste of virtual memory just to be filled with
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000783 /// zeroes
784 void assignOffsets(uint64_t startOffset) {
785 int startSection = 0;
786 int currSection = 0;
787 SectionIter startSectionIter, endSectionIter;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000788 // slice align is set to the max alignment of the chunks that are
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000789 // contained in the slice
790 uint64_t sliceAlign = 0;
791 // Current slice size
792 uint64_t curSliceSize = 0;
793 // Current Slice File Offset
794 uint64_t curSliceFileOffset = 0;
795
796 startSectionIter = _sections.begin();
797 endSectionIter = _sections.end();
798 startSection = 0;
799 bool isFirstSection = true;
800 for (auto si = _sections.begin(); si != _sections.end(); ++si) {
801 if (isFirstSection) {
802 // align the startOffset to the section alignment
Michael J. Spencera2c97272013-01-04 21:09:21 +0000803 uint64_t newOffset =
804 llvm::RoundUpToAlignment(startOffset, (*si)->align2());
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000805 curSliceFileOffset = newOffset;
806 sliceAlign = (*si)->align2();
807 this->setFileOffset(startOffset);
808 (*si)->setFileOffset(newOffset);
809 curSliceSize = (*si)->fileSize();
810 isFirstSection = false;
811 } else {
812 uint64_t curOffset = curSliceFileOffset + curSliceSize;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000813 uint64_t newOffset =
814 llvm::RoundUpToAlignment(curOffset, (*si)->align2());
815 SegmentSlice<target_endianness, max_align, is64Bits> *slice = nullptr;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000816 // If the newOffset computed is more than a page away, lets create
817 // a seperate segment, so that memory is not used up while running
818 if ((newOffset - curOffset) > _options.pageSize()) {
819 // TODO: use std::find here
820 for (auto sei = slices_begin(); sei != slices_end(); ++sei) {
821 if ((*sei)->startSection() == startSection) {
822 slice = *sei;
823 break;
824 }
825 }
826 if (!slice) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000827 slice = new (_segmentAllocate.Allocate<
828 SegmentSlice<target_endianness, max_align, is64Bits>>())
829 SegmentSlice<target_endianness, max_align, is64Bits>();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000830 _segmentSlices.push_back(slice);
831 }
832 slice->set(curSliceFileOffset, startSection, currSection);
833 slice->setSections(startSectionIter, endSectionIter);
834 slice->setSize(curSliceSize);
835 slice->setAlign(sliceAlign);
Michael J. Spencera2c97272013-01-04 21:09:21 +0000836 uint64_t newPageOffset =
837 llvm::RoundUpToAlignment(curOffset, _options.pageSize());
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000838 newOffset = llvm::RoundUpToAlignment(newPageOffset, (*si)->align2());
839 curSliceFileOffset = newOffset;
840 startSectionIter = endSectionIter;
841 startSection = currSection;
842 (*si)->setFileOffset(curSliceFileOffset);
843 curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
844 sliceAlign = (*si)->align2();
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +0000845 } else {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000846 if (sliceAlign < (*si)->align2())
847 sliceAlign = (*si)->align2();
848 (*si)->setFileOffset(newOffset);
849 curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
850 }
851 }
852 currSection++;
853 endSectionIter = si;
854 }
Michael J. Spencera2c97272013-01-04 21:09:21 +0000855 SegmentSlice<target_endianness, max_align, is64Bits> *slice = nullptr;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000856 for (auto sei = slices_begin(); sei != slices_end(); ++sei) {
857 // TODO: add std::find
858 if ((*sei)->startSection() == startSection) {
859 slice = *sei;
860 break;
861 }
862 }
863 if (!slice) {
864 slice = new (_segmentAllocate.Allocate
Michael J. Spencera2c97272013-01-04 21:09:21 +0000865 <SegmentSlice<target_endianness, max_align, is64Bits>>())
866 SegmentSlice<target_endianness, max_align, is64Bits>();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000867 _segmentSlices.push_back(slice);
868 }
869 slice->set(curSliceFileOffset, startSection, currSection);
870 slice->setSections(startSectionIter, _sections.end());
871 slice->setSize(curSliceSize);
872 slice->setAlign(sliceAlign);
873 this->_fsize = curSliceFileOffset - startOffset + curSliceSize;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000874 std::stable_sort(slices_begin(), slices_end(),
875 SegmentSlice<target_endianness, max_align, is64Bits>::compare_slices);
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000876 }
877
878 /// \brief Assign virtual addresses to the slices
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000879 void assignVirtualAddress(uint64_t &addr) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000880 for (auto sei = slices_begin(), see = slices_end(); sei != see; ++sei) {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000881 // Align to a page
882 addr = llvm::RoundUpToAlignment(addr, _options.pageSize());
883 // Align to the slice alignment
884 addr = llvm::RoundUpToAlignment(addr, (*sei)->align2());
885
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000886 bool virtualAddressSet = false;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000887 for (auto si = (*sei)->sections_begin(), se = (*sei)->sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000888 si != se; ++si) {
889 // Align the section address
890 addr = llvm::RoundUpToAlignment(addr, (*si)->align2());
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000891 if (!virtualAddressSet) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000892 (*sei)->setVAddr(addr);
893 virtualAddressSet = true;
894 }
895 (*si)->setVAddr(addr);
Michael J. Spencer00b702c2013-01-07 07:59:46 +0000896 if (auto s =
897 dyn_cast<Section<target_endianness, max_align, is64Bits>>(*si))
898 s->assignVirtualAddress(addr);
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000899 else
900 addr += (*si)->memSize();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000901 (*si)->setMemSize(addr - (*si)->virtualAddr());
902 }
903 (*sei)->setMemSize(addr - (*sei)->virtualAddr());
904 }
905 }
906
907 slice_iter slices_begin() {
908 return _segmentSlices.begin();
909 }
910
911 slice_iter slices_end() {
912 return _segmentSlices.end();
913 }
914
Michael J. Spencera2c97272013-01-04 21:09:21 +0000915 // Write the Segment
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000916 void write(ELFWriter *writer, OwningPtr<FileOutputBuffer> &buffer) {
917 for (auto sei = slices_begin(), see = slices_end(); sei != see; ++sei) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000918 for (auto si = (*sei)->sections_begin(), se = (*sei)->sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000919 si != se; ++si) {
920 (*si)->write(writer, buffer);
921 }
922 }
923 }
924
925 // Finalize the segment, before we want to write to the output file
926 void finalize() { }
927
Michael J. Spencera2c97272013-01-04 21:09:21 +0000928 // For LLVM RTTI
929 static inline bool classof(
930 const Chunk<target_endianness, max_align, is64Bits> *c) {
931 return c->kind() ==
932 Chunk<target_endianness, max_align, is64Bits>::K_ELFSegment;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000933 }
934
935 // Getters
936 int32_t sectionCount() const {
937 return _sections.size();
938 }
939
940 ELFLayout::SegmentType segmentType() { return _segmentType; }
941
942 int pageSize() const { return _options.pageSize(); }
943
944 int64_t atomflags() const { return _atomflags; }
945
946 int64_t flags() const {
947 int64_t fl = 0;
948 if (_flags & llvm::ELF::SHF_ALLOC)
949 fl |= llvm::ELF::PF_R;
950 if (_flags & llvm::ELF::SHF_WRITE)
951 fl |= llvm::ELF::PF_W;
952 if (_flags & llvm::ELF::SHF_EXECINSTR)
953 fl |= llvm::ELF::PF_X;
954 return fl;
955 }
956
957 int64_t numSlices() const {
958 return _segmentSlices.size();
959 }
960
961private:
Michael J. Spencer00b702c2013-01-07 07:59:46 +0000962 /// \brief Section or some other chunk type.
963 std::vector<Chunk<target_endianness, max_align, is64Bits> *> _sections;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000964 std::vector<SegmentSlice<target_endianness, max_align, is64Bits> *>
965 _segmentSlices;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000966 ELFLayout::SegmentType _segmentType;
967 int64_t _flags;
968 int64_t _atomflags;
969 const WriterOptionsELF _options;
970 llvm::BumpPtrAllocator _segmentAllocate;
971};
972
973/// \brief The class represents the ELF String Table
Michael J. Spencera2c97272013-01-04 21:09:21 +0000974template<support::endianness target_endianness,
975 std::size_t max_align,
976 bool is64Bits>
977class ELFStringTable : public Section<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000978public:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000979 ELFStringTable(const char *str, int32_t order)
980 : Section<target_endianness, max_align, is64Bits>(
981 str,
982 llvm::ELF::SHT_STRTAB,
983 DefinedAtom::perm___,
984 order,
985 Section<target_endianness, max_align, is64Bits>::K_StringTable) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000986 // the string table has a NULL entry for which
987 // add an empty string
988 _strings.push_back("");
989 this->_fsize = 1;
990 this->_align2 = 1;
991 this->setOrder(order);
992 }
993
Michael J. Spencera2c97272013-01-04 21:09:21 +0000994 static inline bool classof(
995 const Chunk<target_endianness, max_align, is64Bits> *c) {
996 return c->kind() ==
997 Section<target_endianness, max_align, is64Bits>::K_StringTable;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000998 }
999
1000 uint64_t addString(const StringRef symname) {
1001 _strings.push_back(symname);
1002 uint64_t offset = this->_fsize;
1003 this->_fsize += symname.size() + 1;
1004 return offset;
1005 }
1006
Michael J. Spencera2c97272013-01-04 21:09:21 +00001007 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001008 OwningPtr<FileOutputBuffer> &buffer) {
1009 uint8_t *chunkBuffer = buffer->getBufferStart();
1010 uint8_t *dest = chunkBuffer + this->fileOffset();
1011 for (auto si : _strings) {
1012 memcpy(dest, si.data(), si.size());
1013 dest += si.size();
1014 memcpy(dest, "", 1);
1015 dest += 1;
1016 }
1017 }
1018
1019 void finalize() { }
1020
1021private:
1022 std::vector<StringRef> _strings;
1023};
1024
Michael J. Spencera2c97272013-01-04 21:09:21 +00001025/// \brief The ELFSymbolTable class represents the symbol table in a ELF file
1026template<support::endianness target_endianness,
1027 std::size_t max_align,
1028 bool is64Bits>
1029class ELFSymbolTable : public Section<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001030public:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001031 typedef object::Elf_Sym_Impl<target_endianness, max_align, is64Bits> Elf_Sym;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001032
Michael J. Spencera2c97272013-01-04 21:09:21 +00001033 ELFSymbolTable(const char *str, int32_t order)
1034 : Section<target_endianness, max_align, is64Bits>(
1035 str,
1036 llvm::ELF::SHT_SYMTAB,
1037 0,
1038 order,
1039 Section<target_endianness, max_align, is64Bits>::K_SymbolTable) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001040 this->setOrder(order);
1041 Elf_Sym *symbol = new (_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001042 memset((void *)symbol, 0, sizeof(Elf_Sym));
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001043 _symbolTable.push_back(symbol);
1044 this->_entSize = sizeof(Elf_Sym);
1045 this->_fsize = sizeof(Elf_Sym);
1046 this->_align2 = sizeof(void *);
1047 }
1048
Michael J. Spencera2c97272013-01-04 21:09:21 +00001049 static inline bool classof(
1050 const Chunk<target_endianness, max_align, is64Bits> *c) {
1051 return c->kind() ==
1052 Section<target_endianness, max_align, is64Bits>::K_SymbolTable;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001053 }
1054
1055 void addSymbol(const Atom *atom, int32_t sectionIndex, uint64_t addr = 0) {
1056 Elf_Sym *symbol = new(_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
1057 unsigned char binding = 0, type = 0;
1058 symbol->st_name = _stringSection->addString(atom->name());
1059 symbol->st_size = 0;
1060 symbol->st_shndx = sectionIndex;
1061 symbol->st_value = 0;
1062 symbol->st_other = ELF::STV_DEFAULT;
1063 if (const DefinedAtom *da = llvm::dyn_cast<const DefinedAtom>(atom)){
1064 symbol->st_size = da->size();
1065 lld::DefinedAtom::ContentType ct;
1066 switch (ct = da->contentType()){
1067 case DefinedAtom::typeCode:
1068 symbol->st_value = addr;
1069 type = ELF::STT_FUNC;
1070 break;
1071 case DefinedAtom::typeData:
Michael J. Spencer8de83642013-01-07 08:00:42 +00001072 case DefinedAtom::typeConstant:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001073 symbol->st_value = addr;
1074 type = ELF::STT_OBJECT;
1075 break;
1076 case DefinedAtom::typeZeroFill:
Michael J. Spencer28c65942013-01-07 07:05:52 +00001077 type = ELF::STT_OBJECT;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001078 symbol->st_value = addr;
1079 break;
1080 default:
1081 type = ELF::STT_NOTYPE;
1082 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001083 if (da->scope() == DefinedAtom::scopeTranslationUnit)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001084 binding = ELF::STB_LOCAL;
1085 else
1086 binding = ELF::STB_GLOBAL;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001087 } else if (const AbsoluteAtom *aa =
1088 llvm::dyn_cast<const AbsoluteAtom>(atom)){
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001089 type = ELF::STT_OBJECT;
1090 symbol->st_shndx = ELF::SHN_ABS;
1091 switch (aa->scope()) {
1092 case AbsoluteAtom::scopeLinkageUnit:
1093 symbol->st_other = ELF::STV_HIDDEN;
1094 binding = ELF::STB_LOCAL;
1095 break;
1096 case AbsoluteAtom::scopeTranslationUnit:
1097 binding = ELF::STB_LOCAL;
1098 break;
1099 case AbsoluteAtom::scopeGlobal:
1100 binding = ELF::STB_GLOBAL;
1101 break;
1102 }
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001103 symbol->st_value = addr;
1104 } else {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001105 symbol->st_value = 0;
1106 type = ELF::STT_NOTYPE;
1107 binding = ELF::STB_WEAK;
1108 }
1109 symbol->setBindingAndType(binding, type);
1110 _symbolTable.push_back(symbol);
1111 this->_fsize += sizeof(Elf_Sym);
1112 }
1113
Michael J. Spencera2c97272013-01-04 21:09:21 +00001114 void setStringSection(
1115 ELFStringTable<target_endianness, max_align, is64Bits> *s) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001116 _stringSection = s;
1117 }
1118
1119 void finalize() {
1120 // sh_info should be one greater than last symbol with STB_LOCAL binding
1121 // we sort the symbol table to keep all local symbols at the beginning
1122 std::stable_sort(_symbolTable.begin(), _symbolTable.end(),
1123 [](const Elf_Sym *A, const Elf_Sym *B) {
1124 return A->getBinding() < B->getBinding();
Michael J. Spencera2c97272013-01-04 21:09:21 +00001125 });
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001126 uint16_t shInfo = 0;
1127 for (auto i : _symbolTable) {
1128 if (i->getBinding() != ELF::STB_LOCAL)
1129 break;
1130 shInfo++;
1131 }
1132 this->_shInfo = shInfo;
1133 this->setLink(_stringSection->ordinal());
1134 }
1135
Michael J. Spencera2c97272013-01-04 21:09:21 +00001136 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001137 OwningPtr<FileOutputBuffer> &buffer) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001138 uint8_t *chunkBuffer = buffer->getBufferStart();
1139 uint8_t *dest = chunkBuffer + this->fileOffset();
1140 for (auto sti : _symbolTable) {
1141 memcpy(dest, sti, sizeof(Elf_Sym));
1142 dest += sizeof(Elf_Sym);
1143 }
1144 }
1145
1146private:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001147 ELFStringTable<target_endianness, max_align, is64Bits> *_stringSection;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001148 std::vector<Elf_Sym*> _symbolTable;
1149 llvm::BumpPtrAllocator _symbolAllocate;
1150 int64_t _link;
1151};
1152
1153/// \brief An ELFHeader represents the Elf[32/64]_Ehdr structure at the
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001154/// start of an ELF executable file.
Michael J. Spencera2c97272013-01-04 21:09:21 +00001155template<support::endianness target_endianness,
1156 std::size_t max_align,
1157 bool is64Bits>
1158class ELFHeader : public Chunk<target_endianness, max_align, is64Bits> {
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001159public:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001160 typedef Elf_Ehdr_Impl<target_endianness, max_align, is64Bits> Elf_Ehdr;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001161
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001162 ELFHeader()
Michael J. Spencera2c97272013-01-04 21:09:21 +00001163 : Chunk<target_endianness, max_align, is64Bits>(
1164 "elfhdr", Chunk<target_endianness, max_align, is64Bits>::K_ELFHeader) {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001165 this->_align2 = is64Bits ? 8 : 4;
1166 this->_fsize = sizeof(Elf_Ehdr);
1167 this->_msize = sizeof(Elf_Ehdr);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001168 memset(_eh.e_ident, 0, llvm::ELF::EI_NIDENT);
1169 e_ident(ELF::EI_MAG0, 0x7f);
1170 e_ident(ELF::EI_MAG1, 'E');
1171 e_ident(ELF::EI_MAG2, 'L');
1172 e_ident(ELF::EI_MAG3, 'F');
1173 e_ehsize(sizeof(Elf_Ehdr));
1174 e_flags(2);
1175 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001176 void e_ident(int I, unsigned char C) { _eh.e_ident[I] = C; }
1177 void e_type(uint16_t type) { _eh.e_type = type; }
1178 void e_machine(uint16_t machine) { _eh.e_machine = machine; }
1179 void e_version(uint32_t version) { _eh.e_version = version; }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001180 void e_entry(int64_t entry) { _eh.e_entry = entry; }
1181 void e_phoff(int64_t phoff) { _eh.e_phoff = phoff; }
1182 void e_shoff(int64_t shoff) { _eh.e_shoff = shoff; }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001183 void e_flags(uint32_t flags) { _eh.e_flags = flags; }
1184 void e_ehsize(uint16_t ehsize) { _eh.e_ehsize = ehsize; }
1185 void e_phentsize(uint16_t phentsize) { _eh.e_phentsize = phentsize; }
1186 void e_phnum(uint16_t phnum) { _eh.e_phnum = phnum; }
1187 void e_shentsize(uint16_t shentsize) { _eh.e_shentsize = shentsize; }
1188 void e_shnum(uint16_t shnum) { _eh.e_shnum = shnum; }
1189 void e_shstrndx(uint16_t shstrndx) { _eh.e_shstrndx = shstrndx; }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001190 uint64_t fileSize() { return sizeof (Elf_Ehdr); }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001191
Michael J. Spencera2c97272013-01-04 21:09:21 +00001192 static inline bool classof(
1193 const Chunk<target_endianness, max_align, is64Bits> *c) {
1194 return c->Kind() ==
1195 Chunk<target_endianness, max_align, is64Bits>::K_ELFHeader;
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001196 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001197
Michael J. Spencera2c97272013-01-04 21:09:21 +00001198 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001199 OwningPtr<FileOutputBuffer> &buffer) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001200 uint8_t *chunkBuffer = buffer->getBufferStart();
1201 uint8_t *atomContent = chunkBuffer + this->fileOffset();
1202 memcpy(atomContent, &_eh, fileSize());
1203 }
1204
1205 void finalize() { }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001206
1207private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001208 Elf_Ehdr _eh;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001209};
1210
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001211/// \brief An ELFProgramHeader represents the Elf[32/64]_Phdr structure at the
1212/// start of an ELF executable file.
Michael J. Spencera2c97272013-01-04 21:09:21 +00001213template<support::endianness target_endianness,
1214 std::size_t max_align,
1215 bool is64Bits>
1216class ELFProgramHeader : public Chunk<target_endianness, max_align, is64Bits> {
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001217public:
Michael J. Spencerfd3981d2013-01-06 05:40:27 +00001218 typedef Elf_Phdr_Impl<target_endianness, max_align, is64Bits> Elf_Phdr;
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001219 typedef typename std::vector<Elf_Phdr *>::iterator PhIterT;
1220
1221 /// \brief Find a program header entry, given the type of entry that
1222 /// we are looking for
1223 class FindPhdr {
1224 public:
1225 FindPhdr(uint64_t type, uint64_t flags, uint64_t flagsClear)
1226 : _type(type)
1227 , _flags(flags)
1228 , _flagsClear(flagsClear)
1229 {}
1230
Shankar Easwaran37c52822013-01-10 18:16:10 +00001231 bool operator()(const Elf_Phdr *j) const {
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001232 return ((j->p_type == _type) &&
1233 ((j->p_flags & _flags) == _flags) &&
1234 (!(j->p_flags & _flagsClear)));
1235 }
1236 private:
1237 uint64_t _type;
1238 uint64_t _flags;
1239 uint64_t _flagsClear;
1240 };
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001241
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001242 ELFProgramHeader()
Michael J. Spencera2c97272013-01-04 21:09:21 +00001243 : Chunk<target_endianness, max_align, is64Bits>(
1244 "elfphdr",
Reid Klecknere974bd12013-01-05 02:21:42 +00001245 Chunk<target_endianness, max_align, is64Bits>::K_ELFProgramHeader) {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001246 this->_align2 = is64Bits ? 8 : 4;
Reid Klecknere974bd12013-01-05 02:21:42 +00001247 resetProgramHeaders();
1248 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001249
Michael J. Spencera2c97272013-01-04 21:09:21 +00001250 bool addSegment(Segment<target_endianness, max_align, is64Bits> *segment) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001251 Elf_Phdr *phdr = nullptr;
1252 bool ret = false;
1253
Michael J. Spencera2c97272013-01-04 21:09:21 +00001254 for (auto sei = segment->slices_begin(), see = segment->slices_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001255 sei != see; ++sei) {
1256 if (_phi == _ph.end()) {
1257 phdr = new(_allocator.Allocate<Elf_Phdr>()) Elf_Phdr;
1258 _ph.push_back(phdr);
1259 _phi = _ph.end();
1260 ret = true;
1261 } else {
1262 phdr = (*_phi);
1263 ++_phi;
1264 }
1265 phdr->p_type = segment->segmentType();
1266 phdr->p_offset = (*sei)->fileOffset();
1267 phdr->p_vaddr = (*sei)->virtualAddr();
1268 phdr->p_paddr = (*sei)->virtualAddr();
1269 phdr->p_filesz = (*sei)->fileSize();
1270 phdr->p_memsz = (*sei)->memSize();
1271 phdr->p_flags = segment->flags();
Michael J. Spencera2c97272013-01-04 21:09:21 +00001272 phdr->p_align = (phdr->p_type == llvm::ELF::PT_LOAD) ?
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001273 segment->pageSize() : (*sei)->align2();
1274 }
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001275
1276 this->_fsize = fileSize();
1277 this->_msize = this->_fsize;
1278
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001279 return ret;
1280 }
1281
1282 void resetProgramHeaders() {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001283 _phi = _ph.begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001284 }
1285
Michael J. Spencera2c97272013-01-04 21:09:21 +00001286 uint64_t fileSize() {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001287 return sizeof(Elf_Phdr) * _ph.size();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001288 }
1289
Michael J. Spencera2c97272013-01-04 21:09:21 +00001290 static inline bool classof(
1291 const Chunk<target_endianness, max_align, is64Bits> *c) {
1292 return c->Kind() ==
1293 Chunk<target_endianness, max_align, is64Bits>::K_ELFProgramHeader;
1294 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001295
Michael J. Spencera2c97272013-01-04 21:09:21 +00001296 void write(ELFWriter *writer,
1297 OwningPtr<FileOutputBuffer> &buffer) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001298 uint8_t *chunkBuffer = buffer->getBufferStart();
1299 uint8_t *dest = chunkBuffer + this->fileOffset();
1300 for (auto phi : _ph) {
1301 memcpy(dest, phi, sizeof(Elf_Phdr));
1302 dest += sizeof(Elf_Phdr);
1303 }
1304 }
1305
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001306 /// \brief find a program header entry in the list of program headers
1307 PhIterT findProgramHeader(uint64_t type, uint64_t flags, uint64_t flagClear) {
1308 return std::find_if(_ph.begin(), _ph.end(),
1309 FindPhdr(type, flags, flagClear));
1310 }
1311
1312 PhIterT begin() {
1313 return _ph.begin();
1314 }
1315
1316 PhIterT end() {
1317 return _ph.end();
1318 }
1319
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001320 void finalize() { }
1321
Michael J. Spencera2c97272013-01-04 21:09:21 +00001322 int64_t entsize() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001323 return sizeof(Elf_Phdr);
1324 }
1325
1326 int64_t numHeaders() {
1327 return _ph.size();
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001328 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001329
1330private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001331 std::vector<Elf_Phdr *> _ph;
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001332 PhIterT _phi;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001333 llvm::BumpPtrAllocator _allocator;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001334};
1335
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001336/// \brief An ELFSectionHeader represents the Elf[32/64]_Shdr structure
1337/// at the end of the file
Michael J. Spencera2c97272013-01-04 21:09:21 +00001338template<support::endianness target_endianness,
1339 std::size_t max_align,
1340 bool is64Bits>
1341class ELFSectionHeader : public Chunk<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001342public:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001343 typedef Elf_Shdr_Impl<target_endianness, max_align, is64Bits> Elf_Shdr;
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001344
Michael J. Spencera2c97272013-01-04 21:09:21 +00001345 ELFSectionHeader(int32_t order)
1346 : Chunk<target_endianness, max_align, is64Bits>(
1347 "shdr",
1348 Chunk<target_endianness, max_align, is64Bits>::K_ELFSectionHeader) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001349 this->_fsize = 0;
1350 this->_align2 = 8;
1351 this->setOrder(order);
1352 // The first element in the list is always NULL
1353 Elf_Shdr *nullshdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
1354 ::memset(nullshdr, 0, sizeof (Elf_Shdr));
1355 _sectionInfo.push_back(nullshdr);
1356 this->_fsize += sizeof (Elf_Shdr);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001357 }
1358
Michael J. Spencera2c97272013-01-04 21:09:21 +00001359 uint16_t fileSize() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001360 return sizeof(Elf_Shdr) * _sectionInfo.size();
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001361 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001362
Michael J. Spencera2c97272013-01-04 21:09:21 +00001363 void appendSection(
1364 MergedSections<target_endianness, max_align, is64Bits> *section) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001365 Elf_Shdr *shdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
1366 shdr->sh_name = _stringSection->addString(section->name());
1367 shdr->sh_type = section->type();
1368 shdr->sh_flags = section->flags();
1369 shdr->sh_offset = section->fileOffset();
1370 shdr->sh_addr = section->virtualAddr();
1371 shdr->sh_size = section->memSize();
1372 shdr->sh_link = section->link();
1373 shdr->sh_info = section->shinfo();
1374 shdr->sh_addralign = section->align2();
1375 shdr->sh_entsize = section->entsize();
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001376 _sectionInfo.push_back(shdr);
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001377 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001378
Michael J. Spencera2c97272013-01-04 21:09:21 +00001379 void updateSection(Section<target_endianness, max_align, is64Bits> *section) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001380 Elf_Shdr *shdr = _sectionInfo[section->ordinal()];
1381 shdr->sh_type = section->type();
1382 shdr->sh_flags = section->flags();
1383 shdr->sh_offset = section->fileOffset();
1384 shdr->sh_addr = section->virtualAddr();
1385 shdr->sh_size = section->fileSize();
1386 shdr->sh_link = section->link();
1387 shdr->sh_info = section->shinfo();
1388 shdr->sh_addralign = section->align2();
1389 shdr->sh_entsize = section->entsize();
1390 }
1391
Michael J. Spencera2c97272013-01-04 21:09:21 +00001392 static inline bool classof(
1393 const Chunk<target_endianness, max_align, is64Bits> *c) {
1394 return c->getChunkKind() ==
1395 Chunk<target_endianness, max_align, is64Bits>::K_ELFSectionHeader;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001396 }
1397
Michael J. Spencera2c97272013-01-04 21:09:21 +00001398 void setStringSection(
1399 ELFStringTable<target_endianness, max_align, is64Bits> *s) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001400 _stringSection = s;
1401 }
1402
Michael J. Spencera2c97272013-01-04 21:09:21 +00001403 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001404 OwningPtr<FileOutputBuffer> &buffer) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001405 uint8_t *chunkBuffer = buffer->getBufferStart();
1406 uint8_t *dest = chunkBuffer + this->fileOffset();
1407 for (auto shi : _sectionInfo) {
1408 memcpy(dest, shi, sizeof(Elf_Shdr));
1409 dest += sizeof(Elf_Shdr);
1410 }
1411 _stringSection->write(writer, buffer);
1412 }
1413
1414 void finalize() { }
1415
Michael J. Spencera2c97272013-01-04 21:09:21 +00001416 int64_t entsize() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001417 return sizeof(Elf_Shdr);
1418 }
1419
1420 int64_t numHeaders() {
1421 return _sectionInfo.size();
1422 }
1423
1424private:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001425 ELFStringTable<target_endianness, max_align, is64Bits> *_stringSection;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001426 std::vector<Elf_Shdr*> _sectionInfo;
1427 llvm::BumpPtrAllocator _sectionAllocate;
1428};
1429
Michael J. Spencera2c97272013-01-04 21:09:21 +00001430/// \brief The DefaultELFLayout class is used by the Writer to arrange
1431/// sections and segments in the order determined by the target ELF
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001432/// format. The writer creates a single instance of the DefaultELFLayout
Michael J. Spencera2c97272013-01-04 21:09:21 +00001433/// class
1434template<support::endianness target_endianness,
1435 std::size_t max_align,
1436 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001437class DefaultELFLayout : public ELFLayout {
1438public:
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001439
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001440 // The order in which the sections appear in the output file
Michael J. Spencera2c97272013-01-04 21:09:21 +00001441 // If its determined, that the layout needs to change
1442 // just changing the order of enumerations would essentially
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001443 // change the layout in the output file
1444 enum DefaultSectionOrder {
1445 ORDER_NOT_DEFINED = 0,
1446 ORDER_INTERP,
1447 ORDER_NOTE,
1448 ORDER_HASH,
1449 ORDER_DYNAMIC_SYMBOLS,
1450 ORDER_DYNAMIC_STRINGS,
1451 ORDER_INIT,
1452 ORDER_TEXT,
1453 ORDER_PLT,
1454 ORDER_FINI,
1455 ORDER_RODATA,
1456 ORDER_EH_FRAME,
1457 ORDER_EH_FRAMEHDR,
1458 ORDER_CTORS,
1459 ORDER_DTORS,
1460 ORDER_DYNAMIC,
1461 ORDER_GOT,
1462 ORDER_GOT_PLT,
1463 ORDER_DATA,
1464 ORDER_BSS,
1465 ORDER_OTHER,
1466 ORDER_SECTION_STRINGS,
1467 ORDER_SYMBOL_TABLE,
1468 ORDER_STRING_TABLE,
1469 ORDER_SECTION_HEADERS
1470 };
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001471
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001472public:
1473
1474 // The Key used for creating Sections
Michael J. Spencera2c97272013-01-04 21:09:21 +00001475 // The sections are created using
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001476 // SectionName, [contentType, contentPermissions]
Michael J. Spencera2c97272013-01-04 21:09:21 +00001477 typedef std::pair<StringRef,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001478 std::pair<int32_t, int32_t>> Key;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001479 typedef typename std::vector<
1480 Chunk<target_endianness, max_align, is64Bits> *>::iterator ChunkIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001481 // The key used for Segments
Michael J. Spencera2c97272013-01-04 21:09:21 +00001482 // The segments are created using
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001483 // SegmentName, Segment flags
1484 typedef std::pair<StringRef, int64_t> SegmentKey;
1485 // Merged Sections contain the map of Sectionnames to a vector of sections,
1486 // that have been merged to form a single section
Michael J. Spencera2c97272013-01-04 21:09:21 +00001487 typedef std::map<StringRef, MergedSections<
1488 target_endianness, max_align, is64Bits> *> MergedSectionMapT;
1489 typedef typename std::vector<MergedSections<
1490 target_endianness, max_align, is64Bits> *>::iterator MergedSectionIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001491
1492 // HashKey for the Section
1493 class HashKey {
1494 public:
1495 int64_t operator() (const Key &k) const {
1496 // k.first = section Name
1497 // k.second = [contentType, Permissions]
1498 return llvm::hash_combine(k.first, k.second.first, k.second.second);
1499 }
1500 };
1501
1502 // HashKey for the Segment
1503 class SegmentHashKey {
1504 public:
1505 int64_t operator() (const SegmentKey &k) const {
1506 // k.first = SegmentName
1507 // k.second = SegmentFlags
1508 return llvm::hash_combine(k.first, k.second);
1509 }
1510 };
1511
Michael J. Spencera2c97272013-01-04 21:09:21 +00001512 typedef std::unordered_map<Key, Section<
1513 target_endianness, max_align, is64Bits>*, HashKey> SectionMapT;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001514 typedef std::unordered_map<SegmentKey,
Michael J. Spencera2c97272013-01-04 21:09:21 +00001515 Segment<target_endianness, max_align, is64Bits>*,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001516 SegmentHashKey> SegmentMapT;
1517
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001518 /// \brief All absolute atoms are created in the ELF Layout by using
1519 /// an AbsoluteAtomPair. Contains a pair of AbsoluteAtom and the
1520 /// value which is the address of the absolute atom
1521 class AbsoluteAtomPair {
1522 public:
1523 AbsoluteAtomPair(const AbsoluteAtom *a, int64_t value)
1524 : _absoluteAtom(a)
1525 , _value(value) { }
1526
1527 const AbsoluteAtom *absoluteAtom() { return _absoluteAtom; }
1528 int64_t value() const { return _value; }
1529 void setValue(int64_t val) { _value = val; }
1530
1531 private:
1532 const AbsoluteAtom *_absoluteAtom;
1533 int64_t _value;
1534 };
1535
1536 /// \brief find a absolute atom pair given a absolute atom name
1537 struct FindByName {
1538 const std::string name;
1539 FindByName(const StringRef name) : name(name) {}
1540 bool operator()(AbsoluteAtomPair& j) {
1541 return j.absoluteAtom()->name() == name;
1542 }
1543 };
1544
1545 typedef typename std::vector<AbsoluteAtomPair>::iterator AbsoluteAtomIterT;
1546
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001547 DefaultELFLayout(const WriterOptionsELF &options):_options(options) { }
1548
1549 /// \brief Return the section order for a input section
1550 virtual SectionOrder getSectionOrder
1551 (const StringRef name,
1552 int32_t contentType,
1553 int32_t contentPermissions) {
1554 switch (contentType) {
1555 case DefinedAtom::typeCode:
1556 return llvm::StringSwitch<Reference::Kind>(name)
1557 .StartsWith(".eh_frame_hdr", ORDER_EH_FRAMEHDR)
1558 .StartsWith(".eh_frame", ORDER_EH_FRAME)
1559 .StartsWith(".init", ORDER_INIT)
1560 .StartsWith(".fini", ORDER_FINI)
1561 .StartsWith(".hash", ORDER_HASH)
1562 .Default(ORDER_TEXT);
1563
1564 case DefinedAtom::typeConstant:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001565 return ORDER_RODATA;
1566
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001567 case DefinedAtom::typeData:
1568 return ORDER_DATA;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001569
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001570 case DefinedAtom::typeZeroFill:
1571 return ORDER_BSS;
1572
1573 default:
1574 // If we get passed in a section push it to OTHER
Michael J. Spencera2c97272013-01-04 21:09:21 +00001575 if (contentPermissions == DefinedAtom::perm___)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001576 return ORDER_OTHER;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001577
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001578 return ORDER_NOT_DEFINED;
1579 }
1580 }
1581
1582 /// \brief This maps the input sections to the output section names
1583 StringRef getSectionName(const StringRef name,
1584 const int32_t contentType) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001585 if (contentType == DefinedAtom::typeZeroFill)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001586 return ".bss";
Michael J. Spencera2c97272013-01-04 21:09:21 +00001587 if (name.startswith(".text"))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001588 return ".text";
Michael J. Spencera2c97272013-01-04 21:09:21 +00001589 if (name.startswith(".rodata"))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001590 return ".rodata";
1591 return name;
1592 }
1593
1594 /// \brief Gets the segment for a output section
Michael J. Spencera2c97272013-01-04 21:09:21 +00001595 virtual ELFLayout::SegmentType getSegmentType(
1596 Section<target_endianness, max_align, is64Bits> *section) const {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001597 switch(section->order()) {
1598 case ORDER_INTERP:
1599 return llvm::ELF::PT_INTERP;
1600
1601 case ORDER_TEXT:
1602 case ORDER_HASH:
1603 case ORDER_DYNAMIC_SYMBOLS:
1604 case ORDER_DYNAMIC_STRINGS:
1605 case ORDER_INIT:
1606 case ORDER_PLT:
1607 case ORDER_FINI:
1608 case ORDER_RODATA:
1609 case ORDER_EH_FRAME:
1610 case ORDER_EH_FRAMEHDR:
1611 return llvm::ELF::PT_LOAD;
1612
1613 case ORDER_NOTE:
1614 return llvm::ELF::PT_NOTE;
1615
1616 case ORDER_DYNAMIC:
1617 return llvm::ELF::PT_DYNAMIC;
1618
1619 case ORDER_CTORS:
1620 case ORDER_DTORS:
1621 case ORDER_GOT:
1622 return llvm::ELF::PT_GNU_RELRO;
1623
1624 case ORDER_GOT_PLT:
1625 case ORDER_DATA:
1626 case ORDER_BSS:
1627 return llvm::ELF::PT_LOAD;
1628
1629 default:
1630 return llvm::ELF::PT_NULL;
1631 }
1632 }
1633
1634 /// \brief Returns true/false depending on whether the section has a Output
1635 // segment or not
Michael J. Spencera2c97272013-01-04 21:09:21 +00001636 static bool hasOutputSegment(Section<target_endianness, max_align,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001637 is64Bits> *section) {
1638 switch(section->order()) {
1639 case ORDER_INTERP:
1640 case ORDER_HASH:
1641 case ORDER_DYNAMIC_SYMBOLS:
1642 case ORDER_DYNAMIC_STRINGS:
1643 case ORDER_INIT:
1644 case ORDER_PLT:
1645 case ORDER_TEXT:
1646 case ORDER_FINI:
1647 case ORDER_RODATA:
1648 case ORDER_EH_FRAME:
1649 case ORDER_EH_FRAMEHDR:
1650 case ORDER_NOTE:
1651 case ORDER_DYNAMIC:
1652 case ORDER_CTORS:
1653 case ORDER_DTORS:
1654 case ORDER_GOT:
1655 case ORDER_GOT_PLT:
1656 case ORDER_DATA:
1657 case ORDER_BSS:
1658 return true;
1659
1660 default:
1661 return false;
1662 }
1663 }
1664
1665 // Adds an atom to the section
1666 virtual error_code addAtom(const Atom *atom) {
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001667 if (const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom)) {
1668 const StringRef sectionName =
1669 getSectionName(definedAtom->customSectionName(),
1670 definedAtom->contentType());
1671 const lld::DefinedAtom::ContentPermissions permissions =
1672 definedAtom->permissions();
1673 const lld::DefinedAtom::ContentType contentType =
1674 definedAtom->contentType();
1675 const Key key(sectionName, std::make_pair(contentType, permissions));
1676 const std::pair<Key, Section<target_endianness, max_align, is64Bits> *>
1677 currentSection(key, nullptr);
1678 std::pair<typename SectionMapT::iterator, bool>
1679 sectionInsert(_sectionMap.insert(currentSection));
1680 Section<target_endianness, max_align, is64Bits> *section;
1681 // the section is already in the map
1682 if (!sectionInsert.second) {
1683 section = sectionInsert.first->second;
1684 section->setContentPermissions(permissions);
1685 } else {
1686 SectionOrder section_order = getSectionOrder(sectionName,
1687 contentType,
1688 permissions);
1689 section = new (_allocator.Allocate
1690 <Section<target_endianness, max_align, is64Bits>>())
1691 Section<target_endianness, max_align, is64Bits>
1692 (sectionName, contentType,
1693 permissions, section_order);
1694 sectionInsert.first->second = section;
1695 section->setOrder(section_order);
1696 _sections.push_back(section);
1697 }
1698 section->appendAtom(atom);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001699 }
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001700 // Absolute atoms are not part of any section, they are global for the whole
1701 // link
1702 else if (const AbsoluteAtom *absoluteAtom = dyn_cast<AbsoluteAtom>(atom)) {
1703 _absoluteAtoms.push_back(AbsoluteAtomPair(absoluteAtom,
1704 absoluteAtom->value()));
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001705 }
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001706 else
1707 llvm_unreachable("Only absolute / defined atoms can be added here");
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001708 return error_code::success();
1709 }
1710
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001711 /// \brief find a absolute atom given a name
1712 AbsoluteAtomIterT findAbsoluteAtom(const StringRef name) {
1713 return std::find_if(_absoluteAtoms.begin(), _absoluteAtoms.end(),
1714 FindByName(name));
1715 }
1716
1717 /// \bried Begin/End iterators
1718 AbsoluteAtomIterT absAtomsBegin() {
1719 return _absoluteAtoms.begin();
1720 }
1721
1722 AbsoluteAtomIterT absAtomsEnd() {
1723 return _absoluteAtoms.end();
1724 }
1725
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001726 // Merge sections with the same name into a MergedSections
1727 void mergeSimiliarSections() {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001728 MergedSections<target_endianness, max_align, is64Bits> *mergedSection;
1729
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001730 for (auto &si : _sections) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001731 const std::pair<StringRef,
1732 MergedSections<target_endianness, max_align, is64Bits> *>
1733 currentMergedSections(si->name(), nullptr);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001734 std::pair<typename MergedSectionMapT::iterator, bool>
1735 mergedSectionInsert
1736 (_mergedSectionMap.insert(currentMergedSections));
1737 if (!mergedSectionInsert.second) {
1738 mergedSection = mergedSectionInsert.first->second;
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001739 } else {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001740 mergedSection = new (_allocator.Allocate<
1741 MergedSections<target_endianness, max_align, is64Bits>>())
1742 MergedSections<target_endianness, max_align, is64Bits>(si->name());
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001743 _mergedSections.push_back(mergedSection);
1744 mergedSectionInsert.first->second = mergedSection;
1745 }
1746 mergedSection->appendSection(si);
1747 }
1748 }
1749
1750 void assignSectionsToSegments() {
1751 // sort the sections by their order as defined by the layout
1752 std::stable_sort(_sections.begin(), _sections.end(),
Michael J. Spencera2c97272013-01-04 21:09:21 +00001753 [](Chunk<target_endianness, max_align, is64Bits> *A,
1754 Chunk<target_endianness, max_align, is64Bits> *B) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001755 return A->order() < B->order();
1756 });
1757 // Merge all sections
1758 mergeSimiliarSections();
1759 // Set the ordinal after sorting the sections
1760 int ordinal = 1;
1761 for (auto &msi : _mergedSections) {
1762 (*msi).setOrdinal(ordinal);
1763 for (auto ai = (*msi).begin_sections(), ae = (*msi).end_sections();
1764 ai != ae; ++ai) {
1765 (*ai)->setOrdinal(ordinal);
1766 }
1767 ++ordinal;
1768 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001769 Section<target_endianness, max_align, is64Bits> *section;
1770 Segment<target_endianness, max_align, is64Bits> *segment;
1771 for (auto msi = merged_sections_begin(), mse = merged_sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001772 msi != mse; ++msi) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001773 for (auto ai = (*msi)->begin_sections(), ae = (*msi)->end_sections();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001774 ai != ae; ++ai) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001775 if ((*ai)->kind() ==
1776 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection) {
1777 section = llvm::dyn_cast<
1778 Section<target_endianness, max_align, is64Bits>>(*ai);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001779 if (!hasOutputSegment(section))
1780 continue;
1781 (*msi)->setHasSegment();
1782 section->setSegment(getSegmentType(section));
1783 const StringRef segmentName = section->segmentKindToStr();
1784 // Use the flags of the merged Section for the segment
1785 const SegmentKey key(segmentName, (*msi)->flags());
Michael J. Spencera2c97272013-01-04 21:09:21 +00001786 const std::pair<SegmentKey,
1787 Segment<target_endianness, max_align, is64Bits> *>
1788 currentSegment(key, nullptr);
1789 std::pair<typename SegmentMapT::iterator, bool>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001790 segmentInsert(_segmentMap.insert(currentSegment));
1791
1792 if (!segmentInsert.second) {
1793 segment = segmentInsert.first->second;
1794 } else {
1795 segment = new (_allocator.Allocate
Michael J. Spencera2c97272013-01-04 21:09:21 +00001796 <Segment<target_endianness, max_align, is64Bits>>())
1797 Segment<target_endianness, max_align, is64Bits>
1798 (segmentName, getSegmentType(section),
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001799 _options);
1800 segmentInsert.first->second = segment;
1801 _segments.push_back(segment);
1802 }
1803 segment->append(section);
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001804 }
1805 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001806 }
1807 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001808
Michael J. Spencera2c97272013-01-04 21:09:21 +00001809 void addSection(Chunk<target_endianness, max_align, is64Bits> *c) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001810 _sections.push_back(c);
1811 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001812
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001813 void assignFileOffsets() {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001814 std::sort(_segments.begin(),
1815 _segments.end(),
1816 Segment<target_endianness, max_align, is64Bits>::compareSegments);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001817 int ordinal = 0;
1818 // Compute the number of segments that might be needed, so that the
1819 // size of the program header can be computed
1820 uint64_t offset = 0;
1821 for (auto si : _segments) {
1822 si->setOrdinal(++ordinal);
1823 si->assignOffsets(offset);
1824 offset += si->fileSize();
1825 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001826 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001827
Michael J. Spencera2c97272013-01-04 21:09:21 +00001828 void setELFHeader(ELFHeader<target_endianness, max_align, is64Bits> *e) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001829 _elfHeader = e;
1830 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001831
Michael J. Spencera2c97272013-01-04 21:09:21 +00001832 void setProgramHeader(
1833 ELFProgramHeader<target_endianness, max_align, is64Bits> *p) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001834 _programHeader = p;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001835 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001836
1837 void assignVirtualAddress() {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001838 if (_segments.empty())
1839 return;
1840
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001841 uint64_t virtualAddress = _options.baseAddress();
1842
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001843 // HACK: This is a super dirty hack. The elf header and program header are
1844 // not part of a section, but we need them to be loaded at the base address
1845 // so that AT_PHDR is set correctly by the loader and so they are accessible
1846 // at runtime. To do this we simply prepend them to the first Segment and
1847 // let the layout logic take care of it.
1848 _segments[0]->prepend(_programHeader);
1849 _segments[0]->prepend(_elfHeader);
1850
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001851 bool newSegmentHeaderAdded = true;
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001852 while (true) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001853 for (auto si : _segments) {
1854 newSegmentHeaderAdded = _programHeader->addSegment(si);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001855 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001856 if (!newSegmentHeaderAdded)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001857 break;
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001858 uint64_t fileoffset = 0;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001859 uint64_t address = virtualAddress;
1860 // Fix the offsets after adding the program header
1861 for (auto &si : _segments) {
1862 // Align the segment to a page boundary
1863 fileoffset = llvm::RoundUpToAlignment(fileoffset, _options.pageSize());
1864 si->assignOffsets(fileoffset);
1865 fileoffset = si->fileOffset() + si->fileSize();
1866 }
1867 // start assigning virtual addresses
1868 for (auto si = _segments.begin(); si != _segments.end(); ++si) {
1869 (*si)->setVAddr(virtualAddress);
1870 // The first segment has the virtualAddress set to the base address as
1871 // we have added the file header and the program header dont align the
Michael J. Spencera2c97272013-01-04 21:09:21 +00001872 // first segment to the pagesize
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001873 (*si)->assignVirtualAddress(address);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001874 (*si)->setMemSize(address - virtualAddress);
1875 virtualAddress = llvm::RoundUpToAlignment(address, _options.pageSize());
1876 }
1877 _programHeader->resetProgramHeaders();
1878 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001879 Section<target_endianness, max_align, is64Bits> *section;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001880 // Fix the offsets of all the atoms within a section
1881 for (auto &si : _sections) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001882 section =
1883 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(si);
1884 if (section &&
1885 DefaultELFLayout<target_endianness,
1886 max_align, is64Bits>::hasOutputSegment(section))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001887 section->assignOffsets(section->fileOffset());
1888 }
1889 // Set the size of the merged Sections
Michael J. Spencera2c97272013-01-04 21:09:21 +00001890 for (auto msi = merged_sections_begin(), mse = merged_sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001891 msi != mse; ++msi) {
1892 uint64_t sectionfileoffset = 0;
1893 uint64_t startFileOffset = 0;
1894 uint64_t sectionsize = 0;
1895 bool isFirstSection = true;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001896 for (auto si = (*msi)->begin_sections(); si != (*msi)->end_sections();
1897 ++si) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001898 if (isFirstSection) {
1899 startFileOffset = (*si)->fileOffset();
1900 isFirstSection = false;
1901 }
1902 sectionfileoffset = (*si)->fileOffset();
1903 sectionsize = (*si)->fileSize();
1904 }
1905 sectionsize = (sectionfileoffset - startFileOffset) + sectionsize;
1906 (*msi)->setFileOffset(startFileOffset);
1907 (*msi)->setSize(sectionsize);
1908 }
1909 // Set the virtual addr of the merged Sections
Michael J. Spencera2c97272013-01-04 21:09:21 +00001910 for (auto msi = merged_sections_begin(), mse = merged_sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001911 msi != mse; ++msi) {
1912 uint64_t sectionstartaddr = 0;
1913 uint64_t startaddr = 0;
1914 uint64_t sectionsize = 0;
1915 bool isFirstSection = true;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001916 for (auto si = (*msi)->begin_sections(), se = (*msi)->end_sections();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001917 si != se; ++si) {
1918 if (isFirstSection) {
1919 startaddr = (*si)->virtualAddr();
1920 isFirstSection = false;
1921 }
1922 sectionstartaddr = (*si)->virtualAddr();
1923 sectionsize = (*si)->memSize();
1924 }
1925 sectionsize = (sectionstartaddr - startaddr) + sectionsize;
1926 (*msi)->setMemSize(sectionsize);
1927 (*msi)->setAddr(startaddr);
1928 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001929 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001930
1931 void assignOffsetsForMiscSections() {
1932 uint64_t fileoffset = 0;
1933 uint64_t size = 0;
1934 for (auto si : _segments) {
1935 fileoffset = si->fileOffset();
1936 size = si->fileSize();
1937 }
1938 fileoffset = fileoffset + size;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001939 Section<target_endianness, max_align, is64Bits> *section;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001940 for (auto si : _sections) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001941 section =
1942 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(si);
1943 if (section &&
1944 DefaultELFLayout<target_endianness,
1945 max_align, is64Bits>::hasOutputSegment(section))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001946 continue;
1947 fileoffset = llvm::RoundUpToAlignment(fileoffset, si->align2());
1948 si->setFileOffset(fileoffset);
1949 si->setVAddr(0);
1950 fileoffset += si->fileSize();
1951 }
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001952 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001953
1954 void finalize() {
1955 for (auto &si : _sections) {
1956 si->finalize();
1957 }
1958 }
1959
1960 bool findAtomAddrByName(const StringRef name, uint64_t &addr) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001961 Section<target_endianness, max_align, is64Bits> *section;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001962 for (auto ai = _sections.begin(); ai != _sections.end(); ++ai) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001963 if ((*ai)->kind() ==
1964 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection) {
1965 section =
1966 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(*ai);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001967 if (section->findAtomAddrByName(name, addr))
1968 return true;
1969 }
1970 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001971 return false;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001972 }
1973
Michael J. Spencera2c97272013-01-04 21:09:21 +00001974 MergedSectionIter merged_sections_begin() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001975 return _mergedSections.begin();
1976 }
1977
Michael J. Spencera2c97272013-01-04 21:09:21 +00001978 MergedSectionIter merged_sections_end() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001979 return _mergedSections.end();
1980 }
1981
1982 ChunkIter sections_begin() {
1983 return _sections.begin();
1984 }
1985 ChunkIter sections_end() {
1986 return _sections.end();
1987 }
1988
1989 ChunkIter segments_begin() {
1990 return _segments.begin();
1991 }
1992
1993 ChunkIter segments_end() {
1994 return _segments.end();
1995 }
1996
Michael J. Spencera2c97272013-01-04 21:09:21 +00001997 ELFHeader<target_endianness, max_align, is64Bits> *elfHeader() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001998 return _elfHeader;
1999 }
2000
Michael J. Spencera2c97272013-01-04 21:09:21 +00002001 ELFProgramHeader<target_endianness, max_align, is64Bits> *elfProgramHeader() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002002 return _programHeader;
Hemant Kulkarni08e410292012-10-01 23:53:20 +00002003 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002004
2005private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002006 SectionMapT _sectionMap;
2007 MergedSectionMapT _mergedSectionMap;
2008 SegmentMapT _segmentMap;
Michael J. Spencera2c97272013-01-04 21:09:21 +00002009 std::vector<Chunk<target_endianness, max_align, is64Bits> *> _sections;
2010 std::vector<Segment<target_endianness, max_align, is64Bits> *> _segments;
2011 std::vector<MergedSections<target_endianness, max_align, is64Bits> *>
2012 _mergedSections;
2013 ELFHeader<target_endianness, max_align, is64Bits> *_elfHeader;
2014 ELFProgramHeader<target_endianness, max_align, is64Bits> *_programHeader;
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002015 std::vector<AbsoluteAtomPair> _absoluteAtoms;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002016 llvm::BumpPtrAllocator _allocator;
2017 const WriterOptionsELF &_options;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002018};
2019
2020//===----------------------------------------------------------------------===//
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002021// ELFExecutableWriter Class
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002022//===----------------------------------------------------------------------===//
Michael J. Spencera2c97272013-01-04 21:09:21 +00002023template<support::endianness target_endianness,
2024 std::size_t max_align,
2025 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002026class ELFExecutableWriter : public ELFWriter {
2027public:
Michael J. Spencera2c97272013-01-04 21:09:21 +00002028 typedef Elf_Shdr_Impl<target_endianness, max_align, is64Bits> Elf_Shdr;
2029 typedef Elf_Sym_Impl<target_endianness, max_align, is64Bits> Elf_Sym;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002030
2031 ELFExecutableWriter(const WriterOptionsELF &options);
2032
2033private:
Michael J. Spencera2c97272013-01-04 21:09:21 +00002034 // build the sections that need to be created
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002035 void buildChunks(const lld::File &file);
2036 virtual error_code writeFile(const lld::File &File, StringRef path);
2037 void buildAtomToAddressMap();
2038 void buildSymbolTable ();
2039 void buildSectionHeaderTable();
2040 void assignSectionsWithNoSegments();
2041 void addAbsoluteUndefinedSymbols(const lld::File &File);
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002042 void addDefaultAtoms();
2043 void addFiles(InputFiles&);
2044 void finalizeDefaultAtomValues();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002045
Michael J. Spencera2c97272013-01-04 21:09:21 +00002046 uint64_t addressOfAtom(const Atom *atom) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002047 return _atomToAddressMap[atom];
2048 }
2049
2050 KindHandler *kindHandler() { return _referenceKindHandler.get(); }
2051
2052 void createDefaultSections();
2053
2054 const WriterOptionsELF &_options;
2055
2056 typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
2057 std::unique_ptr<KindHandler> _referenceKindHandler;
2058 AtomToAddress _atomToAddressMap;
2059 llvm::BumpPtrAllocator _chunkAllocate;
Michael J. Spencera2c97272013-01-04 21:09:21 +00002060 DefaultELFLayout<target_endianness, max_align, is64Bits> *_layout;
2061 ELFHeader<target_endianness, max_align, is64Bits> *_elfHeader;
2062 ELFProgramHeader<target_endianness, max_align, is64Bits> *_programHeader;
2063 ELFSymbolTable<target_endianness, max_align, is64Bits> * _symtab;
2064 ELFStringTable<target_endianness, max_align, is64Bits> *_strtab;
2065 ELFStringTable<target_endianness, max_align, is64Bits> *_shstrtab;
2066 ELFSectionHeader<target_endianness, max_align, is64Bits> *_shdrtab;
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002067 CRuntimeFile<target_endianness, max_align, is64Bits> _runtimeFile;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002068};
2069
2070//===----------------------------------------------------------------------===//
2071// ELFExecutableWriter
2072//===----------------------------------------------------------------------===//
Michael J. Spencera2c97272013-01-04 21:09:21 +00002073template<support::endianness target_endianness,
2074 std::size_t max_align,
2075 bool is64Bits>
2076ELFExecutableWriter<target_endianness, max_align, is64Bits>
2077 ::ELFExecutableWriter(const WriterOptionsELF &options)
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002078 : _options(options)
Sid Manning42064e52012-10-09 02:20:47 +00002079 , _referenceKindHandler(KindHandler::makeHandler(_options.machine(),
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002080 target_endianness))
2081 , _runtimeFile(options) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002082 _layout =
2083 new DefaultELFLayout<target_endianness, max_align, is64Bits>(options);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002084}
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002085
Michael J. Spencera2c97272013-01-04 21:09:21 +00002086template<support::endianness target_endianness,
2087 std::size_t max_align,
2088 bool is64Bits>
2089void ELFExecutableWriter<target_endianness, max_align, is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002090 ::buildChunks(const lld::File &file){
2091 for (const DefinedAtom *definedAtom : file.defined() ) {
2092 _layout->addAtom(definedAtom);
2093 }
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002094 /// Add all the absolute atoms to the layout
2095 for (const AbsoluteAtom *absoluteAtom : file.absolute()) {
2096 _layout->addAtom(absoluteAtom);
2097 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002098}
2099
Michael J. Spencera2c97272013-01-04 21:09:21 +00002100template<support::endianness target_endianness,
2101 std::size_t max_align,
2102 bool is64Bits>
2103void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2104 ::buildSymbolTable () {
2105 Section<target_endianness, max_align, is64Bits> *section;
2106 for (auto si = _layout->sections_begin(); si != _layout->sections_end();
2107 ++si) {
2108 if ((*si)->kind() !=
2109 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002110 continue;
Michael J. Spencera2c97272013-01-04 21:09:21 +00002111 section =
2112 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(*si);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002113 for (auto ai = section->atoms_begin(); ai != section->atoms_end(); ++ai) {
2114 _symtab->addSymbol(ai->first, section->ordinal(), ai->second.second);
Hemant Kulkarni736f7fb2012-11-21 21:07:36 +00002115 }
2116 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002117}
2118
Michael J. Spencera2c97272013-01-04 21:09:21 +00002119template<support::endianness target_endianness,
2120 std::size_t max_align,
2121 bool is64Bits>
2122void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2123 ::addAbsoluteUndefinedSymbols(const lld::File &file) {
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002124 /// add all the absolute symbols that the layout contains to the output symbol
2125 /// table
2126 for (auto absi = _layout->absAtomsBegin(), abse = _layout->absAtomsEnd();
2127 absi != abse; ++absi) {
2128 _symtab->addSymbol(absi->absoluteAtom(), ELF::SHN_ABS, absi->value());
2129 }
Hemant Kulkarni08e410292012-10-01 23:53:20 +00002130 for (const UndefinedAtom *a : file.undefined()) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002131 _symtab->addSymbol(a, ELF::SHN_UNDEF);
Hemant Kulkarni08e410292012-10-01 23:53:20 +00002132 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002133}
2134
Michael J. Spencera2c97272013-01-04 21:09:21 +00002135template<support::endianness target_endianness,
2136 std::size_t max_align,
2137 bool is64Bits>
2138void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2139 ::buildAtomToAddressMap () {
2140 Section<target_endianness, max_align, is64Bits> *section;
2141 for (auto si = _layout->sections_begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002142 si != _layout->sections_end(); ++si) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002143 if ((*si)->kind() !=
2144 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002145 continue;
Michael J. Spencera2c97272013-01-04 21:09:21 +00002146 section =
2147 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(*si);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002148 for (auto ai = section->atoms_begin(); ai != section->atoms_end(); ++ai) {
2149 _atomToAddressMap[ai->first] = (ai)->second.second;
Sid Manningdd110202012-09-25 18:22:09 +00002150 }
2151 }
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002152 /// build the atomToAddressMap that contains absolute symbols too
2153 for (auto absi = _layout->absAtomsBegin(), abse = _layout->absAtomsEnd();
2154 absi != abse; ++absi) {
2155 _atomToAddressMap[absi->absoluteAtom()] = absi->value();
2156 }
Sid Manningdd110202012-09-25 18:22:09 +00002157}
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002158
Michael J. Spencera2c97272013-01-04 21:09:21 +00002159template<support::endianness target_endianness,
2160 std::size_t max_align,
2161 bool is64Bits>
2162void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2163 ::buildSectionHeaderTable() {
2164 for (auto msi = _layout->merged_sections_begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002165 msi != _layout->merged_sections_end(); ++msi) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002166 if ((*msi)->kind() !=
2167 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002168 continue;
2169 if ((*msi)->hasSegment())
2170 _shdrtab->appendSection(*msi);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002171 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002172}
2173
Michael J. Spencera2c97272013-01-04 21:09:21 +00002174template<support::endianness target_endianness,
2175 std::size_t max_align,
2176 bool is64Bits>
2177void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2178 ::assignSectionsWithNoSegments() {
2179 Section<target_endianness, max_align, is64Bits> *section;
2180 for (auto msi = _layout->merged_sections_begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002181 msi != _layout->merged_sections_end(); ++msi) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002182 if ((*msi)->kind() !=
2183 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002184 continue;
2185 if (!(*msi)->hasSegment())
2186 _shdrtab->appendSection(*msi);
2187 }
2188 _layout->assignOffsetsForMiscSections();
Michael J. Spencera2c97272013-01-04 21:09:21 +00002189 for (auto si = _layout->sections_begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002190 si != _layout->sections_end(); ++si) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002191 if ((*si)->kind() !=
2192 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002193 continue;
Michael J. Spencera2c97272013-01-04 21:09:21 +00002194 section =
2195 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(*si);
2196 if (!DefaultELFLayout<target_endianness, max_align, is64Bits>
2197 ::hasOutputSegment(section))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002198 _shdrtab->updateSection(section);
2199 }
2200}
2201
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002202/// \brief Add absolute symbols by default. These are linker added
2203/// absolute symbols
2204template<support::endianness target_endianness,
2205 std::size_t max_align,
2206 bool is64Bits>
2207void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2208 ::addDefaultAtoms() {
2209 _runtimeFile.addUndefinedAtom("_start");
2210 _runtimeFile.addAbsoluteAtom("__bss_start");
2211 _runtimeFile.addAbsoluteAtom("__bss_end");
2212 _runtimeFile.addAbsoluteAtom("_end");
2213 _runtimeFile.addAbsoluteAtom("end");
2214}
2215
2216/// \brief Hook in lld to add CRuntime file
2217template<support::endianness target_endianness,
2218 std::size_t max_align,
2219 bool is64Bits>
2220void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2221 ::addFiles(InputFiles &inputFiles) {
2222 addDefaultAtoms();
2223 inputFiles.prependFile(_runtimeFile);
2224}
2225
2226/// Finalize the value of all the absolute symbols that we
2227/// created
2228template<support::endianness target_endianness,
2229 std::size_t max_align,
2230 bool is64Bits>
2231void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2232 ::finalizeDefaultAtomValues() {
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002233 auto bssStartAtomIter = _layout->findAbsoluteAtom("__bss_start");
2234 auto bssEndAtomIter = _layout->findAbsoluteAtom("__bss_end");
2235 auto underScoreEndAtomIter = _layout->findAbsoluteAtom("_end");
2236 auto endAtomIter = _layout->findAbsoluteAtom("end");
2237
Michael J. Spenceraa8a5a22013-01-10 22:41:05 +00002238 assert(!(bssStartAtomIter == _layout->absAtomsEnd() ||
2239 bssEndAtomIter == _layout->absAtomsEnd() ||
2240 underScoreEndAtomIter == _layout->absAtomsEnd() ||
2241 endAtomIter == _layout->absAtomsEnd()) &&
Shankar Easwaran37c52822013-01-10 18:16:10 +00002242 "Unable to find the absolute atoms that have been added by lld");
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002243
2244 auto phe = _programHeader->findProgramHeader(
2245 llvm::ELF::PT_LOAD,
2246 llvm::ELF::PF_W,
2247 llvm::ELF::PF_X);
2248
Shankar Easwaran37c52822013-01-10 18:16:10 +00002249 assert(!(phe == _programHeader->end()) &&
2250 "Can't find a data segment in the program header!");
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002251
2252 bssStartAtomIter->setValue((*phe)->p_vaddr+(*phe)->p_filesz);
2253 bssEndAtomIter->setValue((*phe)->p_vaddr+(*phe)->p_memsz);
2254 underScoreEndAtomIter->setValue((*phe)->p_vaddr+(*phe)->p_memsz);
2255 endAtomIter->setValue((*phe)->p_vaddr+(*phe)->p_memsz);
2256}
2257
Michael J. Spencera2c97272013-01-04 21:09:21 +00002258template<support::endianness target_endianness,
2259 std::size_t max_align,
2260 bool is64Bits>
2261error_code ELFExecutableWriter<target_endianness, max_align, is64Bits>
2262 ::writeFile(const lld::File &file, StringRef path) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002263 buildChunks(file);
2264 // Create the default sections like the symbol table, string table, and the
2265 // section string table
2266 createDefaultSections();
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002267
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002268 // Set the Layout
2269 _layout->assignSectionsToSegments();
2270 _layout->assignFileOffsets();
2271 _layout->assignVirtualAddress();
2272
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002273 // Finalize the default value of symbols that the linker adds
2274 finalizeDefaultAtomValues();
2275
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002276 // Build the Atom To Address map for applying relocations
2277 buildAtomToAddressMap();
2278
2279 // Create symbol table and section string table
2280 buildSymbolTable();
2281
2282 // add other symbols
2283 addAbsoluteUndefinedSymbols(file);
2284
2285 // Finalize the layout by calling the finalize() functions
2286 _layout->finalize();
2287
2288 // build Section Header table
2289 buildSectionHeaderTable();
2290
2291 // assign Offsets and virtual addresses
2292 // for sections with no segments
2293 assignSectionsWithNoSegments();
2294
2295 uint64_t totalSize = _shdrtab->fileOffset() + _shdrtab->fileSize();
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002296
2297 OwningPtr<FileOutputBuffer> buffer;
2298 error_code ec = FileOutputBuffer::create(path,
2299 totalSize, buffer,
2300 FileOutputBuffer::F_executable);
2301 if (ec)
2302 return ec;
2303
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002304 _elfHeader->e_ident(ELF::EI_CLASS, (_options.is64Bit() ? ELF::ELFCLASS64
2305 : ELF::ELFCLASS32));
Michael J. Spencera2c97272013-01-04 21:09:21 +00002306 _elfHeader->e_ident(ELF::EI_DATA, _options.endianness() == llvm::support::big
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002307 ? ELF::ELFDATA2MSB : ELF::ELFDATA2LSB);
2308 _elfHeader->e_ident(ELF::EI_VERSION, 1);
2309 _elfHeader->e_ident(ELF::EI_OSABI, 0);
2310 _elfHeader->e_type(_options.type());
2311 _elfHeader->e_machine(_options.machine());
2312 _elfHeader->e_version(1);
2313 _elfHeader->e_entry(0ULL);
2314 _elfHeader->e_phoff(_programHeader->fileOffset());
2315 _elfHeader->e_shoff(_shdrtab->fileOffset());
2316 _elfHeader->e_phentsize(_programHeader->entsize());
2317 _elfHeader->e_phnum(_programHeader->numHeaders());
2318 _elfHeader->e_shentsize(_shdrtab->entsize());
2319 _elfHeader->e_shnum(_shdrtab->numHeaders());
2320 _elfHeader->e_shstrndx(_shstrtab->ordinal());
2321 uint64_t virtualAddr = 0;
2322 _layout->findAtomAddrByName("_start", virtualAddr);
2323 _elfHeader->e_entry(virtualAddr);
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00002324
2325 // HACK: We have to write out the header and program header here even though
2326 // they are a member of a segment because only sections are written in the
2327 // following loop.
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002328 _elfHeader->write(this, buffer);
2329 _programHeader->write(this, buffer);
2330
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00002331 for (auto si = _layout->sections_begin(); si != _layout->sections_end(); ++si)
2332 (*si)->write(this, buffer);
2333
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002334 return buffer->commit();
2335}
Nick Kledzikabb69812012-05-31 22:34:00 +00002336
Michael J. Spencera2c97272013-01-04 21:09:21 +00002337template<support::endianness target_endianness,
2338 std::size_t max_align,
2339 bool is64Bits>
2340void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2341 ::createDefaultSections() {
2342 _elfHeader =
2343 new ELFHeader<target_endianness, max_align, is64Bits>();
2344 _programHeader =
2345 new ELFProgramHeader<target_endianness, max_align, is64Bits>();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002346 _layout->setELFHeader(_elfHeader);
2347 _layout->setProgramHeader(_programHeader);
2348
Michael J. Spencera2c97272013-01-04 21:09:21 +00002349 _symtab = new ELFSymbolTable<target_endianness, max_align, is64Bits>(
2350 ".symtab",
2351 DefaultELFLayout<target_endianness, max_align, is64Bits>
2352 ::ORDER_SYMBOL_TABLE);
2353 _strtab = new ELFStringTable<target_endianness, max_align, is64Bits>(
2354 ".strtab",
2355 DefaultELFLayout<target_endianness, max_align, is64Bits>
2356 ::ORDER_STRING_TABLE);
2357 _shstrtab = new ELFStringTable<target_endianness, max_align, is64Bits>(
2358 ".shstrtab",
2359 DefaultELFLayout<target_endianness, max_align, is64Bits>
2360 ::ORDER_SECTION_STRINGS);
2361 _shdrtab = new ELFSectionHeader<target_endianness, max_align, is64Bits>(
2362 DefaultELFLayout<target_endianness, max_align, is64Bits>
2363 ::ORDER_SECTION_HEADERS);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002364 _layout->addSection(_symtab);
2365 _layout->addSection(_strtab);
2366 _layout->addSection(_shstrtab);
2367 _shdrtab->setStringSection(_shstrtab);
2368 _symtab->setStringSection(_strtab);
2369 _layout->addSection(_shdrtab);
Sid Manningdd110202012-09-25 18:22:09 +00002370}
Nick Kledzikabb69812012-05-31 22:34:00 +00002371} // namespace elf
2372
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002373Writer *createWriterELF(const WriterOptionsELF &options) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002374 // Set the default layout to be the static executable layout
Michael J. Spencera2c97272013-01-04 21:09:21 +00002375 // We would set the layout to a dynamic executable layout
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002376 // if we came across any shared libraries in the process
Michael J. Spencera2c97272013-01-04 21:09:21 +00002377
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002378 if (!options.is64Bit() && options.endianness() == llvm::support::little)
Michael J. Spencera2c97272013-01-04 21:09:21 +00002379 return new elf::ELFExecutableWriter<support::little, 4, false>(options);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002380 else if (options.is64Bit() && options.endianness() == llvm::support::little)
Michael J. Spencera2c97272013-01-04 21:09:21 +00002381 return new elf::ELFExecutableWriter<support::little, 8, true>(options);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002382 else if (!options.is64Bit() && options.endianness() == llvm::support::big)
Michael J. Spencera2c97272013-01-04 21:09:21 +00002383 return new elf::ELFExecutableWriter<support::big, 4, false>(options);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002384 else if (options.is64Bit() && options.endianness() == llvm::support::big)
Michael J. Spencera2c97272013-01-04 21:09:21 +00002385 return new elf::ELFExecutableWriter<support::big, 8, true>(options);
Nick Kledzikabb69812012-05-31 22:34:00 +00002386
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002387 llvm_unreachable("Invalid Options!");
Nick Kledzikabb69812012-05-31 22:34:00 +00002388}
Nick Kledzikabb69812012-05-31 22:34:00 +00002389} // namespace lld