blob: b6e847ef4dbe804a7e73521d88f87060aeb41358 [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 Easwaran495d38b2012-12-27 02:26:30 +000037#include "AtomsELF.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:
276 _atoms.push_back(std::make_pair(atom, std::make_pair(fOffset, 0)));
277 this->_fsize = fOffset + definedAtom->size();
278 this->_msize = mOffset + definedAtom->size();
279 break;
280 case DefinedAtom::typeZeroFill:
281 _atoms.push_back(std::make_pair(atom, std::make_pair(mOffset, 0)));
282 this->_msize = mOffset + definedAtom->size();
283 break;
284 default:
285 this->_fsize = fOffset + definedAtom->size();
286 this->_msize = mOffset + definedAtom->size();
287 break;
288 }
289 break;
290 default:
291 llvm_unreachable("Expecting only definedAtoms being passed here");
292 break;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000293 }
294 // Set the section alignment to the largest alignment
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000295 // std::max doesnot support uint64_t
Michael J. Spencera2c97272013-01-04 21:09:21 +0000296 if (this->_align2 < align2)
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000297 this->_align2 = align2;
298 }
299
Michael J. Spencera2c97272013-01-04 21:09:21 +0000300 /// \brief Set the virtual address of each Atom in the Section. This
301 /// routine gets called after the linker fixes up the virtual address
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000302 /// of the section
303 void assignVirtualAddress(uint64_t &addr) {
304 for (auto &ai : _atoms) {
305 ai.second.second = addr + ai.second.first;
306 }
307 addr += this->memSize();
308 }
309
Michael J. Spencera2c97272013-01-04 21:09:21 +0000310 /// \brief Set the file offset of each Atom in the section. This routine
311 /// gets called after the linker fixes up the section offset
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000312 void assignOffsets(uint64_t offset) {
313 for (auto &ai : _atoms) {
314 ai.second.first = offset + ai.second.first;
315 }
316 }
317
Michael J. Spencera2c97272013-01-04 21:09:21 +0000318 /// \brief Find the Atom address given a name, this is needed to to properly
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000319 /// apply relocation. The section class calls this to find the atom address
320 /// to fix the relocation
321 bool findAtomAddrByName(const StringRef name, uint64_t &addr) {
322 for (auto ai : _atoms) {
323 if (ai.first->name() == name) {
324 addr = ai.second.second;
325 return true;
326 }
327 }
328 return false;
329 }
330
331 /// \brief Does the Atom occupy any disk space
332 bool occupiesNoDiskSpace() const {
333 return _contentType == DefinedAtom::typeZeroFill;
334 }
335
Michael J. Spencera2c97272013-01-04 21:09:21 +0000336 /// \brief The permission of the section is the most permissive permission
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000337 /// of all atoms that the section contains
338 void setContentPermissions(int32_t perm) {
339 _contentPermissions = std::max(perm, _contentPermissions);
340 }
341
342 /// \brief Get the section flags, defined by the permissions of the section
343 int64_t flags() {
344 switch (_contentPermissions) {
345 case DefinedAtom::perm___:
346 return 0;
347
348 case DefinedAtom::permR__:
349 return llvm::ELF::SHF_ALLOC;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000350
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000351 case DefinedAtom::permR_X:
352 return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000353
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000354 case DefinedAtom::permRW_:
355 case DefinedAtom::permRW_L:
356 return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000357
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000358 case DefinedAtom::permRWX:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000359 return llvm::ELF::SHF_ALLOC |
360 llvm::ELF::SHF_WRITE |
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000361 llvm::ELF::SHF_EXECINSTR;
362
363 default:
364 break;
365 }
366 return llvm::ELF::SHF_ALLOC;
367 }
368
369 /// \brief Return the raw flags, we need this to sort segments
370 int64_t atomflags() const {
371 return _contentPermissions;
372 }
373
Michael J. Spencera2c97272013-01-04 21:09:21 +0000374 /// \brief Return the section type, the returned value is recorded in the
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000375 /// sh_type field of the Section Header
376 int type() {
377 switch (_contentType) {
378 case DefinedAtom::typeCode:
379 case DefinedAtom::typeData:
380 case DefinedAtom::typeConstant:
381 return llvm::ELF::SHT_PROGBITS;
382
383 case DefinedAtom::typeZeroFill:
384 return llvm::ELF::SHT_NOBITS;
385
386 // Case to handle section types
387 // Symtab, String Table ...
388 default:
389 return _contentType;
390 }
391 }
392
Michael J. Spencera2c97272013-01-04 21:09:21 +0000393 /// \brief Returns the section link field, the returned value is
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000394 /// recorded in the sh_link field of the Section Header
395 int link() const {
396 return _link;
397 }
398
399 void setLink(int32_t link) {
400 _link = link;
401 }
402
Michael J. Spencera2c97272013-01-04 21:09:21 +0000403 /// \brief Returns the section entsize field, the returned value is
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000404 /// recorded in the sh_entsize field of the Section Header
405 int entsize() const {
406 return _entSize;
407 }
408
Michael J. Spencera2c97272013-01-04 21:09:21 +0000409 /// \brief Returns the shinfo field, the returned value is
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000410 /// recorded in the sh_info field of the Section Header
Michael J. Spencera2c97272013-01-04 21:09:21 +0000411 int shinfo() const {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000412 return _shInfo;
413 }
414
415 /// \brief Records the segmentType, that this section belongs to
416 void setSegment(const ELFLayout::SegmentType segmentType) {
417 _segmentType = segmentType;
418 }
419
420 /// \brief convert the segment type to a String for diagnostics
421 /// and printing purposes
422 StringRef segmentKindToStr() const {
423 switch(_segmentType) {
424 case llvm::ELF::PT_INTERP:
425 return "INTERP";
426 case llvm::ELF::PT_LOAD:
427 return "LOAD";
428 case llvm::ELF::PT_GNU_EH_FRAME:
429 return "EH_FRAME";
430 case llvm::ELF::PT_NOTE:
431 return "NOTE";
432 case llvm::ELF::PT_DYNAMIC:
433 return "DYNAMIC";
434 case llvm::ELF::PT_GNU_RELRO:
435 return "RELRO";
436 case llvm::ELF::PT_NULL:
437 return "NULL";
438 default:
439 return "UNKNOWN";
440 }
441 }
442
443 /// \brief for LLVM style RTTI information
Michael J. Spencera2c97272013-01-04 21:09:21 +0000444 static inline bool classof(
445 const Chunk<target_endianness, max_align, is64Bits> *c) {
446 return c->kind() ==
447 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000448 }
449
450 /// \brief Finalize the section contents before writing
451 void finalize() { }
452
Michael J. Spencera2c97272013-01-04 21:09:21 +0000453 /// \brief Write the section and the atom contents to the buffer
454 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000455 OwningPtr<FileOutputBuffer> &buffer) {
456 uint8_t *chunkBuffer = buffer->getBufferStart();
457 for (auto &ai : _atoms) {
458 const DefinedAtom *definedAtom = llvm::dyn_cast<DefinedAtom>(ai.first);
459 // Copy raw content of atom to file buffer.
460 ArrayRef<uint8_t> content = definedAtom->rawContent();
461 uint64_t contentSize = content.size();
462 if (contentSize == 0)
463 continue;
464 uint8_t *atomContent = chunkBuffer + ai.second.first;
465 std::copy_n(content.data(), contentSize, atomContent);
466 for (auto ref = definedAtom->begin(); ref != definedAtom->end(); ++ref) {
467 uint32_t offset = ref->offsetInAtom();
468 uint64_t targetAddress = 0;
469 if (ref->target() != nullptr)
470 targetAddress = writer->addressOfAtom(ref->target());
471 else
472 assert(0 && "Found the target to be NULL");
473 uint64_t fixupAddress = writer->addressOfAtom(ai.first) + offset;
474 // apply the relocation
Michael J. Spencera2c97272013-01-04 21:09:21 +0000475 writer->kindHandler()->applyFixup(ref->kind(),
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000476 ref->addend(),
477 &atomContent[offset],
478 fixupAddress,
479 targetAddress);
480 }
481 }
482 }
483
484 /// Atom Iterators
Michael J. Spencera2c97272013-01-04 21:09:21 +0000485 typedef typename std::vector<std::pair<const Atom *,
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000486 std::pair<uint64_t, uint64_t>>>::iterator atom_iter;
487
488 atom_iter atoms_begin() { return _atoms.begin(); }
489
490 atom_iter atoms_end() { return _atoms.end(); }
491
492protected:
493 int32_t _contentType;
494 int32_t _contentPermissions;
495 SectionKind _sectionKind;
496 // An Atom is appended to the vector with the following fields
497 // field1 : Atom
498 // field2 : fileoffset (initially set with a base offset of 0)
499 // field3 : virtual address
500 std::vector<std::pair<const Atom *, std::pair<uint64_t, uint64_t>>> _atoms;
501 ELFLayout::SegmentType _segmentType;
502 int64_t _entSize;
503 int64_t _shInfo;
504 int64_t _link;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000505};
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000506
Michael J. Spencera2c97272013-01-04 21:09:21 +0000507/// \brief A MergedSections represents a set of sections grouped by the same
508/// name. The output file that gets written by the linker has sections grouped
509/// by similiar names
510template<support::endianness target_endianness,
511 std::size_t max_align,
512 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000513class MergedSections {
514public:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000515 MergedSections(StringRef name)
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000516 : _name(name)
517 ,_hasSegment(false)
518 ,_ordinal(0)
519 ,_flags(0)
520 ,_size(0)
521 ,_memSize(0)
522 ,_fileOffset(0)
523 ,_virtualAddr(0)
524 ,_shInfo(0)
525 ,_entSize(0)
526 ,_link(0)
527 ,_align2(0)
528 ,_kind(0)
529 ,_type(0) { }
Michael J. Spencera2c97272013-01-04 21:09:21 +0000530
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000531 // Set the MergedSections is associated with a segment
532 void setHasSegment() { _hasSegment = true; }
533
Michael J. Spencera2c97272013-01-04 21:09:21 +0000534 /// Sets the ordinal
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000535 void setOrdinal(uint64_t ordinal) {
536 _ordinal = ordinal;
537 }
538
Michael J. Spencera2c97272013-01-04 21:09:21 +0000539 /// Sets the Memory size
540 void setMemSize(uint64_t memsz) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000541 _memSize = memsz;
542 }
543
544 /// Sets the size fo the merged Section
545 void setSize(uint64_t fsiz) {
546 _size = fsiz;
547 }
548
Michael J. Spencera2c97272013-01-04 21:09:21 +0000549 // The offset of the first section contained in the merged section is
550 // contained here
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000551 void setFileOffset(uint64_t foffset) {
552 _fileOffset = foffset;
553 }
554
555 // Sets the starting address of the section
556 void setAddr(uint64_t addr) {
557 _virtualAddr = addr;
558 }
559
560 // Appends a section into the list of sections that are part of this Merged
561 // Section
Michael J. Spencera2c97272013-01-04 21:09:21 +0000562 void appendSection(Chunk<target_endianness, max_align, is64Bits> *c) {
563 if (c->align2() > _align2)
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000564 _align2 = c->align2();
Michael J. Spencera2c97272013-01-04 21:09:21 +0000565 if (c->kind() ==
566 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection) {
567 Section<target_endianness, max_align, is64Bits> *section;
568 section =
569 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(c);
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000570 _link = section->link();
571 _shInfo = section->shinfo();
572 _entSize = section->entsize();
573 _type = section->type();
574 if (_flags < section->flags())
575 _flags = section->flags();
576 }
577 _kind = c->kind();
578 _sections.push_back(c);
579 }
580
581 // Iterators
Michael J. Spencera2c97272013-01-04 21:09:21 +0000582 typedef typename std::vector<
583 Chunk<target_endianness, max_align, is64Bits> *>::iterator ChunkIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000584
585 ChunkIter begin_sections() { return _sections.begin(); }
586
587 ChunkIter end_sections() { return _sections.end(); }
588
589 // The below functions returns the properties of the MergeSection
590 bool hasSegment() const { return _hasSegment; }
591
592 StringRef name() const { return _name; }
593
594 int64_t shinfo() const { return _shInfo; }
595
596 uint64_t align2() const { return _align2; }
597
598 int64_t link() const { return _link; }
599
600 int64_t type() const { return _type; }
601
602 uint64_t virtualAddr() const { return _virtualAddr; }
603
604 int64_t ordinal() const { return _ordinal; }
605
606 int64_t kind() const { return _kind; }
607
608 uint64_t fileSize() const { return _size; }
609
610 int64_t entsize() const { return _entSize; }
611
612 uint64_t fileOffset() const { return _fileOffset; }
613
614 int64_t flags() const { return _flags; }
615
616 uint64_t memSize() { return _memSize; }
617
618private:
619 StringRef _name;
620 bool _hasSegment;
621 uint64_t _ordinal;
622 int64_t _flags;
623 uint64_t _size;
624 uint64_t _memSize;
625 uint64_t _fileOffset;
626 uint64_t _virtualAddr;
627 int64_t _shInfo;
628 int64_t _entSize;
629 int64_t _link;
630 uint64_t _align2;
631 int64_t _kind;
632 int64_t _type;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000633 std::vector<Chunk<target_endianness, max_align, is64Bits> *> _sections;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000634};
635
Michael J. Spencera2c97272013-01-04 21:09:21 +0000636/// \brief A segment can be divided into segment slices
637/// depending on how the segments can be split
638template<support::endianness target_endianness,
639 std::size_t max_align,
640 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000641class SegmentSlice {
642public:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000643 typedef typename std::vector<
Michael J. Spencer00b702c2013-01-07 07:59:46 +0000644 Chunk<target_endianness, max_align, is64Bits> *>::iterator sectionIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000645
646 SegmentSlice() { }
647
648 /// Set the segment slice so that it begins at the offset specified
Michael J. Spencera2c97272013-01-04 21:09:21 +0000649 /// by fileoffset and set the start of the slice to be s and the end
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000650 /// of the slice to be e
651 void set(uint64_t fileoffset, int32_t s, int e) {
652 _startSection = s;
653 _endSection = e+1;
654 _offset = fileoffset;
655 }
656
657 // Set the segment slice start and end iterators. This is used to walk through
658 // the sections that are part of the Segment slice
659 void setSections(sectionIter start, sectionIter end) {
660 _startSectionIter = start;
661 _endSectionIter = end;
662 }
663
664 // Return the fileOffset of the slice
665 uint64_t fileOffset() const { return _offset; }
666
667 // Return the size of the slice
668 uint64_t fileSize() const { return _size; }
669
670 // Return the start of the slice
671 int32_t startSection() const { return _startSection; }
672
673 // Return the start address of the slice
674 uint64_t virtualAddr() const { return _addr; }
675
676 // Return the memory size of the slice
677 uint64_t memSize() const { return _memSize; }
678
679 // Return the alignment of the slice
680 uint64_t align2() const { return _align2; }
681
682 void setSize(uint64_t sz) { _size = sz; }
683
684 void setMemSize(uint64_t memsz) { _memSize = memsz; }
685
686 void setVAddr(uint64_t addr) { _addr = addr; }
687
688 void setAlign(uint64_t align) { _align2 = align; }
689
Michael J. Spencera2c97272013-01-04 21:09:21 +0000690 static bool compare_slices(
691 SegmentSlice<target_endianness, max_align, is64Bits> *a,
692 SegmentSlice<target_endianness, max_align, is64Bits> *b) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000693 return (a->startSection() < b->startSection());
694 }
695
696 // Functions to run through the slice
697 sectionIter sections_begin() { return _startSectionIter; }
698
699 sectionIter sections_end() { return _endSectionIter; }
700
701private:
702 int32_t _startSection;
703 int32_t _endSection;
704 sectionIter _startSectionIter;
705 sectionIter _endSectionIter;
706 uint64_t _addr;
707 uint64_t _offset;
708 uint64_t _size;
709 uint64_t _align2;
710 uint64_t _memSize;
711};
712
713/// \brief A segment contains a set of sections, that have similiar properties
714// the sections are already seperated based on different flags and properties
715// the segment is just a way to concatenate sections to segments
Michael J. Spencera2c97272013-01-04 21:09:21 +0000716template<support::endianness target_endianness,
717 std::size_t max_align,
718 bool is64Bits>
719class Segment : public Chunk<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000720public:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000721 typedef typename std::vector<SegmentSlice<
722 target_endianness, max_align, is64Bits> *>::iterator slice_iter;
723 typedef typename std::vector<
Michael J. Spencer00b702c2013-01-07 07:59:46 +0000724 Chunk<target_endianness, max_align, is64Bits> *>::iterator SectionIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000725
726 Segment(const StringRef name,
727 const ELFLayout::SegmentType type,
728 const WriterOptionsELF &options)
Michael J. Spencera2c97272013-01-04 21:09:21 +0000729 : Chunk<target_endianness, max_align, is64Bits>(name,
730 Chunk<target_endianness, max_align, is64Bits>::K_ELFSegment)
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000731 , _segmentType(type)
732 , _flags(0)
733 , _atomflags(0)
734 , _options(options) {
735 this->_align2 = 0;
736 this->_fsize = 0;
737 }
738
739 /// append a section to a segment
Michael J. Spencera2c97272013-01-04 21:09:21 +0000740 void append(Section<target_endianness, max_align, is64Bits> *section) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000741 _sections.push_back(section);
742 if (_flags < section->flags())
743 _flags = section->flags();
744 if (_atomflags < section->atomflags())
745 _atomflags = section->atomflags();
746 if (this->_align2 < section->align2())
747 this->_align2 = section->align2();
748 }
749
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000750 /// Prepend a generic chunk to the segment.
751 void prepend(Chunk<target_endianness, max_align, is64Bits> *c) {
752 _sections.insert(_sections.begin(), c);
753 }
754
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000755 /// Sort segments depending on the property
756 /// If we have a Program Header segment, it should appear first
757 /// If we have a INTERP segment, that should appear after the Program Header
758 /// All Loadable segments appear next in this order
759 /// All Read Write Execute segments follow
760 /// All Read Execute segments appear next
761 /// All Read only segments appear first
Michael J. Spencera2c97272013-01-04 21:09:21 +0000762 /// All Write execute segments follow
763 static bool compareSegments(
764 Segment<target_endianness, max_align, is64Bits> *sega,
765 Segment<target_endianness, max_align, is64Bits> *segb) {
766 if (sega->atomflags() < segb->atomflags())
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000767 return false;
768 return true;
769 }
770
771 /// \brief Start assigning file offset to the segment chunks The fileoffset
772 /// needs to be page at the start of the segment and in addition the
773 /// fileoffset needs to be aligned to the max section alignment within the
774 /// segment. This is required so that the ELF property p_poffset % p_align =
775 /// p_vaddr mod p_align holds true.
776 /// The algorithm starts off by assigning the startOffset thats passed in as
777 /// parameter to the first section in the segment, if the difference between
778 /// the newly computed offset is greater than a page, then we create a segment
Michael J. Spencera2c97272013-01-04 21:09:21 +0000779 /// slice, as it would be a waste of virtual memory just to be filled with
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000780 /// zeroes
781 void assignOffsets(uint64_t startOffset) {
782 int startSection = 0;
783 int currSection = 0;
784 SectionIter startSectionIter, endSectionIter;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000785 // slice align is set to the max alignment of the chunks that are
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000786 // contained in the slice
787 uint64_t sliceAlign = 0;
788 // Current slice size
789 uint64_t curSliceSize = 0;
790 // Current Slice File Offset
791 uint64_t curSliceFileOffset = 0;
792
793 startSectionIter = _sections.begin();
794 endSectionIter = _sections.end();
795 startSection = 0;
796 bool isFirstSection = true;
797 for (auto si = _sections.begin(); si != _sections.end(); ++si) {
798 if (isFirstSection) {
799 // align the startOffset to the section alignment
Michael J. Spencera2c97272013-01-04 21:09:21 +0000800 uint64_t newOffset =
801 llvm::RoundUpToAlignment(startOffset, (*si)->align2());
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000802 curSliceFileOffset = newOffset;
803 sliceAlign = (*si)->align2();
804 this->setFileOffset(startOffset);
805 (*si)->setFileOffset(newOffset);
806 curSliceSize = (*si)->fileSize();
807 isFirstSection = false;
808 } else {
809 uint64_t curOffset = curSliceFileOffset + curSliceSize;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000810 uint64_t newOffset =
811 llvm::RoundUpToAlignment(curOffset, (*si)->align2());
812 SegmentSlice<target_endianness, max_align, is64Bits> *slice = nullptr;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000813 // If the newOffset computed is more than a page away, lets create
814 // a seperate segment, so that memory is not used up while running
815 if ((newOffset - curOffset) > _options.pageSize()) {
816 // TODO: use std::find here
817 for (auto sei = slices_begin(); sei != slices_end(); ++sei) {
818 if ((*sei)->startSection() == startSection) {
819 slice = *sei;
820 break;
821 }
822 }
823 if (!slice) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000824 slice = new (_segmentAllocate.Allocate<
825 SegmentSlice<target_endianness, max_align, is64Bits>>())
826 SegmentSlice<target_endianness, max_align, is64Bits>();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000827 _segmentSlices.push_back(slice);
828 }
829 slice->set(curSliceFileOffset, startSection, currSection);
830 slice->setSections(startSectionIter, endSectionIter);
831 slice->setSize(curSliceSize);
832 slice->setAlign(sliceAlign);
Michael J. Spencera2c97272013-01-04 21:09:21 +0000833 uint64_t newPageOffset =
834 llvm::RoundUpToAlignment(curOffset, _options.pageSize());
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000835 newOffset = llvm::RoundUpToAlignment(newPageOffset, (*si)->align2());
836 curSliceFileOffset = newOffset;
837 startSectionIter = endSectionIter;
838 startSection = currSection;
839 (*si)->setFileOffset(curSliceFileOffset);
840 curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
841 sliceAlign = (*si)->align2();
842 }
843 else {
844 if (sliceAlign < (*si)->align2())
845 sliceAlign = (*si)->align2();
846 (*si)->setFileOffset(newOffset);
847 curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
848 }
849 }
850 currSection++;
851 endSectionIter = si;
852 }
Michael J. Spencera2c97272013-01-04 21:09:21 +0000853 SegmentSlice<target_endianness, max_align, is64Bits> *slice = nullptr;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000854 for (auto sei = slices_begin(); sei != slices_end(); ++sei) {
855 // TODO: add std::find
856 if ((*sei)->startSection() == startSection) {
857 slice = *sei;
858 break;
859 }
860 }
861 if (!slice) {
862 slice = new (_segmentAllocate.Allocate
Michael J. Spencera2c97272013-01-04 21:09:21 +0000863 <SegmentSlice<target_endianness, max_align, is64Bits>>())
864 SegmentSlice<target_endianness, max_align, is64Bits>();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000865 _segmentSlices.push_back(slice);
866 }
867 slice->set(curSliceFileOffset, startSection, currSection);
868 slice->setSections(startSectionIter, _sections.end());
869 slice->setSize(curSliceSize);
870 slice->setAlign(sliceAlign);
871 this->_fsize = curSliceFileOffset - startOffset + curSliceSize;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000872 std::stable_sort(slices_begin(), slices_end(),
873 SegmentSlice<target_endianness, max_align, is64Bits>::compare_slices);
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000874 }
875
876 /// \brief Assign virtual addresses to the slices
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000877 void assignVirtualAddress(uint64_t &addr) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000878 for (auto sei = slices_begin(), see = slices_end(); sei != see; ++sei) {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000879 // Align to a page
880 addr = llvm::RoundUpToAlignment(addr, _options.pageSize());
881 // Align to the slice alignment
882 addr = llvm::RoundUpToAlignment(addr, (*sei)->align2());
883
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000884 bool virtualAddressSet = false;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000885 for (auto si = (*sei)->sections_begin(), se = (*sei)->sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000886 si != se; ++si) {
887 // Align the section address
888 addr = llvm::RoundUpToAlignment(addr, (*si)->align2());
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000889 if (!virtualAddressSet) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000890 (*sei)->setVAddr(addr);
891 virtualAddressSet = true;
892 }
893 (*si)->setVAddr(addr);
Michael J. Spencer00b702c2013-01-07 07:59:46 +0000894 if (auto s =
895 dyn_cast<Section<target_endianness, max_align, is64Bits>>(*si))
896 s->assignVirtualAddress(addr);
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000897 else
898 addr += (*si)->memSize();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000899 (*si)->setMemSize(addr - (*si)->virtualAddr());
900 }
901 (*sei)->setMemSize(addr - (*sei)->virtualAddr());
902 }
903 }
904
905 slice_iter slices_begin() {
906 return _segmentSlices.begin();
907 }
908
909 slice_iter slices_end() {
910 return _segmentSlices.end();
911 }
912
Michael J. Spencera2c97272013-01-04 21:09:21 +0000913 // Write the Segment
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000914 void write(ELFWriter *writer, OwningPtr<FileOutputBuffer> &buffer) {
915 for (auto sei = slices_begin(), see = slices_end(); sei != see; ++sei) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000916 for (auto si = (*sei)->sections_begin(), se = (*sei)->sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000917 si != se; ++si) {
918 (*si)->write(writer, buffer);
919 }
920 }
921 }
922
923 // Finalize the segment, before we want to write to the output file
924 void finalize() { }
925
Michael J. Spencera2c97272013-01-04 21:09:21 +0000926 // For LLVM RTTI
927 static inline bool classof(
928 const Chunk<target_endianness, max_align, is64Bits> *c) {
929 return c->kind() ==
930 Chunk<target_endianness, max_align, is64Bits>::K_ELFSegment;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000931 }
932
933 // Getters
934 int32_t sectionCount() const {
935 return _sections.size();
936 }
937
938 ELFLayout::SegmentType segmentType() { return _segmentType; }
939
940 int pageSize() const { return _options.pageSize(); }
941
942 int64_t atomflags() const { return _atomflags; }
943
944 int64_t flags() const {
945 int64_t fl = 0;
946 if (_flags & llvm::ELF::SHF_ALLOC)
947 fl |= llvm::ELF::PF_R;
948 if (_flags & llvm::ELF::SHF_WRITE)
949 fl |= llvm::ELF::PF_W;
950 if (_flags & llvm::ELF::SHF_EXECINSTR)
951 fl |= llvm::ELF::PF_X;
952 return fl;
953 }
954
955 int64_t numSlices() const {
956 return _segmentSlices.size();
957 }
958
959private:
Michael J. Spencer00b702c2013-01-07 07:59:46 +0000960 /// \brief Section or some other chunk type.
961 std::vector<Chunk<target_endianness, max_align, is64Bits> *> _sections;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000962 std::vector<SegmentSlice<target_endianness, max_align, is64Bits> *>
963 _segmentSlices;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000964 ELFLayout::SegmentType _segmentType;
965 int64_t _flags;
966 int64_t _atomflags;
967 const WriterOptionsELF _options;
968 llvm::BumpPtrAllocator _segmentAllocate;
969};
970
971/// \brief The class represents the ELF String Table
Michael J. Spencera2c97272013-01-04 21:09:21 +0000972template<support::endianness target_endianness,
973 std::size_t max_align,
974 bool is64Bits>
975class ELFStringTable : public Section<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000976public:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000977 ELFStringTable(const char *str, int32_t order)
978 : Section<target_endianness, max_align, is64Bits>(
979 str,
980 llvm::ELF::SHT_STRTAB,
981 DefinedAtom::perm___,
982 order,
983 Section<target_endianness, max_align, is64Bits>::K_StringTable) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000984 // the string table has a NULL entry for which
985 // add an empty string
986 _strings.push_back("");
987 this->_fsize = 1;
988 this->_align2 = 1;
989 this->setOrder(order);
990 }
991
Michael J. Spencera2c97272013-01-04 21:09:21 +0000992 static inline bool classof(
993 const Chunk<target_endianness, max_align, is64Bits> *c) {
994 return c->kind() ==
995 Section<target_endianness, max_align, is64Bits>::K_StringTable;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000996 }
997
998 uint64_t addString(const StringRef symname) {
999 _strings.push_back(symname);
1000 uint64_t offset = this->_fsize;
1001 this->_fsize += symname.size() + 1;
1002 return offset;
1003 }
1004
Michael J. Spencera2c97272013-01-04 21:09:21 +00001005 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001006 OwningPtr<FileOutputBuffer> &buffer) {
1007 uint8_t *chunkBuffer = buffer->getBufferStart();
1008 uint8_t *dest = chunkBuffer + this->fileOffset();
1009 for (auto si : _strings) {
1010 memcpy(dest, si.data(), si.size());
1011 dest += si.size();
1012 memcpy(dest, "", 1);
1013 dest += 1;
1014 }
1015 }
1016
1017 void finalize() { }
1018
1019private:
1020 std::vector<StringRef> _strings;
1021};
1022
Michael J. Spencera2c97272013-01-04 21:09:21 +00001023/// \brief The ELFSymbolTable class represents the symbol table in a ELF file
1024template<support::endianness target_endianness,
1025 std::size_t max_align,
1026 bool is64Bits>
1027class ELFSymbolTable : public Section<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001028public:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001029 typedef object::Elf_Sym_Impl<target_endianness, max_align, is64Bits> Elf_Sym;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001030
Michael J. Spencera2c97272013-01-04 21:09:21 +00001031 ELFSymbolTable(const char *str, int32_t order)
1032 : Section<target_endianness, max_align, is64Bits>(
1033 str,
1034 llvm::ELF::SHT_SYMTAB,
1035 0,
1036 order,
1037 Section<target_endianness, max_align, is64Bits>::K_SymbolTable) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001038 this->setOrder(order);
1039 Elf_Sym *symbol = new (_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001040 memset((void *)symbol, 0, sizeof(Elf_Sym));
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001041 _symbolTable.push_back(symbol);
1042 this->_entSize = sizeof(Elf_Sym);
1043 this->_fsize = sizeof(Elf_Sym);
1044 this->_align2 = sizeof(void *);
1045 }
1046
Michael J. Spencera2c97272013-01-04 21:09:21 +00001047 static inline bool classof(
1048 const Chunk<target_endianness, max_align, is64Bits> *c) {
1049 return c->kind() ==
1050 Section<target_endianness, max_align, is64Bits>::K_SymbolTable;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001051 }
1052
1053 void addSymbol(const Atom *atom, int32_t sectionIndex, uint64_t addr = 0) {
1054 Elf_Sym *symbol = new(_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
1055 unsigned char binding = 0, type = 0;
1056 symbol->st_name = _stringSection->addString(atom->name());
1057 symbol->st_size = 0;
1058 symbol->st_shndx = sectionIndex;
1059 symbol->st_value = 0;
1060 symbol->st_other = ELF::STV_DEFAULT;
1061 if (const DefinedAtom *da = llvm::dyn_cast<const DefinedAtom>(atom)){
1062 symbol->st_size = da->size();
1063 lld::DefinedAtom::ContentType ct;
1064 switch (ct = da->contentType()){
1065 case DefinedAtom::typeCode:
1066 symbol->st_value = addr;
1067 type = ELF::STT_FUNC;
1068 break;
1069 case DefinedAtom::typeData:
1070 symbol->st_value = addr;
1071 type = ELF::STT_OBJECT;
1072 break;
1073 case DefinedAtom::typeZeroFill:
Michael J. Spencer28c65942013-01-07 07:05:52 +00001074 type = ELF::STT_OBJECT;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001075 symbol->st_value = addr;
1076 break;
1077 default:
1078 type = ELF::STT_NOTYPE;
1079 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001080 if (da->scope() == DefinedAtom::scopeTranslationUnit)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001081 binding = ELF::STB_LOCAL;
1082 else
1083 binding = ELF::STB_GLOBAL;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001084 } else if (const AbsoluteAtom *aa =
1085 llvm::dyn_cast<const AbsoluteAtom>(atom)){
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001086 type = ELF::STT_OBJECT;
1087 symbol->st_shndx = ELF::SHN_ABS;
1088 switch (aa->scope()) {
1089 case AbsoluteAtom::scopeLinkageUnit:
1090 symbol->st_other = ELF::STV_HIDDEN;
1091 binding = ELF::STB_LOCAL;
1092 break;
1093 case AbsoluteAtom::scopeTranslationUnit:
1094 binding = ELF::STB_LOCAL;
1095 break;
1096 case AbsoluteAtom::scopeGlobal:
1097 binding = ELF::STB_GLOBAL;
1098 break;
1099 }
1100 symbol->st_value = aa->value();
Michael J. Spencera2c97272013-01-04 21:09:21 +00001101 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001102 else {
1103 symbol->st_value = 0;
1104 type = ELF::STT_NOTYPE;
1105 binding = ELF::STB_WEAK;
1106 }
1107 symbol->setBindingAndType(binding, type);
1108 _symbolTable.push_back(symbol);
1109 this->_fsize += sizeof(Elf_Sym);
1110 }
1111
Michael J. Spencera2c97272013-01-04 21:09:21 +00001112 void setStringSection(
1113 ELFStringTable<target_endianness, max_align, is64Bits> *s) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001114 _stringSection = s;
1115 }
1116
1117 void finalize() {
1118 // sh_info should be one greater than last symbol with STB_LOCAL binding
1119 // we sort the symbol table to keep all local symbols at the beginning
1120 std::stable_sort(_symbolTable.begin(), _symbolTable.end(),
1121 [](const Elf_Sym *A, const Elf_Sym *B) {
1122 return A->getBinding() < B->getBinding();
Michael J. Spencera2c97272013-01-04 21:09:21 +00001123 });
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001124 uint16_t shInfo = 0;
1125 for (auto i : _symbolTable) {
1126 if (i->getBinding() != ELF::STB_LOCAL)
1127 break;
1128 shInfo++;
1129 }
1130 this->_shInfo = shInfo;
1131 this->setLink(_stringSection->ordinal());
1132 }
1133
Michael J. Spencera2c97272013-01-04 21:09:21 +00001134 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001135 OwningPtr<FileOutputBuffer> &buffer) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001136 uint8_t *chunkBuffer = buffer->getBufferStart();
1137 uint8_t *dest = chunkBuffer + this->fileOffset();
1138 for (auto sti : _symbolTable) {
1139 memcpy(dest, sti, sizeof(Elf_Sym));
1140 dest += sizeof(Elf_Sym);
1141 }
1142 }
1143
1144private:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001145 ELFStringTable<target_endianness, max_align, is64Bits> *_stringSection;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001146 std::vector<Elf_Sym*> _symbolTable;
1147 llvm::BumpPtrAllocator _symbolAllocate;
1148 int64_t _link;
1149};
1150
1151/// \brief An ELFHeader represents the Elf[32/64]_Ehdr structure at the
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001152/// start of an ELF executable file.
Michael J. Spencera2c97272013-01-04 21:09:21 +00001153template<support::endianness target_endianness,
1154 std::size_t max_align,
1155 bool is64Bits>
1156class ELFHeader : public Chunk<target_endianness, max_align, is64Bits> {
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001157public:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001158 typedef Elf_Ehdr_Impl<target_endianness, max_align, is64Bits> Elf_Ehdr;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001159
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001160 ELFHeader()
Michael J. Spencera2c97272013-01-04 21:09:21 +00001161 : Chunk<target_endianness, max_align, is64Bits>(
1162 "elfhdr", Chunk<target_endianness, max_align, is64Bits>::K_ELFHeader) {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001163 this->_align2 = is64Bits ? 8 : 4;
1164 this->_fsize = sizeof(Elf_Ehdr);
1165 this->_msize = sizeof(Elf_Ehdr);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001166 memset(_eh.e_ident, 0, llvm::ELF::EI_NIDENT);
1167 e_ident(ELF::EI_MAG0, 0x7f);
1168 e_ident(ELF::EI_MAG1, 'E');
1169 e_ident(ELF::EI_MAG2, 'L');
1170 e_ident(ELF::EI_MAG3, 'F');
1171 e_ehsize(sizeof(Elf_Ehdr));
1172 e_flags(2);
1173 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001174 void e_ident(int I, unsigned char C) { _eh.e_ident[I] = C; }
1175 void e_type(uint16_t type) { _eh.e_type = type; }
1176 void e_machine(uint16_t machine) { _eh.e_machine = machine; }
1177 void e_version(uint32_t version) { _eh.e_version = version; }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001178 void e_entry(int64_t entry) { _eh.e_entry = entry; }
1179 void e_phoff(int64_t phoff) { _eh.e_phoff = phoff; }
1180 void e_shoff(int64_t shoff) { _eh.e_shoff = shoff; }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001181 void e_flags(uint32_t flags) { _eh.e_flags = flags; }
1182 void e_ehsize(uint16_t ehsize) { _eh.e_ehsize = ehsize; }
1183 void e_phentsize(uint16_t phentsize) { _eh.e_phentsize = phentsize; }
1184 void e_phnum(uint16_t phnum) { _eh.e_phnum = phnum; }
1185 void e_shentsize(uint16_t shentsize) { _eh.e_shentsize = shentsize; }
1186 void e_shnum(uint16_t shnum) { _eh.e_shnum = shnum; }
1187 void e_shstrndx(uint16_t shstrndx) { _eh.e_shstrndx = shstrndx; }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001188 uint64_t fileSize() { return sizeof (Elf_Ehdr); }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001189
Michael J. Spencera2c97272013-01-04 21:09:21 +00001190 static inline bool classof(
1191 const Chunk<target_endianness, max_align, is64Bits> *c) {
1192 return c->Kind() ==
1193 Chunk<target_endianness, max_align, is64Bits>::K_ELFHeader;
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001194 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001195
Michael J. Spencera2c97272013-01-04 21:09:21 +00001196 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001197 OwningPtr<FileOutputBuffer> &buffer) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001198 uint8_t *chunkBuffer = buffer->getBufferStart();
1199 uint8_t *atomContent = chunkBuffer + this->fileOffset();
1200 memcpy(atomContent, &_eh, fileSize());
1201 }
1202
1203 void finalize() { }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001204
1205private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001206 Elf_Ehdr _eh;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001207};
1208
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001209/// \brief An ELFProgramHeader represents the Elf[32/64]_Phdr structure at the
1210/// start of an ELF executable file.
Michael J. Spencera2c97272013-01-04 21:09:21 +00001211template<support::endianness target_endianness,
1212 std::size_t max_align,
1213 bool is64Bits>
1214class ELFProgramHeader : public Chunk<target_endianness, max_align, is64Bits> {
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001215public:
Michael J. Spencerfd3981d2013-01-06 05:40:27 +00001216 typedef Elf_Phdr_Impl<target_endianness, max_align, is64Bits> Elf_Phdr;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001217
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001218 ELFProgramHeader()
Michael J. Spencera2c97272013-01-04 21:09:21 +00001219 : Chunk<target_endianness, max_align, is64Bits>(
1220 "elfphdr",
Reid Klecknere974bd12013-01-05 02:21:42 +00001221 Chunk<target_endianness, max_align, is64Bits>::K_ELFProgramHeader) {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001222 this->_align2 = is64Bits ? 8 : 4;
Reid Klecknere974bd12013-01-05 02:21:42 +00001223 resetProgramHeaders();
1224 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001225
Michael J. Spencera2c97272013-01-04 21:09:21 +00001226 bool addSegment(Segment<target_endianness, max_align, is64Bits> *segment) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001227 Elf_Phdr *phdr = nullptr;
1228 bool ret = false;
1229
Michael J. Spencera2c97272013-01-04 21:09:21 +00001230 for (auto sei = segment->slices_begin(), see = segment->slices_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001231 sei != see; ++sei) {
1232 if (_phi == _ph.end()) {
1233 phdr = new(_allocator.Allocate<Elf_Phdr>()) Elf_Phdr;
1234 _ph.push_back(phdr);
1235 _phi = _ph.end();
1236 ret = true;
1237 } else {
1238 phdr = (*_phi);
1239 ++_phi;
1240 }
1241 phdr->p_type = segment->segmentType();
1242 phdr->p_offset = (*sei)->fileOffset();
1243 phdr->p_vaddr = (*sei)->virtualAddr();
1244 phdr->p_paddr = (*sei)->virtualAddr();
1245 phdr->p_filesz = (*sei)->fileSize();
1246 phdr->p_memsz = (*sei)->memSize();
1247 phdr->p_flags = segment->flags();
Michael J. Spencera2c97272013-01-04 21:09:21 +00001248 phdr->p_align = (phdr->p_type == llvm::ELF::PT_LOAD) ?
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001249 segment->pageSize() : (*sei)->align2();
1250 }
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001251
1252 this->_fsize = fileSize();
1253 this->_msize = this->_fsize;
1254
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001255 return ret;
1256 }
1257
1258 void resetProgramHeaders() {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001259 _phi = _ph.begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001260 }
1261
Michael J. Spencera2c97272013-01-04 21:09:21 +00001262 uint64_t fileSize() {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001263 return sizeof(Elf_Phdr) * _ph.size();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001264 }
1265
Michael J. Spencera2c97272013-01-04 21:09:21 +00001266 static inline bool classof(
1267 const Chunk<target_endianness, max_align, is64Bits> *c) {
1268 return c->Kind() ==
1269 Chunk<target_endianness, max_align, is64Bits>::K_ELFProgramHeader;
1270 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001271
Michael J. Spencera2c97272013-01-04 21:09:21 +00001272 void write(ELFWriter *writer,
1273 OwningPtr<FileOutputBuffer> &buffer) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001274 uint8_t *chunkBuffer = buffer->getBufferStart();
1275 uint8_t *dest = chunkBuffer + this->fileOffset();
1276 for (auto phi : _ph) {
1277 memcpy(dest, phi, sizeof(Elf_Phdr));
1278 dest += sizeof(Elf_Phdr);
1279 }
1280 }
1281
1282 void finalize() { }
1283
Michael J. Spencera2c97272013-01-04 21:09:21 +00001284 int64_t entsize() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001285 return sizeof(Elf_Phdr);
1286 }
1287
1288 int64_t numHeaders() {
1289 return _ph.size();
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001290 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001291
1292private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001293 std::vector<Elf_Phdr *> _ph;
1294 typedef typename std::vector<Elf_Phdr *>::iterator ph_iter;
1295 ph_iter _phi;
1296 llvm::BumpPtrAllocator _allocator;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001297};
1298
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001299/// \brief An ELFSectionHeader represents the Elf[32/64]_Shdr structure
1300/// at the end of the file
Michael J. Spencera2c97272013-01-04 21:09:21 +00001301template<support::endianness target_endianness,
1302 std::size_t max_align,
1303 bool is64Bits>
1304class ELFSectionHeader : public Chunk<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001305public:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001306 typedef Elf_Shdr_Impl<target_endianness, max_align, is64Bits> Elf_Shdr;
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001307
Michael J. Spencera2c97272013-01-04 21:09:21 +00001308 ELFSectionHeader(int32_t order)
1309 : Chunk<target_endianness, max_align, is64Bits>(
1310 "shdr",
1311 Chunk<target_endianness, max_align, is64Bits>::K_ELFSectionHeader) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001312 this->_fsize = 0;
1313 this->_align2 = 8;
1314 this->setOrder(order);
1315 // The first element in the list is always NULL
1316 Elf_Shdr *nullshdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
1317 ::memset(nullshdr, 0, sizeof (Elf_Shdr));
1318 _sectionInfo.push_back(nullshdr);
1319 this->_fsize += sizeof (Elf_Shdr);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001320 }
1321
Michael J. Spencera2c97272013-01-04 21:09:21 +00001322 uint16_t fileSize() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001323 return sizeof(Elf_Shdr) * _sectionInfo.size();
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001324 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001325
Michael J. Spencera2c97272013-01-04 21:09:21 +00001326 void appendSection(
1327 MergedSections<target_endianness, max_align, is64Bits> *section) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001328 Elf_Shdr *shdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
1329 shdr->sh_name = _stringSection->addString(section->name());
1330 shdr->sh_type = section->type();
1331 shdr->sh_flags = section->flags();
1332 shdr->sh_offset = section->fileOffset();
1333 shdr->sh_addr = section->virtualAddr();
1334 shdr->sh_size = section->memSize();
1335 shdr->sh_link = section->link();
1336 shdr->sh_info = section->shinfo();
1337 shdr->sh_addralign = section->align2();
1338 shdr->sh_entsize = section->entsize();
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001339 _sectionInfo.push_back(shdr);
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001340 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001341
Michael J. Spencera2c97272013-01-04 21:09:21 +00001342 void updateSection(Section<target_endianness, max_align, is64Bits> *section) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001343 Elf_Shdr *shdr = _sectionInfo[section->ordinal()];
1344 shdr->sh_type = section->type();
1345 shdr->sh_flags = section->flags();
1346 shdr->sh_offset = section->fileOffset();
1347 shdr->sh_addr = section->virtualAddr();
1348 shdr->sh_size = section->fileSize();
1349 shdr->sh_link = section->link();
1350 shdr->sh_info = section->shinfo();
1351 shdr->sh_addralign = section->align2();
1352 shdr->sh_entsize = section->entsize();
1353 }
1354
Michael J. Spencera2c97272013-01-04 21:09:21 +00001355 static inline bool classof(
1356 const Chunk<target_endianness, max_align, is64Bits> *c) {
1357 return c->getChunkKind() ==
1358 Chunk<target_endianness, max_align, is64Bits>::K_ELFSectionHeader;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001359 }
1360
Michael J. Spencera2c97272013-01-04 21:09:21 +00001361 void setStringSection(
1362 ELFStringTable<target_endianness, max_align, is64Bits> *s) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001363 _stringSection = s;
1364 }
1365
Michael J. Spencera2c97272013-01-04 21:09:21 +00001366 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001367 OwningPtr<FileOutputBuffer> &buffer) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001368 uint8_t *chunkBuffer = buffer->getBufferStart();
1369 uint8_t *dest = chunkBuffer + this->fileOffset();
1370 for (auto shi : _sectionInfo) {
1371 memcpy(dest, shi, sizeof(Elf_Shdr));
1372 dest += sizeof(Elf_Shdr);
1373 }
1374 _stringSection->write(writer, buffer);
1375 }
1376
1377 void finalize() { }
1378
Michael J. Spencera2c97272013-01-04 21:09:21 +00001379 int64_t entsize() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001380 return sizeof(Elf_Shdr);
1381 }
1382
1383 int64_t numHeaders() {
1384 return _sectionInfo.size();
1385 }
1386
1387private:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001388 ELFStringTable<target_endianness, max_align, is64Bits> *_stringSection;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001389 std::vector<Elf_Shdr*> _sectionInfo;
1390 llvm::BumpPtrAllocator _sectionAllocate;
1391};
1392
Michael J. Spencera2c97272013-01-04 21:09:21 +00001393/// \brief The DefaultELFLayout class is used by the Writer to arrange
1394/// sections and segments in the order determined by the target ELF
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001395/// format. The writer creates a single instance of the DefaultELFLayout
Michael J. Spencera2c97272013-01-04 21:09:21 +00001396/// class
1397template<support::endianness target_endianness,
1398 std::size_t max_align,
1399 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001400class DefaultELFLayout : public ELFLayout {
1401public:
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001402
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001403 // The order in which the sections appear in the output file
Michael J. Spencera2c97272013-01-04 21:09:21 +00001404 // If its determined, that the layout needs to change
1405 // just changing the order of enumerations would essentially
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001406 // change the layout in the output file
1407 enum DefaultSectionOrder {
1408 ORDER_NOT_DEFINED = 0,
1409 ORDER_INTERP,
1410 ORDER_NOTE,
1411 ORDER_HASH,
1412 ORDER_DYNAMIC_SYMBOLS,
1413 ORDER_DYNAMIC_STRINGS,
1414 ORDER_INIT,
1415 ORDER_TEXT,
1416 ORDER_PLT,
1417 ORDER_FINI,
1418 ORDER_RODATA,
1419 ORDER_EH_FRAME,
1420 ORDER_EH_FRAMEHDR,
1421 ORDER_CTORS,
1422 ORDER_DTORS,
1423 ORDER_DYNAMIC,
1424 ORDER_GOT,
1425 ORDER_GOT_PLT,
1426 ORDER_DATA,
1427 ORDER_BSS,
1428 ORDER_OTHER,
1429 ORDER_SECTION_STRINGS,
1430 ORDER_SYMBOL_TABLE,
1431 ORDER_STRING_TABLE,
1432 ORDER_SECTION_HEADERS
1433 };
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001434
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001435public:
1436
1437 // The Key used for creating Sections
Michael J. Spencera2c97272013-01-04 21:09:21 +00001438 // The sections are created using
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001439 // SectionName, [contentType, contentPermissions]
Michael J. Spencera2c97272013-01-04 21:09:21 +00001440 typedef std::pair<StringRef,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001441 std::pair<int32_t, int32_t>> Key;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001442 typedef typename std::vector<
1443 Chunk<target_endianness, max_align, is64Bits> *>::iterator ChunkIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001444 // The key used for Segments
Michael J. Spencera2c97272013-01-04 21:09:21 +00001445 // The segments are created using
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001446 // SegmentName, Segment flags
1447 typedef std::pair<StringRef, int64_t> SegmentKey;
1448 // Merged Sections contain the map of Sectionnames to a vector of sections,
1449 // that have been merged to form a single section
Michael J. Spencera2c97272013-01-04 21:09:21 +00001450 typedef std::map<StringRef, MergedSections<
1451 target_endianness, max_align, is64Bits> *> MergedSectionMapT;
1452 typedef typename std::vector<MergedSections<
1453 target_endianness, max_align, is64Bits> *>::iterator MergedSectionIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001454
1455 // HashKey for the Section
1456 class HashKey {
1457 public:
1458 int64_t operator() (const Key &k) const {
1459 // k.first = section Name
1460 // k.second = [contentType, Permissions]
1461 return llvm::hash_combine(k.first, k.second.first, k.second.second);
1462 }
1463 };
1464
1465 // HashKey for the Segment
1466 class SegmentHashKey {
1467 public:
1468 int64_t operator() (const SegmentKey &k) const {
1469 // k.first = SegmentName
1470 // k.second = SegmentFlags
1471 return llvm::hash_combine(k.first, k.second);
1472 }
1473 };
1474
Michael J. Spencera2c97272013-01-04 21:09:21 +00001475 typedef std::unordered_map<Key, Section<
1476 target_endianness, max_align, is64Bits>*, HashKey> SectionMapT;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001477 typedef std::unordered_map<SegmentKey,
Michael J. Spencera2c97272013-01-04 21:09:21 +00001478 Segment<target_endianness, max_align, is64Bits>*,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001479 SegmentHashKey> SegmentMapT;
1480
1481 DefaultELFLayout(const WriterOptionsELF &options):_options(options) { }
1482
1483 /// \brief Return the section order for a input section
1484 virtual SectionOrder getSectionOrder
1485 (const StringRef name,
1486 int32_t contentType,
1487 int32_t contentPermissions) {
1488 switch (contentType) {
1489 case DefinedAtom::typeCode:
1490 return llvm::StringSwitch<Reference::Kind>(name)
1491 .StartsWith(".eh_frame_hdr", ORDER_EH_FRAMEHDR)
1492 .StartsWith(".eh_frame", ORDER_EH_FRAME)
1493 .StartsWith(".init", ORDER_INIT)
1494 .StartsWith(".fini", ORDER_FINI)
1495 .StartsWith(".hash", ORDER_HASH)
1496 .Default(ORDER_TEXT);
1497
1498 case DefinedAtom::typeConstant:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001499 return ORDER_RODATA;
1500
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001501 case DefinedAtom::typeData:
1502 return ORDER_DATA;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001503
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001504 case DefinedAtom::typeZeroFill:
1505 return ORDER_BSS;
1506
1507 default:
1508 // If we get passed in a section push it to OTHER
Michael J. Spencera2c97272013-01-04 21:09:21 +00001509 if (contentPermissions == DefinedAtom::perm___)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001510 return ORDER_OTHER;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001511
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001512 return ORDER_NOT_DEFINED;
1513 }
1514 }
1515
1516 /// \brief This maps the input sections to the output section names
1517 StringRef getSectionName(const StringRef name,
1518 const int32_t contentType) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001519 if (contentType == DefinedAtom::typeZeroFill)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001520 return ".bss";
Michael J. Spencera2c97272013-01-04 21:09:21 +00001521 if (name.startswith(".text"))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001522 return ".text";
Michael J. Spencera2c97272013-01-04 21:09:21 +00001523 if (name.startswith(".rodata"))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001524 return ".rodata";
1525 return name;
1526 }
1527
1528 /// \brief Gets the segment for a output section
Michael J. Spencera2c97272013-01-04 21:09:21 +00001529 virtual ELFLayout::SegmentType getSegmentType(
1530 Section<target_endianness, max_align, is64Bits> *section) const {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001531 switch(section->order()) {
1532 case ORDER_INTERP:
1533 return llvm::ELF::PT_INTERP;
1534
1535 case ORDER_TEXT:
1536 case ORDER_HASH:
1537 case ORDER_DYNAMIC_SYMBOLS:
1538 case ORDER_DYNAMIC_STRINGS:
1539 case ORDER_INIT:
1540 case ORDER_PLT:
1541 case ORDER_FINI:
1542 case ORDER_RODATA:
1543 case ORDER_EH_FRAME:
1544 case ORDER_EH_FRAMEHDR:
1545 return llvm::ELF::PT_LOAD;
1546
1547 case ORDER_NOTE:
1548 return llvm::ELF::PT_NOTE;
1549
1550 case ORDER_DYNAMIC:
1551 return llvm::ELF::PT_DYNAMIC;
1552
1553 case ORDER_CTORS:
1554 case ORDER_DTORS:
1555 case ORDER_GOT:
1556 return llvm::ELF::PT_GNU_RELRO;
1557
1558 case ORDER_GOT_PLT:
1559 case ORDER_DATA:
1560 case ORDER_BSS:
1561 return llvm::ELF::PT_LOAD;
1562
1563 default:
1564 return llvm::ELF::PT_NULL;
1565 }
1566 }
1567
1568 /// \brief Returns true/false depending on whether the section has a Output
1569 // segment or not
Michael J. Spencera2c97272013-01-04 21:09:21 +00001570 static bool hasOutputSegment(Section<target_endianness, max_align,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001571 is64Bits> *section) {
1572 switch(section->order()) {
1573 case ORDER_INTERP:
1574 case ORDER_HASH:
1575 case ORDER_DYNAMIC_SYMBOLS:
1576 case ORDER_DYNAMIC_STRINGS:
1577 case ORDER_INIT:
1578 case ORDER_PLT:
1579 case ORDER_TEXT:
1580 case ORDER_FINI:
1581 case ORDER_RODATA:
1582 case ORDER_EH_FRAME:
1583 case ORDER_EH_FRAMEHDR:
1584 case ORDER_NOTE:
1585 case ORDER_DYNAMIC:
1586 case ORDER_CTORS:
1587 case ORDER_DTORS:
1588 case ORDER_GOT:
1589 case ORDER_GOT_PLT:
1590 case ORDER_DATA:
1591 case ORDER_BSS:
1592 return true;
1593
1594 default:
1595 return false;
1596 }
1597 }
1598
1599 // Adds an atom to the section
1600 virtual error_code addAtom(const Atom *atom) {
1601 const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom);
Michael J. Spencera2c97272013-01-04 21:09:21 +00001602 const StringRef sectionName =
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001603 getSectionName(definedAtom->customSectionName(),
1604 definedAtom->contentType());
Michael J. Spencera2c97272013-01-04 21:09:21 +00001605 const lld::DefinedAtom::ContentPermissions permissions =
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001606 definedAtom->permissions();
Michael J. Spencera2c97272013-01-04 21:09:21 +00001607 const lld::DefinedAtom::ContentType contentType =
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001608 definedAtom->contentType();
1609 const Key key(sectionName, std::make_pair(contentType, permissions));
Michael J. Spencera2c97272013-01-04 21:09:21 +00001610 const std::pair<Key, Section<target_endianness, max_align, is64Bits> *>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001611 currentSection(key, nullptr);
Michael J. Spencera2c97272013-01-04 21:09:21 +00001612 std::pair<typename SectionMapT::iterator, bool>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001613 sectionInsert(_sectionMap.insert(currentSection));
Michael J. Spencera2c97272013-01-04 21:09:21 +00001614 Section<target_endianness, max_align, is64Bits> *section;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001615 // the section is already in the map
1616 if (!sectionInsert.second) {
1617 section = sectionInsert.first->second;
1618 section->setContentPermissions(permissions);
1619 }
1620 else {
1621 SectionOrder section_order = getSectionOrder(sectionName,
1622 contentType,
1623 permissions);
1624 section = new (_allocator.Allocate
Michael J. Spencera2c97272013-01-04 21:09:21 +00001625 <Section<target_endianness, max_align, is64Bits>>())
1626 Section<target_endianness, max_align, is64Bits>
1627 (sectionName, contentType,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001628 permissions, section_order);
1629 sectionInsert.first->second = section;
1630 section->setOrder(section_order);
1631 _sections.push_back(section);
1632 }
1633 section->appendAtom(atom);
1634 return error_code::success();
1635 }
1636
1637 // Merge sections with the same name into a MergedSections
1638 void mergeSimiliarSections() {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001639 MergedSections<target_endianness, max_align, is64Bits> *mergedSection;
1640
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001641 for (auto &si : _sections) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001642 const std::pair<StringRef,
1643 MergedSections<target_endianness, max_align, is64Bits> *>
1644 currentMergedSections(si->name(), nullptr);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001645 std::pair<typename MergedSectionMapT::iterator, bool>
1646 mergedSectionInsert
1647 (_mergedSectionMap.insert(currentMergedSections));
1648 if (!mergedSectionInsert.second) {
1649 mergedSection = mergedSectionInsert.first->second;
1650 }
1651 else {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001652 mergedSection = new (_allocator.Allocate<
1653 MergedSections<target_endianness, max_align, is64Bits>>())
1654 MergedSections<target_endianness, max_align, is64Bits>(si->name());
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001655 _mergedSections.push_back(mergedSection);
1656 mergedSectionInsert.first->second = mergedSection;
1657 }
1658 mergedSection->appendSection(si);
1659 }
1660 }
1661
1662 void assignSectionsToSegments() {
1663 // sort the sections by their order as defined by the layout
1664 std::stable_sort(_sections.begin(), _sections.end(),
Michael J. Spencera2c97272013-01-04 21:09:21 +00001665 [](Chunk<target_endianness, max_align, is64Bits> *A,
1666 Chunk<target_endianness, max_align, is64Bits> *B) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001667 return A->order() < B->order();
1668 });
1669 // Merge all sections
1670 mergeSimiliarSections();
1671 // Set the ordinal after sorting the sections
1672 int ordinal = 1;
1673 for (auto &msi : _mergedSections) {
1674 (*msi).setOrdinal(ordinal);
1675 for (auto ai = (*msi).begin_sections(), ae = (*msi).end_sections();
1676 ai != ae; ++ai) {
1677 (*ai)->setOrdinal(ordinal);
1678 }
1679 ++ordinal;
1680 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001681 Section<target_endianness, max_align, is64Bits> *section;
1682 Segment<target_endianness, max_align, is64Bits> *segment;
1683 for (auto msi = merged_sections_begin(), mse = merged_sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001684 msi != mse; ++msi) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001685 for (auto ai = (*msi)->begin_sections(), ae = (*msi)->end_sections();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001686 ai != ae; ++ai) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001687 if ((*ai)->kind() ==
1688 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection) {
1689 section = llvm::dyn_cast<
1690 Section<target_endianness, max_align, is64Bits>>(*ai);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001691 if (!hasOutputSegment(section))
1692 continue;
1693 (*msi)->setHasSegment();
1694 section->setSegment(getSegmentType(section));
1695 const StringRef segmentName = section->segmentKindToStr();
1696 // Use the flags of the merged Section for the segment
1697 const SegmentKey key(segmentName, (*msi)->flags());
Michael J. Spencera2c97272013-01-04 21:09:21 +00001698 const std::pair<SegmentKey,
1699 Segment<target_endianness, max_align, is64Bits> *>
1700 currentSegment(key, nullptr);
1701 std::pair<typename SegmentMapT::iterator, bool>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001702 segmentInsert(_segmentMap.insert(currentSegment));
1703
1704 if (!segmentInsert.second) {
1705 segment = segmentInsert.first->second;
1706 } else {
1707 segment = new (_allocator.Allocate
Michael J. Spencera2c97272013-01-04 21:09:21 +00001708 <Segment<target_endianness, max_align, is64Bits>>())
1709 Segment<target_endianness, max_align, is64Bits>
1710 (segmentName, getSegmentType(section),
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001711 _options);
1712 segmentInsert.first->second = segment;
1713 _segments.push_back(segment);
1714 }
1715 segment->append(section);
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001716 }
1717 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001718 }
1719 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001720
Michael J. Spencera2c97272013-01-04 21:09:21 +00001721 void addSection(Chunk<target_endianness, max_align, is64Bits> *c) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001722 _sections.push_back(c);
1723 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001724
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001725 void assignFileOffsets() {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001726 std::sort(_segments.begin(),
1727 _segments.end(),
1728 Segment<target_endianness, max_align, is64Bits>::compareSegments);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001729 int ordinal = 0;
1730 // Compute the number of segments that might be needed, so that the
1731 // size of the program header can be computed
1732 uint64_t offset = 0;
1733 for (auto si : _segments) {
1734 si->setOrdinal(++ordinal);
1735 si->assignOffsets(offset);
1736 offset += si->fileSize();
1737 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001738 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001739
Michael J. Spencera2c97272013-01-04 21:09:21 +00001740 void setELFHeader(ELFHeader<target_endianness, max_align, is64Bits> *e) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001741 _elfHeader = e;
1742 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001743
Michael J. Spencera2c97272013-01-04 21:09:21 +00001744 void setProgramHeader(
1745 ELFProgramHeader<target_endianness, max_align, is64Bits> *p) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001746 _programHeader = p;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001747 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001748
1749 void assignVirtualAddress() {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001750 if (_segments.empty())
1751 return;
1752
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001753 uint64_t virtualAddress = _options.baseAddress();
1754
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001755 // HACK: This is a super dirty hack. The elf header and program header are
1756 // not part of a section, but we need them to be loaded at the base address
1757 // so that AT_PHDR is set correctly by the loader and so they are accessible
1758 // at runtime. To do this we simply prepend them to the first Segment and
1759 // let the layout logic take care of it.
1760 _segments[0]->prepend(_programHeader);
1761 _segments[0]->prepend(_elfHeader);
1762
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001763 bool newSegmentHeaderAdded = true;
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001764 while (true) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001765 for (auto si : _segments) {
1766 newSegmentHeaderAdded = _programHeader->addSegment(si);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001767 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001768 if (!newSegmentHeaderAdded)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001769 break;
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001770 uint64_t fileoffset = 0;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001771 uint64_t address = virtualAddress;
1772 // Fix the offsets after adding the program header
1773 for (auto &si : _segments) {
1774 // Align the segment to a page boundary
1775 fileoffset = llvm::RoundUpToAlignment(fileoffset, _options.pageSize());
1776 si->assignOffsets(fileoffset);
1777 fileoffset = si->fileOffset() + si->fileSize();
1778 }
1779 // start assigning virtual addresses
1780 for (auto si = _segments.begin(); si != _segments.end(); ++si) {
1781 (*si)->setVAddr(virtualAddress);
1782 // The first segment has the virtualAddress set to the base address as
1783 // we have added the file header and the program header dont align the
Michael J. Spencera2c97272013-01-04 21:09:21 +00001784 // first segment to the pagesize
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001785 (*si)->assignVirtualAddress(address);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001786 (*si)->setMemSize(address - virtualAddress);
1787 virtualAddress = llvm::RoundUpToAlignment(address, _options.pageSize());
1788 }
1789 _programHeader->resetProgramHeaders();
1790 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001791 Section<target_endianness, max_align, is64Bits> *section;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001792 // Fix the offsets of all the atoms within a section
1793 for (auto &si : _sections) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001794 section =
1795 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(si);
1796 if (section &&
1797 DefaultELFLayout<target_endianness,
1798 max_align, is64Bits>::hasOutputSegment(section))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001799 section->assignOffsets(section->fileOffset());
1800 }
1801 // Set the size of the merged Sections
Michael J. Spencera2c97272013-01-04 21:09:21 +00001802 for (auto msi = merged_sections_begin(), mse = merged_sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001803 msi != mse; ++msi) {
1804 uint64_t sectionfileoffset = 0;
1805 uint64_t startFileOffset = 0;
1806 uint64_t sectionsize = 0;
1807 bool isFirstSection = true;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001808 for (auto si = (*msi)->begin_sections(); si != (*msi)->end_sections();
1809 ++si) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001810 if (isFirstSection) {
1811 startFileOffset = (*si)->fileOffset();
1812 isFirstSection = false;
1813 }
1814 sectionfileoffset = (*si)->fileOffset();
1815 sectionsize = (*si)->fileSize();
1816 }
1817 sectionsize = (sectionfileoffset - startFileOffset) + sectionsize;
1818 (*msi)->setFileOffset(startFileOffset);
1819 (*msi)->setSize(sectionsize);
1820 }
1821 // Set the virtual addr of the merged Sections
Michael J. Spencera2c97272013-01-04 21:09:21 +00001822 for (auto msi = merged_sections_begin(), mse = merged_sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001823 msi != mse; ++msi) {
1824 uint64_t sectionstartaddr = 0;
1825 uint64_t startaddr = 0;
1826 uint64_t sectionsize = 0;
1827 bool isFirstSection = true;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001828 for (auto si = (*msi)->begin_sections(), se = (*msi)->end_sections();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001829 si != se; ++si) {
1830 if (isFirstSection) {
1831 startaddr = (*si)->virtualAddr();
1832 isFirstSection = false;
1833 }
1834 sectionstartaddr = (*si)->virtualAddr();
1835 sectionsize = (*si)->memSize();
1836 }
1837 sectionsize = (sectionstartaddr - startaddr) + sectionsize;
1838 (*msi)->setMemSize(sectionsize);
1839 (*msi)->setAddr(startaddr);
1840 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001841 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001842
1843 void assignOffsetsForMiscSections() {
1844 uint64_t fileoffset = 0;
1845 uint64_t size = 0;
1846 for (auto si : _segments) {
1847 fileoffset = si->fileOffset();
1848 size = si->fileSize();
1849 }
1850 fileoffset = fileoffset + size;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001851 Section<target_endianness, max_align, is64Bits> *section;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001852 for (auto si : _sections) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001853 section =
1854 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(si);
1855 if (section &&
1856 DefaultELFLayout<target_endianness,
1857 max_align, is64Bits>::hasOutputSegment(section))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001858 continue;
1859 fileoffset = llvm::RoundUpToAlignment(fileoffset, si->align2());
1860 si->setFileOffset(fileoffset);
1861 si->setVAddr(0);
1862 fileoffset += si->fileSize();
1863 }
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001864 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001865
1866 void finalize() {
1867 for (auto &si : _sections) {
1868 si->finalize();
1869 }
1870 }
1871
1872 bool findAtomAddrByName(const StringRef name, uint64_t &addr) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001873 Section<target_endianness, max_align, is64Bits> *section;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001874 for (auto ai = _sections.begin(); ai != _sections.end(); ++ai) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001875 if ((*ai)->kind() ==
1876 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection) {
1877 section =
1878 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(*ai);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001879 if (section->findAtomAddrByName(name, addr))
1880 return true;
1881 }
1882 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001883 return false;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001884 }
1885
Michael J. Spencera2c97272013-01-04 21:09:21 +00001886 MergedSectionIter merged_sections_begin() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001887 return _mergedSections.begin();
1888 }
1889
Michael J. Spencera2c97272013-01-04 21:09:21 +00001890 MergedSectionIter merged_sections_end() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001891 return _mergedSections.end();
1892 }
1893
1894 ChunkIter sections_begin() {
1895 return _sections.begin();
1896 }
1897 ChunkIter sections_end() {
1898 return _sections.end();
1899 }
1900
1901 ChunkIter segments_begin() {
1902 return _segments.begin();
1903 }
1904
1905 ChunkIter segments_end() {
1906 return _segments.end();
1907 }
1908
Michael J. Spencera2c97272013-01-04 21:09:21 +00001909 ELFHeader<target_endianness, max_align, is64Bits> *elfHeader() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001910 return _elfHeader;
1911 }
1912
Michael J. Spencera2c97272013-01-04 21:09:21 +00001913 ELFProgramHeader<target_endianness, max_align, is64Bits> *elfProgramHeader() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001914 return _programHeader;
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001915 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001916
1917private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001918 SectionMapT _sectionMap;
1919 MergedSectionMapT _mergedSectionMap;
1920 SegmentMapT _segmentMap;
Sid Manningdd110202012-09-25 18:22:09 +00001921
Michael J. Spencera2c97272013-01-04 21:09:21 +00001922 std::vector<Chunk<target_endianness, max_align, is64Bits> *> _sections;
1923 std::vector<Segment<target_endianness, max_align, is64Bits> *> _segments;
1924 std::vector<MergedSections<target_endianness, max_align, is64Bits> *>
1925 _mergedSections;
1926 ELFHeader<target_endianness, max_align, is64Bits> *_elfHeader;
1927 ELFProgramHeader<target_endianness, max_align, is64Bits> *_programHeader;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001928 llvm::BumpPtrAllocator _allocator;
1929 const WriterOptionsELF &_options;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001930};
1931
1932//===----------------------------------------------------------------------===//
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001933// ELFExecutableWriter Class
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001934//===----------------------------------------------------------------------===//
Michael J. Spencera2c97272013-01-04 21:09:21 +00001935template<support::endianness target_endianness,
1936 std::size_t max_align,
1937 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001938class ELFExecutableWriter : public ELFWriter {
1939public:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001940 typedef Elf_Shdr_Impl<target_endianness, max_align, is64Bits> Elf_Shdr;
1941 typedef Elf_Sym_Impl<target_endianness, max_align, is64Bits> Elf_Sym;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001942
1943 ELFExecutableWriter(const WriterOptionsELF &options);
1944
1945private:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001946 // build the sections that need to be created
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001947 void buildChunks(const lld::File &file);
1948 virtual error_code writeFile(const lld::File &File, StringRef path);
1949 void buildAtomToAddressMap();
1950 void buildSymbolTable ();
1951 void buildSectionHeaderTable();
1952 void assignSectionsWithNoSegments();
1953 void addAbsoluteUndefinedSymbols(const lld::File &File);
1954
Michael J. Spencera2c97272013-01-04 21:09:21 +00001955 uint64_t addressOfAtom(const Atom *atom) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001956 return _atomToAddressMap[atom];
1957 }
1958
1959 KindHandler *kindHandler() { return _referenceKindHandler.get(); }
1960
1961 void createDefaultSections();
1962
1963 const WriterOptionsELF &_options;
1964
1965 typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
1966 std::unique_ptr<KindHandler> _referenceKindHandler;
1967 AtomToAddress _atomToAddressMap;
1968 llvm::BumpPtrAllocator _chunkAllocate;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001969 DefaultELFLayout<target_endianness, max_align, is64Bits> *_layout;
1970 ELFHeader<target_endianness, max_align, is64Bits> *_elfHeader;
1971 ELFProgramHeader<target_endianness, max_align, is64Bits> *_programHeader;
1972 ELFSymbolTable<target_endianness, max_align, is64Bits> * _symtab;
1973 ELFStringTable<target_endianness, max_align, is64Bits> *_strtab;
1974 ELFStringTable<target_endianness, max_align, is64Bits> *_shstrtab;
1975 ELFSectionHeader<target_endianness, max_align, is64Bits> *_shdrtab;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001976};
1977
1978//===----------------------------------------------------------------------===//
1979// ELFExecutableWriter
1980//===----------------------------------------------------------------------===//
Michael J. Spencera2c97272013-01-04 21:09:21 +00001981template<support::endianness target_endianness,
1982 std::size_t max_align,
1983 bool is64Bits>
1984ELFExecutableWriter<target_endianness, max_align, is64Bits>
1985 ::ELFExecutableWriter(const WriterOptionsELF &options)
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001986 : _options(options)
Sid Manning42064e52012-10-09 02:20:47 +00001987 , _referenceKindHandler(KindHandler::makeHandler(_options.machine(),
Michael J. Spencera2c97272013-01-04 21:09:21 +00001988 target_endianness)) {
1989 _layout =
1990 new DefaultELFLayout<target_endianness, max_align, is64Bits>(options);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001991}
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001992
Michael J. Spencera2c97272013-01-04 21:09:21 +00001993template<support::endianness target_endianness,
1994 std::size_t max_align,
1995 bool is64Bits>
1996void ELFExecutableWriter<target_endianness, max_align, is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001997 ::buildChunks(const lld::File &file){
1998 for (const DefinedAtom *definedAtom : file.defined() ) {
1999 _layout->addAtom(definedAtom);
2000 }
2001}
2002
Michael J. Spencera2c97272013-01-04 21:09:21 +00002003template<support::endianness target_endianness,
2004 std::size_t max_align,
2005 bool is64Bits>
2006void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2007 ::buildSymbolTable () {
2008 Section<target_endianness, max_align, is64Bits> *section;
2009 for (auto si = _layout->sections_begin(); si != _layout->sections_end();
2010 ++si) {
2011 if ((*si)->kind() !=
2012 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002013 continue;
Michael J. Spencera2c97272013-01-04 21:09:21 +00002014 section =
2015 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(*si);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002016 for (auto ai = section->atoms_begin(); ai != section->atoms_end(); ++ai) {
2017 _symtab->addSymbol(ai->first, section->ordinal(), ai->second.second);
Hemant Kulkarni736f7fb2012-11-21 21:07:36 +00002018 }
2019 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002020}
2021
Michael J. Spencera2c97272013-01-04 21:09:21 +00002022template<support::endianness target_endianness,
2023 std::size_t max_align,
2024 bool is64Bits>
2025void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2026 ::addAbsoluteUndefinedSymbols(const lld::File &file) {
Hemant Kulkarni08e410292012-10-01 23:53:20 +00002027 for (const UndefinedAtom *a : file.undefined()) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002028 _symtab->addSymbol(a, ELF::SHN_UNDEF);
Hemant Kulkarni08e410292012-10-01 23:53:20 +00002029 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00002030
Hemant Kulkarni08e410292012-10-01 23:53:20 +00002031 for (const AbsoluteAtom *a : file.absolute()) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002032 _symtab->addSymbol(a, ELF::SHN_ABS);
Hemant Kulkarni08e410292012-10-01 23:53:20 +00002033 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002034}
2035
Michael J. Spencera2c97272013-01-04 21:09:21 +00002036template<support::endianness target_endianness,
2037 std::size_t max_align,
2038 bool is64Bits>
2039void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2040 ::buildAtomToAddressMap () {
2041 Section<target_endianness, max_align, is64Bits> *section;
2042 for (auto si = _layout->sections_begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002043 si != _layout->sections_end(); ++si) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002044 if ((*si)->kind() !=
2045 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002046 continue;
Michael J. Spencera2c97272013-01-04 21:09:21 +00002047 section =
2048 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(*si);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002049 for (auto ai = section->atoms_begin(); ai != section->atoms_end(); ++ai) {
2050 _atomToAddressMap[ai->first] = (ai)->second.second;
Sid Manningdd110202012-09-25 18:22:09 +00002051 }
2052 }
Sid Manningdd110202012-09-25 18:22:09 +00002053}
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002054
Michael J. Spencera2c97272013-01-04 21:09:21 +00002055template<support::endianness target_endianness,
2056 std::size_t max_align,
2057 bool is64Bits>
2058void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2059 ::buildSectionHeaderTable() {
2060 for (auto msi = _layout->merged_sections_begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002061 msi != _layout->merged_sections_end(); ++msi) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002062 if ((*msi)->kind() !=
2063 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002064 continue;
2065 if ((*msi)->hasSegment())
2066 _shdrtab->appendSection(*msi);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002067 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002068}
2069
Michael J. Spencera2c97272013-01-04 21:09:21 +00002070template<support::endianness target_endianness,
2071 std::size_t max_align,
2072 bool is64Bits>
2073void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2074 ::assignSectionsWithNoSegments() {
2075 Section<target_endianness, max_align, is64Bits> *section;
2076 for (auto msi = _layout->merged_sections_begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002077 msi != _layout->merged_sections_end(); ++msi) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002078 if ((*msi)->kind() !=
2079 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002080 continue;
2081 if (!(*msi)->hasSegment())
2082 _shdrtab->appendSection(*msi);
2083 }
2084 _layout->assignOffsetsForMiscSections();
Michael J. Spencera2c97272013-01-04 21:09:21 +00002085 for (auto si = _layout->sections_begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002086 si != _layout->sections_end(); ++si) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002087 if ((*si)->kind() !=
2088 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002089 continue;
Michael J. Spencera2c97272013-01-04 21:09:21 +00002090 section =
2091 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(*si);
2092 if (!DefaultELFLayout<target_endianness, max_align, is64Bits>
2093 ::hasOutputSegment(section))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002094 _shdrtab->updateSection(section);
2095 }
2096}
2097
Michael J. Spencera2c97272013-01-04 21:09:21 +00002098template<support::endianness target_endianness,
2099 std::size_t max_align,
2100 bool is64Bits>
2101error_code ELFExecutableWriter<target_endianness, max_align, is64Bits>
2102 ::writeFile(const lld::File &file, StringRef path) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002103 buildChunks(file);
2104 // Create the default sections like the symbol table, string table, and the
2105 // section string table
2106 createDefaultSections();
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002107
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002108 // Set the Layout
2109 _layout->assignSectionsToSegments();
2110 _layout->assignFileOffsets();
2111 _layout->assignVirtualAddress();
2112
2113 // Build the Atom To Address map for applying relocations
2114 buildAtomToAddressMap();
2115
2116 // Create symbol table and section string table
2117 buildSymbolTable();
2118
2119 // add other symbols
2120 addAbsoluteUndefinedSymbols(file);
2121
2122 // Finalize the layout by calling the finalize() functions
2123 _layout->finalize();
2124
2125 // build Section Header table
2126 buildSectionHeaderTable();
2127
2128 // assign Offsets and virtual addresses
2129 // for sections with no segments
2130 assignSectionsWithNoSegments();
2131
2132 uint64_t totalSize = _shdrtab->fileOffset() + _shdrtab->fileSize();
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002133
2134 OwningPtr<FileOutputBuffer> buffer;
2135 error_code ec = FileOutputBuffer::create(path,
2136 totalSize, buffer,
2137 FileOutputBuffer::F_executable);
2138 if (ec)
2139 return ec;
2140
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002141 _elfHeader->e_ident(ELF::EI_CLASS, (_options.is64Bit() ? ELF::ELFCLASS64
2142 : ELF::ELFCLASS32));
Michael J. Spencera2c97272013-01-04 21:09:21 +00002143 _elfHeader->e_ident(ELF::EI_DATA, _options.endianness() == llvm::support::big
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002144 ? ELF::ELFDATA2MSB : ELF::ELFDATA2LSB);
2145 _elfHeader->e_ident(ELF::EI_VERSION, 1);
2146 _elfHeader->e_ident(ELF::EI_OSABI, 0);
2147 _elfHeader->e_type(_options.type());
2148 _elfHeader->e_machine(_options.machine());
2149 _elfHeader->e_version(1);
2150 _elfHeader->e_entry(0ULL);
2151 _elfHeader->e_phoff(_programHeader->fileOffset());
2152 _elfHeader->e_shoff(_shdrtab->fileOffset());
2153 _elfHeader->e_phentsize(_programHeader->entsize());
2154 _elfHeader->e_phnum(_programHeader->numHeaders());
2155 _elfHeader->e_shentsize(_shdrtab->entsize());
2156 _elfHeader->e_shnum(_shdrtab->numHeaders());
2157 _elfHeader->e_shstrndx(_shstrtab->ordinal());
2158 uint64_t virtualAddr = 0;
2159 _layout->findAtomAddrByName("_start", virtualAddr);
2160 _elfHeader->e_entry(virtualAddr);
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00002161
2162 // HACK: We have to write out the header and program header here even though
2163 // they are a member of a segment because only sections are written in the
2164 // following loop.
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002165 _elfHeader->write(this, buffer);
2166 _programHeader->write(this, buffer);
2167
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00002168 for (auto si = _layout->sections_begin(); si != _layout->sections_end(); ++si)
2169 (*si)->write(this, buffer);
2170
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002171 return buffer->commit();
2172}
Nick Kledzikabb69812012-05-31 22:34:00 +00002173
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 ::createDefaultSections() {
2179 _elfHeader =
2180 new ELFHeader<target_endianness, max_align, is64Bits>();
2181 _programHeader =
2182 new ELFProgramHeader<target_endianness, max_align, is64Bits>();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002183 _layout->setELFHeader(_elfHeader);
2184 _layout->setProgramHeader(_programHeader);
2185
Michael J. Spencera2c97272013-01-04 21:09:21 +00002186 _symtab = new ELFSymbolTable<target_endianness, max_align, is64Bits>(
2187 ".symtab",
2188 DefaultELFLayout<target_endianness, max_align, is64Bits>
2189 ::ORDER_SYMBOL_TABLE);
2190 _strtab = new ELFStringTable<target_endianness, max_align, is64Bits>(
2191 ".strtab",
2192 DefaultELFLayout<target_endianness, max_align, is64Bits>
2193 ::ORDER_STRING_TABLE);
2194 _shstrtab = new ELFStringTable<target_endianness, max_align, is64Bits>(
2195 ".shstrtab",
2196 DefaultELFLayout<target_endianness, max_align, is64Bits>
2197 ::ORDER_SECTION_STRINGS);
2198 _shdrtab = new ELFSectionHeader<target_endianness, max_align, is64Bits>(
2199 DefaultELFLayout<target_endianness, max_align, is64Bits>
2200 ::ORDER_SECTION_HEADERS);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002201 _layout->addSection(_symtab);
2202 _layout->addSection(_strtab);
2203 _layout->addSection(_shstrtab);
2204 _shdrtab->setStringSection(_shstrtab);
2205 _symtab->setStringSection(_strtab);
2206 _layout->addSection(_shdrtab);
Sid Manningdd110202012-09-25 18:22:09 +00002207}
Nick Kledzikabb69812012-05-31 22:34:00 +00002208} // namespace elf
2209
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002210Writer *createWriterELF(const WriterOptionsELF &options) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002211 // Set the default layout to be the static executable layout
Michael J. Spencera2c97272013-01-04 21:09:21 +00002212 // We would set the layout to a dynamic executable layout
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002213 // if we came across any shared libraries in the process
Michael J. Spencera2c97272013-01-04 21:09:21 +00002214
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002215 if (!options.is64Bit() && options.endianness() == llvm::support::little)
Michael J. Spencera2c97272013-01-04 21:09:21 +00002216 return new elf::ELFExecutableWriter<support::little, 4, false>(options);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002217 else if (options.is64Bit() && options.endianness() == llvm::support::little)
Michael J. Spencera2c97272013-01-04 21:09:21 +00002218 return new elf::ELFExecutableWriter<support::little, 8, true>(options);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002219 else if (!options.is64Bit() && options.endianness() == llvm::support::big)
Michael J. Spencera2c97272013-01-04 21:09:21 +00002220 return new elf::ELFExecutableWriter<support::big, 4, false>(options);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002221 else if (options.is64Bit() && options.endianness() == llvm::support::big)
Michael J. Spencera2c97272013-01-04 21:09:21 +00002222 return new elf::ELFExecutableWriter<support::big, 8, true>(options);
Nick Kledzikabb69812012-05-31 22:34:00 +00002223
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002224 llvm_unreachable("Invalid Options!");
Nick Kledzikabb69812012-05-31 22:34:00 +00002225}
Nick Kledzikabb69812012-05-31 22:34:00 +00002226} // namespace lld