blob: 580984c0820a560f3074f7806b3a432ac94a3465 [file] [log] [blame]
Nick Kledzikabb69812012-05-31 22:34:00 +00001//===- lib/ReaderWriter/ELF/WriterELF.cpp ---------------------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lld/ReaderWriter/WriterELF.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000011#include "ReferenceKinds.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000012
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000013#include "lld/Core/DefinedAtom.h"
14#include "lld/Core/File.h"
15#include "lld/Core/InputFiles.h"
16#include "lld/Core/Reference.h"
17#include "lld/Core/SharedLibraryAtom.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000018#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/DenseMap.h"
Shankar Easwaran495d38b2012-12-27 02:26:30 +000020#include "llvm/ADT/Hashing.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000021#include "llvm/ADT/OwningPtr.h"
22#include "llvm/ADT/SmallVector.h"
Shankar Easwaran495d38b2012-12-27 02:26:30 +000023#include "llvm/ADT/StringExtras.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000024#include "llvm/ADT/StringMap.h"
25#include "llvm/ADT/StringRef.h"
Shankar Easwaran495d38b2012-12-27 02:26:30 +000026#include "llvm/ADT/StringSwitch.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000027#include "llvm/Object/ELF.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000028#include "llvm/Support/Allocator.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000029#include "llvm/Support/Debug.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000030#include "llvm/Support/ELF.h"
31#include "llvm/Support/ErrorHandling.h"
32#include "llvm/Support/FileOutputBuffer.h"
33#include "llvm/Support/Format.h"
34#include "llvm/Support/MathExtras.h"
35#include "llvm/Support/raw_ostream.h"
36#include "llvm/Support/system_error.h"
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +000037#include "ExecutableAtoms.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000038
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000039#include <map>
Shankar Easwaran495d38b2012-12-27 02:26:30 +000040#include <unordered_map>
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000041#include <tuple>
42#include <vector>
Nick Kledzikabb69812012-05-31 22:34:00 +000043
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000044using namespace llvm;
45using namespace llvm::object;
Nick Kledzikabb69812012-05-31 22:34:00 +000046namespace lld {
47namespace elf {
Michael J. Spencera2c97272013-01-04 21:09:21 +000048template<support::endianness target_endianness,
49 std::size_t max_align,
50 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +000051class ELFExecutableWriter;
Hemant Kulkarni87dbac02012-11-13 21:34:45 +000052
Shankar Easwaran495d38b2012-12-27 02:26:30 +000053/// \brief The ELFWriter class is a base class for the linker to write
54/// various kinds of ELF files.
55class ELFWriter : public Writer {
Michael J. Spencera2c97272013-01-04 21:09:21 +000056public:
57 ELFWriter() { }
Shankar Easwaran495d38b2012-12-27 02:26:30 +000058
Michael J. Spencera2c97272013-01-04 21:09:21 +000059public:
60 /// \brief builds the chunks that needs to be written to the output
61 /// ELF file
62 virtual void buildChunks(const lld::File &file) = 0;
Shankar Easwaran495d38b2012-12-27 02:26:30 +000063
Michael J. Spencera2c97272013-01-04 21:09:21 +000064 /// \brief Writes the chunks into the output file specified by path
65 virtual error_code writeFile(const lld::File &File, StringRef path) = 0;
Shankar Easwaran495d38b2012-12-27 02:26:30 +000066
Michael J. Spencer37568522013-01-11 22:39:56 +000067 /// \brief Get the virtual address of \p atom after layout.
Michael J. Spencera2c97272013-01-04 21:09:21 +000068 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
Michael J. Spencer4ffbd602013-01-11 22:39:44 +0000206struct AtomLayout {
207 AtomLayout(const Atom *a, uint64_t fileOff, uint64_t virAddr)
208 : _atom(a), _fileOffset(fileOff), _virtualAddr(virAddr) {}
209
210 AtomLayout()
211 : _atom(nullptr), _fileOffset(0), _virtualAddr(0) {}
212
213 const Atom *_atom;
214 uint64_t _fileOffset;
215 uint64_t _virtualAddr;
216};
217
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000218/// \brief A section contains a set of atoms that have similiar properties
219/// The atoms that have similiar properties are merged to form a section
Michael J. Spencera2c97272013-01-04 21:09:21 +0000220template<support::endianness target_endianness,
221 std::size_t max_align,
222 bool is64Bits>
223class Section : public Chunk<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000224public:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000225 // The Kind of section that the object represents
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000226 enum SectionKind {
227 K_Default,
228 K_SymbolTable,
229 K_StringTable,
230 };
231 // Create a section object, the section is set to the default type if the
232 // caller doesnot set it
Michael J. Spencera2c97272013-01-04 21:09:21 +0000233 Section(const StringRef sectionName,
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000234 const int32_t contentType,
235 const int32_t contentPermissions,
236 const int32_t order,
Michael J. Spencera2c97272013-01-04 21:09:21 +0000237 const SectionKind kind = K_Default)
238 : Chunk<target_endianness, max_align, is64Bits>(
239 sectionName, Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000240 , _contentType(contentType)
241 , _contentPermissions(contentPermissions)
242 , _sectionKind(kind)
243 , _entSize(0)
244 , _shInfo(0)
245 , _link(0) {
246 this->setOrder(order);
247 }
248
249 /// return the section kind
250 SectionKind sectionKind() const {
251 return _sectionKind;
252 }
253
254 /// Align the offset to the required modulus defined by the atom alignment
255 uint64_t alignOffset(uint64_t offset, DefinedAtom::Alignment &atomAlign) {
256 uint64_t requiredModulus = atomAlign.modulus;
257 uint64_t align2 = 1u << atomAlign.powerOf2;
258 uint64_t currentModulus = (offset % align2);
259 uint64_t retOffset = offset;
260 if (currentModulus != requiredModulus) {
261 if (requiredModulus > currentModulus)
262 retOffset += requiredModulus - currentModulus;
263 else
264 retOffset += align2 + requiredModulus - currentModulus;
265 }
266 return retOffset;
267 }
268
Michael J. Spencera2c97272013-01-04 21:09:21 +0000269 // \brief Append an atom to a Section. The atom gets pushed into a vector
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000270 // contains the atom, the atom file offset, the atom virtual address
271 // the atom file offset is aligned appropriately as set by the Reader
272 void appendAtom(const Atom *atom) {
273 Atom::Definition atomType = atom->definition();
Michael J. Spencer7fe77f82013-01-15 06:55:11 +0000274 const DefinedAtom *definedAtom = cast<DefinedAtom>(atom);
275
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000276 DefinedAtom::Alignment atomAlign = definedAtom->alignment();
277 uint64_t align2 = 1u << atomAlign.powerOf2;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000278 // Align the atom to the required modulus/ align the file offset and the
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000279 // memory offset seperately this is required so that BSS symbols are handled
280 // properly as the BSS symbols only occupy memory size and not file size
281 uint64_t fOffset = alignOffset(this->fileSize(), atomAlign);
282 uint64_t mOffset = alignOffset(this->memSize(), atomAlign);
283 switch (atomType) {
284 case Atom::definitionRegular:
285 switch(definedAtom->contentType()) {
286 case DefinedAtom::typeCode:
287 case DefinedAtom::typeData:
Michael J. Spencer8de83642013-01-07 08:00:42 +0000288 case DefinedAtom::typeConstant:
Michael J. Spencer4ffbd602013-01-11 22:39:44 +0000289 _atoms.push_back(AtomLayout(atom, fOffset, 0));
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000290 this->_fsize = fOffset + definedAtom->size();
291 this->_msize = mOffset + definedAtom->size();
292 break;
293 case DefinedAtom::typeZeroFill:
Michael J. Spencer4ffbd602013-01-11 22:39:44 +0000294 _atoms.push_back(AtomLayout(atom, mOffset, 0));
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000295 this->_msize = mOffset + definedAtom->size();
296 break;
297 default:
298 this->_fsize = fOffset + definedAtom->size();
299 this->_msize = mOffset + definedAtom->size();
300 break;
301 }
302 break;
303 default:
304 llvm_unreachable("Expecting only definedAtoms being passed here");
305 break;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000306 }
307 // Set the section alignment to the largest alignment
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000308 // std::max doesnot support uint64_t
Michael J. Spencera2c97272013-01-04 21:09:21 +0000309 if (this->_align2 < align2)
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000310 this->_align2 = align2;
311 }
312
Michael J. Spencera2c97272013-01-04 21:09:21 +0000313 /// \brief Set the virtual address of each Atom in the Section. This
314 /// routine gets called after the linker fixes up the virtual address
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000315 /// of the section
316 void assignVirtualAddress(uint64_t &addr) {
317 for (auto &ai : _atoms) {
Michael J. Spencer4ffbd602013-01-11 22:39:44 +0000318 ai._virtualAddr = addr + ai._fileOffset;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000319 }
320 addr += this->memSize();
321 }
322
Michael J. Spencera2c97272013-01-04 21:09:21 +0000323 /// \brief Set the file offset of each Atom in the section. This routine
324 /// gets called after the linker fixes up the section offset
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000325 void assignOffsets(uint64_t offset) {
326 for (auto &ai : _atoms) {
Michael J. Spencer4ffbd602013-01-11 22:39:44 +0000327 ai._fileOffset = offset + ai._fileOffset;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000328 }
329 }
330
Michael J. Spencera2c97272013-01-04 21:09:21 +0000331 /// \brief Find the Atom address given a name, this is needed to to properly
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000332 /// apply relocation. The section class calls this to find the atom address
333 /// to fix the relocation
334 bool findAtomAddrByName(const StringRef name, uint64_t &addr) {
335 for (auto ai : _atoms) {
Michael J. Spencer4ffbd602013-01-11 22:39:44 +0000336 if (ai._atom->name() == name) {
337 addr = ai._virtualAddr;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000338 return true;
339 }
340 }
341 return false;
342 }
343
344 /// \brief Does the Atom occupy any disk space
345 bool occupiesNoDiskSpace() const {
346 return _contentType == DefinedAtom::typeZeroFill;
347 }
348
Michael J. Spencera2c97272013-01-04 21:09:21 +0000349 /// \brief The permission of the section is the most permissive permission
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000350 /// of all atoms that the section contains
351 void setContentPermissions(int32_t perm) {
352 _contentPermissions = std::max(perm, _contentPermissions);
353 }
354
355 /// \brief Get the section flags, defined by the permissions of the section
356 int64_t flags() {
357 switch (_contentPermissions) {
358 case DefinedAtom::perm___:
359 return 0;
360
361 case DefinedAtom::permR__:
362 return llvm::ELF::SHF_ALLOC;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000363
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000364 case DefinedAtom::permR_X:
365 return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000366
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000367 case DefinedAtom::permRW_:
368 case DefinedAtom::permRW_L:
369 return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000370
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000371 case DefinedAtom::permRWX:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000372 return llvm::ELF::SHF_ALLOC |
373 llvm::ELF::SHF_WRITE |
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000374 llvm::ELF::SHF_EXECINSTR;
375
376 default:
377 break;
378 }
379 return llvm::ELF::SHF_ALLOC;
380 }
381
382 /// \brief Return the raw flags, we need this to sort segments
383 int64_t atomflags() const {
384 return _contentPermissions;
385 }
386
Michael J. Spencera2c97272013-01-04 21:09:21 +0000387 /// \brief Return the section type, the returned value is recorded in the
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000388 /// sh_type field of the Section Header
389 int type() {
390 switch (_contentType) {
391 case DefinedAtom::typeCode:
392 case DefinedAtom::typeData:
393 case DefinedAtom::typeConstant:
394 return llvm::ELF::SHT_PROGBITS;
395
396 case DefinedAtom::typeZeroFill:
397 return llvm::ELF::SHT_NOBITS;
398
399 // Case to handle section types
400 // Symtab, String Table ...
401 default:
402 return _contentType;
403 }
404 }
405
Michael J. Spencera2c97272013-01-04 21:09:21 +0000406 /// \brief Returns the section link field, the returned value is
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000407 /// recorded in the sh_link field of the Section Header
408 int link() const {
409 return _link;
410 }
411
412 void setLink(int32_t link) {
413 _link = link;
414 }
415
Michael J. Spencera2c97272013-01-04 21:09:21 +0000416 /// \brief Returns the section entsize field, the returned value is
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000417 /// recorded in the sh_entsize field of the Section Header
418 int entsize() const {
419 return _entSize;
420 }
421
Michael J. Spencera2c97272013-01-04 21:09:21 +0000422 /// \brief Returns the shinfo field, the returned value is
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000423 /// recorded in the sh_info field of the Section Header
Michael J. Spencera2c97272013-01-04 21:09:21 +0000424 int shinfo() const {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000425 return _shInfo;
426 }
427
428 /// \brief Records the segmentType, that this section belongs to
429 void setSegment(const ELFLayout::SegmentType segmentType) {
430 _segmentType = segmentType;
431 }
432
433 /// \brief convert the segment type to a String for diagnostics
434 /// and printing purposes
435 StringRef segmentKindToStr() const {
436 switch(_segmentType) {
437 case llvm::ELF::PT_INTERP:
438 return "INTERP";
439 case llvm::ELF::PT_LOAD:
440 return "LOAD";
441 case llvm::ELF::PT_GNU_EH_FRAME:
442 return "EH_FRAME";
443 case llvm::ELF::PT_NOTE:
444 return "NOTE";
445 case llvm::ELF::PT_DYNAMIC:
446 return "DYNAMIC";
447 case llvm::ELF::PT_GNU_RELRO:
448 return "RELRO";
449 case llvm::ELF::PT_NULL:
450 return "NULL";
451 default:
452 return "UNKNOWN";
453 }
454 }
455
456 /// \brief for LLVM style RTTI information
Michael J. Spencera2c97272013-01-04 21:09:21 +0000457 static inline bool classof(
458 const Chunk<target_endianness, max_align, is64Bits> *c) {
459 return c->kind() ==
460 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000461 }
462
463 /// \brief Finalize the section contents before writing
464 void finalize() { }
465
Michael J. Spencera2c97272013-01-04 21:09:21 +0000466 /// \brief Write the section and the atom contents to the buffer
467 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000468 OwningPtr<FileOutputBuffer> &buffer) {
469 uint8_t *chunkBuffer = buffer->getBufferStart();
470 for (auto &ai : _atoms) {
Michael J. Spencer7fe77f82013-01-15 06:55:11 +0000471 const DefinedAtom *definedAtom = cast<DefinedAtom>(ai._atom);
Michael J. Spencer8de83642013-01-07 08:00:42 +0000472 if (definedAtom->contentType() == DefinedAtom::typeZeroFill)
473 continue;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000474 // Copy raw content of atom to file buffer.
475 ArrayRef<uint8_t> content = definedAtom->rawContent();
476 uint64_t contentSize = content.size();
477 if (contentSize == 0)
478 continue;
Michael J. Spencer4ffbd602013-01-11 22:39:44 +0000479 uint8_t *atomContent = chunkBuffer + ai._fileOffset;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000480 std::copy_n(content.data(), contentSize, atomContent);
481 for (auto ref = definedAtom->begin(); ref != definedAtom->end(); ++ref) {
482 uint32_t offset = ref->offsetInAtom();
483 uint64_t targetAddress = 0;
Michael J. Spencerbbe4b982013-01-11 21:38:36 +0000484 assert(ref->target() != nullptr && "Found the target to be NULL");
485 targetAddress = writer->addressOfAtom(ref->target());
Michael J. Spencer4ffbd602013-01-11 22:39:44 +0000486 uint64_t fixupAddress = writer->addressOfAtom(ai._atom) + offset;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000487 // apply the relocation
Michael J. Spencera2c97272013-01-04 21:09:21 +0000488 writer->kindHandler()->applyFixup(ref->kind(),
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000489 ref->addend(),
490 &atomContent[offset],
491 fixupAddress,
492 targetAddress);
493 }
494 }
495 }
496
497 /// Atom Iterators
Michael J. Spencer4ffbd602013-01-11 22:39:44 +0000498 typedef typename std::vector<AtomLayout>::iterator atom_iter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000499
500 atom_iter atoms_begin() { return _atoms.begin(); }
501
502 atom_iter atoms_end() { return _atoms.end(); }
503
504protected:
505 int32_t _contentType;
506 int32_t _contentPermissions;
Michael J. Spencer4ffbd602013-01-11 22:39:44 +0000507 SectionKind _sectionKind;
508 std::vector<AtomLayout> _atoms;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000509 ELFLayout::SegmentType _segmentType;
510 int64_t _entSize;
511 int64_t _shInfo;
512 int64_t _link;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000513};
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000514
Michael J. Spencera2c97272013-01-04 21:09:21 +0000515/// \brief A MergedSections represents a set of sections grouped by the same
516/// name. The output file that gets written by the linker has sections grouped
517/// by similiar names
518template<support::endianness target_endianness,
519 std::size_t max_align,
520 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000521class MergedSections {
522public:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000523 MergedSections(StringRef name)
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000524 : _name(name)
525 ,_hasSegment(false)
526 ,_ordinal(0)
527 ,_flags(0)
528 ,_size(0)
529 ,_memSize(0)
530 ,_fileOffset(0)
531 ,_virtualAddr(0)
532 ,_shInfo(0)
533 ,_entSize(0)
534 ,_link(0)
535 ,_align2(0)
536 ,_kind(0)
537 ,_type(0) { }
Michael J. Spencera2c97272013-01-04 21:09:21 +0000538
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000539 // Set the MergedSections is associated with a segment
540 void setHasSegment() { _hasSegment = true; }
541
Michael J. Spencera2c97272013-01-04 21:09:21 +0000542 /// Sets the ordinal
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000543 void setOrdinal(uint64_t ordinal) {
544 _ordinal = ordinal;
545 }
546
Michael J. Spencera2c97272013-01-04 21:09:21 +0000547 /// Sets the Memory size
548 void setMemSize(uint64_t memsz) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000549 _memSize = memsz;
550 }
551
552 /// Sets the size fo the merged Section
553 void setSize(uint64_t fsiz) {
554 _size = fsiz;
555 }
556
Michael J. Spencera2c97272013-01-04 21:09:21 +0000557 // The offset of the first section contained in the merged section is
558 // contained here
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000559 void setFileOffset(uint64_t foffset) {
560 _fileOffset = foffset;
561 }
562
563 // Sets the starting address of the section
564 void setAddr(uint64_t addr) {
565 _virtualAddr = addr;
566 }
567
568 // Appends a section into the list of sections that are part of this Merged
569 // Section
Michael J. Spencera2c97272013-01-04 21:09:21 +0000570 void appendSection(Chunk<target_endianness, max_align, is64Bits> *c) {
571 if (c->align2() > _align2)
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000572 _align2 = c->align2();
Michael J. Spencer7fe77f82013-01-15 06:55:11 +0000573 if (const auto section =
574 dyn_cast<Section<target_endianness, max_align, is64Bits>>(c)) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000575 _link = section->link();
576 _shInfo = section->shinfo();
577 _entSize = section->entsize();
578 _type = section->type();
579 if (_flags < section->flags())
580 _flags = section->flags();
581 }
582 _kind = c->kind();
583 _sections.push_back(c);
584 }
585
586 // Iterators
Michael J. Spencera2c97272013-01-04 21:09:21 +0000587 typedef typename std::vector<
588 Chunk<target_endianness, max_align, is64Bits> *>::iterator ChunkIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000589
590 ChunkIter begin_sections() { return _sections.begin(); }
591
592 ChunkIter end_sections() { return _sections.end(); }
593
594 // The below functions returns the properties of the MergeSection
595 bool hasSegment() const { return _hasSegment; }
596
597 StringRef name() const { return _name; }
598
599 int64_t shinfo() const { return _shInfo; }
600
601 uint64_t align2() const { return _align2; }
602
603 int64_t link() const { return _link; }
604
605 int64_t type() const { return _type; }
606
607 uint64_t virtualAddr() const { return _virtualAddr; }
608
609 int64_t ordinal() const { return _ordinal; }
610
611 int64_t kind() const { return _kind; }
612
613 uint64_t fileSize() const { return _size; }
614
615 int64_t entsize() const { return _entSize; }
616
617 uint64_t fileOffset() const { return _fileOffset; }
618
619 int64_t flags() const { return _flags; }
620
621 uint64_t memSize() { return _memSize; }
622
623private:
624 StringRef _name;
625 bool _hasSegment;
626 uint64_t _ordinal;
627 int64_t _flags;
628 uint64_t _size;
629 uint64_t _memSize;
630 uint64_t _fileOffset;
631 uint64_t _virtualAddr;
632 int64_t _shInfo;
633 int64_t _entSize;
634 int64_t _link;
635 uint64_t _align2;
636 int64_t _kind;
637 int64_t _type;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000638 std::vector<Chunk<target_endianness, max_align, is64Bits> *> _sections;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000639};
640
Michael J. Spencera2c97272013-01-04 21:09:21 +0000641/// \brief A segment can be divided into segment slices
642/// depending on how the segments can be split
643template<support::endianness target_endianness,
644 std::size_t max_align,
645 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000646class SegmentSlice {
647public:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000648 typedef typename std::vector<
Michael J. Spencer00b702c2013-01-07 07:59:46 +0000649 Chunk<target_endianness, max_align, is64Bits> *>::iterator sectionIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000650
651 SegmentSlice() { }
652
653 /// Set the segment slice so that it begins at the offset specified
Michael J. Spencera2c97272013-01-04 21:09:21 +0000654 /// by fileoffset and set the start of the slice to be s and the end
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000655 /// of the slice to be e
656 void set(uint64_t fileoffset, int32_t s, int e) {
657 _startSection = s;
658 _endSection = e+1;
659 _offset = fileoffset;
660 }
661
662 // Set the segment slice start and end iterators. This is used to walk through
663 // the sections that are part of the Segment slice
664 void setSections(sectionIter start, sectionIter end) {
665 _startSectionIter = start;
666 _endSectionIter = end;
667 }
668
669 // Return the fileOffset of the slice
670 uint64_t fileOffset() const { return _offset; }
671
672 // Return the size of the slice
673 uint64_t fileSize() const { return _size; }
674
675 // Return the start of the slice
676 int32_t startSection() const { return _startSection; }
677
678 // Return the start address of the slice
679 uint64_t virtualAddr() const { return _addr; }
680
681 // Return the memory size of the slice
682 uint64_t memSize() const { return _memSize; }
683
684 // Return the alignment of the slice
685 uint64_t align2() const { return _align2; }
686
687 void setSize(uint64_t sz) { _size = sz; }
688
689 void setMemSize(uint64_t memsz) { _memSize = memsz; }
690
691 void setVAddr(uint64_t addr) { _addr = addr; }
692
693 void setAlign(uint64_t align) { _align2 = align; }
694
Michael J. Spencera2c97272013-01-04 21:09:21 +0000695 static bool compare_slices(
696 SegmentSlice<target_endianness, max_align, is64Bits> *a,
697 SegmentSlice<target_endianness, max_align, is64Bits> *b) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000698 return (a->startSection() < b->startSection());
699 }
700
701 // Functions to run through the slice
702 sectionIter sections_begin() { return _startSectionIter; }
703
704 sectionIter sections_end() { return _endSectionIter; }
705
706private:
707 int32_t _startSection;
708 int32_t _endSection;
709 sectionIter _startSectionIter;
710 sectionIter _endSectionIter;
711 uint64_t _addr;
712 uint64_t _offset;
713 uint64_t _size;
714 uint64_t _align2;
715 uint64_t _memSize;
716};
717
718/// \brief A segment contains a set of sections, that have similiar properties
719// the sections are already seperated based on different flags and properties
720// the segment is just a way to concatenate sections to segments
Michael J. Spencera2c97272013-01-04 21:09:21 +0000721template<support::endianness target_endianness,
722 std::size_t max_align,
723 bool is64Bits>
724class Segment : public Chunk<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000725public:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000726 typedef typename std::vector<SegmentSlice<
727 target_endianness, max_align, is64Bits> *>::iterator slice_iter;
728 typedef typename std::vector<
Michael J. Spencer00b702c2013-01-07 07:59:46 +0000729 Chunk<target_endianness, max_align, is64Bits> *>::iterator SectionIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000730
731 Segment(const StringRef name,
732 const ELFLayout::SegmentType type,
733 const WriterOptionsELF &options)
Michael J. Spencera2c97272013-01-04 21:09:21 +0000734 : Chunk<target_endianness, max_align, is64Bits>(name,
735 Chunk<target_endianness, max_align, is64Bits>::K_ELFSegment)
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000736 , _segmentType(type)
737 , _flags(0)
738 , _atomflags(0)
739 , _options(options) {
740 this->_align2 = 0;
741 this->_fsize = 0;
742 }
743
744 /// append a section to a segment
Michael J. Spencera2c97272013-01-04 21:09:21 +0000745 void append(Section<target_endianness, max_align, is64Bits> *section) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000746 _sections.push_back(section);
747 if (_flags < section->flags())
748 _flags = section->flags();
749 if (_atomflags < section->atomflags())
750 _atomflags = section->atomflags();
751 if (this->_align2 < section->align2())
752 this->_align2 = section->align2();
753 }
754
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000755 /// Prepend a generic chunk to the segment.
756 void prepend(Chunk<target_endianness, max_align, is64Bits> *c) {
757 _sections.insert(_sections.begin(), c);
758 }
759
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000760 /// Sort segments depending on the property
761 /// If we have a Program Header segment, it should appear first
762 /// If we have a INTERP segment, that should appear after the Program Header
763 /// All Loadable segments appear next in this order
764 /// All Read Write Execute segments follow
765 /// All Read Execute segments appear next
766 /// All Read only segments appear first
Michael J. Spencera2c97272013-01-04 21:09:21 +0000767 /// All Write execute segments follow
768 static bool compareSegments(
769 Segment<target_endianness, max_align, is64Bits> *sega,
770 Segment<target_endianness, max_align, is64Bits> *segb) {
771 if (sega->atomflags() < segb->atomflags())
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000772 return false;
773 return true;
774 }
775
776 /// \brief Start assigning file offset to the segment chunks The fileoffset
777 /// needs to be page at the start of the segment and in addition the
778 /// fileoffset needs to be aligned to the max section alignment within the
779 /// segment. This is required so that the ELF property p_poffset % p_align =
780 /// p_vaddr mod p_align holds true.
781 /// The algorithm starts off by assigning the startOffset thats passed in as
782 /// parameter to the first section in the segment, if the difference between
783 /// the newly computed offset is greater than a page, then we create a segment
Michael J. Spencera2c97272013-01-04 21:09:21 +0000784 /// slice, as it would be a waste of virtual memory just to be filled with
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000785 /// zeroes
786 void assignOffsets(uint64_t startOffset) {
787 int startSection = 0;
788 int currSection = 0;
789 SectionIter startSectionIter, endSectionIter;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000790 // slice align is set to the max alignment of the chunks that are
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000791 // contained in the slice
792 uint64_t sliceAlign = 0;
793 // Current slice size
794 uint64_t curSliceSize = 0;
795 // Current Slice File Offset
796 uint64_t curSliceFileOffset = 0;
797
798 startSectionIter = _sections.begin();
799 endSectionIter = _sections.end();
800 startSection = 0;
801 bool isFirstSection = true;
802 for (auto si = _sections.begin(); si != _sections.end(); ++si) {
803 if (isFirstSection) {
804 // align the startOffset to the section alignment
Michael J. Spencera2c97272013-01-04 21:09:21 +0000805 uint64_t newOffset =
806 llvm::RoundUpToAlignment(startOffset, (*si)->align2());
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000807 curSliceFileOffset = newOffset;
808 sliceAlign = (*si)->align2();
809 this->setFileOffset(startOffset);
810 (*si)->setFileOffset(newOffset);
811 curSliceSize = (*si)->fileSize();
812 isFirstSection = false;
813 } else {
814 uint64_t curOffset = curSliceFileOffset + curSliceSize;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000815 uint64_t newOffset =
816 llvm::RoundUpToAlignment(curOffset, (*si)->align2());
817 SegmentSlice<target_endianness, max_align, is64Bits> *slice = nullptr;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000818 // If the newOffset computed is more than a page away, lets create
819 // a seperate segment, so that memory is not used up while running
820 if ((newOffset - curOffset) > _options.pageSize()) {
821 // TODO: use std::find here
822 for (auto sei = slices_begin(); sei != slices_end(); ++sei) {
823 if ((*sei)->startSection() == startSection) {
824 slice = *sei;
825 break;
826 }
827 }
828 if (!slice) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000829 slice = new (_segmentAllocate.Allocate<
830 SegmentSlice<target_endianness, max_align, is64Bits>>())
831 SegmentSlice<target_endianness, max_align, is64Bits>();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000832 _segmentSlices.push_back(slice);
833 }
834 slice->set(curSliceFileOffset, startSection, currSection);
835 slice->setSections(startSectionIter, endSectionIter);
836 slice->setSize(curSliceSize);
837 slice->setAlign(sliceAlign);
Michael J. Spencera2c97272013-01-04 21:09:21 +0000838 uint64_t newPageOffset =
839 llvm::RoundUpToAlignment(curOffset, _options.pageSize());
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000840 newOffset = llvm::RoundUpToAlignment(newPageOffset, (*si)->align2());
841 curSliceFileOffset = newOffset;
842 startSectionIter = endSectionIter;
843 startSection = currSection;
844 (*si)->setFileOffset(curSliceFileOffset);
845 curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
846 sliceAlign = (*si)->align2();
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +0000847 } else {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000848 if (sliceAlign < (*si)->align2())
849 sliceAlign = (*si)->align2();
850 (*si)->setFileOffset(newOffset);
851 curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
852 }
853 }
854 currSection++;
855 endSectionIter = si;
856 }
Michael J. Spencera2c97272013-01-04 21:09:21 +0000857 SegmentSlice<target_endianness, max_align, is64Bits> *slice = nullptr;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000858 for (auto sei = slices_begin(); sei != slices_end(); ++sei) {
859 // TODO: add std::find
860 if ((*sei)->startSection() == startSection) {
861 slice = *sei;
862 break;
863 }
864 }
865 if (!slice) {
866 slice = new (_segmentAllocate.Allocate
Michael J. Spencera2c97272013-01-04 21:09:21 +0000867 <SegmentSlice<target_endianness, max_align, is64Bits>>())
868 SegmentSlice<target_endianness, max_align, is64Bits>();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000869 _segmentSlices.push_back(slice);
870 }
871 slice->set(curSliceFileOffset, startSection, currSection);
872 slice->setSections(startSectionIter, _sections.end());
873 slice->setSize(curSliceSize);
874 slice->setAlign(sliceAlign);
875 this->_fsize = curSliceFileOffset - startOffset + curSliceSize;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000876 std::stable_sort(slices_begin(), slices_end(),
877 SegmentSlice<target_endianness, max_align, is64Bits>::compare_slices);
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000878 }
879
880 /// \brief Assign virtual addresses to the slices
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000881 void assignVirtualAddress(uint64_t &addr) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000882 for (auto sei = slices_begin(), see = slices_end(); sei != see; ++sei) {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000883 // Align to a page
884 addr = llvm::RoundUpToAlignment(addr, _options.pageSize());
885 // Align to the slice alignment
886 addr = llvm::RoundUpToAlignment(addr, (*sei)->align2());
887
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000888 bool virtualAddressSet = false;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000889 for (auto si = (*sei)->sections_begin(), se = (*sei)->sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000890 si != se; ++si) {
891 // Align the section address
892 addr = llvm::RoundUpToAlignment(addr, (*si)->align2());
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000893 if (!virtualAddressSet) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000894 (*sei)->setVAddr(addr);
895 virtualAddressSet = true;
896 }
897 (*si)->setVAddr(addr);
Michael J. Spencer00b702c2013-01-07 07:59:46 +0000898 if (auto s =
899 dyn_cast<Section<target_endianness, max_align, is64Bits>>(*si))
900 s->assignVirtualAddress(addr);
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000901 else
902 addr += (*si)->memSize();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000903 (*si)->setMemSize(addr - (*si)->virtualAddr());
904 }
905 (*sei)->setMemSize(addr - (*sei)->virtualAddr());
906 }
907 }
908
909 slice_iter slices_begin() {
910 return _segmentSlices.begin();
911 }
912
913 slice_iter slices_end() {
914 return _segmentSlices.end();
915 }
916
Michael J. Spencera2c97272013-01-04 21:09:21 +0000917 // Write the Segment
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000918 void write(ELFWriter *writer, OwningPtr<FileOutputBuffer> &buffer) {
919 for (auto sei = slices_begin(), see = slices_end(); sei != see; ++sei) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000920 for (auto si = (*sei)->sections_begin(), se = (*sei)->sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000921 si != se; ++si) {
922 (*si)->write(writer, buffer);
923 }
924 }
925 }
926
927 // Finalize the segment, before we want to write to the output file
928 void finalize() { }
929
Michael J. Spencera2c97272013-01-04 21:09:21 +0000930 // For LLVM RTTI
931 static inline bool classof(
932 const Chunk<target_endianness, max_align, is64Bits> *c) {
933 return c->kind() ==
934 Chunk<target_endianness, max_align, is64Bits>::K_ELFSegment;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000935 }
936
937 // Getters
938 int32_t sectionCount() const {
939 return _sections.size();
940 }
941
942 ELFLayout::SegmentType segmentType() { return _segmentType; }
943
944 int pageSize() const { return _options.pageSize(); }
945
946 int64_t atomflags() const { return _atomflags; }
947
948 int64_t flags() const {
949 int64_t fl = 0;
950 if (_flags & llvm::ELF::SHF_ALLOC)
951 fl |= llvm::ELF::PF_R;
952 if (_flags & llvm::ELF::SHF_WRITE)
953 fl |= llvm::ELF::PF_W;
954 if (_flags & llvm::ELF::SHF_EXECINSTR)
955 fl |= llvm::ELF::PF_X;
956 return fl;
957 }
958
959 int64_t numSlices() const {
960 return _segmentSlices.size();
961 }
962
963private:
Michael J. Spencer00b702c2013-01-07 07:59:46 +0000964 /// \brief Section or some other chunk type.
965 std::vector<Chunk<target_endianness, max_align, is64Bits> *> _sections;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000966 std::vector<SegmentSlice<target_endianness, max_align, is64Bits> *>
967 _segmentSlices;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000968 ELFLayout::SegmentType _segmentType;
969 int64_t _flags;
970 int64_t _atomflags;
971 const WriterOptionsELF _options;
972 llvm::BumpPtrAllocator _segmentAllocate;
973};
974
975/// \brief The class represents the ELF String Table
Michael J. Spencera2c97272013-01-04 21:09:21 +0000976template<support::endianness target_endianness,
977 std::size_t max_align,
978 bool is64Bits>
979class ELFStringTable : public Section<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000980public:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000981 ELFStringTable(const char *str, int32_t order)
982 : Section<target_endianness, max_align, is64Bits>(
983 str,
984 llvm::ELF::SHT_STRTAB,
985 DefinedAtom::perm___,
986 order,
987 Section<target_endianness, max_align, is64Bits>::K_StringTable) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000988 // the string table has a NULL entry for which
989 // add an empty string
990 _strings.push_back("");
991 this->_fsize = 1;
992 this->_align2 = 1;
993 this->setOrder(order);
994 }
995
Michael J. Spencera2c97272013-01-04 21:09:21 +0000996 static inline bool classof(
997 const Chunk<target_endianness, max_align, is64Bits> *c) {
998 return c->kind() ==
999 Section<target_endianness, max_align, is64Bits>::K_StringTable;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001000 }
1001
1002 uint64_t addString(const StringRef symname) {
1003 _strings.push_back(symname);
1004 uint64_t offset = this->_fsize;
1005 this->_fsize += symname.size() + 1;
1006 return offset;
1007 }
1008
Michael J. Spencera2c97272013-01-04 21:09:21 +00001009 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001010 OwningPtr<FileOutputBuffer> &buffer) {
1011 uint8_t *chunkBuffer = buffer->getBufferStart();
1012 uint8_t *dest = chunkBuffer + this->fileOffset();
1013 for (auto si : _strings) {
1014 memcpy(dest, si.data(), si.size());
1015 dest += si.size();
1016 memcpy(dest, "", 1);
1017 dest += 1;
1018 }
1019 }
1020
1021 void finalize() { }
1022
1023private:
1024 std::vector<StringRef> _strings;
1025};
1026
Michael J. Spencera2c97272013-01-04 21:09:21 +00001027/// \brief The ELFSymbolTable class represents the symbol table in a ELF file
1028template<support::endianness target_endianness,
1029 std::size_t max_align,
1030 bool is64Bits>
1031class ELFSymbolTable : public Section<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001032public:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001033 typedef object::Elf_Sym_Impl<target_endianness, max_align, is64Bits> Elf_Sym;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001034
Michael J. Spencera2c97272013-01-04 21:09:21 +00001035 ELFSymbolTable(const char *str, int32_t order)
1036 : Section<target_endianness, max_align, is64Bits>(
1037 str,
1038 llvm::ELF::SHT_SYMTAB,
1039 0,
1040 order,
1041 Section<target_endianness, max_align, is64Bits>::K_SymbolTable) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001042 this->setOrder(order);
1043 Elf_Sym *symbol = new (_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001044 memset((void *)symbol, 0, sizeof(Elf_Sym));
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001045 _symbolTable.push_back(symbol);
1046 this->_entSize = sizeof(Elf_Sym);
1047 this->_fsize = sizeof(Elf_Sym);
1048 this->_align2 = sizeof(void *);
1049 }
1050
Michael J. Spencera2c97272013-01-04 21:09:21 +00001051 static inline bool classof(
1052 const Chunk<target_endianness, max_align, is64Bits> *c) {
1053 return c->kind() ==
1054 Section<target_endianness, max_align, is64Bits>::K_SymbolTable;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001055 }
1056
1057 void addSymbol(const Atom *atom, int32_t sectionIndex, uint64_t addr = 0) {
1058 Elf_Sym *symbol = new(_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
1059 unsigned char binding = 0, type = 0;
1060 symbol->st_name = _stringSection->addString(atom->name());
1061 symbol->st_size = 0;
1062 symbol->st_shndx = sectionIndex;
1063 symbol->st_value = 0;
1064 symbol->st_other = ELF::STV_DEFAULT;
Michael J. Spencer7fe77f82013-01-15 06:55:11 +00001065 if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom)){
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001066 symbol->st_size = da->size();
1067 lld::DefinedAtom::ContentType ct;
1068 switch (ct = da->contentType()){
1069 case DefinedAtom::typeCode:
1070 symbol->st_value = addr;
1071 type = ELF::STT_FUNC;
1072 break;
1073 case DefinedAtom::typeData:
Michael J. Spencer8de83642013-01-07 08:00:42 +00001074 case DefinedAtom::typeConstant:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001075 symbol->st_value = addr;
1076 type = ELF::STT_OBJECT;
1077 break;
1078 case DefinedAtom::typeZeroFill:
Michael J. Spencer28c65942013-01-07 07:05:52 +00001079 type = ELF::STT_OBJECT;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001080 symbol->st_value = addr;
1081 break;
1082 default:
1083 type = ELF::STT_NOTYPE;
1084 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001085 if (da->scope() == DefinedAtom::scopeTranslationUnit)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001086 binding = ELF::STB_LOCAL;
1087 else
1088 binding = ELF::STB_GLOBAL;
Michael J. Spencer7fe77f82013-01-15 06:55:11 +00001089 } else if (const AbsoluteAtom *aa = dyn_cast<const AbsoluteAtom>(atom)){
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001090 type = ELF::STT_OBJECT;
1091 symbol->st_shndx = ELF::SHN_ABS;
1092 switch (aa->scope()) {
1093 case AbsoluteAtom::scopeLinkageUnit:
1094 symbol->st_other = ELF::STV_HIDDEN;
1095 binding = ELF::STB_LOCAL;
1096 break;
1097 case AbsoluteAtom::scopeTranslationUnit:
1098 binding = ELF::STB_LOCAL;
1099 break;
1100 case AbsoluteAtom::scopeGlobal:
1101 binding = ELF::STB_GLOBAL;
1102 break;
1103 }
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001104 symbol->st_value = addr;
1105 } else {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001106 symbol->st_value = 0;
1107 type = ELF::STT_NOTYPE;
1108 binding = ELF::STB_WEAK;
1109 }
1110 symbol->setBindingAndType(binding, type);
1111 _symbolTable.push_back(symbol);
1112 this->_fsize += sizeof(Elf_Sym);
1113 }
1114
Michael J. Spencera2c97272013-01-04 21:09:21 +00001115 void setStringSection(
1116 ELFStringTable<target_endianness, max_align, is64Bits> *s) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001117 _stringSection = s;
1118 }
1119
1120 void finalize() {
1121 // sh_info should be one greater than last symbol with STB_LOCAL binding
1122 // we sort the symbol table to keep all local symbols at the beginning
1123 std::stable_sort(_symbolTable.begin(), _symbolTable.end(),
1124 [](const Elf_Sym *A, const Elf_Sym *B) {
1125 return A->getBinding() < B->getBinding();
Michael J. Spencera2c97272013-01-04 21:09:21 +00001126 });
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001127 uint16_t shInfo = 0;
1128 for (auto i : _symbolTable) {
1129 if (i->getBinding() != ELF::STB_LOCAL)
1130 break;
1131 shInfo++;
1132 }
1133 this->_shInfo = shInfo;
1134 this->setLink(_stringSection->ordinal());
1135 }
1136
Michael J. Spencera2c97272013-01-04 21:09:21 +00001137 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001138 OwningPtr<FileOutputBuffer> &buffer) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001139 uint8_t *chunkBuffer = buffer->getBufferStart();
1140 uint8_t *dest = chunkBuffer + this->fileOffset();
1141 for (auto sti : _symbolTable) {
1142 memcpy(dest, sti, sizeof(Elf_Sym));
1143 dest += sizeof(Elf_Sym);
1144 }
1145 }
1146
1147private:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001148 ELFStringTable<target_endianness, max_align, is64Bits> *_stringSection;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001149 std::vector<Elf_Sym*> _symbolTable;
1150 llvm::BumpPtrAllocator _symbolAllocate;
1151 int64_t _link;
1152};
1153
1154/// \brief An ELFHeader represents the Elf[32/64]_Ehdr structure at the
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001155/// start of an ELF executable file.
Michael J. Spencera2c97272013-01-04 21:09:21 +00001156template<support::endianness target_endianness,
1157 std::size_t max_align,
1158 bool is64Bits>
1159class ELFHeader : public Chunk<target_endianness, max_align, is64Bits> {
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001160public:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001161 typedef Elf_Ehdr_Impl<target_endianness, max_align, is64Bits> Elf_Ehdr;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001162
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001163 ELFHeader()
Michael J. Spencera2c97272013-01-04 21:09:21 +00001164 : Chunk<target_endianness, max_align, is64Bits>(
1165 "elfhdr", Chunk<target_endianness, max_align, is64Bits>::K_ELFHeader) {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001166 this->_align2 = is64Bits ? 8 : 4;
1167 this->_fsize = sizeof(Elf_Ehdr);
1168 this->_msize = sizeof(Elf_Ehdr);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001169 memset(_eh.e_ident, 0, llvm::ELF::EI_NIDENT);
1170 e_ident(ELF::EI_MAG0, 0x7f);
1171 e_ident(ELF::EI_MAG1, 'E');
1172 e_ident(ELF::EI_MAG2, 'L');
1173 e_ident(ELF::EI_MAG3, 'F');
1174 e_ehsize(sizeof(Elf_Ehdr));
1175 e_flags(2);
1176 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001177 void e_ident(int I, unsigned char C) { _eh.e_ident[I] = C; }
1178 void e_type(uint16_t type) { _eh.e_type = type; }
1179 void e_machine(uint16_t machine) { _eh.e_machine = machine; }
1180 void e_version(uint32_t version) { _eh.e_version = version; }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001181 void e_entry(int64_t entry) { _eh.e_entry = entry; }
1182 void e_phoff(int64_t phoff) { _eh.e_phoff = phoff; }
1183 void e_shoff(int64_t shoff) { _eh.e_shoff = shoff; }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001184 void e_flags(uint32_t flags) { _eh.e_flags = flags; }
1185 void e_ehsize(uint16_t ehsize) { _eh.e_ehsize = ehsize; }
1186 void e_phentsize(uint16_t phentsize) { _eh.e_phentsize = phentsize; }
1187 void e_phnum(uint16_t phnum) { _eh.e_phnum = phnum; }
1188 void e_shentsize(uint16_t shentsize) { _eh.e_shentsize = shentsize; }
1189 void e_shnum(uint16_t shnum) { _eh.e_shnum = shnum; }
1190 void e_shstrndx(uint16_t shstrndx) { _eh.e_shstrndx = shstrndx; }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001191 uint64_t fileSize() { return sizeof (Elf_Ehdr); }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001192
Michael J. Spencera2c97272013-01-04 21:09:21 +00001193 static inline bool classof(
1194 const Chunk<target_endianness, max_align, is64Bits> *c) {
1195 return c->Kind() ==
1196 Chunk<target_endianness, max_align, is64Bits>::K_ELFHeader;
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001197 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001198
Michael J. Spencera2c97272013-01-04 21:09:21 +00001199 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001200 OwningPtr<FileOutputBuffer> &buffer) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001201 uint8_t *chunkBuffer = buffer->getBufferStart();
1202 uint8_t *atomContent = chunkBuffer + this->fileOffset();
1203 memcpy(atomContent, &_eh, fileSize());
1204 }
1205
1206 void finalize() { }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001207
1208private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001209 Elf_Ehdr _eh;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001210};
1211
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001212/// \brief An ELFProgramHeader represents the Elf[32/64]_Phdr structure at the
1213/// start of an ELF executable file.
Michael J. Spencera2c97272013-01-04 21:09:21 +00001214template<support::endianness target_endianness,
1215 std::size_t max_align,
1216 bool is64Bits>
1217class ELFProgramHeader : public Chunk<target_endianness, max_align, is64Bits> {
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001218public:
Michael J. Spencerfd3981d2013-01-06 05:40:27 +00001219 typedef Elf_Phdr_Impl<target_endianness, max_align, is64Bits> Elf_Phdr;
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001220 typedef typename std::vector<Elf_Phdr *>::iterator PhIterT;
1221
1222 /// \brief Find a program header entry, given the type of entry that
1223 /// we are looking for
1224 class FindPhdr {
1225 public:
1226 FindPhdr(uint64_t type, uint64_t flags, uint64_t flagsClear)
1227 : _type(type)
1228 , _flags(flags)
1229 , _flagsClear(flagsClear)
1230 {}
1231
Shankar Easwaran37c52822013-01-10 18:16:10 +00001232 bool operator()(const Elf_Phdr *j) const {
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001233 return ((j->p_type == _type) &&
1234 ((j->p_flags & _flags) == _flags) &&
1235 (!(j->p_flags & _flagsClear)));
1236 }
1237 private:
1238 uint64_t _type;
1239 uint64_t _flags;
1240 uint64_t _flagsClear;
1241 };
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001242
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001243 ELFProgramHeader()
Michael J. Spencera2c97272013-01-04 21:09:21 +00001244 : Chunk<target_endianness, max_align, is64Bits>(
1245 "elfphdr",
Reid Klecknere974bd12013-01-05 02:21:42 +00001246 Chunk<target_endianness, max_align, is64Bits>::K_ELFProgramHeader) {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001247 this->_align2 = is64Bits ? 8 : 4;
Reid Klecknere974bd12013-01-05 02:21:42 +00001248 resetProgramHeaders();
1249 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001250
Michael J. Spencera2c97272013-01-04 21:09:21 +00001251 bool addSegment(Segment<target_endianness, max_align, is64Bits> *segment) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001252 Elf_Phdr *phdr = nullptr;
1253 bool ret = false;
1254
Michael J. Spencera2c97272013-01-04 21:09:21 +00001255 for (auto sei = segment->slices_begin(), see = segment->slices_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001256 sei != see; ++sei) {
1257 if (_phi == _ph.end()) {
1258 phdr = new(_allocator.Allocate<Elf_Phdr>()) Elf_Phdr;
1259 _ph.push_back(phdr);
1260 _phi = _ph.end();
1261 ret = true;
1262 } else {
1263 phdr = (*_phi);
1264 ++_phi;
1265 }
1266 phdr->p_type = segment->segmentType();
1267 phdr->p_offset = (*sei)->fileOffset();
1268 phdr->p_vaddr = (*sei)->virtualAddr();
1269 phdr->p_paddr = (*sei)->virtualAddr();
1270 phdr->p_filesz = (*sei)->fileSize();
1271 phdr->p_memsz = (*sei)->memSize();
1272 phdr->p_flags = segment->flags();
Michael J. Spencera2c97272013-01-04 21:09:21 +00001273 phdr->p_align = (phdr->p_type == llvm::ELF::PT_LOAD) ?
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001274 segment->pageSize() : (*sei)->align2();
1275 }
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001276
1277 this->_fsize = fileSize();
1278 this->_msize = this->_fsize;
1279
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001280 return ret;
1281 }
1282
1283 void resetProgramHeaders() {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001284 _phi = _ph.begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001285 }
1286
Michael J. Spencera2c97272013-01-04 21:09:21 +00001287 uint64_t fileSize() {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001288 return sizeof(Elf_Phdr) * _ph.size();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001289 }
1290
Michael J. Spencera2c97272013-01-04 21:09:21 +00001291 static inline bool classof(
1292 const Chunk<target_endianness, max_align, is64Bits> *c) {
1293 return c->Kind() ==
1294 Chunk<target_endianness, max_align, is64Bits>::K_ELFProgramHeader;
1295 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001296
Michael J. Spencera2c97272013-01-04 21:09:21 +00001297 void write(ELFWriter *writer,
1298 OwningPtr<FileOutputBuffer> &buffer) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001299 uint8_t *chunkBuffer = buffer->getBufferStart();
1300 uint8_t *dest = chunkBuffer + this->fileOffset();
1301 for (auto phi : _ph) {
1302 memcpy(dest, phi, sizeof(Elf_Phdr));
1303 dest += sizeof(Elf_Phdr);
1304 }
1305 }
1306
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001307 /// \brief find a program header entry in the list of program headers
1308 PhIterT findProgramHeader(uint64_t type, uint64_t flags, uint64_t flagClear) {
1309 return std::find_if(_ph.begin(), _ph.end(),
1310 FindPhdr(type, flags, flagClear));
1311 }
1312
1313 PhIterT begin() {
1314 return _ph.begin();
1315 }
1316
1317 PhIterT end() {
1318 return _ph.end();
1319 }
1320
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001321 void finalize() { }
1322
Michael J. Spencera2c97272013-01-04 21:09:21 +00001323 int64_t entsize() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001324 return sizeof(Elf_Phdr);
1325 }
1326
1327 int64_t numHeaders() {
1328 return _ph.size();
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001329 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001330
1331private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001332 std::vector<Elf_Phdr *> _ph;
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001333 PhIterT _phi;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001334 llvm::BumpPtrAllocator _allocator;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001335};
1336
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001337/// \brief An ELFSectionHeader represents the Elf[32/64]_Shdr structure
1338/// at the end of the file
Michael J. Spencera2c97272013-01-04 21:09:21 +00001339template<support::endianness target_endianness,
1340 std::size_t max_align,
1341 bool is64Bits>
1342class ELFSectionHeader : public Chunk<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001343public:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001344 typedef Elf_Shdr_Impl<target_endianness, max_align, is64Bits> Elf_Shdr;
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001345
Michael J. Spencera2c97272013-01-04 21:09:21 +00001346 ELFSectionHeader(int32_t order)
1347 : Chunk<target_endianness, max_align, is64Bits>(
1348 "shdr",
1349 Chunk<target_endianness, max_align, is64Bits>::K_ELFSectionHeader) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001350 this->_fsize = 0;
1351 this->_align2 = 8;
1352 this->setOrder(order);
1353 // The first element in the list is always NULL
1354 Elf_Shdr *nullshdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
1355 ::memset(nullshdr, 0, sizeof (Elf_Shdr));
1356 _sectionInfo.push_back(nullshdr);
1357 this->_fsize += sizeof (Elf_Shdr);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001358 }
1359
Michael J. Spencera2c97272013-01-04 21:09:21 +00001360 uint16_t fileSize() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001361 return sizeof(Elf_Shdr) * _sectionInfo.size();
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001362 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001363
Michael J. Spencera2c97272013-01-04 21:09:21 +00001364 void appendSection(
1365 MergedSections<target_endianness, max_align, is64Bits> *section) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001366 Elf_Shdr *shdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
1367 shdr->sh_name = _stringSection->addString(section->name());
1368 shdr->sh_type = section->type();
1369 shdr->sh_flags = section->flags();
1370 shdr->sh_offset = section->fileOffset();
1371 shdr->sh_addr = section->virtualAddr();
1372 shdr->sh_size = section->memSize();
1373 shdr->sh_link = section->link();
1374 shdr->sh_info = section->shinfo();
1375 shdr->sh_addralign = section->align2();
1376 shdr->sh_entsize = section->entsize();
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001377 _sectionInfo.push_back(shdr);
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001378 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001379
Michael J. Spencera2c97272013-01-04 21:09:21 +00001380 void updateSection(Section<target_endianness, max_align, is64Bits> *section) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001381 Elf_Shdr *shdr = _sectionInfo[section->ordinal()];
1382 shdr->sh_type = section->type();
1383 shdr->sh_flags = section->flags();
1384 shdr->sh_offset = section->fileOffset();
1385 shdr->sh_addr = section->virtualAddr();
1386 shdr->sh_size = section->fileSize();
1387 shdr->sh_link = section->link();
1388 shdr->sh_info = section->shinfo();
1389 shdr->sh_addralign = section->align2();
1390 shdr->sh_entsize = section->entsize();
1391 }
1392
Michael J. Spencera2c97272013-01-04 21:09:21 +00001393 static inline bool classof(
1394 const Chunk<target_endianness, max_align, is64Bits> *c) {
1395 return c->getChunkKind() ==
1396 Chunk<target_endianness, max_align, is64Bits>::K_ELFSectionHeader;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001397 }
1398
Michael J. Spencera2c97272013-01-04 21:09:21 +00001399 void setStringSection(
1400 ELFStringTable<target_endianness, max_align, is64Bits> *s) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001401 _stringSection = s;
1402 }
1403
Michael J. Spencera2c97272013-01-04 21:09:21 +00001404 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001405 OwningPtr<FileOutputBuffer> &buffer) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001406 uint8_t *chunkBuffer = buffer->getBufferStart();
1407 uint8_t *dest = chunkBuffer + this->fileOffset();
1408 for (auto shi : _sectionInfo) {
1409 memcpy(dest, shi, sizeof(Elf_Shdr));
1410 dest += sizeof(Elf_Shdr);
1411 }
1412 _stringSection->write(writer, buffer);
1413 }
1414
1415 void finalize() { }
1416
Michael J. Spencera2c97272013-01-04 21:09:21 +00001417 int64_t entsize() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001418 return sizeof(Elf_Shdr);
1419 }
1420
1421 int64_t numHeaders() {
1422 return _sectionInfo.size();
1423 }
1424
1425private:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001426 ELFStringTable<target_endianness, max_align, is64Bits> *_stringSection;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001427 std::vector<Elf_Shdr*> _sectionInfo;
1428 llvm::BumpPtrAllocator _sectionAllocate;
1429};
1430
Michael J. Spencera2c97272013-01-04 21:09:21 +00001431/// \brief The DefaultELFLayout class is used by the Writer to arrange
1432/// sections and segments in the order determined by the target ELF
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001433/// format. The writer creates a single instance of the DefaultELFLayout
Michael J. Spencera2c97272013-01-04 21:09:21 +00001434/// class
1435template<support::endianness target_endianness,
1436 std::size_t max_align,
1437 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001438class DefaultELFLayout : public ELFLayout {
1439public:
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001440
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001441 // The order in which the sections appear in the output file
Michael J. Spencera2c97272013-01-04 21:09:21 +00001442 // If its determined, that the layout needs to change
1443 // just changing the order of enumerations would essentially
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001444 // change the layout in the output file
1445 enum DefaultSectionOrder {
1446 ORDER_NOT_DEFINED = 0,
1447 ORDER_INTERP,
1448 ORDER_NOTE,
1449 ORDER_HASH,
1450 ORDER_DYNAMIC_SYMBOLS,
1451 ORDER_DYNAMIC_STRINGS,
1452 ORDER_INIT,
1453 ORDER_TEXT,
1454 ORDER_PLT,
1455 ORDER_FINI,
1456 ORDER_RODATA,
1457 ORDER_EH_FRAME,
1458 ORDER_EH_FRAMEHDR,
1459 ORDER_CTORS,
1460 ORDER_DTORS,
Michael J. Spencerecd5f402013-01-10 22:41:42 +00001461 ORDER_INIT_ARRAY,
1462 ORDER_FINI_ARRAY,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001463 ORDER_DYNAMIC,
1464 ORDER_GOT,
1465 ORDER_GOT_PLT,
1466 ORDER_DATA,
1467 ORDER_BSS,
1468 ORDER_OTHER,
1469 ORDER_SECTION_STRINGS,
1470 ORDER_SYMBOL_TABLE,
1471 ORDER_STRING_TABLE,
1472 ORDER_SECTION_HEADERS
1473 };
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001474
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001475public:
1476
1477 // The Key used for creating Sections
Michael J. Spencera2c97272013-01-04 21:09:21 +00001478 // The sections are created using
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001479 // SectionName, [contentType, contentPermissions]
Michael J. Spencera2c97272013-01-04 21:09:21 +00001480 typedef std::pair<StringRef,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001481 std::pair<int32_t, int32_t>> Key;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001482 typedef typename std::vector<
1483 Chunk<target_endianness, max_align, is64Bits> *>::iterator ChunkIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001484 // The key used for Segments
Michael J. Spencera2c97272013-01-04 21:09:21 +00001485 // The segments are created using
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001486 // SegmentName, Segment flags
1487 typedef std::pair<StringRef, int64_t> SegmentKey;
1488 // Merged Sections contain the map of Sectionnames to a vector of sections,
1489 // that have been merged to form a single section
Michael J. Spencera2c97272013-01-04 21:09:21 +00001490 typedef std::map<StringRef, MergedSections<
1491 target_endianness, max_align, is64Bits> *> MergedSectionMapT;
1492 typedef typename std::vector<MergedSections<
1493 target_endianness, max_align, is64Bits> *>::iterator MergedSectionIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001494
1495 // HashKey for the Section
1496 class HashKey {
1497 public:
1498 int64_t operator() (const Key &k) const {
1499 // k.first = section Name
1500 // k.second = [contentType, Permissions]
1501 return llvm::hash_combine(k.first, k.second.first, k.second.second);
1502 }
1503 };
1504
1505 // HashKey for the Segment
1506 class SegmentHashKey {
1507 public:
1508 int64_t operator() (const SegmentKey &k) const {
1509 // k.first = SegmentName
1510 // k.second = SegmentFlags
1511 return llvm::hash_combine(k.first, k.second);
1512 }
1513 };
1514
Michael J. Spencera2c97272013-01-04 21:09:21 +00001515 typedef std::unordered_map<Key, Section<
1516 target_endianness, max_align, is64Bits>*, HashKey> SectionMapT;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001517 typedef std::unordered_map<SegmentKey,
Michael J. Spencera2c97272013-01-04 21:09:21 +00001518 Segment<target_endianness, max_align, is64Bits>*,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001519 SegmentHashKey> SegmentMapT;
1520
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001521 /// \brief All absolute atoms are created in the ELF Layout by using
1522 /// an AbsoluteAtomPair. Contains a pair of AbsoluteAtom and the
1523 /// value which is the address of the absolute atom
1524 class AbsoluteAtomPair {
1525 public:
1526 AbsoluteAtomPair(const AbsoluteAtom *a, int64_t value)
1527 : _absoluteAtom(a)
1528 , _value(value) { }
1529
1530 const AbsoluteAtom *absoluteAtom() { return _absoluteAtom; }
1531 int64_t value() const { return _value; }
1532 void setValue(int64_t val) { _value = val; }
1533
1534 private:
1535 const AbsoluteAtom *_absoluteAtom;
1536 int64_t _value;
1537 };
1538
1539 /// \brief find a absolute atom pair given a absolute atom name
1540 struct FindByName {
Nick Kledzik343ecbd2013-01-14 22:10:22 +00001541 const std::string _name;
Shankar Easwaranf6dc0822013-01-15 03:02:33 +00001542 FindByName(StringRef name) : _name(name) {}
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001543 bool operator()(AbsoluteAtomPair& j) {
Nick Kledzik343ecbd2013-01-14 22:10:22 +00001544 return j.absoluteAtom()->name() == _name;
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001545 }
1546 };
1547
1548 typedef typename std::vector<AbsoluteAtomPair>::iterator AbsoluteAtomIterT;
1549
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001550 DefaultELFLayout(const WriterOptionsELF &options):_options(options) { }
1551
1552 /// \brief Return the section order for a input section
1553 virtual SectionOrder getSectionOrder
1554 (const StringRef name,
1555 int32_t contentType,
1556 int32_t contentPermissions) {
1557 switch (contentType) {
1558 case DefinedAtom::typeCode:
1559 return llvm::StringSwitch<Reference::Kind>(name)
1560 .StartsWith(".eh_frame_hdr", ORDER_EH_FRAMEHDR)
1561 .StartsWith(".eh_frame", ORDER_EH_FRAME)
1562 .StartsWith(".init", ORDER_INIT)
1563 .StartsWith(".fini", ORDER_FINI)
1564 .StartsWith(".hash", ORDER_HASH)
1565 .Default(ORDER_TEXT);
1566
1567 case DefinedAtom::typeConstant:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001568 return ORDER_RODATA;
1569
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001570 case DefinedAtom::typeData:
Michael J. Spencerecd5f402013-01-10 22:41:42 +00001571 return llvm::StringSwitch<Reference::Kind>(name)
1572 .StartsWith(".init_array", ORDER_INIT_ARRAY)
1573 .Default(ORDER_DATA);
Michael J. Spencera2c97272013-01-04 21:09:21 +00001574
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001575 case DefinedAtom::typeZeroFill:
1576 return ORDER_BSS;
1577
1578 default:
1579 // If we get passed in a section push it to OTHER
Michael J. Spencera2c97272013-01-04 21:09:21 +00001580 if (contentPermissions == DefinedAtom::perm___)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001581 return ORDER_OTHER;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001582
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001583 return ORDER_NOT_DEFINED;
1584 }
1585 }
1586
1587 /// \brief This maps the input sections to the output section names
1588 StringRef getSectionName(const StringRef name,
1589 const int32_t contentType) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001590 if (contentType == DefinedAtom::typeZeroFill)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001591 return ".bss";
Michael J. Spencera2c97272013-01-04 21:09:21 +00001592 if (name.startswith(".text"))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001593 return ".text";
Michael J. Spencera2c97272013-01-04 21:09:21 +00001594 if (name.startswith(".rodata"))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001595 return ".rodata";
1596 return name;
1597 }
1598
1599 /// \brief Gets the segment for a output section
Michael J. Spencera2c97272013-01-04 21:09:21 +00001600 virtual ELFLayout::SegmentType getSegmentType(
1601 Section<target_endianness, max_align, is64Bits> *section) const {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001602 switch(section->order()) {
1603 case ORDER_INTERP:
1604 return llvm::ELF::PT_INTERP;
1605
1606 case ORDER_TEXT:
1607 case ORDER_HASH:
1608 case ORDER_DYNAMIC_SYMBOLS:
1609 case ORDER_DYNAMIC_STRINGS:
1610 case ORDER_INIT:
1611 case ORDER_PLT:
1612 case ORDER_FINI:
1613 case ORDER_RODATA:
1614 case ORDER_EH_FRAME:
1615 case ORDER_EH_FRAMEHDR:
1616 return llvm::ELF::PT_LOAD;
1617
1618 case ORDER_NOTE:
1619 return llvm::ELF::PT_NOTE;
1620
1621 case ORDER_DYNAMIC:
1622 return llvm::ELF::PT_DYNAMIC;
1623
1624 case ORDER_CTORS:
1625 case ORDER_DTORS:
1626 case ORDER_GOT:
1627 return llvm::ELF::PT_GNU_RELRO;
1628
1629 case ORDER_GOT_PLT:
1630 case ORDER_DATA:
1631 case ORDER_BSS:
Michael J. Spencerecd5f402013-01-10 22:41:42 +00001632 case ORDER_INIT_ARRAY:
1633 case ORDER_FINI_ARRAY:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001634 return llvm::ELF::PT_LOAD;
1635
1636 default:
1637 return llvm::ELF::PT_NULL;
1638 }
1639 }
1640
1641 /// \brief Returns true/false depending on whether the section has a Output
1642 // segment or not
Michael J. Spencera2c97272013-01-04 21:09:21 +00001643 static bool hasOutputSegment(Section<target_endianness, max_align,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001644 is64Bits> *section) {
1645 switch(section->order()) {
1646 case ORDER_INTERP:
1647 case ORDER_HASH:
1648 case ORDER_DYNAMIC_SYMBOLS:
1649 case ORDER_DYNAMIC_STRINGS:
1650 case ORDER_INIT:
1651 case ORDER_PLT:
1652 case ORDER_TEXT:
1653 case ORDER_FINI:
1654 case ORDER_RODATA:
1655 case ORDER_EH_FRAME:
1656 case ORDER_EH_FRAMEHDR:
1657 case ORDER_NOTE:
1658 case ORDER_DYNAMIC:
1659 case ORDER_CTORS:
1660 case ORDER_DTORS:
1661 case ORDER_GOT:
1662 case ORDER_GOT_PLT:
1663 case ORDER_DATA:
Michael J. Spencerecd5f402013-01-10 22:41:42 +00001664 case ORDER_INIT_ARRAY:
1665 case ORDER_FINI_ARRAY:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001666 case ORDER_BSS:
1667 return true;
1668
1669 default:
1670 return false;
1671 }
1672 }
1673
1674 // Adds an atom to the section
1675 virtual error_code addAtom(const Atom *atom) {
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001676 if (const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom)) {
1677 const StringRef sectionName =
1678 getSectionName(definedAtom->customSectionName(),
1679 definedAtom->contentType());
1680 const lld::DefinedAtom::ContentPermissions permissions =
1681 definedAtom->permissions();
1682 const lld::DefinedAtom::ContentType contentType =
1683 definedAtom->contentType();
1684 const Key key(sectionName, std::make_pair(contentType, permissions));
1685 const std::pair<Key, Section<target_endianness, max_align, is64Bits> *>
1686 currentSection(key, nullptr);
1687 std::pair<typename SectionMapT::iterator, bool>
1688 sectionInsert(_sectionMap.insert(currentSection));
1689 Section<target_endianness, max_align, is64Bits> *section;
1690 // the section is already in the map
1691 if (!sectionInsert.second) {
1692 section = sectionInsert.first->second;
1693 section->setContentPermissions(permissions);
1694 } else {
1695 SectionOrder section_order = getSectionOrder(sectionName,
1696 contentType,
1697 permissions);
1698 section = new (_allocator.Allocate
1699 <Section<target_endianness, max_align, is64Bits>>())
1700 Section<target_endianness, max_align, is64Bits>
1701 (sectionName, contentType,
1702 permissions, section_order);
1703 sectionInsert.first->second = section;
1704 section->setOrder(section_order);
1705 _sections.push_back(section);
1706 }
1707 section->appendAtom(atom);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001708 }
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001709 // Absolute atoms are not part of any section, they are global for the whole
1710 // link
1711 else if (const AbsoluteAtom *absoluteAtom = dyn_cast<AbsoluteAtom>(atom)) {
1712 _absoluteAtoms.push_back(AbsoluteAtomPair(absoluteAtom,
1713 absoluteAtom->value()));
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001714 }
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001715 else
1716 llvm_unreachable("Only absolute / defined atoms can be added here");
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001717 return error_code::success();
1718 }
1719
Shankar Easwaranb1d09c02013-01-11 18:56:11 +00001720 /// \brief Find an output Section given a section name.
1721 MergedSections<target_endianness, max_align, is64Bits> *
Michael J. Spencerecd5f402013-01-10 22:41:42 +00001722 findOutputSection(StringRef name) {
Shankar Easwaranb1d09c02013-01-11 18:56:11 +00001723 auto iter = _mergedSectionMap.find(name);
1724 if (iter == _mergedSectionMap.end())
1725 return nullptr;
1726 return iter->second;
Michael J. Spencerecd5f402013-01-10 22:41:42 +00001727 }
1728
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001729 /// \brief find a absolute atom given a name
1730 AbsoluteAtomIterT findAbsoluteAtom(const StringRef name) {
1731 return std::find_if(_absoluteAtoms.begin(), _absoluteAtoms.end(),
1732 FindByName(name));
1733 }
1734
1735 /// \bried Begin/End iterators
1736 AbsoluteAtomIterT absAtomsBegin() {
1737 return _absoluteAtoms.begin();
1738 }
1739
1740 AbsoluteAtomIterT absAtomsEnd() {
1741 return _absoluteAtoms.end();
1742 }
1743
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001744 // Merge sections with the same name into a MergedSections
1745 void mergeSimiliarSections() {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001746 MergedSections<target_endianness, max_align, is64Bits> *mergedSection;
1747
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001748 for (auto &si : _sections) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001749 const std::pair<StringRef,
1750 MergedSections<target_endianness, max_align, is64Bits> *>
1751 currentMergedSections(si->name(), nullptr);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001752 std::pair<typename MergedSectionMapT::iterator, bool>
1753 mergedSectionInsert
1754 (_mergedSectionMap.insert(currentMergedSections));
1755 if (!mergedSectionInsert.second) {
1756 mergedSection = mergedSectionInsert.first->second;
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001757 } else {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001758 mergedSection = new (_allocator.Allocate<
1759 MergedSections<target_endianness, max_align, is64Bits>>())
1760 MergedSections<target_endianness, max_align, is64Bits>(si->name());
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001761 _mergedSections.push_back(mergedSection);
1762 mergedSectionInsert.first->second = mergedSection;
1763 }
1764 mergedSection->appendSection(si);
1765 }
1766 }
1767
1768 void assignSectionsToSegments() {
1769 // sort the sections by their order as defined by the layout
1770 std::stable_sort(_sections.begin(), _sections.end(),
Michael J. Spencera2c97272013-01-04 21:09:21 +00001771 [](Chunk<target_endianness, max_align, is64Bits> *A,
1772 Chunk<target_endianness, max_align, is64Bits> *B) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001773 return A->order() < B->order();
1774 });
1775 // Merge all sections
1776 mergeSimiliarSections();
1777 // Set the ordinal after sorting the sections
1778 int ordinal = 1;
1779 for (auto &msi : _mergedSections) {
1780 (*msi).setOrdinal(ordinal);
1781 for (auto ai = (*msi).begin_sections(), ae = (*msi).end_sections();
1782 ai != ae; ++ai) {
1783 (*ai)->setOrdinal(ordinal);
1784 }
1785 ++ordinal;
1786 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001787 for (auto msi = merged_sections_begin(), mse = merged_sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001788 msi != mse; ++msi) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001789 for (auto ai = (*msi)->begin_sections(), ae = (*msi)->end_sections();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001790 ai != ae; ++ai) {
Michael J. Spencer7fe77f82013-01-15 06:55:11 +00001791 if (auto section =
1792 dyn_cast<Section<target_endianness, max_align, is64Bits>>(*ai)) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001793 if (!hasOutputSegment(section))
1794 continue;
1795 (*msi)->setHasSegment();
1796 section->setSegment(getSegmentType(section));
1797 const StringRef segmentName = section->segmentKindToStr();
1798 // Use the flags of the merged Section for the segment
1799 const SegmentKey key(segmentName, (*msi)->flags());
Michael J. Spencera2c97272013-01-04 21:09:21 +00001800 const std::pair<SegmentKey,
1801 Segment<target_endianness, max_align, is64Bits> *>
1802 currentSegment(key, nullptr);
1803 std::pair<typename SegmentMapT::iterator, bool>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001804 segmentInsert(_segmentMap.insert(currentSegment));
Michael J. Spencer7fe77f82013-01-15 06:55:11 +00001805 Segment<target_endianness, max_align, is64Bits> *segment;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001806 if (!segmentInsert.second) {
1807 segment = segmentInsert.first->second;
1808 } else {
1809 segment = new (_allocator.Allocate
Michael J. Spencera2c97272013-01-04 21:09:21 +00001810 <Segment<target_endianness, max_align, is64Bits>>())
1811 Segment<target_endianness, max_align, is64Bits>
1812 (segmentName, getSegmentType(section),
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001813 _options);
1814 segmentInsert.first->second = segment;
1815 _segments.push_back(segment);
1816 }
1817 segment->append(section);
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001818 }
1819 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001820 }
1821 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001822
Michael J. Spencera2c97272013-01-04 21:09:21 +00001823 void addSection(Chunk<target_endianness, max_align, is64Bits> *c) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001824 _sections.push_back(c);
1825 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001826
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001827 void assignFileOffsets() {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001828 std::sort(_segments.begin(),
1829 _segments.end(),
1830 Segment<target_endianness, max_align, is64Bits>::compareSegments);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001831 int ordinal = 0;
1832 // Compute the number of segments that might be needed, so that the
1833 // size of the program header can be computed
1834 uint64_t offset = 0;
1835 for (auto si : _segments) {
1836 si->setOrdinal(++ordinal);
1837 si->assignOffsets(offset);
1838 offset += si->fileSize();
1839 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001840 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001841
Michael J. Spencera2c97272013-01-04 21:09:21 +00001842 void setELFHeader(ELFHeader<target_endianness, max_align, is64Bits> *e) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001843 _elfHeader = e;
1844 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001845
Michael J. Spencera2c97272013-01-04 21:09:21 +00001846 void setProgramHeader(
1847 ELFProgramHeader<target_endianness, max_align, is64Bits> *p) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001848 _programHeader = p;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001849 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001850
1851 void assignVirtualAddress() {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001852 if (_segments.empty())
1853 return;
1854
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001855 uint64_t virtualAddress = _options.baseAddress();
1856
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001857 // HACK: This is a super dirty hack. The elf header and program header are
1858 // not part of a section, but we need them to be loaded at the base address
1859 // so that AT_PHDR is set correctly by the loader and so they are accessible
1860 // at runtime. To do this we simply prepend them to the first Segment and
1861 // let the layout logic take care of it.
1862 _segments[0]->prepend(_programHeader);
1863 _segments[0]->prepend(_elfHeader);
1864
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001865 bool newSegmentHeaderAdded = true;
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001866 while (true) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001867 for (auto si : _segments) {
1868 newSegmentHeaderAdded = _programHeader->addSegment(si);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001869 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001870 if (!newSegmentHeaderAdded)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001871 break;
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001872 uint64_t fileoffset = 0;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001873 uint64_t address = virtualAddress;
1874 // Fix the offsets after adding the program header
1875 for (auto &si : _segments) {
1876 // Align the segment to a page boundary
1877 fileoffset = llvm::RoundUpToAlignment(fileoffset, _options.pageSize());
1878 si->assignOffsets(fileoffset);
1879 fileoffset = si->fileOffset() + si->fileSize();
1880 }
1881 // start assigning virtual addresses
1882 for (auto si = _segments.begin(); si != _segments.end(); ++si) {
1883 (*si)->setVAddr(virtualAddress);
1884 // The first segment has the virtualAddress set to the base address as
1885 // we have added the file header and the program header dont align the
Michael J. Spencera2c97272013-01-04 21:09:21 +00001886 // first segment to the pagesize
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001887 (*si)->assignVirtualAddress(address);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001888 (*si)->setMemSize(address - virtualAddress);
1889 virtualAddress = llvm::RoundUpToAlignment(address, _options.pageSize());
1890 }
1891 _programHeader->resetProgramHeaders();
1892 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001893 Section<target_endianness, max_align, is64Bits> *section;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001894 // Fix the offsets of all the atoms within a section
1895 for (auto &si : _sections) {
Michael J. Spencer7fe77f82013-01-15 06:55:11 +00001896 section = dyn_cast<Section<target_endianness, max_align, is64Bits>>(si);
Michael J. Spencera2c97272013-01-04 21:09:21 +00001897 if (section &&
1898 DefaultELFLayout<target_endianness,
1899 max_align, is64Bits>::hasOutputSegment(section))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001900 section->assignOffsets(section->fileOffset());
1901 }
1902 // Set the size of the merged Sections
Michael J. Spencera2c97272013-01-04 21:09:21 +00001903 for (auto msi = merged_sections_begin(), mse = merged_sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001904 msi != mse; ++msi) {
1905 uint64_t sectionfileoffset = 0;
1906 uint64_t startFileOffset = 0;
1907 uint64_t sectionsize = 0;
1908 bool isFirstSection = true;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001909 for (auto si = (*msi)->begin_sections(); si != (*msi)->end_sections();
1910 ++si) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001911 if (isFirstSection) {
1912 startFileOffset = (*si)->fileOffset();
1913 isFirstSection = false;
1914 }
1915 sectionfileoffset = (*si)->fileOffset();
1916 sectionsize = (*si)->fileSize();
1917 }
1918 sectionsize = (sectionfileoffset - startFileOffset) + sectionsize;
1919 (*msi)->setFileOffset(startFileOffset);
1920 (*msi)->setSize(sectionsize);
1921 }
1922 // Set the virtual addr of the merged Sections
Michael J. Spencera2c97272013-01-04 21:09:21 +00001923 for (auto msi = merged_sections_begin(), mse = merged_sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001924 msi != mse; ++msi) {
1925 uint64_t sectionstartaddr = 0;
1926 uint64_t startaddr = 0;
1927 uint64_t sectionsize = 0;
1928 bool isFirstSection = true;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001929 for (auto si = (*msi)->begin_sections(), se = (*msi)->end_sections();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001930 si != se; ++si) {
1931 if (isFirstSection) {
1932 startaddr = (*si)->virtualAddr();
1933 isFirstSection = false;
1934 }
1935 sectionstartaddr = (*si)->virtualAddr();
1936 sectionsize = (*si)->memSize();
1937 }
1938 sectionsize = (sectionstartaddr - startaddr) + sectionsize;
1939 (*msi)->setMemSize(sectionsize);
1940 (*msi)->setAddr(startaddr);
1941 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001942 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001943
1944 void assignOffsetsForMiscSections() {
1945 uint64_t fileoffset = 0;
1946 uint64_t size = 0;
1947 for (auto si : _segments) {
1948 fileoffset = si->fileOffset();
1949 size = si->fileSize();
1950 }
1951 fileoffset = fileoffset + size;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001952 Section<target_endianness, max_align, is64Bits> *section;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001953 for (auto si : _sections) {
Michael J. Spencer7fe77f82013-01-15 06:55:11 +00001954 section = dyn_cast<Section<target_endianness, max_align, is64Bits>>(si);
Michael J. Spencera2c97272013-01-04 21:09:21 +00001955 if (section &&
1956 DefaultELFLayout<target_endianness,
1957 max_align, is64Bits>::hasOutputSegment(section))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001958 continue;
1959 fileoffset = llvm::RoundUpToAlignment(fileoffset, si->align2());
1960 si->setFileOffset(fileoffset);
1961 si->setVAddr(0);
1962 fileoffset += si->fileSize();
1963 }
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001964 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001965
1966 void finalize() {
1967 for (auto &si : _sections) {
1968 si->finalize();
1969 }
1970 }
1971
1972 bool findAtomAddrByName(const StringRef name, uint64_t &addr) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001973 for (auto ai = _sections.begin(); ai != _sections.end(); ++ai) {
Michael J. Spencer7fe77f82013-01-15 06:55:11 +00001974 if (auto section =
1975 dyn_cast<Section<target_endianness, max_align, is64Bits>>(*ai)) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001976 if (section->findAtomAddrByName(name, addr))
1977 return true;
1978 }
1979 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001980 return false;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001981 }
1982
Michael J. Spencera2c97272013-01-04 21:09:21 +00001983 MergedSectionIter merged_sections_begin() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001984 return _mergedSections.begin();
1985 }
1986
Michael J. Spencera2c97272013-01-04 21:09:21 +00001987 MergedSectionIter merged_sections_end() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001988 return _mergedSections.end();
1989 }
1990
1991 ChunkIter sections_begin() {
1992 return _sections.begin();
1993 }
1994 ChunkIter sections_end() {
1995 return _sections.end();
1996 }
1997
1998 ChunkIter segments_begin() {
1999 return _segments.begin();
2000 }
2001
2002 ChunkIter segments_end() {
2003 return _segments.end();
2004 }
2005
Michael J. Spencera2c97272013-01-04 21:09:21 +00002006 ELFHeader<target_endianness, max_align, is64Bits> *elfHeader() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002007 return _elfHeader;
2008 }
2009
Michael J. Spencera2c97272013-01-04 21:09:21 +00002010 ELFProgramHeader<target_endianness, max_align, is64Bits> *elfProgramHeader() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002011 return _programHeader;
Hemant Kulkarni08e410292012-10-01 23:53:20 +00002012 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002013
2014private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002015 SectionMapT _sectionMap;
2016 MergedSectionMapT _mergedSectionMap;
2017 SegmentMapT _segmentMap;
Michael J. Spencera2c97272013-01-04 21:09:21 +00002018 std::vector<Chunk<target_endianness, max_align, is64Bits> *> _sections;
2019 std::vector<Segment<target_endianness, max_align, is64Bits> *> _segments;
2020 std::vector<MergedSections<target_endianness, max_align, is64Bits> *>
2021 _mergedSections;
2022 ELFHeader<target_endianness, max_align, is64Bits> *_elfHeader;
2023 ELFProgramHeader<target_endianness, max_align, is64Bits> *_programHeader;
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002024 std::vector<AbsoluteAtomPair> _absoluteAtoms;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002025 llvm::BumpPtrAllocator _allocator;
2026 const WriterOptionsELF &_options;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002027};
2028
2029//===----------------------------------------------------------------------===//
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002030// ELFExecutableWriter Class
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002031//===----------------------------------------------------------------------===//
Michael J. Spencera2c97272013-01-04 21:09:21 +00002032template<support::endianness target_endianness,
2033 std::size_t max_align,
2034 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002035class ELFExecutableWriter : public ELFWriter {
2036public:
Michael J. Spencera2c97272013-01-04 21:09:21 +00002037 typedef Elf_Shdr_Impl<target_endianness, max_align, is64Bits> Elf_Shdr;
2038 typedef Elf_Sym_Impl<target_endianness, max_align, is64Bits> Elf_Sym;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002039
2040 ELFExecutableWriter(const WriterOptionsELF &options);
2041
2042private:
Michael J. Spencera2c97272013-01-04 21:09:21 +00002043 // build the sections that need to be created
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002044 void buildChunks(const lld::File &file);
2045 virtual error_code writeFile(const lld::File &File, StringRef path);
2046 void buildAtomToAddressMap();
2047 void buildSymbolTable ();
2048 void buildSectionHeaderTable();
2049 void assignSectionsWithNoSegments();
2050 void addAbsoluteUndefinedSymbols(const lld::File &File);
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002051 void addDefaultAtoms();
2052 void addFiles(InputFiles&);
2053 void finalizeDefaultAtomValues();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002054
Michael J. Spencera2c97272013-01-04 21:09:21 +00002055 uint64_t addressOfAtom(const Atom *atom) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002056 return _atomToAddressMap[atom];
2057 }
2058
2059 KindHandler *kindHandler() { return _referenceKindHandler.get(); }
2060
2061 void createDefaultSections();
2062
2063 const WriterOptionsELF &_options;
2064
2065 typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
2066 std::unique_ptr<KindHandler> _referenceKindHandler;
2067 AtomToAddress _atomToAddressMap;
2068 llvm::BumpPtrAllocator _chunkAllocate;
Michael J. Spencera2c97272013-01-04 21:09:21 +00002069 DefaultELFLayout<target_endianness, max_align, is64Bits> *_layout;
2070 ELFHeader<target_endianness, max_align, is64Bits> *_elfHeader;
2071 ELFProgramHeader<target_endianness, max_align, is64Bits> *_programHeader;
2072 ELFSymbolTable<target_endianness, max_align, is64Bits> * _symtab;
2073 ELFStringTable<target_endianness, max_align, is64Bits> *_strtab;
2074 ELFStringTable<target_endianness, max_align, is64Bits> *_shstrtab;
2075 ELFSectionHeader<target_endianness, max_align, is64Bits> *_shdrtab;
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002076 CRuntimeFile<target_endianness, max_align, is64Bits> _runtimeFile;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002077};
2078
2079//===----------------------------------------------------------------------===//
2080// ELFExecutableWriter
2081//===----------------------------------------------------------------------===//
Michael J. Spencera2c97272013-01-04 21:09:21 +00002082template<support::endianness target_endianness,
2083 std::size_t max_align,
2084 bool is64Bits>
2085ELFExecutableWriter<target_endianness, max_align, is64Bits>
2086 ::ELFExecutableWriter(const WriterOptionsELF &options)
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002087 : _options(options)
Sid Manning42064e52012-10-09 02:20:47 +00002088 , _referenceKindHandler(KindHandler::makeHandler(_options.machine(),
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002089 target_endianness))
2090 , _runtimeFile(options) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002091 _layout =
2092 new DefaultELFLayout<target_endianness, max_align, is64Bits>(options);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002093}
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002094
Michael J. Spencera2c97272013-01-04 21:09:21 +00002095template<support::endianness target_endianness,
2096 std::size_t max_align,
2097 bool is64Bits>
2098void ELFExecutableWriter<target_endianness, max_align, is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002099 ::buildChunks(const lld::File &file){
2100 for (const DefinedAtom *definedAtom : file.defined() ) {
2101 _layout->addAtom(definedAtom);
2102 }
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002103 /// Add all the absolute atoms to the layout
2104 for (const AbsoluteAtom *absoluteAtom : file.absolute()) {
2105 _layout->addAtom(absoluteAtom);
2106 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002107}
2108
Michael J. Spencera2c97272013-01-04 21:09:21 +00002109template<support::endianness target_endianness,
2110 std::size_t max_align,
2111 bool is64Bits>
2112void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2113 ::buildSymbolTable () {
2114 Section<target_endianness, max_align, is64Bits> *section;
2115 for (auto si = _layout->sections_begin(); si != _layout->sections_end();
2116 ++si) {
Michael J. Spencer7fe77f82013-01-15 06:55:11 +00002117 if (auto section =
2118 dyn_cast<Section<target_endianness, max_align, is64Bits>>(*si)) {
2119 for (auto ai = section->atoms_begin(); ai != section->atoms_end(); ++ai) {
2120 _symtab->addSymbol(ai->_atom, section->ordinal(), ai->_virtualAddr);
2121 }
Hemant Kulkarni736f7fb2012-11-21 21:07:36 +00002122 }
2123 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002124}
2125
Michael J. Spencera2c97272013-01-04 21:09:21 +00002126template<support::endianness target_endianness,
2127 std::size_t max_align,
2128 bool is64Bits>
2129void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2130 ::addAbsoluteUndefinedSymbols(const lld::File &file) {
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002131 /// add all the absolute symbols that the layout contains to the output symbol
2132 /// table
2133 for (auto absi = _layout->absAtomsBegin(), abse = _layout->absAtomsEnd();
2134 absi != abse; ++absi) {
2135 _symtab->addSymbol(absi->absoluteAtom(), ELF::SHN_ABS, absi->value());
2136 }
Hemant Kulkarni08e410292012-10-01 23:53:20 +00002137 for (const UndefinedAtom *a : file.undefined()) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002138 _symtab->addSymbol(a, ELF::SHN_UNDEF);
Hemant Kulkarni08e410292012-10-01 23:53:20 +00002139 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002140}
2141
Michael J. Spencera2c97272013-01-04 21:09:21 +00002142template<support::endianness target_endianness,
2143 std::size_t max_align,
2144 bool is64Bits>
2145void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2146 ::buildAtomToAddressMap () {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002147 for (auto si = _layout->sections_begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002148 si != _layout->sections_end(); ++si) {
Michael J. Spencer7fe77f82013-01-15 06:55:11 +00002149 if (auto section =
2150 dyn_cast<Section<target_endianness, max_align, is64Bits>>(*si))
2151 for (auto ai = section->atoms_begin(); ai != section->atoms_end(); ++ai) {
2152 _atomToAddressMap[ai->_atom] = (ai)->_virtualAddr;
2153 }
Sid Manningdd110202012-09-25 18:22:09 +00002154 }
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002155 /// build the atomToAddressMap that contains absolute symbols too
2156 for (auto absi = _layout->absAtomsBegin(), abse = _layout->absAtomsEnd();
2157 absi != abse; ++absi) {
2158 _atomToAddressMap[absi->absoluteAtom()] = absi->value();
2159 }
Sid Manningdd110202012-09-25 18:22:09 +00002160}
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002161
Michael J. Spencera2c97272013-01-04 21:09:21 +00002162template<support::endianness target_endianness,
2163 std::size_t max_align,
2164 bool is64Bits>
2165void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2166 ::buildSectionHeaderTable() {
2167 for (auto msi = _layout->merged_sections_begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002168 msi != _layout->merged_sections_end(); ++msi) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002169 if ((*msi)->kind() !=
2170 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002171 continue;
2172 if ((*msi)->hasSegment())
2173 _shdrtab->appendSection(*msi);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002174 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002175}
2176
Michael J. Spencera2c97272013-01-04 21:09:21 +00002177template<support::endianness target_endianness,
2178 std::size_t max_align,
2179 bool is64Bits>
2180void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2181 ::assignSectionsWithNoSegments() {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002182 for (auto msi = _layout->merged_sections_begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002183 msi != _layout->merged_sections_end(); ++msi) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002184 if ((*msi)->kind() !=
2185 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002186 continue;
2187 if (!(*msi)->hasSegment())
2188 _shdrtab->appendSection(*msi);
2189 }
2190 _layout->assignOffsetsForMiscSections();
Michael J. Spencera2c97272013-01-04 21:09:21 +00002191 for (auto si = _layout->sections_begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002192 si != _layout->sections_end(); ++si) {
Michael J. Spencer7fe77f82013-01-15 06:55:11 +00002193 if (auto section =
2194 dyn_cast<Section<target_endianness, max_align, is64Bits>>(*si))
2195 if (!DefaultELFLayout<target_endianness, max_align, is64Bits>
2196 ::hasOutputSegment(section))
2197 _shdrtab->updateSection(section);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002198 }
2199}
2200
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002201/// \brief Add absolute symbols by default. These are linker added
2202/// absolute symbols
2203template<support::endianness target_endianness,
2204 std::size_t max_align,
2205 bool is64Bits>
2206void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2207 ::addDefaultAtoms() {
2208 _runtimeFile.addUndefinedAtom("_start");
2209 _runtimeFile.addAbsoluteAtom("__bss_start");
2210 _runtimeFile.addAbsoluteAtom("__bss_end");
2211 _runtimeFile.addAbsoluteAtom("_end");
2212 _runtimeFile.addAbsoluteAtom("end");
Michael J. Spencerecd5f402013-01-10 22:41:42 +00002213 _runtimeFile.addAbsoluteAtom("__init_array_start");
2214 _runtimeFile.addAbsoluteAtom("__init_array_end");
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002215}
2216
2217/// \brief Hook in lld to add CRuntime file
2218template<support::endianness target_endianness,
2219 std::size_t max_align,
2220 bool is64Bits>
2221void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2222 ::addFiles(InputFiles &inputFiles) {
2223 addDefaultAtoms();
2224 inputFiles.prependFile(_runtimeFile);
2225}
2226
2227/// Finalize the value of all the absolute symbols that we
2228/// created
2229template<support::endianness target_endianness,
2230 std::size_t max_align,
2231 bool is64Bits>
2232void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2233 ::finalizeDefaultAtomValues() {
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002234 auto bssStartAtomIter = _layout->findAbsoluteAtom("__bss_start");
2235 auto bssEndAtomIter = _layout->findAbsoluteAtom("__bss_end");
2236 auto underScoreEndAtomIter = _layout->findAbsoluteAtom("_end");
2237 auto endAtomIter = _layout->findAbsoluteAtom("end");
Michael J. Spencerecd5f402013-01-10 22:41:42 +00002238 auto initArrayStartIter = _layout->findAbsoluteAtom("__init_array_start");
2239 auto initArrayEndIter = _layout->findAbsoluteAtom("__init_array_end");
2240
2241 auto section = _layout->findOutputSection(".init_array");
2242 if (section) {
2243 initArrayStartIter->setValue(section->virtualAddr());
2244 initArrayEndIter->setValue(section->virtualAddr() +
2245 section->memSize());
2246 } else {
2247 initArrayStartIter->setValue(0);
2248 initArrayEndIter->setValue(0);
2249 }
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002250
Michael J. Spenceraa8a5a22013-01-10 22:41:05 +00002251 assert(!(bssStartAtomIter == _layout->absAtomsEnd() ||
2252 bssEndAtomIter == _layout->absAtomsEnd() ||
2253 underScoreEndAtomIter == _layout->absAtomsEnd() ||
2254 endAtomIter == _layout->absAtomsEnd()) &&
Shankar Easwaran37c52822013-01-10 18:16:10 +00002255 "Unable to find the absolute atoms that have been added by lld");
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002256
2257 auto phe = _programHeader->findProgramHeader(
2258 llvm::ELF::PT_LOAD,
2259 llvm::ELF::PF_W,
2260 llvm::ELF::PF_X);
2261
Shankar Easwaran37c52822013-01-10 18:16:10 +00002262 assert(!(phe == _programHeader->end()) &&
2263 "Can't find a data segment in the program header!");
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002264
2265 bssStartAtomIter->setValue((*phe)->p_vaddr+(*phe)->p_filesz);
2266 bssEndAtomIter->setValue((*phe)->p_vaddr+(*phe)->p_memsz);
2267 underScoreEndAtomIter->setValue((*phe)->p_vaddr+(*phe)->p_memsz);
2268 endAtomIter->setValue((*phe)->p_vaddr+(*phe)->p_memsz);
2269}
2270
Michael J. Spencera2c97272013-01-04 21:09:21 +00002271template<support::endianness target_endianness,
2272 std::size_t max_align,
2273 bool is64Bits>
2274error_code ELFExecutableWriter<target_endianness, max_align, is64Bits>
2275 ::writeFile(const lld::File &file, StringRef path) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002276 buildChunks(file);
2277 // Create the default sections like the symbol table, string table, and the
2278 // section string table
2279 createDefaultSections();
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002280
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002281 // Set the Layout
2282 _layout->assignSectionsToSegments();
2283 _layout->assignFileOffsets();
2284 _layout->assignVirtualAddress();
2285
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002286 // Finalize the default value of symbols that the linker adds
2287 finalizeDefaultAtomValues();
2288
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002289 // Build the Atom To Address map for applying relocations
2290 buildAtomToAddressMap();
2291
2292 // Create symbol table and section string table
2293 buildSymbolTable();
2294
2295 // add other symbols
2296 addAbsoluteUndefinedSymbols(file);
2297
2298 // Finalize the layout by calling the finalize() functions
2299 _layout->finalize();
2300
2301 // build Section Header table
2302 buildSectionHeaderTable();
2303
2304 // assign Offsets and virtual addresses
2305 // for sections with no segments
2306 assignSectionsWithNoSegments();
2307
2308 uint64_t totalSize = _shdrtab->fileOffset() + _shdrtab->fileSize();
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002309
2310 OwningPtr<FileOutputBuffer> buffer;
2311 error_code ec = FileOutputBuffer::create(path,
2312 totalSize, buffer,
2313 FileOutputBuffer::F_executable);
2314 if (ec)
2315 return ec;
2316
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002317 _elfHeader->e_ident(ELF::EI_CLASS, (_options.is64Bit() ? ELF::ELFCLASS64
2318 : ELF::ELFCLASS32));
Michael J. Spencera2c97272013-01-04 21:09:21 +00002319 _elfHeader->e_ident(ELF::EI_DATA, _options.endianness() == llvm::support::big
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002320 ? ELF::ELFDATA2MSB : ELF::ELFDATA2LSB);
2321 _elfHeader->e_ident(ELF::EI_VERSION, 1);
2322 _elfHeader->e_ident(ELF::EI_OSABI, 0);
2323 _elfHeader->e_type(_options.type());
2324 _elfHeader->e_machine(_options.machine());
2325 _elfHeader->e_version(1);
2326 _elfHeader->e_entry(0ULL);
2327 _elfHeader->e_phoff(_programHeader->fileOffset());
2328 _elfHeader->e_shoff(_shdrtab->fileOffset());
2329 _elfHeader->e_phentsize(_programHeader->entsize());
2330 _elfHeader->e_phnum(_programHeader->numHeaders());
2331 _elfHeader->e_shentsize(_shdrtab->entsize());
2332 _elfHeader->e_shnum(_shdrtab->numHeaders());
2333 _elfHeader->e_shstrndx(_shstrtab->ordinal());
2334 uint64_t virtualAddr = 0;
2335 _layout->findAtomAddrByName("_start", virtualAddr);
2336 _elfHeader->e_entry(virtualAddr);
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00002337
2338 // HACK: We have to write out the header and program header here even though
2339 // they are a member of a segment because only sections are written in the
2340 // following loop.
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002341 _elfHeader->write(this, buffer);
2342 _programHeader->write(this, buffer);
2343
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00002344 for (auto si = _layout->sections_begin(); si != _layout->sections_end(); ++si)
2345 (*si)->write(this, buffer);
2346
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002347 return buffer->commit();
2348}
Nick Kledzikabb69812012-05-31 22:34:00 +00002349
Michael J. Spencera2c97272013-01-04 21:09:21 +00002350template<support::endianness target_endianness,
2351 std::size_t max_align,
2352 bool is64Bits>
2353void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2354 ::createDefaultSections() {
2355 _elfHeader =
2356 new ELFHeader<target_endianness, max_align, is64Bits>();
2357 _programHeader =
2358 new ELFProgramHeader<target_endianness, max_align, is64Bits>();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002359 _layout->setELFHeader(_elfHeader);
2360 _layout->setProgramHeader(_programHeader);
2361
Michael J. Spencera2c97272013-01-04 21:09:21 +00002362 _symtab = new ELFSymbolTable<target_endianness, max_align, is64Bits>(
2363 ".symtab",
2364 DefaultELFLayout<target_endianness, max_align, is64Bits>
2365 ::ORDER_SYMBOL_TABLE);
2366 _strtab = new ELFStringTable<target_endianness, max_align, is64Bits>(
2367 ".strtab",
2368 DefaultELFLayout<target_endianness, max_align, is64Bits>
2369 ::ORDER_STRING_TABLE);
2370 _shstrtab = new ELFStringTable<target_endianness, max_align, is64Bits>(
2371 ".shstrtab",
2372 DefaultELFLayout<target_endianness, max_align, is64Bits>
2373 ::ORDER_SECTION_STRINGS);
2374 _shdrtab = new ELFSectionHeader<target_endianness, max_align, is64Bits>(
2375 DefaultELFLayout<target_endianness, max_align, is64Bits>
2376 ::ORDER_SECTION_HEADERS);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002377 _layout->addSection(_symtab);
2378 _layout->addSection(_strtab);
2379 _layout->addSection(_shstrtab);
2380 _shdrtab->setStringSection(_shstrtab);
2381 _symtab->setStringSection(_strtab);
2382 _layout->addSection(_shdrtab);
Sid Manningdd110202012-09-25 18:22:09 +00002383}
Nick Kledzikabb69812012-05-31 22:34:00 +00002384} // namespace elf
2385
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002386Writer *createWriterELF(const WriterOptionsELF &options) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002387 // Set the default layout to be the static executable layout
Michael J. Spencera2c97272013-01-04 21:09:21 +00002388 // We would set the layout to a dynamic executable layout
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002389 // if we came across any shared libraries in the process
Michael J. Spencera2c97272013-01-04 21:09:21 +00002390
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002391 if (!options.is64Bit() && options.endianness() == llvm::support::little)
Michael J. Spencera2c97272013-01-04 21:09:21 +00002392 return new elf::ELFExecutableWriter<support::little, 4, false>(options);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002393 else if (options.is64Bit() && options.endianness() == llvm::support::little)
Michael J. Spencera2c97272013-01-04 21:09:21 +00002394 return new elf::ELFExecutableWriter<support::little, 8, true>(options);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002395 else if (!options.is64Bit() && options.endianness() == llvm::support::big)
Michael J. Spencera2c97272013-01-04 21:09:21 +00002396 return new elf::ELFExecutableWriter<support::big, 4, false>(options);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002397 else if (options.is64Bit() && options.endianness() == llvm::support::big)
Michael J. Spencera2c97272013-01-04 21:09:21 +00002398 return new elf::ELFExecutableWriter<support::big, 8, true>(options);
Nick Kledzikabb69812012-05-31 22:34:00 +00002399
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002400 llvm_unreachable("Invalid Options!");
Nick Kledzikabb69812012-05-31 22:34:00 +00002401}
Nick Kledzikabb69812012-05-31 22:34:00 +00002402} // namespace lld