blob: 3bf5427badcb804d808c5c6c02bbe2d6ef008493 [file] [log] [blame]
Nick Kledzikabb69812012-05-31 22:34:00 +00001//===- lib/ReaderWriter/ELF/WriterELF.cpp ---------------------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lld/ReaderWriter/WriterELF.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000011#include "ReferenceKinds.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000012
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000013#include "lld/Core/DefinedAtom.h"
14#include "lld/Core/File.h"
15#include "lld/Core/InputFiles.h"
16#include "lld/Core/Reference.h"
17#include "lld/Core/SharedLibraryAtom.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000018#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/DenseMap.h"
Shankar Easwaran495d38b2012-12-27 02:26:30 +000020#include "llvm/ADT/Hashing.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000021#include "llvm/ADT/OwningPtr.h"
22#include "llvm/ADT/SmallVector.h"
Shankar Easwaran495d38b2012-12-27 02:26:30 +000023#include "llvm/ADT/StringExtras.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000024#include "llvm/ADT/StringMap.h"
25#include "llvm/ADT/StringRef.h"
Shankar Easwaran495d38b2012-12-27 02:26:30 +000026#include "llvm/ADT/StringSwitch.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000027#include "llvm/Object/ELF.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000028#include "llvm/Support/Allocator.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000029#include "llvm/Support/Debug.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000030#include "llvm/Support/ELF.h"
31#include "llvm/Support/ErrorHandling.h"
32#include "llvm/Support/FileOutputBuffer.h"
33#include "llvm/Support/Format.h"
34#include "llvm/Support/MathExtras.h"
35#include "llvm/Support/raw_ostream.h"
36#include "llvm/Support/system_error.h"
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +000037#include "ExecutableAtoms.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000038
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000039#include <map>
Shankar Easwaran495d38b2012-12-27 02:26:30 +000040#include <unordered_map>
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000041#include <tuple>
42#include <vector>
Nick Kledzikabb69812012-05-31 22:34:00 +000043
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000044using namespace llvm;
45using namespace llvm::object;
Nick Kledzikabb69812012-05-31 22:34:00 +000046namespace lld {
47namespace elf {
Michael J. Spencera2c97272013-01-04 21:09:21 +000048template<support::endianness target_endianness,
49 std::size_t max_align,
50 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +000051class ELFExecutableWriter;
Hemant Kulkarni87dbac02012-11-13 21:34:45 +000052
Shankar Easwaran495d38b2012-12-27 02:26:30 +000053/// \brief The ELFWriter class is a base class for the linker to write
54/// various kinds of ELF files.
55class ELFWriter : public Writer {
Michael J. Spencera2c97272013-01-04 21:09:21 +000056public:
57 ELFWriter() { }
Shankar Easwaran495d38b2012-12-27 02:26:30 +000058
Michael J. Spencera2c97272013-01-04 21:09:21 +000059public:
60 /// \brief builds the chunks that needs to be written to the output
61 /// ELF file
62 virtual void buildChunks(const lld::File &file) = 0;
Shankar Easwaran495d38b2012-12-27 02:26:30 +000063
Michael J. Spencera2c97272013-01-04 21:09:21 +000064 /// \brief Writes the chunks into the output file specified by path
65 virtual error_code writeFile(const lld::File &File, StringRef path) = 0;
Shankar Easwaran495d38b2012-12-27 02:26:30 +000066
Michael J. Spencera2c97272013-01-04 21:09:21 +000067 /// \brief Writes the chunks into the output file specified by path
68 virtual uint64_t addressOfAtom(const Atom *atom) = 0;
Shankar Easwaran495d38b2012-12-27 02:26:30 +000069
Michael J. Spencera2c97272013-01-04 21:09:21 +000070 /// \brief Return the processing function to apply Relocations
71 virtual KindHandler *kindHandler() = 0;
Hemant Kulkarni87dbac02012-11-13 21:34:45 +000072};
73
Shankar Easwaran495d38b2012-12-27 02:26:30 +000074/// \brief A chunk is a contiguous region of space
Michael J. Spencera2c97272013-01-04 21:09:21 +000075template<support::endianness target_endianness,
76 std::size_t max_align,
77 bool is64Bits>
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000078class Chunk {
79public:
Shankar Easwaran495d38b2012-12-27 02:26:30 +000080
81 /// \brief Describes the type of Chunk
82 enum Kind {
83 K_ELFHeader, // ELF Header
84 K_ELFProgramHeader, // Program Header
85 K_ELFSegment, // Segment
86 K_ELFSection, // Section
87 K_ELFSectionHeader // Section header
Hemant Kulkarni87dbac02012-11-13 21:34:45 +000088 };
Michael J. Spencera2c97272013-01-04 21:09:21 +000089 Chunk(StringRef name, Kind kind)
Shankar Easwaran495d38b2012-12-27 02:26:30 +000090 : _name(name)
91 , _kind(kind)
92 , _fsize(0)
93 , _msize(0)
94 , _align2(0)
95 , _order(0)
96 , _ordinal(1)
97 , _start(0)
98 , _fileoffset(0) {}
99 virtual ~Chunk() {}
Michael J. Spencera2c97272013-01-04 21:09:21 +0000100 // Does the chunk occupy disk space
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000101 virtual bool occupiesNoDiskSpace() const {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000102 return false;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000103 }
104 // The name of the chunk
105 StringRef name() const { return _name; }
106 // Kind of chunk
107 Kind kind() const { return _kind; }
108 uint64_t fileSize() const { return _fsize; }
109 uint64_t align2() const { return _align2; }
110 void appendAtom() const;
111
112 // The ordinal value of the chunk
113 uint64_t ordinal() const { return _ordinal;}
114 void setOrdinal(uint64_t newVal) { _ordinal = newVal;}
115 // The order in which the chunk would appear in the output file
116 uint64_t order() const { return _order; }
117 void setOrder(uint32_t order) { _order = order; }
118 // Output file offset of the chunk
119 uint64_t fileOffset() const { return _fileoffset; }
120 void setFileOffset(uint64_t offset) { _fileoffset = offset; }
121 // Output start address of the chunk
122 void setVAddr(uint64_t start) { _start = start; }
123 uint64_t virtualAddr() const { return _start; }
124 // Does the chunk occupy memory during execution ?
125 uint64_t memSize() const { return _msize; }
126 void setMemSize(uint64_t msize) { _msize = msize; }
Michael J. Spencera2c97272013-01-04 21:09:21 +0000127 // Writer the chunk
128 virtual void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000129 OwningPtr<FileOutputBuffer> &buffer) = 0;
130 // Finalize the chunk before writing
131 virtual void finalize() = 0;
132
Hemant Kulkarni927bbc22012-09-14 16:11:34 +0000133protected:
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000134 StringRef _name;
135 Kind _kind;
136 uint64_t _fsize;
137 uint64_t _msize;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +0000138 uint64_t _align2;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000139 uint32_t _order;
Hemant Kulkarni08e410292012-10-01 23:53:20 +0000140 uint64_t _ordinal;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000141 uint64_t _start;
142 uint64_t _fileoffset;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +0000143};
144
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000145/// \brief The ELFLayoutOptions encapsulates the options used by all Layouts
146/// Examples of the ELFLayoutOptions would be a script that would be used
Michael J. Spencera2c97272013-01-04 21:09:21 +0000147/// to drive the layout
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000148class ELFLayoutOptions {
Hemant Kulkarni927bbc22012-09-14 16:11:34 +0000149public:
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000150 ELFLayoutOptions() { }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +0000151
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000152 ELFLayoutOptions(StringRef &linker_script) : _script(linker_script)
153 {}
Hemant Kulkarni87dbac02012-11-13 21:34:45 +0000154
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000155 /// parse the linker script
156 error_code parseLinkerScript();
Hemant Kulkarni736f7fb2012-11-21 21:07:36 +0000157
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000158 /// Is the current section present in the linker script
159 bool isSectionPresent();
160
Hemant Kulkarni08e410292012-10-01 23:53:20 +0000161private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000162 StringRef _script;
Hemant Kulkarni08e410292012-10-01 23:53:20 +0000163};
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000164
Michael J. Spencera2c97272013-01-04 21:09:21 +0000165/// \brief The ELFLayout is an abstract class for managing the final layout for
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000166/// the kind of binaries(Shared Libraries / Relocatables / Executables 0
Michael J. Spencera2c97272013-01-04 21:09:21 +0000167/// Each architecture (Hexagon, PowerPC, MIPS) would have a concrete
168/// subclass derived from ELFLayout for generating each binary thats
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000169// needed by the lld linker
170class ELFLayout {
171public:
172 typedef uint32_t SectionOrder;
173 typedef uint32_t SegmentType;
174 typedef uint32_t Flags;
175
176public:
177 /// Return the order the section would appear in the output file
178 virtual SectionOrder getSectionOrder
179 (const StringRef name,
180 int32_t contentType,
181 int32_t contentPerm) = 0;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000182 /// append the Atom to the layout and create appropriate sections
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000183 virtual error_code addAtom(const Atom *atom) = 0;
184 /// find the Atom Address in the current layout
185 virtual bool findAtomAddrByName(const StringRef name, uint64_t &addr) = 0;
186 /// associates a section to a segment
187 virtual void assignSectionsToSegments() = 0;
188 /// associates a virtual address to the segment, section, and the atom
189 virtual void assignVirtualAddress() = 0;
190 /// associates a file offset to the segment, section and the atom
191 virtual void assignFileOffsets() = 0;
192
193public:
194 ELFLayout() {}
Michael J. Spencera2c97272013-01-04 21:09:21 +0000195 ELFLayout(WriterOptionsELF &writerOptions,
196 ELFLayoutOptions &layoutOptions)
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000197 : _writerOptions(writerOptions)
198 , _layoutOptions(layoutOptions) {}
199 virtual ~ELFLayout() { }
200
201private:
202 WriterOptionsELF _writerOptions;
203 ELFLayoutOptions _layoutOptions;
204};
205
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();
274 const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom);
275 assert(atom != nullptr && "Expecting the atom to be a DefinedAtom");
276 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. Spencer4ffbd602013-01-11 22:39:44 +0000471 const DefinedAtom *definedAtom = llvm::dyn_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. Spencera2c97272013-01-04 21:09:21 +0000573 if (c->kind() ==
574 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection) {
575 Section<target_endianness, max_align, is64Bits> *section;
576 section =
577 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(c);
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000578 _link = section->link();
579 _shInfo = section->shinfo();
580 _entSize = section->entsize();
581 _type = section->type();
582 if (_flags < section->flags())
583 _flags = section->flags();
584 }
585 _kind = c->kind();
586 _sections.push_back(c);
587 }
588
589 // Iterators
Michael J. Spencera2c97272013-01-04 21:09:21 +0000590 typedef typename std::vector<
591 Chunk<target_endianness, max_align, is64Bits> *>::iterator ChunkIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000592
593 ChunkIter begin_sections() { return _sections.begin(); }
594
595 ChunkIter end_sections() { return _sections.end(); }
596
597 // The below functions returns the properties of the MergeSection
598 bool hasSegment() const { return _hasSegment; }
599
600 StringRef name() const { return _name; }
601
602 int64_t shinfo() const { return _shInfo; }
603
604 uint64_t align2() const { return _align2; }
605
606 int64_t link() const { return _link; }
607
608 int64_t type() const { return _type; }
609
610 uint64_t virtualAddr() const { return _virtualAddr; }
611
612 int64_t ordinal() const { return _ordinal; }
613
614 int64_t kind() const { return _kind; }
615
616 uint64_t fileSize() const { return _size; }
617
618 int64_t entsize() const { return _entSize; }
619
620 uint64_t fileOffset() const { return _fileOffset; }
621
622 int64_t flags() const { return _flags; }
623
624 uint64_t memSize() { return _memSize; }
625
626private:
627 StringRef _name;
628 bool _hasSegment;
629 uint64_t _ordinal;
630 int64_t _flags;
631 uint64_t _size;
632 uint64_t _memSize;
633 uint64_t _fileOffset;
634 uint64_t _virtualAddr;
635 int64_t _shInfo;
636 int64_t _entSize;
637 int64_t _link;
638 uint64_t _align2;
639 int64_t _kind;
640 int64_t _type;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000641 std::vector<Chunk<target_endianness, max_align, is64Bits> *> _sections;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000642};
643
Michael J. Spencera2c97272013-01-04 21:09:21 +0000644/// \brief A segment can be divided into segment slices
645/// depending on how the segments can be split
646template<support::endianness target_endianness,
647 std::size_t max_align,
648 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000649class SegmentSlice {
650public:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000651 typedef typename std::vector<
Michael J. Spencer00b702c2013-01-07 07:59:46 +0000652 Chunk<target_endianness, max_align, is64Bits> *>::iterator sectionIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000653
654 SegmentSlice() { }
655
656 /// Set the segment slice so that it begins at the offset specified
Michael J. Spencera2c97272013-01-04 21:09:21 +0000657 /// by fileoffset and set the start of the slice to be s and the end
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000658 /// of the slice to be e
659 void set(uint64_t fileoffset, int32_t s, int e) {
660 _startSection = s;
661 _endSection = e+1;
662 _offset = fileoffset;
663 }
664
665 // Set the segment slice start and end iterators. This is used to walk through
666 // the sections that are part of the Segment slice
667 void setSections(sectionIter start, sectionIter end) {
668 _startSectionIter = start;
669 _endSectionIter = end;
670 }
671
672 // Return the fileOffset of the slice
673 uint64_t fileOffset() const { return _offset; }
674
675 // Return the size of the slice
676 uint64_t fileSize() const { return _size; }
677
678 // Return the start of the slice
679 int32_t startSection() const { return _startSection; }
680
681 // Return the start address of the slice
682 uint64_t virtualAddr() const { return _addr; }
683
684 // Return the memory size of the slice
685 uint64_t memSize() const { return _memSize; }
686
687 // Return the alignment of the slice
688 uint64_t align2() const { return _align2; }
689
690 void setSize(uint64_t sz) { _size = sz; }
691
692 void setMemSize(uint64_t memsz) { _memSize = memsz; }
693
694 void setVAddr(uint64_t addr) { _addr = addr; }
695
696 void setAlign(uint64_t align) { _align2 = align; }
697
Michael J. Spencera2c97272013-01-04 21:09:21 +0000698 static bool compare_slices(
699 SegmentSlice<target_endianness, max_align, is64Bits> *a,
700 SegmentSlice<target_endianness, max_align, is64Bits> *b) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000701 return (a->startSection() < b->startSection());
702 }
703
704 // Functions to run through the slice
705 sectionIter sections_begin() { return _startSectionIter; }
706
707 sectionIter sections_end() { return _endSectionIter; }
708
709private:
710 int32_t _startSection;
711 int32_t _endSection;
712 sectionIter _startSectionIter;
713 sectionIter _endSectionIter;
714 uint64_t _addr;
715 uint64_t _offset;
716 uint64_t _size;
717 uint64_t _align2;
718 uint64_t _memSize;
719};
720
721/// \brief A segment contains a set of sections, that have similiar properties
722// the sections are already seperated based on different flags and properties
723// the segment is just a way to concatenate sections to segments
Michael J. Spencera2c97272013-01-04 21:09:21 +0000724template<support::endianness target_endianness,
725 std::size_t max_align,
726 bool is64Bits>
727class Segment : public Chunk<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000728public:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000729 typedef typename std::vector<SegmentSlice<
730 target_endianness, max_align, is64Bits> *>::iterator slice_iter;
731 typedef typename std::vector<
Michael J. Spencer00b702c2013-01-07 07:59:46 +0000732 Chunk<target_endianness, max_align, is64Bits> *>::iterator SectionIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000733
734 Segment(const StringRef name,
735 const ELFLayout::SegmentType type,
736 const WriterOptionsELF &options)
Michael J. Spencera2c97272013-01-04 21:09:21 +0000737 : Chunk<target_endianness, max_align, is64Bits>(name,
738 Chunk<target_endianness, max_align, is64Bits>::K_ELFSegment)
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000739 , _segmentType(type)
740 , _flags(0)
741 , _atomflags(0)
742 , _options(options) {
743 this->_align2 = 0;
744 this->_fsize = 0;
745 }
746
747 /// append a section to a segment
Michael J. Spencera2c97272013-01-04 21:09:21 +0000748 void append(Section<target_endianness, max_align, is64Bits> *section) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000749 _sections.push_back(section);
750 if (_flags < section->flags())
751 _flags = section->flags();
752 if (_atomflags < section->atomflags())
753 _atomflags = section->atomflags();
754 if (this->_align2 < section->align2())
755 this->_align2 = section->align2();
756 }
757
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000758 /// Prepend a generic chunk to the segment.
759 void prepend(Chunk<target_endianness, max_align, is64Bits> *c) {
760 _sections.insert(_sections.begin(), c);
761 }
762
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000763 /// Sort segments depending on the property
764 /// If we have a Program Header segment, it should appear first
765 /// If we have a INTERP segment, that should appear after the Program Header
766 /// All Loadable segments appear next in this order
767 /// All Read Write Execute segments follow
768 /// All Read Execute segments appear next
769 /// All Read only segments appear first
Michael J. Spencera2c97272013-01-04 21:09:21 +0000770 /// All Write execute segments follow
771 static bool compareSegments(
772 Segment<target_endianness, max_align, is64Bits> *sega,
773 Segment<target_endianness, max_align, is64Bits> *segb) {
774 if (sega->atomflags() < segb->atomflags())
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000775 return false;
776 return true;
777 }
778
779 /// \brief Start assigning file offset to the segment chunks The fileoffset
780 /// needs to be page at the start of the segment and in addition the
781 /// fileoffset needs to be aligned to the max section alignment within the
782 /// segment. This is required so that the ELF property p_poffset % p_align =
783 /// p_vaddr mod p_align holds true.
784 /// The algorithm starts off by assigning the startOffset thats passed in as
785 /// parameter to the first section in the segment, if the difference between
786 /// the newly computed offset is greater than a page, then we create a segment
Michael J. Spencera2c97272013-01-04 21:09:21 +0000787 /// slice, as it would be a waste of virtual memory just to be filled with
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000788 /// zeroes
789 void assignOffsets(uint64_t startOffset) {
790 int startSection = 0;
791 int currSection = 0;
792 SectionIter startSectionIter, endSectionIter;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000793 // slice align is set to the max alignment of the chunks that are
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000794 // contained in the slice
795 uint64_t sliceAlign = 0;
796 // Current slice size
797 uint64_t curSliceSize = 0;
798 // Current Slice File Offset
799 uint64_t curSliceFileOffset = 0;
800
801 startSectionIter = _sections.begin();
802 endSectionIter = _sections.end();
803 startSection = 0;
804 bool isFirstSection = true;
805 for (auto si = _sections.begin(); si != _sections.end(); ++si) {
806 if (isFirstSection) {
807 // align the startOffset to the section alignment
Michael J. Spencera2c97272013-01-04 21:09:21 +0000808 uint64_t newOffset =
809 llvm::RoundUpToAlignment(startOffset, (*si)->align2());
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000810 curSliceFileOffset = newOffset;
811 sliceAlign = (*si)->align2();
812 this->setFileOffset(startOffset);
813 (*si)->setFileOffset(newOffset);
814 curSliceSize = (*si)->fileSize();
815 isFirstSection = false;
816 } else {
817 uint64_t curOffset = curSliceFileOffset + curSliceSize;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000818 uint64_t newOffset =
819 llvm::RoundUpToAlignment(curOffset, (*si)->align2());
820 SegmentSlice<target_endianness, max_align, is64Bits> *slice = nullptr;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000821 // If the newOffset computed is more than a page away, lets create
822 // a seperate segment, so that memory is not used up while running
823 if ((newOffset - curOffset) > _options.pageSize()) {
824 // TODO: use std::find here
825 for (auto sei = slices_begin(); sei != slices_end(); ++sei) {
826 if ((*sei)->startSection() == startSection) {
827 slice = *sei;
828 break;
829 }
830 }
831 if (!slice) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000832 slice = new (_segmentAllocate.Allocate<
833 SegmentSlice<target_endianness, max_align, is64Bits>>())
834 SegmentSlice<target_endianness, max_align, is64Bits>();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000835 _segmentSlices.push_back(slice);
836 }
837 slice->set(curSliceFileOffset, startSection, currSection);
838 slice->setSections(startSectionIter, endSectionIter);
839 slice->setSize(curSliceSize);
840 slice->setAlign(sliceAlign);
Michael J. Spencera2c97272013-01-04 21:09:21 +0000841 uint64_t newPageOffset =
842 llvm::RoundUpToAlignment(curOffset, _options.pageSize());
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000843 newOffset = llvm::RoundUpToAlignment(newPageOffset, (*si)->align2());
844 curSliceFileOffset = newOffset;
845 startSectionIter = endSectionIter;
846 startSection = currSection;
847 (*si)->setFileOffset(curSliceFileOffset);
848 curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
849 sliceAlign = (*si)->align2();
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +0000850 } else {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000851 if (sliceAlign < (*si)->align2())
852 sliceAlign = (*si)->align2();
853 (*si)->setFileOffset(newOffset);
854 curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
855 }
856 }
857 currSection++;
858 endSectionIter = si;
859 }
Michael J. Spencera2c97272013-01-04 21:09:21 +0000860 SegmentSlice<target_endianness, max_align, is64Bits> *slice = nullptr;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000861 for (auto sei = slices_begin(); sei != slices_end(); ++sei) {
862 // TODO: add std::find
863 if ((*sei)->startSection() == startSection) {
864 slice = *sei;
865 break;
866 }
867 }
868 if (!slice) {
869 slice = new (_segmentAllocate.Allocate
Michael J. Spencera2c97272013-01-04 21:09:21 +0000870 <SegmentSlice<target_endianness, max_align, is64Bits>>())
871 SegmentSlice<target_endianness, max_align, is64Bits>();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000872 _segmentSlices.push_back(slice);
873 }
874 slice->set(curSliceFileOffset, startSection, currSection);
875 slice->setSections(startSectionIter, _sections.end());
876 slice->setSize(curSliceSize);
877 slice->setAlign(sliceAlign);
878 this->_fsize = curSliceFileOffset - startOffset + curSliceSize;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000879 std::stable_sort(slices_begin(), slices_end(),
880 SegmentSlice<target_endianness, max_align, is64Bits>::compare_slices);
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000881 }
882
883 /// \brief Assign virtual addresses to the slices
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000884 void assignVirtualAddress(uint64_t &addr) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000885 for (auto sei = slices_begin(), see = slices_end(); sei != see; ++sei) {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000886 // Align to a page
887 addr = llvm::RoundUpToAlignment(addr, _options.pageSize());
888 // Align to the slice alignment
889 addr = llvm::RoundUpToAlignment(addr, (*sei)->align2());
890
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000891 bool virtualAddressSet = false;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000892 for (auto si = (*sei)->sections_begin(), se = (*sei)->sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000893 si != se; ++si) {
894 // Align the section address
895 addr = llvm::RoundUpToAlignment(addr, (*si)->align2());
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000896 if (!virtualAddressSet) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000897 (*sei)->setVAddr(addr);
898 virtualAddressSet = true;
899 }
900 (*si)->setVAddr(addr);
Michael J. Spencer00b702c2013-01-07 07:59:46 +0000901 if (auto s =
902 dyn_cast<Section<target_endianness, max_align, is64Bits>>(*si))
903 s->assignVirtualAddress(addr);
Michael J. Spencer1ac382f02013-01-07 08:00:04 +0000904 else
905 addr += (*si)->memSize();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000906 (*si)->setMemSize(addr - (*si)->virtualAddr());
907 }
908 (*sei)->setMemSize(addr - (*sei)->virtualAddr());
909 }
910 }
911
912 slice_iter slices_begin() {
913 return _segmentSlices.begin();
914 }
915
916 slice_iter slices_end() {
917 return _segmentSlices.end();
918 }
919
Michael J. Spencera2c97272013-01-04 21:09:21 +0000920 // Write the Segment
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000921 void write(ELFWriter *writer, OwningPtr<FileOutputBuffer> &buffer) {
922 for (auto sei = slices_begin(), see = slices_end(); sei != see; ++sei) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000923 for (auto si = (*sei)->sections_begin(), se = (*sei)->sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000924 si != se; ++si) {
925 (*si)->write(writer, buffer);
926 }
927 }
928 }
929
930 // Finalize the segment, before we want to write to the output file
931 void finalize() { }
932
Michael J. Spencera2c97272013-01-04 21:09:21 +0000933 // For LLVM RTTI
934 static inline bool classof(
935 const Chunk<target_endianness, max_align, is64Bits> *c) {
936 return c->kind() ==
937 Chunk<target_endianness, max_align, is64Bits>::K_ELFSegment;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000938 }
939
940 // Getters
941 int32_t sectionCount() const {
942 return _sections.size();
943 }
944
945 ELFLayout::SegmentType segmentType() { return _segmentType; }
946
947 int pageSize() const { return _options.pageSize(); }
948
949 int64_t atomflags() const { return _atomflags; }
950
951 int64_t flags() const {
952 int64_t fl = 0;
953 if (_flags & llvm::ELF::SHF_ALLOC)
954 fl |= llvm::ELF::PF_R;
955 if (_flags & llvm::ELF::SHF_WRITE)
956 fl |= llvm::ELF::PF_W;
957 if (_flags & llvm::ELF::SHF_EXECINSTR)
958 fl |= llvm::ELF::PF_X;
959 return fl;
960 }
961
962 int64_t numSlices() const {
963 return _segmentSlices.size();
964 }
965
966private:
Michael J. Spencer00b702c2013-01-07 07:59:46 +0000967 /// \brief Section or some other chunk type.
968 std::vector<Chunk<target_endianness, max_align, is64Bits> *> _sections;
Michael J. Spencera2c97272013-01-04 21:09:21 +0000969 std::vector<SegmentSlice<target_endianness, max_align, is64Bits> *>
970 _segmentSlices;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000971 ELFLayout::SegmentType _segmentType;
972 int64_t _flags;
973 int64_t _atomflags;
974 const WriterOptionsELF _options;
975 llvm::BumpPtrAllocator _segmentAllocate;
976};
977
978/// \brief The class represents the ELF String Table
Michael J. Spencera2c97272013-01-04 21:09:21 +0000979template<support::endianness target_endianness,
980 std::size_t max_align,
981 bool is64Bits>
982class ELFStringTable : public Section<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000983public:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000984 ELFStringTable(const char *str, int32_t order)
985 : Section<target_endianness, max_align, is64Bits>(
986 str,
987 llvm::ELF::SHT_STRTAB,
988 DefinedAtom::perm___,
989 order,
990 Section<target_endianness, max_align, is64Bits>::K_StringTable) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000991 // the string table has a NULL entry for which
992 // add an empty string
993 _strings.push_back("");
994 this->_fsize = 1;
995 this->_align2 = 1;
996 this->setOrder(order);
997 }
998
Michael J. Spencera2c97272013-01-04 21:09:21 +0000999 static inline bool classof(
1000 const Chunk<target_endianness, max_align, is64Bits> *c) {
1001 return c->kind() ==
1002 Section<target_endianness, max_align, is64Bits>::K_StringTable;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001003 }
1004
1005 uint64_t addString(const StringRef symname) {
1006 _strings.push_back(symname);
1007 uint64_t offset = this->_fsize;
1008 this->_fsize += symname.size() + 1;
1009 return offset;
1010 }
1011
Michael J. Spencera2c97272013-01-04 21:09:21 +00001012 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001013 OwningPtr<FileOutputBuffer> &buffer) {
1014 uint8_t *chunkBuffer = buffer->getBufferStart();
1015 uint8_t *dest = chunkBuffer + this->fileOffset();
1016 for (auto si : _strings) {
1017 memcpy(dest, si.data(), si.size());
1018 dest += si.size();
1019 memcpy(dest, "", 1);
1020 dest += 1;
1021 }
1022 }
1023
1024 void finalize() { }
1025
1026private:
1027 std::vector<StringRef> _strings;
1028};
1029
Michael J. Spencera2c97272013-01-04 21:09:21 +00001030/// \brief The ELFSymbolTable class represents the symbol table in a ELF file
1031template<support::endianness target_endianness,
1032 std::size_t max_align,
1033 bool is64Bits>
1034class ELFSymbolTable : public Section<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001035public:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001036 typedef object::Elf_Sym_Impl<target_endianness, max_align, is64Bits> Elf_Sym;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001037
Michael J. Spencera2c97272013-01-04 21:09:21 +00001038 ELFSymbolTable(const char *str, int32_t order)
1039 : Section<target_endianness, max_align, is64Bits>(
1040 str,
1041 llvm::ELF::SHT_SYMTAB,
1042 0,
1043 order,
1044 Section<target_endianness, max_align, is64Bits>::K_SymbolTable) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001045 this->setOrder(order);
1046 Elf_Sym *symbol = new (_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001047 memset((void *)symbol, 0, sizeof(Elf_Sym));
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001048 _symbolTable.push_back(symbol);
1049 this->_entSize = sizeof(Elf_Sym);
1050 this->_fsize = sizeof(Elf_Sym);
1051 this->_align2 = sizeof(void *);
1052 }
1053
Michael J. Spencera2c97272013-01-04 21:09:21 +00001054 static inline bool classof(
1055 const Chunk<target_endianness, max_align, is64Bits> *c) {
1056 return c->kind() ==
1057 Section<target_endianness, max_align, is64Bits>::K_SymbolTable;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001058 }
1059
1060 void addSymbol(const Atom *atom, int32_t sectionIndex, uint64_t addr = 0) {
1061 Elf_Sym *symbol = new(_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
1062 unsigned char binding = 0, type = 0;
1063 symbol->st_name = _stringSection->addString(atom->name());
1064 symbol->st_size = 0;
1065 symbol->st_shndx = sectionIndex;
1066 symbol->st_value = 0;
1067 symbol->st_other = ELF::STV_DEFAULT;
1068 if (const DefinedAtom *da = llvm::dyn_cast<const DefinedAtom>(atom)){
1069 symbol->st_size = da->size();
1070 lld::DefinedAtom::ContentType ct;
1071 switch (ct = da->contentType()){
1072 case DefinedAtom::typeCode:
1073 symbol->st_value = addr;
1074 type = ELF::STT_FUNC;
1075 break;
1076 case DefinedAtom::typeData:
Michael J. Spencer8de83642013-01-07 08:00:42 +00001077 case DefinedAtom::typeConstant:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001078 symbol->st_value = addr;
1079 type = ELF::STT_OBJECT;
1080 break;
1081 case DefinedAtom::typeZeroFill:
Michael J. Spencer28c65942013-01-07 07:05:52 +00001082 type = ELF::STT_OBJECT;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001083 symbol->st_value = addr;
1084 break;
1085 default:
1086 type = ELF::STT_NOTYPE;
1087 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001088 if (da->scope() == DefinedAtom::scopeTranslationUnit)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001089 binding = ELF::STB_LOCAL;
1090 else
1091 binding = ELF::STB_GLOBAL;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001092 } else if (const AbsoluteAtom *aa =
1093 llvm::dyn_cast<const AbsoluteAtom>(atom)){
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001094 type = ELF::STT_OBJECT;
1095 symbol->st_shndx = ELF::SHN_ABS;
1096 switch (aa->scope()) {
1097 case AbsoluteAtom::scopeLinkageUnit:
1098 symbol->st_other = ELF::STV_HIDDEN;
1099 binding = ELF::STB_LOCAL;
1100 break;
1101 case AbsoluteAtom::scopeTranslationUnit:
1102 binding = ELF::STB_LOCAL;
1103 break;
1104 case AbsoluteAtom::scopeGlobal:
1105 binding = ELF::STB_GLOBAL;
1106 break;
1107 }
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001108 symbol->st_value = addr;
1109 } else {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001110 symbol->st_value = 0;
1111 type = ELF::STT_NOTYPE;
1112 binding = ELF::STB_WEAK;
1113 }
1114 symbol->setBindingAndType(binding, type);
1115 _symbolTable.push_back(symbol);
1116 this->_fsize += sizeof(Elf_Sym);
1117 }
1118
Michael J. Spencera2c97272013-01-04 21:09:21 +00001119 void setStringSection(
1120 ELFStringTable<target_endianness, max_align, is64Bits> *s) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001121 _stringSection = s;
1122 }
1123
1124 void finalize() {
1125 // sh_info should be one greater than last symbol with STB_LOCAL binding
1126 // we sort the symbol table to keep all local symbols at the beginning
1127 std::stable_sort(_symbolTable.begin(), _symbolTable.end(),
1128 [](const Elf_Sym *A, const Elf_Sym *B) {
1129 return A->getBinding() < B->getBinding();
Michael J. Spencera2c97272013-01-04 21:09:21 +00001130 });
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001131 uint16_t shInfo = 0;
1132 for (auto i : _symbolTable) {
1133 if (i->getBinding() != ELF::STB_LOCAL)
1134 break;
1135 shInfo++;
1136 }
1137 this->_shInfo = shInfo;
1138 this->setLink(_stringSection->ordinal());
1139 }
1140
Michael J. Spencera2c97272013-01-04 21:09:21 +00001141 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001142 OwningPtr<FileOutputBuffer> &buffer) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001143 uint8_t *chunkBuffer = buffer->getBufferStart();
1144 uint8_t *dest = chunkBuffer + this->fileOffset();
1145 for (auto sti : _symbolTable) {
1146 memcpy(dest, sti, sizeof(Elf_Sym));
1147 dest += sizeof(Elf_Sym);
1148 }
1149 }
1150
1151private:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001152 ELFStringTable<target_endianness, max_align, is64Bits> *_stringSection;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001153 std::vector<Elf_Sym*> _symbolTable;
1154 llvm::BumpPtrAllocator _symbolAllocate;
1155 int64_t _link;
1156};
1157
1158/// \brief An ELFHeader represents the Elf[32/64]_Ehdr structure at the
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001159/// start of an ELF executable file.
Michael J. Spencera2c97272013-01-04 21:09:21 +00001160template<support::endianness target_endianness,
1161 std::size_t max_align,
1162 bool is64Bits>
1163class ELFHeader : public Chunk<target_endianness, max_align, is64Bits> {
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001164public:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001165 typedef Elf_Ehdr_Impl<target_endianness, max_align, is64Bits> Elf_Ehdr;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001166
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001167 ELFHeader()
Michael J. Spencera2c97272013-01-04 21:09:21 +00001168 : Chunk<target_endianness, max_align, is64Bits>(
1169 "elfhdr", Chunk<target_endianness, max_align, is64Bits>::K_ELFHeader) {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001170 this->_align2 = is64Bits ? 8 : 4;
1171 this->_fsize = sizeof(Elf_Ehdr);
1172 this->_msize = sizeof(Elf_Ehdr);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001173 memset(_eh.e_ident, 0, llvm::ELF::EI_NIDENT);
1174 e_ident(ELF::EI_MAG0, 0x7f);
1175 e_ident(ELF::EI_MAG1, 'E');
1176 e_ident(ELF::EI_MAG2, 'L');
1177 e_ident(ELF::EI_MAG3, 'F');
1178 e_ehsize(sizeof(Elf_Ehdr));
1179 e_flags(2);
1180 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001181 void e_ident(int I, unsigned char C) { _eh.e_ident[I] = C; }
1182 void e_type(uint16_t type) { _eh.e_type = type; }
1183 void e_machine(uint16_t machine) { _eh.e_machine = machine; }
1184 void e_version(uint32_t version) { _eh.e_version = version; }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001185 void e_entry(int64_t entry) { _eh.e_entry = entry; }
1186 void e_phoff(int64_t phoff) { _eh.e_phoff = phoff; }
1187 void e_shoff(int64_t shoff) { _eh.e_shoff = shoff; }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001188 void e_flags(uint32_t flags) { _eh.e_flags = flags; }
1189 void e_ehsize(uint16_t ehsize) { _eh.e_ehsize = ehsize; }
1190 void e_phentsize(uint16_t phentsize) { _eh.e_phentsize = phentsize; }
1191 void e_phnum(uint16_t phnum) { _eh.e_phnum = phnum; }
1192 void e_shentsize(uint16_t shentsize) { _eh.e_shentsize = shentsize; }
1193 void e_shnum(uint16_t shnum) { _eh.e_shnum = shnum; }
1194 void e_shstrndx(uint16_t shstrndx) { _eh.e_shstrndx = shstrndx; }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001195 uint64_t fileSize() { return sizeof (Elf_Ehdr); }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001196
Michael J. Spencera2c97272013-01-04 21:09:21 +00001197 static inline bool classof(
1198 const Chunk<target_endianness, max_align, is64Bits> *c) {
1199 return c->Kind() ==
1200 Chunk<target_endianness, max_align, is64Bits>::K_ELFHeader;
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001201 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001202
Michael J. Spencera2c97272013-01-04 21:09:21 +00001203 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001204 OwningPtr<FileOutputBuffer> &buffer) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001205 uint8_t *chunkBuffer = buffer->getBufferStart();
1206 uint8_t *atomContent = chunkBuffer + this->fileOffset();
1207 memcpy(atomContent, &_eh, fileSize());
1208 }
1209
1210 void finalize() { }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001211
1212private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001213 Elf_Ehdr _eh;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001214};
1215
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001216/// \brief An ELFProgramHeader represents the Elf[32/64]_Phdr structure at the
1217/// start of an ELF executable file.
Michael J. Spencera2c97272013-01-04 21:09:21 +00001218template<support::endianness target_endianness,
1219 std::size_t max_align,
1220 bool is64Bits>
1221class ELFProgramHeader : public Chunk<target_endianness, max_align, is64Bits> {
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001222public:
Michael J. Spencerfd3981d2013-01-06 05:40:27 +00001223 typedef Elf_Phdr_Impl<target_endianness, max_align, is64Bits> Elf_Phdr;
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001224 typedef typename std::vector<Elf_Phdr *>::iterator PhIterT;
1225
1226 /// \brief Find a program header entry, given the type of entry that
1227 /// we are looking for
1228 class FindPhdr {
1229 public:
1230 FindPhdr(uint64_t type, uint64_t flags, uint64_t flagsClear)
1231 : _type(type)
1232 , _flags(flags)
1233 , _flagsClear(flagsClear)
1234 {}
1235
Shankar Easwaran37c52822013-01-10 18:16:10 +00001236 bool operator()(const Elf_Phdr *j) const {
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001237 return ((j->p_type == _type) &&
1238 ((j->p_flags & _flags) == _flags) &&
1239 (!(j->p_flags & _flagsClear)));
1240 }
1241 private:
1242 uint64_t _type;
1243 uint64_t _flags;
1244 uint64_t _flagsClear;
1245 };
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001246
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001247 ELFProgramHeader()
Michael J. Spencera2c97272013-01-04 21:09:21 +00001248 : Chunk<target_endianness, max_align, is64Bits>(
1249 "elfphdr",
Reid Klecknere974bd12013-01-05 02:21:42 +00001250 Chunk<target_endianness, max_align, is64Bits>::K_ELFProgramHeader) {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001251 this->_align2 = is64Bits ? 8 : 4;
Reid Klecknere974bd12013-01-05 02:21:42 +00001252 resetProgramHeaders();
1253 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001254
Michael J. Spencera2c97272013-01-04 21:09:21 +00001255 bool addSegment(Segment<target_endianness, max_align, is64Bits> *segment) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001256 Elf_Phdr *phdr = nullptr;
1257 bool ret = false;
1258
Michael J. Spencera2c97272013-01-04 21:09:21 +00001259 for (auto sei = segment->slices_begin(), see = segment->slices_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001260 sei != see; ++sei) {
1261 if (_phi == _ph.end()) {
1262 phdr = new(_allocator.Allocate<Elf_Phdr>()) Elf_Phdr;
1263 _ph.push_back(phdr);
1264 _phi = _ph.end();
1265 ret = true;
1266 } else {
1267 phdr = (*_phi);
1268 ++_phi;
1269 }
1270 phdr->p_type = segment->segmentType();
1271 phdr->p_offset = (*sei)->fileOffset();
1272 phdr->p_vaddr = (*sei)->virtualAddr();
1273 phdr->p_paddr = (*sei)->virtualAddr();
1274 phdr->p_filesz = (*sei)->fileSize();
1275 phdr->p_memsz = (*sei)->memSize();
1276 phdr->p_flags = segment->flags();
Michael J. Spencera2c97272013-01-04 21:09:21 +00001277 phdr->p_align = (phdr->p_type == llvm::ELF::PT_LOAD) ?
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001278 segment->pageSize() : (*sei)->align2();
1279 }
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001280
1281 this->_fsize = fileSize();
1282 this->_msize = this->_fsize;
1283
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001284 return ret;
1285 }
1286
1287 void resetProgramHeaders() {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001288 _phi = _ph.begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001289 }
1290
Michael J. Spencera2c97272013-01-04 21:09:21 +00001291 uint64_t fileSize() {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001292 return sizeof(Elf_Phdr) * _ph.size();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001293 }
1294
Michael J. Spencera2c97272013-01-04 21:09:21 +00001295 static inline bool classof(
1296 const Chunk<target_endianness, max_align, is64Bits> *c) {
1297 return c->Kind() ==
1298 Chunk<target_endianness, max_align, is64Bits>::K_ELFProgramHeader;
1299 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001300
Michael J. Spencera2c97272013-01-04 21:09:21 +00001301 void write(ELFWriter *writer,
1302 OwningPtr<FileOutputBuffer> &buffer) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001303 uint8_t *chunkBuffer = buffer->getBufferStart();
1304 uint8_t *dest = chunkBuffer + this->fileOffset();
1305 for (auto phi : _ph) {
1306 memcpy(dest, phi, sizeof(Elf_Phdr));
1307 dest += sizeof(Elf_Phdr);
1308 }
1309 }
1310
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001311 /// \brief find a program header entry in the list of program headers
1312 PhIterT findProgramHeader(uint64_t type, uint64_t flags, uint64_t flagClear) {
1313 return std::find_if(_ph.begin(), _ph.end(),
1314 FindPhdr(type, flags, flagClear));
1315 }
1316
1317 PhIterT begin() {
1318 return _ph.begin();
1319 }
1320
1321 PhIterT end() {
1322 return _ph.end();
1323 }
1324
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001325 void finalize() { }
1326
Michael J. Spencera2c97272013-01-04 21:09:21 +00001327 int64_t entsize() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001328 return sizeof(Elf_Phdr);
1329 }
1330
1331 int64_t numHeaders() {
1332 return _ph.size();
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001333 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001334
1335private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001336 std::vector<Elf_Phdr *> _ph;
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001337 PhIterT _phi;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001338 llvm::BumpPtrAllocator _allocator;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001339};
1340
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001341/// \brief An ELFSectionHeader represents the Elf[32/64]_Shdr structure
1342/// at the end of the file
Michael J. Spencera2c97272013-01-04 21:09:21 +00001343template<support::endianness target_endianness,
1344 std::size_t max_align,
1345 bool is64Bits>
1346class ELFSectionHeader : public Chunk<target_endianness, max_align, is64Bits> {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001347public:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001348 typedef Elf_Shdr_Impl<target_endianness, max_align, is64Bits> Elf_Shdr;
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001349
Michael J. Spencera2c97272013-01-04 21:09:21 +00001350 ELFSectionHeader(int32_t order)
1351 : Chunk<target_endianness, max_align, is64Bits>(
1352 "shdr",
1353 Chunk<target_endianness, max_align, is64Bits>::K_ELFSectionHeader) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001354 this->_fsize = 0;
1355 this->_align2 = 8;
1356 this->setOrder(order);
1357 // The first element in the list is always NULL
1358 Elf_Shdr *nullshdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
1359 ::memset(nullshdr, 0, sizeof (Elf_Shdr));
1360 _sectionInfo.push_back(nullshdr);
1361 this->_fsize += sizeof (Elf_Shdr);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001362 }
1363
Michael J. Spencera2c97272013-01-04 21:09:21 +00001364 uint16_t fileSize() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001365 return sizeof(Elf_Shdr) * _sectionInfo.size();
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001366 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001367
Michael J. Spencera2c97272013-01-04 21:09:21 +00001368 void appendSection(
1369 MergedSections<target_endianness, max_align, is64Bits> *section) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001370 Elf_Shdr *shdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
1371 shdr->sh_name = _stringSection->addString(section->name());
1372 shdr->sh_type = section->type();
1373 shdr->sh_flags = section->flags();
1374 shdr->sh_offset = section->fileOffset();
1375 shdr->sh_addr = section->virtualAddr();
1376 shdr->sh_size = section->memSize();
1377 shdr->sh_link = section->link();
1378 shdr->sh_info = section->shinfo();
1379 shdr->sh_addralign = section->align2();
1380 shdr->sh_entsize = section->entsize();
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001381 _sectionInfo.push_back(shdr);
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001382 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001383
Michael J. Spencera2c97272013-01-04 21:09:21 +00001384 void updateSection(Section<target_endianness, max_align, is64Bits> *section) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001385 Elf_Shdr *shdr = _sectionInfo[section->ordinal()];
1386 shdr->sh_type = section->type();
1387 shdr->sh_flags = section->flags();
1388 shdr->sh_offset = section->fileOffset();
1389 shdr->sh_addr = section->virtualAddr();
1390 shdr->sh_size = section->fileSize();
1391 shdr->sh_link = section->link();
1392 shdr->sh_info = section->shinfo();
1393 shdr->sh_addralign = section->align2();
1394 shdr->sh_entsize = section->entsize();
1395 }
1396
Michael J. Spencera2c97272013-01-04 21:09:21 +00001397 static inline bool classof(
1398 const Chunk<target_endianness, max_align, is64Bits> *c) {
1399 return c->getChunkKind() ==
1400 Chunk<target_endianness, max_align, is64Bits>::K_ELFSectionHeader;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001401 }
1402
Michael J. Spencera2c97272013-01-04 21:09:21 +00001403 void setStringSection(
1404 ELFStringTable<target_endianness, max_align, is64Bits> *s) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001405 _stringSection = s;
1406 }
1407
Michael J. Spencera2c97272013-01-04 21:09:21 +00001408 void write(ELFWriter *writer,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001409 OwningPtr<FileOutputBuffer> &buffer) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001410 uint8_t *chunkBuffer = buffer->getBufferStart();
1411 uint8_t *dest = chunkBuffer + this->fileOffset();
1412 for (auto shi : _sectionInfo) {
1413 memcpy(dest, shi, sizeof(Elf_Shdr));
1414 dest += sizeof(Elf_Shdr);
1415 }
1416 _stringSection->write(writer, buffer);
1417 }
1418
1419 void finalize() { }
1420
Michael J. Spencera2c97272013-01-04 21:09:21 +00001421 int64_t entsize() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001422 return sizeof(Elf_Shdr);
1423 }
1424
1425 int64_t numHeaders() {
1426 return _sectionInfo.size();
1427 }
1428
1429private:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001430 ELFStringTable<target_endianness, max_align, is64Bits> *_stringSection;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001431 std::vector<Elf_Shdr*> _sectionInfo;
1432 llvm::BumpPtrAllocator _sectionAllocate;
1433};
1434
Michael J. Spencera2c97272013-01-04 21:09:21 +00001435/// \brief The DefaultELFLayout class is used by the Writer to arrange
1436/// sections and segments in the order determined by the target ELF
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001437/// format. The writer creates a single instance of the DefaultELFLayout
Michael J. Spencera2c97272013-01-04 21:09:21 +00001438/// class
1439template<support::endianness target_endianness,
1440 std::size_t max_align,
1441 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001442class DefaultELFLayout : public ELFLayout {
1443public:
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001444
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001445 // The order in which the sections appear in the output file
Michael J. Spencera2c97272013-01-04 21:09:21 +00001446 // If its determined, that the layout needs to change
1447 // just changing the order of enumerations would essentially
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001448 // change the layout in the output file
1449 enum DefaultSectionOrder {
1450 ORDER_NOT_DEFINED = 0,
1451 ORDER_INTERP,
1452 ORDER_NOTE,
1453 ORDER_HASH,
1454 ORDER_DYNAMIC_SYMBOLS,
1455 ORDER_DYNAMIC_STRINGS,
1456 ORDER_INIT,
1457 ORDER_TEXT,
1458 ORDER_PLT,
1459 ORDER_FINI,
1460 ORDER_RODATA,
1461 ORDER_EH_FRAME,
1462 ORDER_EH_FRAMEHDR,
1463 ORDER_CTORS,
1464 ORDER_DTORS,
Michael J. Spencerecd5f402013-01-10 22:41:42 +00001465 ORDER_INIT_ARRAY,
1466 ORDER_FINI_ARRAY,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001467 ORDER_DYNAMIC,
1468 ORDER_GOT,
1469 ORDER_GOT_PLT,
1470 ORDER_DATA,
1471 ORDER_BSS,
1472 ORDER_OTHER,
1473 ORDER_SECTION_STRINGS,
1474 ORDER_SYMBOL_TABLE,
1475 ORDER_STRING_TABLE,
1476 ORDER_SECTION_HEADERS
1477 };
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001478
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001479public:
1480
1481 // The Key used for creating Sections
Michael J. Spencera2c97272013-01-04 21:09:21 +00001482 // The sections are created using
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001483 // SectionName, [contentType, contentPermissions]
Michael J. Spencera2c97272013-01-04 21:09:21 +00001484 typedef std::pair<StringRef,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001485 std::pair<int32_t, int32_t>> Key;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001486 typedef typename std::vector<
1487 Chunk<target_endianness, max_align, is64Bits> *>::iterator ChunkIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001488 // The key used for Segments
Michael J. Spencera2c97272013-01-04 21:09:21 +00001489 // The segments are created using
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001490 // SegmentName, Segment flags
1491 typedef std::pair<StringRef, int64_t> SegmentKey;
1492 // Merged Sections contain the map of Sectionnames to a vector of sections,
1493 // that have been merged to form a single section
Michael J. Spencera2c97272013-01-04 21:09:21 +00001494 typedef std::map<StringRef, MergedSections<
1495 target_endianness, max_align, is64Bits> *> MergedSectionMapT;
1496 typedef typename std::vector<MergedSections<
1497 target_endianness, max_align, is64Bits> *>::iterator MergedSectionIter;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001498
1499 // HashKey for the Section
1500 class HashKey {
1501 public:
1502 int64_t operator() (const Key &k) const {
1503 // k.first = section Name
1504 // k.second = [contentType, Permissions]
1505 return llvm::hash_combine(k.first, k.second.first, k.second.second);
1506 }
1507 };
1508
1509 // HashKey for the Segment
1510 class SegmentHashKey {
1511 public:
1512 int64_t operator() (const SegmentKey &k) const {
1513 // k.first = SegmentName
1514 // k.second = SegmentFlags
1515 return llvm::hash_combine(k.first, k.second);
1516 }
1517 };
1518
Michael J. Spencera2c97272013-01-04 21:09:21 +00001519 typedef std::unordered_map<Key, Section<
1520 target_endianness, max_align, is64Bits>*, HashKey> SectionMapT;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001521 typedef std::unordered_map<SegmentKey,
Michael J. Spencera2c97272013-01-04 21:09:21 +00001522 Segment<target_endianness, max_align, is64Bits>*,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001523 SegmentHashKey> SegmentMapT;
1524
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001525 /// \brief All absolute atoms are created in the ELF Layout by using
1526 /// an AbsoluteAtomPair. Contains a pair of AbsoluteAtom and the
1527 /// value which is the address of the absolute atom
1528 class AbsoluteAtomPair {
1529 public:
1530 AbsoluteAtomPair(const AbsoluteAtom *a, int64_t value)
1531 : _absoluteAtom(a)
1532 , _value(value) { }
1533
1534 const AbsoluteAtom *absoluteAtom() { return _absoluteAtom; }
1535 int64_t value() const { return _value; }
1536 void setValue(int64_t val) { _value = val; }
1537
1538 private:
1539 const AbsoluteAtom *_absoluteAtom;
1540 int64_t _value;
1541 };
1542
1543 /// \brief find a absolute atom pair given a absolute atom name
1544 struct FindByName {
1545 const std::string name;
1546 FindByName(const StringRef name) : name(name) {}
1547 bool operator()(AbsoluteAtomPair& j) {
1548 return j.absoluteAtom()->name() == name;
1549 }
1550 };
1551
1552 typedef typename std::vector<AbsoluteAtomPair>::iterator AbsoluteAtomIterT;
1553
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001554 DefaultELFLayout(const WriterOptionsELF &options):_options(options) { }
1555
1556 /// \brief Return the section order for a input section
1557 virtual SectionOrder getSectionOrder
1558 (const StringRef name,
1559 int32_t contentType,
1560 int32_t contentPermissions) {
1561 switch (contentType) {
1562 case DefinedAtom::typeCode:
1563 return llvm::StringSwitch<Reference::Kind>(name)
1564 .StartsWith(".eh_frame_hdr", ORDER_EH_FRAMEHDR)
1565 .StartsWith(".eh_frame", ORDER_EH_FRAME)
1566 .StartsWith(".init", ORDER_INIT)
1567 .StartsWith(".fini", ORDER_FINI)
1568 .StartsWith(".hash", ORDER_HASH)
1569 .Default(ORDER_TEXT);
1570
1571 case DefinedAtom::typeConstant:
Michael J. Spencera2c97272013-01-04 21:09:21 +00001572 return ORDER_RODATA;
1573
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001574 case DefinedAtom::typeData:
Michael J. Spencerecd5f402013-01-10 22:41:42 +00001575 return llvm::StringSwitch<Reference::Kind>(name)
1576 .StartsWith(".init_array", ORDER_INIT_ARRAY)
1577 .Default(ORDER_DATA);
Michael J. Spencera2c97272013-01-04 21:09:21 +00001578
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001579 case DefinedAtom::typeZeroFill:
1580 return ORDER_BSS;
1581
1582 default:
1583 // If we get passed in a section push it to OTHER
Michael J. Spencera2c97272013-01-04 21:09:21 +00001584 if (contentPermissions == DefinedAtom::perm___)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001585 return ORDER_OTHER;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001586
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001587 return ORDER_NOT_DEFINED;
1588 }
1589 }
1590
1591 /// \brief This maps the input sections to the output section names
1592 StringRef getSectionName(const StringRef name,
1593 const int32_t contentType) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001594 if (contentType == DefinedAtom::typeZeroFill)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001595 return ".bss";
Michael J. Spencera2c97272013-01-04 21:09:21 +00001596 if (name.startswith(".text"))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001597 return ".text";
Michael J. Spencera2c97272013-01-04 21:09:21 +00001598 if (name.startswith(".rodata"))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001599 return ".rodata";
1600 return name;
1601 }
1602
1603 /// \brief Gets the segment for a output section
Michael J. Spencera2c97272013-01-04 21:09:21 +00001604 virtual ELFLayout::SegmentType getSegmentType(
1605 Section<target_endianness, max_align, is64Bits> *section) const {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001606 switch(section->order()) {
1607 case ORDER_INTERP:
1608 return llvm::ELF::PT_INTERP;
1609
1610 case ORDER_TEXT:
1611 case ORDER_HASH:
1612 case ORDER_DYNAMIC_SYMBOLS:
1613 case ORDER_DYNAMIC_STRINGS:
1614 case ORDER_INIT:
1615 case ORDER_PLT:
1616 case ORDER_FINI:
1617 case ORDER_RODATA:
1618 case ORDER_EH_FRAME:
1619 case ORDER_EH_FRAMEHDR:
1620 return llvm::ELF::PT_LOAD;
1621
1622 case ORDER_NOTE:
1623 return llvm::ELF::PT_NOTE;
1624
1625 case ORDER_DYNAMIC:
1626 return llvm::ELF::PT_DYNAMIC;
1627
1628 case ORDER_CTORS:
1629 case ORDER_DTORS:
1630 case ORDER_GOT:
1631 return llvm::ELF::PT_GNU_RELRO;
1632
1633 case ORDER_GOT_PLT:
1634 case ORDER_DATA:
1635 case ORDER_BSS:
Michael J. Spencerecd5f402013-01-10 22:41:42 +00001636 case ORDER_INIT_ARRAY:
1637 case ORDER_FINI_ARRAY:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001638 return llvm::ELF::PT_LOAD;
1639
1640 default:
1641 return llvm::ELF::PT_NULL;
1642 }
1643 }
1644
1645 /// \brief Returns true/false depending on whether the section has a Output
1646 // segment or not
Michael J. Spencera2c97272013-01-04 21:09:21 +00001647 static bool hasOutputSegment(Section<target_endianness, max_align,
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001648 is64Bits> *section) {
1649 switch(section->order()) {
1650 case ORDER_INTERP:
1651 case ORDER_HASH:
1652 case ORDER_DYNAMIC_SYMBOLS:
1653 case ORDER_DYNAMIC_STRINGS:
1654 case ORDER_INIT:
1655 case ORDER_PLT:
1656 case ORDER_TEXT:
1657 case ORDER_FINI:
1658 case ORDER_RODATA:
1659 case ORDER_EH_FRAME:
1660 case ORDER_EH_FRAMEHDR:
1661 case ORDER_NOTE:
1662 case ORDER_DYNAMIC:
1663 case ORDER_CTORS:
1664 case ORDER_DTORS:
1665 case ORDER_GOT:
1666 case ORDER_GOT_PLT:
1667 case ORDER_DATA:
Michael J. Spencerecd5f402013-01-10 22:41:42 +00001668 case ORDER_INIT_ARRAY:
1669 case ORDER_FINI_ARRAY:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001670 case ORDER_BSS:
1671 return true;
1672
1673 default:
1674 return false;
1675 }
1676 }
1677
1678 // Adds an atom to the section
1679 virtual error_code addAtom(const Atom *atom) {
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001680 if (const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom)) {
1681 const StringRef sectionName =
1682 getSectionName(definedAtom->customSectionName(),
1683 definedAtom->contentType());
1684 const lld::DefinedAtom::ContentPermissions permissions =
1685 definedAtom->permissions();
1686 const lld::DefinedAtom::ContentType contentType =
1687 definedAtom->contentType();
1688 const Key key(sectionName, std::make_pair(contentType, permissions));
1689 const std::pair<Key, Section<target_endianness, max_align, is64Bits> *>
1690 currentSection(key, nullptr);
1691 std::pair<typename SectionMapT::iterator, bool>
1692 sectionInsert(_sectionMap.insert(currentSection));
1693 Section<target_endianness, max_align, is64Bits> *section;
1694 // the section is already in the map
1695 if (!sectionInsert.second) {
1696 section = sectionInsert.first->second;
1697 section->setContentPermissions(permissions);
1698 } else {
1699 SectionOrder section_order = getSectionOrder(sectionName,
1700 contentType,
1701 permissions);
1702 section = new (_allocator.Allocate
1703 <Section<target_endianness, max_align, is64Bits>>())
1704 Section<target_endianness, max_align, is64Bits>
1705 (sectionName, contentType,
1706 permissions, section_order);
1707 sectionInsert.first->second = section;
1708 section->setOrder(section_order);
1709 _sections.push_back(section);
1710 }
1711 section->appendAtom(atom);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001712 }
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001713 // Absolute atoms are not part of any section, they are global for the whole
1714 // link
1715 else if (const AbsoluteAtom *absoluteAtom = dyn_cast<AbsoluteAtom>(atom)) {
1716 _absoluteAtoms.push_back(AbsoluteAtomPair(absoluteAtom,
1717 absoluteAtom->value()));
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001718 }
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001719 else
1720 llvm_unreachable("Only absolute / defined atoms can be added here");
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001721 return error_code::success();
1722 }
1723
Shankar Easwaranb1d09c02013-01-11 18:56:11 +00001724 /// \brief Find an output Section given a section name.
1725 MergedSections<target_endianness, max_align, is64Bits> *
Michael J. Spencerecd5f402013-01-10 22:41:42 +00001726 findOutputSection(StringRef name) {
Shankar Easwaranb1d09c02013-01-11 18:56:11 +00001727 auto iter = _mergedSectionMap.find(name);
1728 if (iter == _mergedSectionMap.end())
1729 return nullptr;
1730 return iter->second;
Michael J. Spencerecd5f402013-01-10 22:41:42 +00001731 }
1732
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001733 /// \brief find a absolute atom given a name
1734 AbsoluteAtomIterT findAbsoluteAtom(const StringRef name) {
1735 return std::find_if(_absoluteAtoms.begin(), _absoluteAtoms.end(),
1736 FindByName(name));
1737 }
1738
1739 /// \bried Begin/End iterators
1740 AbsoluteAtomIterT absAtomsBegin() {
1741 return _absoluteAtoms.begin();
1742 }
1743
1744 AbsoluteAtomIterT absAtomsEnd() {
1745 return _absoluteAtoms.end();
1746 }
1747
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001748 // Merge sections with the same name into a MergedSections
1749 void mergeSimiliarSections() {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001750 MergedSections<target_endianness, max_align, is64Bits> *mergedSection;
1751
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001752 for (auto &si : _sections) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001753 const std::pair<StringRef,
1754 MergedSections<target_endianness, max_align, is64Bits> *>
1755 currentMergedSections(si->name(), nullptr);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001756 std::pair<typename MergedSectionMapT::iterator, bool>
1757 mergedSectionInsert
1758 (_mergedSectionMap.insert(currentMergedSections));
1759 if (!mergedSectionInsert.second) {
1760 mergedSection = mergedSectionInsert.first->second;
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00001761 } else {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001762 mergedSection = new (_allocator.Allocate<
1763 MergedSections<target_endianness, max_align, is64Bits>>())
1764 MergedSections<target_endianness, max_align, is64Bits>(si->name());
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001765 _mergedSections.push_back(mergedSection);
1766 mergedSectionInsert.first->second = mergedSection;
1767 }
1768 mergedSection->appendSection(si);
1769 }
1770 }
1771
1772 void assignSectionsToSegments() {
1773 // sort the sections by their order as defined by the layout
1774 std::stable_sort(_sections.begin(), _sections.end(),
Michael J. Spencera2c97272013-01-04 21:09:21 +00001775 [](Chunk<target_endianness, max_align, is64Bits> *A,
1776 Chunk<target_endianness, max_align, is64Bits> *B) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001777 return A->order() < B->order();
1778 });
1779 // Merge all sections
1780 mergeSimiliarSections();
1781 // Set the ordinal after sorting the sections
1782 int ordinal = 1;
1783 for (auto &msi : _mergedSections) {
1784 (*msi).setOrdinal(ordinal);
1785 for (auto ai = (*msi).begin_sections(), ae = (*msi).end_sections();
1786 ai != ae; ++ai) {
1787 (*ai)->setOrdinal(ordinal);
1788 }
1789 ++ordinal;
1790 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001791 Section<target_endianness, max_align, is64Bits> *section;
1792 Segment<target_endianness, max_align, is64Bits> *segment;
1793 for (auto msi = merged_sections_begin(), mse = merged_sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001794 msi != mse; ++msi) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001795 for (auto ai = (*msi)->begin_sections(), ae = (*msi)->end_sections();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001796 ai != ae; ++ai) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001797 if ((*ai)->kind() ==
1798 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection) {
1799 section = llvm::dyn_cast<
1800 Section<target_endianness, max_align, is64Bits>>(*ai);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001801 if (!hasOutputSegment(section))
1802 continue;
1803 (*msi)->setHasSegment();
1804 section->setSegment(getSegmentType(section));
1805 const StringRef segmentName = section->segmentKindToStr();
1806 // Use the flags of the merged Section for the segment
1807 const SegmentKey key(segmentName, (*msi)->flags());
Michael J. Spencera2c97272013-01-04 21:09:21 +00001808 const std::pair<SegmentKey,
1809 Segment<target_endianness, max_align, is64Bits> *>
1810 currentSegment(key, nullptr);
1811 std::pair<typename SegmentMapT::iterator, bool>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001812 segmentInsert(_segmentMap.insert(currentSegment));
1813
1814 if (!segmentInsert.second) {
1815 segment = segmentInsert.first->second;
1816 } else {
1817 segment = new (_allocator.Allocate
Michael J. Spencera2c97272013-01-04 21:09:21 +00001818 <Segment<target_endianness, max_align, is64Bits>>())
1819 Segment<target_endianness, max_align, is64Bits>
1820 (segmentName, getSegmentType(section),
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001821 _options);
1822 segmentInsert.first->second = segment;
1823 _segments.push_back(segment);
1824 }
1825 segment->append(section);
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001826 }
1827 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001828 }
1829 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001830
Michael J. Spencera2c97272013-01-04 21:09:21 +00001831 void addSection(Chunk<target_endianness, max_align, is64Bits> *c) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001832 _sections.push_back(c);
1833 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001834
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001835 void assignFileOffsets() {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001836 std::sort(_segments.begin(),
1837 _segments.end(),
1838 Segment<target_endianness, max_align, is64Bits>::compareSegments);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001839 int ordinal = 0;
1840 // Compute the number of segments that might be needed, so that the
1841 // size of the program header can be computed
1842 uint64_t offset = 0;
1843 for (auto si : _segments) {
1844 si->setOrdinal(++ordinal);
1845 si->assignOffsets(offset);
1846 offset += si->fileSize();
1847 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001848 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001849
Michael J. Spencera2c97272013-01-04 21:09:21 +00001850 void setELFHeader(ELFHeader<target_endianness, max_align, is64Bits> *e) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001851 _elfHeader = e;
1852 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001853
Michael J. Spencera2c97272013-01-04 21:09:21 +00001854 void setProgramHeader(
1855 ELFProgramHeader<target_endianness, max_align, is64Bits> *p) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001856 _programHeader = p;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001857 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001858
1859 void assignVirtualAddress() {
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001860 if (_segments.empty())
1861 return;
1862
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001863 uint64_t virtualAddress = _options.baseAddress();
1864
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001865 // HACK: This is a super dirty hack. The elf header and program header are
1866 // not part of a section, but we need them to be loaded at the base address
1867 // so that AT_PHDR is set correctly by the loader and so they are accessible
1868 // at runtime. To do this we simply prepend them to the first Segment and
1869 // let the layout logic take care of it.
1870 _segments[0]->prepend(_programHeader);
1871 _segments[0]->prepend(_elfHeader);
1872
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001873 bool newSegmentHeaderAdded = true;
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001874 while (true) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001875 for (auto si : _segments) {
1876 newSegmentHeaderAdded = _programHeader->addSegment(si);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001877 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001878 if (!newSegmentHeaderAdded)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001879 break;
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001880 uint64_t fileoffset = 0;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001881 uint64_t address = virtualAddress;
1882 // Fix the offsets after adding the program header
1883 for (auto &si : _segments) {
1884 // Align the segment to a page boundary
1885 fileoffset = llvm::RoundUpToAlignment(fileoffset, _options.pageSize());
1886 si->assignOffsets(fileoffset);
1887 fileoffset = si->fileOffset() + si->fileSize();
1888 }
1889 // start assigning virtual addresses
1890 for (auto si = _segments.begin(); si != _segments.end(); ++si) {
1891 (*si)->setVAddr(virtualAddress);
1892 // The first segment has the virtualAddress set to the base address as
1893 // we have added the file header and the program header dont align the
Michael J. Spencera2c97272013-01-04 21:09:21 +00001894 // first segment to the pagesize
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00001895 (*si)->assignVirtualAddress(address);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001896 (*si)->setMemSize(address - virtualAddress);
1897 virtualAddress = llvm::RoundUpToAlignment(address, _options.pageSize());
1898 }
1899 _programHeader->resetProgramHeaders();
1900 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001901 Section<target_endianness, max_align, is64Bits> *section;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001902 // Fix the offsets of all the atoms within a section
1903 for (auto &si : _sections) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001904 section =
1905 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(si);
1906 if (section &&
1907 DefaultELFLayout<target_endianness,
1908 max_align, is64Bits>::hasOutputSegment(section))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001909 section->assignOffsets(section->fileOffset());
1910 }
1911 // Set the size of the merged Sections
Michael J. Spencera2c97272013-01-04 21:09:21 +00001912 for (auto msi = merged_sections_begin(), mse = merged_sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001913 msi != mse; ++msi) {
1914 uint64_t sectionfileoffset = 0;
1915 uint64_t startFileOffset = 0;
1916 uint64_t sectionsize = 0;
1917 bool isFirstSection = true;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001918 for (auto si = (*msi)->begin_sections(); si != (*msi)->end_sections();
1919 ++si) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001920 if (isFirstSection) {
1921 startFileOffset = (*si)->fileOffset();
1922 isFirstSection = false;
1923 }
1924 sectionfileoffset = (*si)->fileOffset();
1925 sectionsize = (*si)->fileSize();
1926 }
1927 sectionsize = (sectionfileoffset - startFileOffset) + sectionsize;
1928 (*msi)->setFileOffset(startFileOffset);
1929 (*msi)->setSize(sectionsize);
1930 }
1931 // Set the virtual addr of the merged Sections
Michael J. Spencera2c97272013-01-04 21:09:21 +00001932 for (auto msi = merged_sections_begin(), mse = merged_sections_end();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001933 msi != mse; ++msi) {
1934 uint64_t sectionstartaddr = 0;
1935 uint64_t startaddr = 0;
1936 uint64_t sectionsize = 0;
1937 bool isFirstSection = true;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001938 for (auto si = (*msi)->begin_sections(), se = (*msi)->end_sections();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001939 si != se; ++si) {
1940 if (isFirstSection) {
1941 startaddr = (*si)->virtualAddr();
1942 isFirstSection = false;
1943 }
1944 sectionstartaddr = (*si)->virtualAddr();
1945 sectionsize = (*si)->memSize();
1946 }
1947 sectionsize = (sectionstartaddr - startaddr) + sectionsize;
1948 (*msi)->setMemSize(sectionsize);
1949 (*msi)->setAddr(startaddr);
1950 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001951 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001952
1953 void assignOffsetsForMiscSections() {
1954 uint64_t fileoffset = 0;
1955 uint64_t size = 0;
1956 for (auto si : _segments) {
1957 fileoffset = si->fileOffset();
1958 size = si->fileSize();
1959 }
1960 fileoffset = fileoffset + size;
Michael J. Spencera2c97272013-01-04 21:09:21 +00001961 Section<target_endianness, max_align, is64Bits> *section;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001962 for (auto si : _sections) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001963 section =
1964 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(si);
1965 if (section &&
1966 DefaultELFLayout<target_endianness,
1967 max_align, is64Bits>::hasOutputSegment(section))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001968 continue;
1969 fileoffset = llvm::RoundUpToAlignment(fileoffset, si->align2());
1970 si->setFileOffset(fileoffset);
1971 si->setVAddr(0);
1972 fileoffset += si->fileSize();
1973 }
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001974 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001975
1976 void finalize() {
1977 for (auto &si : _sections) {
1978 si->finalize();
1979 }
1980 }
1981
1982 bool findAtomAddrByName(const StringRef name, uint64_t &addr) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001983 Section<target_endianness, max_align, is64Bits> *section;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001984 for (auto ai = _sections.begin(); ai != _sections.end(); ++ai) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00001985 if ((*ai)->kind() ==
1986 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection) {
1987 section =
1988 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(*ai);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001989 if (section->findAtomAddrByName(name, addr))
1990 return true;
1991 }
1992 }
Michael J. Spencera2c97272013-01-04 21:09:21 +00001993 return false;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001994 }
1995
Michael J. Spencera2c97272013-01-04 21:09:21 +00001996 MergedSectionIter merged_sections_begin() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001997 return _mergedSections.begin();
1998 }
1999
Michael J. Spencera2c97272013-01-04 21:09:21 +00002000 MergedSectionIter merged_sections_end() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002001 return _mergedSections.end();
2002 }
2003
2004 ChunkIter sections_begin() {
2005 return _sections.begin();
2006 }
2007 ChunkIter sections_end() {
2008 return _sections.end();
2009 }
2010
2011 ChunkIter segments_begin() {
2012 return _segments.begin();
2013 }
2014
2015 ChunkIter segments_end() {
2016 return _segments.end();
2017 }
2018
Michael J. Spencera2c97272013-01-04 21:09:21 +00002019 ELFHeader<target_endianness, max_align, is64Bits> *elfHeader() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002020 return _elfHeader;
2021 }
2022
Michael J. Spencera2c97272013-01-04 21:09:21 +00002023 ELFProgramHeader<target_endianness, max_align, is64Bits> *elfProgramHeader() {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002024 return _programHeader;
Hemant Kulkarni08e410292012-10-01 23:53:20 +00002025 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002026
2027private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002028 SectionMapT _sectionMap;
2029 MergedSectionMapT _mergedSectionMap;
2030 SegmentMapT _segmentMap;
Michael J. Spencera2c97272013-01-04 21:09:21 +00002031 std::vector<Chunk<target_endianness, max_align, is64Bits> *> _sections;
2032 std::vector<Segment<target_endianness, max_align, is64Bits> *> _segments;
2033 std::vector<MergedSections<target_endianness, max_align, is64Bits> *>
2034 _mergedSections;
2035 ELFHeader<target_endianness, max_align, is64Bits> *_elfHeader;
2036 ELFProgramHeader<target_endianness, max_align, is64Bits> *_programHeader;
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002037 std::vector<AbsoluteAtomPair> _absoluteAtoms;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002038 llvm::BumpPtrAllocator _allocator;
2039 const WriterOptionsELF &_options;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002040};
2041
2042//===----------------------------------------------------------------------===//
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002043// ELFExecutableWriter Class
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002044//===----------------------------------------------------------------------===//
Michael J. Spencera2c97272013-01-04 21:09:21 +00002045template<support::endianness target_endianness,
2046 std::size_t max_align,
2047 bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002048class ELFExecutableWriter : public ELFWriter {
2049public:
Michael J. Spencera2c97272013-01-04 21:09:21 +00002050 typedef Elf_Shdr_Impl<target_endianness, max_align, is64Bits> Elf_Shdr;
2051 typedef Elf_Sym_Impl<target_endianness, max_align, is64Bits> Elf_Sym;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002052
2053 ELFExecutableWriter(const WriterOptionsELF &options);
2054
2055private:
Michael J. Spencera2c97272013-01-04 21:09:21 +00002056 // build the sections that need to be created
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002057 void buildChunks(const lld::File &file);
2058 virtual error_code writeFile(const lld::File &File, StringRef path);
2059 void buildAtomToAddressMap();
2060 void buildSymbolTable ();
2061 void buildSectionHeaderTable();
2062 void assignSectionsWithNoSegments();
2063 void addAbsoluteUndefinedSymbols(const lld::File &File);
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002064 void addDefaultAtoms();
2065 void addFiles(InputFiles&);
2066 void finalizeDefaultAtomValues();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002067
Michael J. Spencera2c97272013-01-04 21:09:21 +00002068 uint64_t addressOfAtom(const Atom *atom) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002069 return _atomToAddressMap[atom];
2070 }
2071
2072 KindHandler *kindHandler() { return _referenceKindHandler.get(); }
2073
2074 void createDefaultSections();
2075
2076 const WriterOptionsELF &_options;
2077
2078 typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
2079 std::unique_ptr<KindHandler> _referenceKindHandler;
2080 AtomToAddress _atomToAddressMap;
2081 llvm::BumpPtrAllocator _chunkAllocate;
Michael J. Spencera2c97272013-01-04 21:09:21 +00002082 DefaultELFLayout<target_endianness, max_align, is64Bits> *_layout;
2083 ELFHeader<target_endianness, max_align, is64Bits> *_elfHeader;
2084 ELFProgramHeader<target_endianness, max_align, is64Bits> *_programHeader;
2085 ELFSymbolTable<target_endianness, max_align, is64Bits> * _symtab;
2086 ELFStringTable<target_endianness, max_align, is64Bits> *_strtab;
2087 ELFStringTable<target_endianness, max_align, is64Bits> *_shstrtab;
2088 ELFSectionHeader<target_endianness, max_align, is64Bits> *_shdrtab;
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002089 CRuntimeFile<target_endianness, max_align, is64Bits> _runtimeFile;
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002090};
2091
2092//===----------------------------------------------------------------------===//
2093// ELFExecutableWriter
2094//===----------------------------------------------------------------------===//
Michael J. Spencera2c97272013-01-04 21:09:21 +00002095template<support::endianness target_endianness,
2096 std::size_t max_align,
2097 bool is64Bits>
2098ELFExecutableWriter<target_endianness, max_align, is64Bits>
2099 ::ELFExecutableWriter(const WriterOptionsELF &options)
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002100 : _options(options)
Sid Manning42064e52012-10-09 02:20:47 +00002101 , _referenceKindHandler(KindHandler::makeHandler(_options.machine(),
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002102 target_endianness))
2103 , _runtimeFile(options) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002104 _layout =
2105 new DefaultELFLayout<target_endianness, max_align, is64Bits>(options);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002106}
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002107
Michael J. Spencera2c97272013-01-04 21:09:21 +00002108template<support::endianness target_endianness,
2109 std::size_t max_align,
2110 bool is64Bits>
2111void ELFExecutableWriter<target_endianness, max_align, is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002112 ::buildChunks(const lld::File &file){
2113 for (const DefinedAtom *definedAtom : file.defined() ) {
2114 _layout->addAtom(definedAtom);
2115 }
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002116 /// Add all the absolute atoms to the layout
2117 for (const AbsoluteAtom *absoluteAtom : file.absolute()) {
2118 _layout->addAtom(absoluteAtom);
2119 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002120}
2121
Michael J. Spencera2c97272013-01-04 21:09:21 +00002122template<support::endianness target_endianness,
2123 std::size_t max_align,
2124 bool is64Bits>
2125void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2126 ::buildSymbolTable () {
2127 Section<target_endianness, max_align, is64Bits> *section;
2128 for (auto si = _layout->sections_begin(); si != _layout->sections_end();
2129 ++si) {
2130 if ((*si)->kind() !=
2131 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002132 continue;
Michael J. Spencera2c97272013-01-04 21:09:21 +00002133 section =
2134 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(*si);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002135 for (auto ai = section->atoms_begin(); ai != section->atoms_end(); ++ai) {
Michael J. Spencer4ffbd602013-01-11 22:39:44 +00002136 _symtab->addSymbol(ai->_atom, section->ordinal(), ai->_virtualAddr);
Hemant Kulkarni736f7fb2012-11-21 21:07:36 +00002137 }
2138 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002139}
2140
Michael J. Spencera2c97272013-01-04 21:09:21 +00002141template<support::endianness target_endianness,
2142 std::size_t max_align,
2143 bool is64Bits>
2144void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2145 ::addAbsoluteUndefinedSymbols(const lld::File &file) {
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002146 /// add all the absolute symbols that the layout contains to the output symbol
2147 /// table
2148 for (auto absi = _layout->absAtomsBegin(), abse = _layout->absAtomsEnd();
2149 absi != abse; ++absi) {
2150 _symtab->addSymbol(absi->absoluteAtom(), ELF::SHN_ABS, absi->value());
2151 }
Hemant Kulkarni08e410292012-10-01 23:53:20 +00002152 for (const UndefinedAtom *a : file.undefined()) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002153 _symtab->addSymbol(a, ELF::SHN_UNDEF);
Hemant Kulkarni08e410292012-10-01 23:53:20 +00002154 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002155}
2156
Michael J. Spencera2c97272013-01-04 21:09:21 +00002157template<support::endianness target_endianness,
2158 std::size_t max_align,
2159 bool is64Bits>
2160void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2161 ::buildAtomToAddressMap () {
2162 Section<target_endianness, max_align, is64Bits> *section;
2163 for (auto si = _layout->sections_begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002164 si != _layout->sections_end(); ++si) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002165 if ((*si)->kind() !=
2166 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002167 continue;
Michael J. Spencer2a5763c2013-01-11 22:39:31 +00002168 section = cast<Section<target_endianness, max_align, is64Bits>>(*si);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002169 for (auto ai = section->atoms_begin(); ai != section->atoms_end(); ++ai) {
Michael J. Spencer4ffbd602013-01-11 22:39:44 +00002170 _atomToAddressMap[ai->_atom] = (ai)->_virtualAddr;
Sid Manningdd110202012-09-25 18:22:09 +00002171 }
2172 }
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002173 /// build the atomToAddressMap that contains absolute symbols too
2174 for (auto absi = _layout->absAtomsBegin(), abse = _layout->absAtomsEnd();
2175 absi != abse; ++absi) {
2176 _atomToAddressMap[absi->absoluteAtom()] = absi->value();
2177 }
Sid Manningdd110202012-09-25 18:22:09 +00002178}
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002179
Michael J. Spencera2c97272013-01-04 21:09:21 +00002180template<support::endianness target_endianness,
2181 std::size_t max_align,
2182 bool is64Bits>
2183void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2184 ::buildSectionHeaderTable() {
2185 for (auto msi = _layout->merged_sections_begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002186 msi != _layout->merged_sections_end(); ++msi) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002187 if ((*msi)->kind() !=
2188 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002189 continue;
2190 if ((*msi)->hasSegment())
2191 _shdrtab->appendSection(*msi);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002192 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002193}
2194
Michael J. Spencera2c97272013-01-04 21:09:21 +00002195template<support::endianness target_endianness,
2196 std::size_t max_align,
2197 bool is64Bits>
2198void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2199 ::assignSectionsWithNoSegments() {
2200 Section<target_endianness, max_align, is64Bits> *section;
2201 for (auto msi = _layout->merged_sections_begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002202 msi != _layout->merged_sections_end(); ++msi) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002203 if ((*msi)->kind() !=
2204 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002205 continue;
2206 if (!(*msi)->hasSegment())
2207 _shdrtab->appendSection(*msi);
2208 }
2209 _layout->assignOffsetsForMiscSections();
Michael J. Spencera2c97272013-01-04 21:09:21 +00002210 for (auto si = _layout->sections_begin();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002211 si != _layout->sections_end(); ++si) {
Michael J. Spencera2c97272013-01-04 21:09:21 +00002212 if ((*si)->kind() !=
2213 Chunk<target_endianness, max_align, is64Bits>::K_ELFSection)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002214 continue;
Michael J. Spencera2c97272013-01-04 21:09:21 +00002215 section =
2216 llvm::dyn_cast<Section<target_endianness, max_align, is64Bits>>(*si);
2217 if (!DefaultELFLayout<target_endianness, max_align, is64Bits>
2218 ::hasOutputSegment(section))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002219 _shdrtab->updateSection(section);
2220 }
2221}
2222
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002223/// \brief Add absolute symbols by default. These are linker added
2224/// absolute symbols
2225template<support::endianness target_endianness,
2226 std::size_t max_align,
2227 bool is64Bits>
2228void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2229 ::addDefaultAtoms() {
2230 _runtimeFile.addUndefinedAtom("_start");
2231 _runtimeFile.addAbsoluteAtom("__bss_start");
2232 _runtimeFile.addAbsoluteAtom("__bss_end");
2233 _runtimeFile.addAbsoluteAtom("_end");
2234 _runtimeFile.addAbsoluteAtom("end");
Michael J. Spencerecd5f402013-01-10 22:41:42 +00002235 _runtimeFile.addAbsoluteAtom("__init_array_start");
2236 _runtimeFile.addAbsoluteAtom("__init_array_end");
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002237}
2238
2239/// \brief Hook in lld to add CRuntime file
2240template<support::endianness target_endianness,
2241 std::size_t max_align,
2242 bool is64Bits>
2243void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2244 ::addFiles(InputFiles &inputFiles) {
2245 addDefaultAtoms();
2246 inputFiles.prependFile(_runtimeFile);
2247}
2248
2249/// Finalize the value of all the absolute symbols that we
2250/// created
2251template<support::endianness target_endianness,
2252 std::size_t max_align,
2253 bool is64Bits>
2254void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2255 ::finalizeDefaultAtomValues() {
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002256 auto bssStartAtomIter = _layout->findAbsoluteAtom("__bss_start");
2257 auto bssEndAtomIter = _layout->findAbsoluteAtom("__bss_end");
2258 auto underScoreEndAtomIter = _layout->findAbsoluteAtom("_end");
2259 auto endAtomIter = _layout->findAbsoluteAtom("end");
Michael J. Spencerecd5f402013-01-10 22:41:42 +00002260 auto initArrayStartIter = _layout->findAbsoluteAtom("__init_array_start");
2261 auto initArrayEndIter = _layout->findAbsoluteAtom("__init_array_end");
2262
2263 auto section = _layout->findOutputSection(".init_array");
2264 if (section) {
2265 initArrayStartIter->setValue(section->virtualAddr());
2266 initArrayEndIter->setValue(section->virtualAddr() +
2267 section->memSize());
2268 } else {
2269 initArrayStartIter->setValue(0);
2270 initArrayEndIter->setValue(0);
2271 }
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002272
Michael J. Spenceraa8a5a22013-01-10 22:41:05 +00002273 assert(!(bssStartAtomIter == _layout->absAtomsEnd() ||
2274 bssEndAtomIter == _layout->absAtomsEnd() ||
2275 underScoreEndAtomIter == _layout->absAtomsEnd() ||
2276 endAtomIter == _layout->absAtomsEnd()) &&
Shankar Easwaran37c52822013-01-10 18:16:10 +00002277 "Unable to find the absolute atoms that have been added by lld");
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002278
2279 auto phe = _programHeader->findProgramHeader(
2280 llvm::ELF::PT_LOAD,
2281 llvm::ELF::PF_W,
2282 llvm::ELF::PF_X);
2283
Shankar Easwaran37c52822013-01-10 18:16:10 +00002284 assert(!(phe == _programHeader->end()) &&
2285 "Can't find a data segment in the program header!");
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002286
2287 bssStartAtomIter->setValue((*phe)->p_vaddr+(*phe)->p_filesz);
2288 bssEndAtomIter->setValue((*phe)->p_vaddr+(*phe)->p_memsz);
2289 underScoreEndAtomIter->setValue((*phe)->p_vaddr+(*phe)->p_memsz);
2290 endAtomIter->setValue((*phe)->p_vaddr+(*phe)->p_memsz);
2291}
2292
Michael J. Spencera2c97272013-01-04 21:09:21 +00002293template<support::endianness target_endianness,
2294 std::size_t max_align,
2295 bool is64Bits>
2296error_code ELFExecutableWriter<target_endianness, max_align, is64Bits>
2297 ::writeFile(const lld::File &file, StringRef path) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002298 buildChunks(file);
2299 // Create the default sections like the symbol table, string table, and the
2300 // section string table
2301 createDefaultSections();
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002302
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002303 // Set the Layout
2304 _layout->assignSectionsToSegments();
2305 _layout->assignFileOffsets();
2306 _layout->assignVirtualAddress();
2307
Shankar Easwaran2ca8e7d2013-01-10 03:16:27 +00002308 // Finalize the default value of symbols that the linker adds
2309 finalizeDefaultAtomValues();
2310
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002311 // Build the Atom To Address map for applying relocations
2312 buildAtomToAddressMap();
2313
2314 // Create symbol table and section string table
2315 buildSymbolTable();
2316
2317 // add other symbols
2318 addAbsoluteUndefinedSymbols(file);
2319
2320 // Finalize the layout by calling the finalize() functions
2321 _layout->finalize();
2322
2323 // build Section Header table
2324 buildSectionHeaderTable();
2325
2326 // assign Offsets and virtual addresses
2327 // for sections with no segments
2328 assignSectionsWithNoSegments();
2329
2330 uint64_t totalSize = _shdrtab->fileOffset() + _shdrtab->fileSize();
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002331
2332 OwningPtr<FileOutputBuffer> buffer;
2333 error_code ec = FileOutputBuffer::create(path,
2334 totalSize, buffer,
2335 FileOutputBuffer::F_executable);
2336 if (ec)
2337 return ec;
2338
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002339 _elfHeader->e_ident(ELF::EI_CLASS, (_options.is64Bit() ? ELF::ELFCLASS64
2340 : ELF::ELFCLASS32));
Michael J. Spencera2c97272013-01-04 21:09:21 +00002341 _elfHeader->e_ident(ELF::EI_DATA, _options.endianness() == llvm::support::big
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002342 ? ELF::ELFDATA2MSB : ELF::ELFDATA2LSB);
2343 _elfHeader->e_ident(ELF::EI_VERSION, 1);
2344 _elfHeader->e_ident(ELF::EI_OSABI, 0);
2345 _elfHeader->e_type(_options.type());
2346 _elfHeader->e_machine(_options.machine());
2347 _elfHeader->e_version(1);
2348 _elfHeader->e_entry(0ULL);
2349 _elfHeader->e_phoff(_programHeader->fileOffset());
2350 _elfHeader->e_shoff(_shdrtab->fileOffset());
2351 _elfHeader->e_phentsize(_programHeader->entsize());
2352 _elfHeader->e_phnum(_programHeader->numHeaders());
2353 _elfHeader->e_shentsize(_shdrtab->entsize());
2354 _elfHeader->e_shnum(_shdrtab->numHeaders());
2355 _elfHeader->e_shstrndx(_shstrtab->ordinal());
2356 uint64_t virtualAddr = 0;
2357 _layout->findAtomAddrByName("_start", virtualAddr);
2358 _elfHeader->e_entry(virtualAddr);
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00002359
2360 // HACK: We have to write out the header and program header here even though
2361 // they are a member of a segment because only sections are written in the
2362 // following loop.
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002363 _elfHeader->write(this, buffer);
2364 _programHeader->write(this, buffer);
2365
Michael J. Spencer1ac382f02013-01-07 08:00:04 +00002366 for (auto si = _layout->sections_begin(); si != _layout->sections_end(); ++si)
2367 (*si)->write(this, buffer);
2368
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002369 return buffer->commit();
2370}
Nick Kledzikabb69812012-05-31 22:34:00 +00002371
Michael J. Spencera2c97272013-01-04 21:09:21 +00002372template<support::endianness target_endianness,
2373 std::size_t max_align,
2374 bool is64Bits>
2375void ELFExecutableWriter<target_endianness, max_align, is64Bits>
2376 ::createDefaultSections() {
2377 _elfHeader =
2378 new ELFHeader<target_endianness, max_align, is64Bits>();
2379 _programHeader =
2380 new ELFProgramHeader<target_endianness, max_align, is64Bits>();
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002381 _layout->setELFHeader(_elfHeader);
2382 _layout->setProgramHeader(_programHeader);
2383
Michael J. Spencera2c97272013-01-04 21:09:21 +00002384 _symtab = new ELFSymbolTable<target_endianness, max_align, is64Bits>(
2385 ".symtab",
2386 DefaultELFLayout<target_endianness, max_align, is64Bits>
2387 ::ORDER_SYMBOL_TABLE);
2388 _strtab = new ELFStringTable<target_endianness, max_align, is64Bits>(
2389 ".strtab",
2390 DefaultELFLayout<target_endianness, max_align, is64Bits>
2391 ::ORDER_STRING_TABLE);
2392 _shstrtab = new ELFStringTable<target_endianness, max_align, is64Bits>(
2393 ".shstrtab",
2394 DefaultELFLayout<target_endianness, max_align, is64Bits>
2395 ::ORDER_SECTION_STRINGS);
2396 _shdrtab = new ELFSectionHeader<target_endianness, max_align, is64Bits>(
2397 DefaultELFLayout<target_endianness, max_align, is64Bits>
2398 ::ORDER_SECTION_HEADERS);
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002399 _layout->addSection(_symtab);
2400 _layout->addSection(_strtab);
2401 _layout->addSection(_shstrtab);
2402 _shdrtab->setStringSection(_shstrtab);
2403 _symtab->setStringSection(_strtab);
2404 _layout->addSection(_shdrtab);
Sid Manningdd110202012-09-25 18:22:09 +00002405}
Nick Kledzikabb69812012-05-31 22:34:00 +00002406} // namespace elf
2407
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002408Writer *createWriterELF(const WriterOptionsELF &options) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002409 // Set the default layout to be the static executable layout
Michael J. Spencera2c97272013-01-04 21:09:21 +00002410 // We would set the layout to a dynamic executable layout
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002411 // if we came across any shared libraries in the process
Michael J. Spencera2c97272013-01-04 21:09:21 +00002412
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002413 if (!options.is64Bit() && options.endianness() == llvm::support::little)
Michael J. Spencera2c97272013-01-04 21:09:21 +00002414 return new elf::ELFExecutableWriter<support::little, 4, false>(options);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002415 else if (options.is64Bit() && options.endianness() == llvm::support::little)
Michael J. Spencera2c97272013-01-04 21:09:21 +00002416 return new elf::ELFExecutableWriter<support::little, 8, true>(options);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002417 else if (!options.is64Bit() && options.endianness() == llvm::support::big)
Michael J. Spencera2c97272013-01-04 21:09:21 +00002418 return new elf::ELFExecutableWriter<support::big, 4, false>(options);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002419 else if (options.is64Bit() && options.endianness() == llvm::support::big)
Michael J. Spencera2c97272013-01-04 21:09:21 +00002420 return new elf::ELFExecutableWriter<support::big, 8, true>(options);
Nick Kledzikabb69812012-05-31 22:34:00 +00002421
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002422 llvm_unreachable("Invalid Options!");
Nick Kledzikabb69812012-05-31 22:34:00 +00002423}
Nick Kledzikabb69812012-05-31 22:34:00 +00002424} // namespace lld