blob: e53f56c22ca2e28786364629b54c7cd4b08d0f8d [file] [log] [blame]
Nick Kledzikabb69812012-05-31 22:34:00 +00001//===- lib/ReaderWriter/ELF/WriterELF.cpp ---------------------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lld/ReaderWriter/WriterELF.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000011#include "ReferenceKinds.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000012
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000013#include "lld/Core/DefinedAtom.h"
14#include "lld/Core/File.h"
15#include "lld/Core/InputFiles.h"
16#include "lld/Core/Reference.h"
17#include "lld/Core/SharedLibraryAtom.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000018#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/DenseMap.h"
Shankar Easwaran495d38b2012-12-27 02:26:30 +000020#include "llvm/ADT/Hashing.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000021#include "llvm/ADT/OwningPtr.h"
22#include "llvm/ADT/SmallVector.h"
Shankar Easwaran495d38b2012-12-27 02:26:30 +000023#include "llvm/ADT/StringExtras.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000024#include "llvm/ADT/StringMap.h"
25#include "llvm/ADT/StringRef.h"
Shankar Easwaran495d38b2012-12-27 02:26:30 +000026#include "llvm/ADT/StringSwitch.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000027#include "llvm/Object/ELF.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000028#include "llvm/Support/Allocator.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000029#include "llvm/Support/Debug.h"
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000030#include "llvm/Support/ELF.h"
31#include "llvm/Support/ErrorHandling.h"
32#include "llvm/Support/FileOutputBuffer.h"
33#include "llvm/Support/Format.h"
34#include "llvm/Support/MathExtras.h"
35#include "llvm/Support/raw_ostream.h"
36#include "llvm/Support/system_error.h"
Shankar Easwaran495d38b2012-12-27 02:26:30 +000037#include "AtomsELF.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000038
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000039#include <map>
Shankar Easwaran495d38b2012-12-27 02:26:30 +000040#include <unordered_map>
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000041#include <tuple>
42#include <vector>
Nick Kledzikabb69812012-05-31 22:34:00 +000043
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000044using namespace llvm;
45using namespace llvm::object;
Nick Kledzikabb69812012-05-31 22:34:00 +000046namespace lld {
47namespace elf {
48
Shankar Easwaran495d38b2012-12-27 02:26:30 +000049template<support::endianness target_endianness, bool is64Bits>
50class ELFExecutableWriter;
Hemant Kulkarni87dbac02012-11-13 21:34:45 +000051
Shankar Easwaran495d38b2012-12-27 02:26:30 +000052/// \brief The ELFWriter class is a base class for the linker to write
53/// various kinds of ELF files.
54class ELFWriter : public Writer {
55 public:
56 ELFWriter() { }
57
58 public:
59 /// \brief builds the chunks that needs to be written to the output
60 /// ELF file
61 virtual void buildChunks(const lld::File &file) = 0;
62
63 /// \brief Writes the chunks into the output file specified by path
64 virtual error_code writeFile(const lld::File &File, StringRef path) = 0;
65
66 /// \brief Writes the chunks into the output file specified by path
67 virtual uint64_t addressOfAtom(const Atom *atom) = 0;
68
69 /// \brief Return the processing function to apply Relocations
70 virtual KindHandler *kindHandler() = 0;
Hemant Kulkarni87dbac02012-11-13 21:34:45 +000071};
72
Shankar Easwaran495d38b2012-12-27 02:26:30 +000073/// \brief A chunk is a contiguous region of space
Hemant Kulkarni927bbc22012-09-14 16:11:34 +000074template<support::endianness target_endianness, bool is64Bits>
75class Chunk {
76public:
Shankar Easwaran495d38b2012-12-27 02:26:30 +000077
78 /// \brief Describes the type of Chunk
79 enum Kind {
80 K_ELFHeader, // ELF Header
81 K_ELFProgramHeader, // Program Header
82 K_ELFSegment, // Segment
83 K_ELFSection, // Section
84 K_ELFSectionHeader // Section header
Hemant Kulkarni87dbac02012-11-13 21:34:45 +000085 };
Shankar Easwaran495d38b2012-12-27 02:26:30 +000086 Chunk(StringRef name, Kind kind)
87 : _name(name)
88 , _kind(kind)
89 , _fsize(0)
90 , _msize(0)
91 , _align2(0)
92 , _order(0)
93 , _ordinal(1)
94 , _start(0)
95 , _fileoffset(0) {}
96 virtual ~Chunk() {}
97 // Does the chunk occupy disk space
98 virtual bool occupiesNoDiskSpace() const {
99 return false;
100 }
101 // The name of the chunk
102 StringRef name() const { return _name; }
103 // Kind of chunk
104 Kind kind() const { return _kind; }
105 uint64_t fileSize() const { return _fsize; }
106 uint64_t align2() const { return _align2; }
107 void appendAtom() const;
108
109 // The ordinal value of the chunk
110 uint64_t ordinal() const { return _ordinal;}
111 void setOrdinal(uint64_t newVal) { _ordinal = newVal;}
112 // The order in which the chunk would appear in the output file
113 uint64_t order() const { return _order; }
114 void setOrder(uint32_t order) { _order = order; }
115 // Output file offset of the chunk
116 uint64_t fileOffset() const { return _fileoffset; }
117 void setFileOffset(uint64_t offset) { _fileoffset = offset; }
118 // Output start address of the chunk
119 void setVAddr(uint64_t start) { _start = start; }
120 uint64_t virtualAddr() const { return _start; }
121 // Does the chunk occupy memory during execution ?
122 uint64_t memSize() const { return _msize; }
123 void setMemSize(uint64_t msize) { _msize = msize; }
124 // Writer the chunk
125 virtual void write(ELFWriter *writer,
126 OwningPtr<FileOutputBuffer> &buffer) = 0;
127 // Finalize the chunk before writing
128 virtual void finalize() = 0;
129
Hemant Kulkarni927bbc22012-09-14 16:11:34 +0000130protected:
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000131 StringRef _name;
132 Kind _kind;
133 uint64_t _fsize;
134 uint64_t _msize;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +0000135 uint64_t _align2;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000136 uint32_t _order;
Hemant Kulkarni08e410292012-10-01 23:53:20 +0000137 uint64_t _ordinal;
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000138 uint64_t _start;
139 uint64_t _fileoffset;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +0000140};
141
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000142/// \brief The ELFLayoutOptions encapsulates the options used by all Layouts
143/// Examples of the ELFLayoutOptions would be a script that would be used
144/// to drive the layout
145class ELFLayoutOptions {
Hemant Kulkarni927bbc22012-09-14 16:11:34 +0000146public:
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000147 ELFLayoutOptions() { }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +0000148
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000149 ELFLayoutOptions(StringRef &linker_script) : _script(linker_script)
150 {}
Hemant Kulkarni87dbac02012-11-13 21:34:45 +0000151
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000152 /// parse the linker script
153 error_code parseLinkerScript();
Hemant Kulkarni736f7fb2012-11-21 21:07:36 +0000154
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000155 /// Is the current section present in the linker script
156 bool isSectionPresent();
157
Hemant Kulkarni08e410292012-10-01 23:53:20 +0000158private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000159 StringRef _script;
Hemant Kulkarni08e410292012-10-01 23:53:20 +0000160};
Shankar Easwaran495d38b2012-12-27 02:26:30 +0000161
162/// \brief The ELFLayout is an abstract class for managing the final layout for
163/// the kind of binaries(Shared Libraries / Relocatables / Executables 0
164/// Each architecture (Hexagon, PowerPC, MIPS) would have a concrete
165/// subclass derived from ELFLayout for generating each binary thats
166// needed by the lld linker
167class ELFLayout {
168public:
169 typedef uint32_t SectionOrder;
170 typedef uint32_t SegmentType;
171 typedef uint32_t Flags;
172
173public:
174 /// Return the order the section would appear in the output file
175 virtual SectionOrder getSectionOrder
176 (const StringRef name,
177 int32_t contentType,
178 int32_t contentPerm) = 0;
179 /// append the Atom to the layout and create appropriate sections
180 virtual error_code addAtom(const Atom *atom) = 0;
181 /// find the Atom Address in the current layout
182 virtual bool findAtomAddrByName(const StringRef name, uint64_t &addr) = 0;
183 /// associates a section to a segment
184 virtual void assignSectionsToSegments() = 0;
185 /// associates a virtual address to the segment, section, and the atom
186 virtual void assignVirtualAddress() = 0;
187 /// associates a file offset to the segment, section and the atom
188 virtual void assignFileOffsets() = 0;
189
190public:
191 ELFLayout() {}
192 ELFLayout(WriterOptionsELF &writerOptions,
193 ELFLayoutOptions &layoutOptions)
194 : _writerOptions(writerOptions)
195 , _layoutOptions(layoutOptions) {}
196 virtual ~ELFLayout() { }
197
198private:
199 WriterOptionsELF _writerOptions;
200 ELFLayoutOptions _layoutOptions;
201};
202
203
204/// \brief A section contains a set of atoms that have similiar properties
205/// The atoms that have similiar properties are merged to form a section
206template<support::endianness target_endianness, bool is64Bits>
207class Section : public Chunk<target_endianness, is64Bits> {
208public:
209 // The Kind of section that the object represents
210 enum SectionKind {
211 K_Default,
212 K_SymbolTable,
213 K_StringTable,
214 };
215 // Create a section object, the section is set to the default type if the
216 // caller doesnot set it
217 Section(const StringRef sectionName,
218 const int32_t contentType,
219 const int32_t contentPermissions,
220 const int32_t order,
221 const SectionKind kind = K_Default)
222 : Chunk<target_endianness, is64Bits>
223 (sectionName, Chunk<target_endianness, is64Bits>::K_ELFSection)
224 , _contentType(contentType)
225 , _contentPermissions(contentPermissions)
226 , _sectionKind(kind)
227 , _entSize(0)
228 , _shInfo(0)
229 , _link(0) {
230 this->setOrder(order);
231 }
232
233 /// return the section kind
234 SectionKind sectionKind() const {
235 return _sectionKind;
236 }
237
238 /// Align the offset to the required modulus defined by the atom alignment
239 uint64_t alignOffset(uint64_t offset, DefinedAtom::Alignment &atomAlign) {
240 uint64_t requiredModulus = atomAlign.modulus;
241 uint64_t align2 = 1u << atomAlign.powerOf2;
242 uint64_t currentModulus = (offset % align2);
243 uint64_t retOffset = offset;
244 if (currentModulus != requiredModulus) {
245 if (requiredModulus > currentModulus)
246 retOffset += requiredModulus - currentModulus;
247 else
248 retOffset += align2 + requiredModulus - currentModulus;
249 }
250 return retOffset;
251 }
252
253 // \brief Append an atom to a Section. The atom gets pushed into a vector
254 // contains the atom, the atom file offset, the atom virtual address
255 // the atom file offset is aligned appropriately as set by the Reader
256 void appendAtom(const Atom *atom) {
257 Atom::Definition atomType = atom->definition();
258 const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom);
259 assert(atom != nullptr && "Expecting the atom to be a DefinedAtom");
260 DefinedAtom::Alignment atomAlign = definedAtom->alignment();
261 uint64_t align2 = 1u << atomAlign.powerOf2;
262 // Align the atom to the required modulus/ align the file offset and the
263 // memory offset seperately this is required so that BSS symbols are handled
264 // properly as the BSS symbols only occupy memory size and not file size
265 uint64_t fOffset = alignOffset(this->fileSize(), atomAlign);
266 uint64_t mOffset = alignOffset(this->memSize(), atomAlign);
267 switch (atomType) {
268 case Atom::definitionRegular:
269 switch(definedAtom->contentType()) {
270 case DefinedAtom::typeCode:
271 case DefinedAtom::typeData:
272 _atoms.push_back(std::make_pair(atom, std::make_pair(fOffset, 0)));
273 this->_fsize = fOffset + definedAtom->size();
274 this->_msize = mOffset + definedAtom->size();
275 break;
276 case DefinedAtom::typeZeroFill:
277 _atoms.push_back(std::make_pair(atom, std::make_pair(mOffset, 0)));
278 this->_msize = mOffset + definedAtom->size();
279 break;
280 default:
281 this->_fsize = fOffset + definedAtom->size();
282 this->_msize = mOffset + definedAtom->size();
283 break;
284 }
285 break;
286 default:
287 llvm_unreachable("Expecting only definedAtoms being passed here");
288 break;
289 }
290 // Set the section alignment to the largest alignment
291 // std::max doesnot support uint64_t
292 if (this->_align2 < align2)
293 this->_align2 = align2;
294 }
295
296 /// \brief Set the virtual address of each Atom in the Section. This
297 /// routine gets called after the linker fixes up the virtual address
298 /// of the section
299 void assignVirtualAddress(uint64_t &addr) {
300 for (auto &ai : _atoms) {
301 ai.second.second = addr + ai.second.first;
302 }
303 addr += this->memSize();
304 }
305
306 /// \brief Set the file offset of each Atom in the section. This routine
307 /// gets called after the linker fixes up the section offset
308 void assignOffsets(uint64_t offset) {
309 for (auto &ai : _atoms) {
310 ai.second.first = offset + ai.second.first;
311 }
312 }
313
314 /// \brief Find the Atom address given a name, this is needed to to properly
315 /// apply relocation. The section class calls this to find the atom address
316 /// to fix the relocation
317 bool findAtomAddrByName(const StringRef name, uint64_t &addr) {
318 for (auto ai : _atoms) {
319 if (ai.first->name() == name) {
320 addr = ai.second.second;
321 return true;
322 }
323 }
324 return false;
325 }
326
327 /// \brief Does the Atom occupy any disk space
328 bool occupiesNoDiskSpace() const {
329 return _contentType == DefinedAtom::typeZeroFill;
330 }
331
332 /// \brief The permission of the section is the most permissive permission
333 /// of all atoms that the section contains
334 void setContentPermissions(int32_t perm) {
335 _contentPermissions = std::max(perm, _contentPermissions);
336 }
337
338 /// \brief Get the section flags, defined by the permissions of the section
339 int64_t flags() {
340 switch (_contentPermissions) {
341 case DefinedAtom::perm___:
342 return 0;
343
344 case DefinedAtom::permR__:
345 return llvm::ELF::SHF_ALLOC;
346
347 case DefinedAtom::permR_X:
348 return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR;
349
350 case DefinedAtom::permRW_:
351 case DefinedAtom::permRW_L:
352 return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE;
353
354 case DefinedAtom::permRWX:
355 return llvm::ELF::SHF_ALLOC |
356 llvm::ELF::SHF_WRITE |
357 llvm::ELF::SHF_EXECINSTR;
358
359 default:
360 break;
361 }
362 return llvm::ELF::SHF_ALLOC;
363 }
364
365 /// \brief Return the raw flags, we need this to sort segments
366 int64_t atomflags() const {
367 return _contentPermissions;
368 }
369
370 /// \brief Return the section type, the returned value is recorded in the
371 /// sh_type field of the Section Header
372 int type() {
373 switch (_contentType) {
374 case DefinedAtom::typeCode:
375 case DefinedAtom::typeData:
376 case DefinedAtom::typeConstant:
377 return llvm::ELF::SHT_PROGBITS;
378
379 case DefinedAtom::typeZeroFill:
380 return llvm::ELF::SHT_NOBITS;
381
382 // Case to handle section types
383 // Symtab, String Table ...
384 default:
385 return _contentType;
386 }
387 }
388
389 /// \brief Returns the section link field, the returned value is
390 /// recorded in the sh_link field of the Section Header
391 int link() const {
392 return _link;
393 }
394
395 void setLink(int32_t link) {
396 _link = link;
397 }
398
399 /// \brief Returns the section entsize field, the returned value is
400 /// recorded in the sh_entsize field of the Section Header
401 int entsize() const {
402 return _entSize;
403 }
404
405 /// \brief Returns the shinfo field, the returned value is
406 /// recorded in the sh_info field of the Section Header
407 int shinfo() const {
408 return _shInfo;
409 }
410
411 /// \brief Records the segmentType, that this section belongs to
412 void setSegment(const ELFLayout::SegmentType segmentType) {
413 _segmentType = segmentType;
414 }
415
416 /// \brief convert the segment type to a String for diagnostics
417 /// and printing purposes
418 StringRef segmentKindToStr() const {
419 switch(_segmentType) {
420 case llvm::ELF::PT_INTERP:
421 return "INTERP";
422 case llvm::ELF::PT_LOAD:
423 return "LOAD";
424 case llvm::ELF::PT_GNU_EH_FRAME:
425 return "EH_FRAME";
426 case llvm::ELF::PT_NOTE:
427 return "NOTE";
428 case llvm::ELF::PT_DYNAMIC:
429 return "DYNAMIC";
430 case llvm::ELF::PT_GNU_RELRO:
431 return "RELRO";
432 case llvm::ELF::PT_NULL:
433 return "NULL";
434 default:
435 return "UNKNOWN";
436 }
437 }
438
439 /// \brief for LLVM style RTTI information
440 static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
441 return c->kind() == Chunk<target_endianness, is64Bits>::K_ELFSection;
442 }
443
444 /// \brief Finalize the section contents before writing
445 void finalize() { }
446
447 /// \brief Write the section and the atom contents to the buffer
448 void write(ELFWriter *writer,
449 OwningPtr<FileOutputBuffer> &buffer) {
450 uint8_t *chunkBuffer = buffer->getBufferStart();
451 for (auto &ai : _atoms) {
452 const DefinedAtom *definedAtom = llvm::dyn_cast<DefinedAtom>(ai.first);
453 // Copy raw content of atom to file buffer.
454 ArrayRef<uint8_t> content = definedAtom->rawContent();
455 uint64_t contentSize = content.size();
456 if (contentSize == 0)
457 continue;
458 uint8_t *atomContent = chunkBuffer + ai.second.first;
459 std::copy_n(content.data(), contentSize, atomContent);
460 for (auto ref = definedAtom->begin(); ref != definedAtom->end(); ++ref) {
461 uint32_t offset = ref->offsetInAtom();
462 uint64_t targetAddress = 0;
463 if (ref->target() != nullptr)
464 targetAddress = writer->addressOfAtom(ref->target());
465 else
466 assert(0 && "Found the target to be NULL");
467 uint64_t fixupAddress = writer->addressOfAtom(ai.first) + offset;
468 // apply the relocation
469 writer->kindHandler()->applyFixup(ref->kind(),
470 ref->addend(),
471 &atomContent[offset],
472 fixupAddress,
473 targetAddress);
474 }
475 }
476 }
477
478 /// Atom Iterators
479 typedef typename std::vector<std::pair<const Atom *,
480 std::pair<uint64_t, uint64_t>>>::iterator atom_iter;
481
482 atom_iter atoms_begin() { return _atoms.begin(); }
483
484 atom_iter atoms_end() { return _atoms.end(); }
485
486protected:
487 int32_t _contentType;
488 int32_t _contentPermissions;
489 SectionKind _sectionKind;
490 // An Atom is appended to the vector with the following fields
491 // field1 : Atom
492 // field2 : fileoffset (initially set with a base offset of 0)
493 // field3 : virtual address
494 std::vector<std::pair<const Atom *, std::pair<uint64_t, uint64_t>>> _atoms;
495 ELFLayout::SegmentType _segmentType;
496 int64_t _entSize;
497 int64_t _shInfo;
498 int64_t _link;
499};
500
501/// \brief A MergedSections represents a set of sections grouped by the same name
502/// The output file that gets written by the linker has sections grouped
503/// by similiar names
504template<support::endianness target_endianness, bool is64Bits>
505class MergedSections {
506public:
507 MergedSections(StringRef name)
508 : _name(name)
509 ,_hasSegment(false)
510 ,_ordinal(0)
511 ,_flags(0)
512 ,_size(0)
513 ,_memSize(0)
514 ,_fileOffset(0)
515 ,_virtualAddr(0)
516 ,_shInfo(0)
517 ,_entSize(0)
518 ,_link(0)
519 ,_align2(0)
520 ,_kind(0)
521 ,_type(0) { }
522
523 // Set the MergedSections is associated with a segment
524 void setHasSegment() { _hasSegment = true; }
525
526 /// Sets the ordinal
527 void setOrdinal(uint64_t ordinal) {
528 _ordinal = ordinal;
529 }
530
531 /// Sets the Memory size
532 void setMemSize(uint64_t memsz) {
533 _memSize = memsz;
534 }
535
536 /// Sets the size fo the merged Section
537 void setSize(uint64_t fsiz) {
538 _size = fsiz;
539 }
540
541 // The offset of the first section contained in the merged section is contained here
542 void setFileOffset(uint64_t foffset) {
543 _fileOffset = foffset;
544 }
545
546 // Sets the starting address of the section
547 void setAddr(uint64_t addr) {
548 _virtualAddr = addr;
549 }
550
551 // Appends a section into the list of sections that are part of this Merged
552 // Section
553 void appendSection(Chunk<target_endianness, is64Bits> *c) {
554 if (c->align2() > _align2)
555 _align2 = c->align2();
556 if (c->kind() == Chunk<target_endianness, is64Bits>::K_ELFSection) {
557 Section<target_endianness, is64Bits> *section;
558 section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(c);
559 _link = section->link();
560 _shInfo = section->shinfo();
561 _entSize = section->entsize();
562 _type = section->type();
563 if (_flags < section->flags())
564 _flags = section->flags();
565 }
566 _kind = c->kind();
567 _sections.push_back(c);
568 }
569
570 // Iterators
571 typedef typename std::vector<Chunk<target_endianness, is64Bits> *>::iterator
572 ChunkIter;
573
574 ChunkIter begin_sections() { return _sections.begin(); }
575
576 ChunkIter end_sections() { return _sections.end(); }
577
578 // The below functions returns the properties of the MergeSection
579 bool hasSegment() const { return _hasSegment; }
580
581 StringRef name() const { return _name; }
582
583 int64_t shinfo() const { return _shInfo; }
584
585 uint64_t align2() const { return _align2; }
586
587 int64_t link() const { return _link; }
588
589 int64_t type() const { return _type; }
590
591 uint64_t virtualAddr() const { return _virtualAddr; }
592
593 int64_t ordinal() const { return _ordinal; }
594
595 int64_t kind() const { return _kind; }
596
597 uint64_t fileSize() const { return _size; }
598
599 int64_t entsize() const { return _entSize; }
600
601 uint64_t fileOffset() const { return _fileOffset; }
602
603 int64_t flags() const { return _flags; }
604
605 uint64_t memSize() { return _memSize; }
606
607private:
608 StringRef _name;
609 bool _hasSegment;
610 uint64_t _ordinal;
611 int64_t _flags;
612 uint64_t _size;
613 uint64_t _memSize;
614 uint64_t _fileOffset;
615 uint64_t _virtualAddr;
616 int64_t _shInfo;
617 int64_t _entSize;
618 int64_t _link;
619 uint64_t _align2;
620 int64_t _kind;
621 int64_t _type;
622 std::vector<Chunk<target_endianness, is64Bits> *> _sections;
623};
624
625/// \brief A segment can be divided into segment slices
626/// depending on how the segments can be split
627template<support::endianness target_endianness, bool is64Bits>
628class SegmentSlice {
629public:
630 typedef typename std::vector<Section<target_endianness, is64Bits> *>::iterator
631 sectionIter;
632
633 SegmentSlice() { }
634
635 /// Set the segment slice so that it begins at the offset specified
636 /// by fileoffset and set the start of the slice to be s and the end
637 /// of the slice to be e
638 void set(uint64_t fileoffset, int32_t s, int e) {
639 _startSection = s;
640 _endSection = e+1;
641 _offset = fileoffset;
642 }
643
644 // Set the segment slice start and end iterators. This is used to walk through
645 // the sections that are part of the Segment slice
646 void setSections(sectionIter start, sectionIter end) {
647 _startSectionIter = start;
648 _endSectionIter = end;
649 }
650
651 // Return the fileOffset of the slice
652 uint64_t fileOffset() const { return _offset; }
653
654 // Return the size of the slice
655 uint64_t fileSize() const { return _size; }
656
657 // Return the start of the slice
658 int32_t startSection() const { return _startSection; }
659
660 // Return the start address of the slice
661 uint64_t virtualAddr() const { return _addr; }
662
663 // Return the memory size of the slice
664 uint64_t memSize() const { return _memSize; }
665
666 // Return the alignment of the slice
667 uint64_t align2() const { return _align2; }
668
669 void setSize(uint64_t sz) { _size = sz; }
670
671 void setMemSize(uint64_t memsz) { _memSize = memsz; }
672
673 void setVAddr(uint64_t addr) { _addr = addr; }
674
675 void setAlign(uint64_t align) { _align2 = align; }
676
677 static bool compare_slices(SegmentSlice<target_endianness, is64Bits> *a,
678 SegmentSlice<target_endianness, is64Bits> *b) {
679 return (a->startSection() < b->startSection());
680 }
681
682 // Functions to run through the slice
683 sectionIter sections_begin() { return _startSectionIter; }
684
685 sectionIter sections_end() { return _endSectionIter; }
686
687private:
688 int32_t _startSection;
689 int32_t _endSection;
690 sectionIter _startSectionIter;
691 sectionIter _endSectionIter;
692 uint64_t _addr;
693 uint64_t _offset;
694 uint64_t _size;
695 uint64_t _align2;
696 uint64_t _memSize;
697};
698
699/// \brief A segment contains a set of sections, that have similiar properties
700// the sections are already seperated based on different flags and properties
701// the segment is just a way to concatenate sections to segments
702template<support::endianness target_endianness, bool is64Bits>
703class Segment : public Chunk<target_endianness, is64Bits> {
704public:
705 typedef typename std::vector
706 <SegmentSlice<target_endianness, is64Bits> *>::iterator slice_iter;
707 typedef typename
708 std::vector<Section<target_endianness, is64Bits> *>::iterator SectionIter;
709
710 Segment(const StringRef name,
711 const ELFLayout::SegmentType type,
712 const WriterOptionsELF &options)
713 : Chunk<target_endianness, is64Bits>(name
714 , Chunk<target_endianness, is64Bits>::K_ELFSegment)
715 , _segmentType(type)
716 , _flags(0)
717 , _atomflags(0)
718 , _options(options) {
719 this->_align2 = 0;
720 this->_fsize = 0;
721 }
722
723 /// append a section to a segment
724 void append(Section<target_endianness, is64Bits> *section) {
725 _sections.push_back(section);
726 if (_flags < section->flags())
727 _flags = section->flags();
728 if (_atomflags < section->atomflags())
729 _atomflags = section->atomflags();
730 if (this->_align2 < section->align2())
731 this->_align2 = section->align2();
732 }
733
734 /// Sort segments depending on the property
735 /// If we have a Program Header segment, it should appear first
736 /// If we have a INTERP segment, that should appear after the Program Header
737 /// All Loadable segments appear next in this order
738 /// All Read Write Execute segments follow
739 /// All Read Execute segments appear next
740 /// All Read only segments appear first
741 /// All Write execute segments follow
742 static bool compareSegments(Segment<target_endianness, is64Bits> *sega,
743 Segment<target_endianness, is64Bits> *segb)
744 {
745
746 if (sega->atomflags() < segb->atomflags())
747 return false;
748 return true;
749 }
750
751 /// \brief Start assigning file offset to the segment chunks The fileoffset
752 /// needs to be page at the start of the segment and in addition the
753 /// fileoffset needs to be aligned to the max section alignment within the
754 /// segment. This is required so that the ELF property p_poffset % p_align =
755 /// p_vaddr mod p_align holds true.
756 /// The algorithm starts off by assigning the startOffset thats passed in as
757 /// parameter to the first section in the segment, if the difference between
758 /// the newly computed offset is greater than a page, then we create a segment
759 /// slice, as it would be a waste of virtual memory just to be filled with
760 /// zeroes
761 void assignOffsets(uint64_t startOffset) {
762 int startSection = 0;
763 int currSection = 0;
764 SectionIter startSectionIter, endSectionIter;
765 // slice align is set to the max alignment of the chunks that are
766 // contained in the slice
767 uint64_t sliceAlign = 0;
768 // Current slice size
769 uint64_t curSliceSize = 0;
770 // Current Slice File Offset
771 uint64_t curSliceFileOffset = 0;
772
773 startSectionIter = _sections.begin();
774 endSectionIter = _sections.end();
775 startSection = 0;
776 bool isFirstSection = true;
777 for (auto si = _sections.begin(); si != _sections.end(); ++si) {
778 if (isFirstSection) {
779 // align the startOffset to the section alignment
780 uint64_t newOffset = llvm::RoundUpToAlignment(startOffset, (*si)->align2());
781 curSliceFileOffset = newOffset;
782 sliceAlign = (*si)->align2();
783 this->setFileOffset(startOffset);
784 (*si)->setFileOffset(newOffset);
785 curSliceSize = (*si)->fileSize();
786 isFirstSection = false;
787 } else {
788 uint64_t curOffset = curSliceFileOffset + curSliceSize;
789 uint64_t newOffset = llvm::RoundUpToAlignment(curOffset, (*si)->align2());
790 SegmentSlice<target_endianness, is64Bits> *slice = nullptr;
791 // If the newOffset computed is more than a page away, lets create
792 // a seperate segment, so that memory is not used up while running
793 if ((newOffset - curOffset) > _options.pageSize()) {
794 // TODO: use std::find here
795 for (auto sei = slices_begin(); sei != slices_end(); ++sei) {
796 if ((*sei)->startSection() == startSection) {
797 slice = *sei;
798 break;
799 }
800 }
801 if (!slice) {
802 slice = new (_segmentAllocate.Allocate
803 <SegmentSlice<target_endianness, is64Bits>>())
804 SegmentSlice<target_endianness, is64Bits>();
805 _segmentSlices.push_back(slice);
806 }
807 slice->set(curSliceFileOffset, startSection, currSection);
808 slice->setSections(startSectionIter, endSectionIter);
809 slice->setSize(curSliceSize);
810 slice->setAlign(sliceAlign);
811 uint64_t newPageOffset = llvm::RoundUpToAlignment(curOffset, _options.pageSize());
812 newOffset = llvm::RoundUpToAlignment(newPageOffset, (*si)->align2());
813 curSliceFileOffset = newOffset;
814 startSectionIter = endSectionIter;
815 startSection = currSection;
816 (*si)->setFileOffset(curSliceFileOffset);
817 curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
818 sliceAlign = (*si)->align2();
819 }
820 else {
821 if (sliceAlign < (*si)->align2())
822 sliceAlign = (*si)->align2();
823 (*si)->setFileOffset(newOffset);
824 curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
825 }
826 }
827 currSection++;
828 endSectionIter = si;
829 }
830 SegmentSlice<target_endianness, is64Bits> *slice = nullptr;
831 for (auto sei = slices_begin(); sei != slices_end(); ++sei) {
832 // TODO: add std::find
833 if ((*sei)->startSection() == startSection) {
834 slice = *sei;
835 break;
836 }
837 }
838 if (!slice) {
839 slice = new (_segmentAllocate.Allocate
840 <SegmentSlice<target_endianness, is64Bits>>())
841 SegmentSlice<target_endianness, is64Bits>();
842 _segmentSlices.push_back(slice);
843 }
844 slice->set(curSliceFileOffset, startSection, currSection);
845 slice->setSections(startSectionIter, _sections.end());
846 slice->setSize(curSliceSize);
847 slice->setAlign(sliceAlign);
848 this->_fsize = curSliceFileOffset - startOffset + curSliceSize;
849 std::stable_sort(slices_begin(), slices_end(),
850 SegmentSlice<target_endianness, is64Bits>::compare_slices);
851 }
852
853 /// \brief Assign virtual addresses to the slices
854 void assignVirtualAddress(uint64_t &addr, bool isFirstSegment) {
855 for (auto sei = slices_begin(), see = slices_end(); sei != see; ++sei) {
856 bool firstSlice = (sei == slices_begin());
857 // The first segment has distinct since it contains the
858 // ELF header and the Program Header, if we get to the first segment
859 // and the first slice, set it to the baseaddress
860 // which is the segment address
861 if (isFirstSegment && firstSlice)
862 (*sei)->setVAddr(this->virtualAddr());
863 else {
864 // Align to a page
865 addr = llvm::RoundUpToAlignment(addr, _options.pageSize());
866 // Align to the slice alignment
867 addr = llvm::RoundUpToAlignment(addr, (*sei)->align2());
868 }
869 bool virtualAddressSet = false;
870 for (auto si = (*sei)->sections_begin(), se = (*sei)->sections_end();
871 si != se; ++si) {
872 // Align the section address
873 addr = llvm::RoundUpToAlignment(addr, (*si)->align2());
874 if (!isFirstSegment && !virtualAddressSet) {
875 (*sei)->setVAddr(addr);
876 virtualAddressSet = true;
877 }
878 (*si)->setVAddr(addr);
879 (*si)->assignVirtualAddress(addr);
880 (*si)->setMemSize(addr - (*si)->virtualAddr());
881 }
882 (*sei)->setMemSize(addr - (*sei)->virtualAddr());
883 }
884 }
885
886 slice_iter slices_begin() {
887 return _segmentSlices.begin();
888 }
889
890 slice_iter slices_end() {
891 return _segmentSlices.end();
892 }
893
894 // Write the Segment
895 void write(ELFWriter *writer, OwningPtr<FileOutputBuffer> &buffer) {
896 for (auto sei = slices_begin(), see = slices_end(); sei != see; ++sei) {
897 for (auto si = (*sei)->sections_begin(), se = (*sei)->sections_end();
898 si != se; ++si) {
899 (*si)->write(writer, buffer);
900 }
901 }
902 }
903
904 // Finalize the segment, before we want to write to the output file
905 void finalize() { }
906
907 // For LLVM RTTI
908 static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
909 return c->kind() == Chunk<target_endianness, is64Bits>::K_ELFSegment;
910 }
911
912 // Getters
913 int32_t sectionCount() const {
914 return _sections.size();
915 }
916
917 ELFLayout::SegmentType segmentType() { return _segmentType; }
918
919 int pageSize() const { return _options.pageSize(); }
920
921 int64_t atomflags() const { return _atomflags; }
922
923 int64_t flags() const {
924 int64_t fl = 0;
925 if (_flags & llvm::ELF::SHF_ALLOC)
926 fl |= llvm::ELF::PF_R;
927 if (_flags & llvm::ELF::SHF_WRITE)
928 fl |= llvm::ELF::PF_W;
929 if (_flags & llvm::ELF::SHF_EXECINSTR)
930 fl |= llvm::ELF::PF_X;
931 return fl;
932 }
933
934 int64_t numSlices() const {
935 return _segmentSlices.size();
936 }
937
938private:
939 std::vector<Section<target_endianness, is64Bits> *> _sections;
940 std::vector<SegmentSlice<target_endianness, is64Bits> *> _segmentSlices;
941 ELFLayout::SegmentType _segmentType;
942 int64_t _flags;
943 int64_t _atomflags;
944 const WriterOptionsELF _options;
945 llvm::BumpPtrAllocator _segmentAllocate;
946};
947
948/// \brief The class represents the ELF String Table
949template<support::endianness target_endianness, bool is64Bits>
950class ELFStringTable : public Section<target_endianness, is64Bits> {
951
952public:
953 ELFStringTable(const char *str,
954 int32_t order):
955 Section<target_endianness, is64Bits>(str,
956 llvm::ELF::SHT_STRTAB,
957 DefinedAtom::perm___,
958 order,
959 Section<target_endianness, is64Bits>::K_StringTable) {
960 // the string table has a NULL entry for which
961 // add an empty string
962 _strings.push_back("");
963 this->_fsize = 1;
964 this->_align2 = 1;
965 this->setOrder(order);
966 }
967
968 static inline bool classof(ELFStringTable<target_endianness, is64Bits> *s) {
969 return true;
970 }
971
972 static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
973 return c->kind() == Section<target_endianness, is64Bits>::K_StringTable;
974 }
975
976 uint64_t addString(const StringRef symname) {
977 _strings.push_back(symname);
978 uint64_t offset = this->_fsize;
979 this->_fsize += symname.size() + 1;
980 return offset;
981 }
982
983 void write(ELFWriter *writer,
984 OwningPtr<FileOutputBuffer> &buffer) {
985 uint8_t *chunkBuffer = buffer->getBufferStart();
986 uint8_t *dest = chunkBuffer + this->fileOffset();
987 for (auto si : _strings) {
988 memcpy(dest, si.data(), si.size());
989 dest += si.size();
990 memcpy(dest, "", 1);
991 dest += 1;
992 }
993 }
994
995 void finalize() { }
996
997private:
998 std::vector<StringRef> _strings;
999};
1000
1001/// \brief The ELFSymbolTable class represents the symbol table in a ELF file
1002template<support::endianness target_endianness, bool is64Bits>
1003class ELFSymbolTable : public Section<target_endianness, is64Bits> {
1004
1005public:
1006 typedef object::Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
1007
1008 ELFSymbolTable(const char *str,
1009 int32_t order)
1010 : Section<target_endianness, is64Bits>(str
1011 , llvm::ELF::SHT_SYMTAB
1012 , 0
1013 , order
1014 , Section<target_endianness, is64Bits>::K_SymbolTable) {
1015 this->setOrder(order);
1016 Elf_Sym *symbol = new (_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
1017 memset ((void *)symbol,0, sizeof(Elf_Sym));
1018 _symbolTable.push_back(symbol);
1019 this->_entSize = sizeof(Elf_Sym);
1020 this->_fsize = sizeof(Elf_Sym);
1021 this->_align2 = sizeof(void *);
1022 }
1023
1024 static inline bool classof(ELFSymbolTable<target_endianness, is64Bits> *s) {
1025 return true;
1026 }
1027
1028 static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
1029 return c->kind() == Section<target_endianness, is64Bits>::K_SymbolTable;
1030 }
1031
1032 void addSymbol(const Atom *atom, int32_t sectionIndex, uint64_t addr = 0) {
1033 Elf_Sym *symbol = new(_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
1034 unsigned char binding = 0, type = 0;
1035 symbol->st_name = _stringSection->addString(atom->name());
1036 symbol->st_size = 0;
1037 symbol->st_shndx = sectionIndex;
1038 symbol->st_value = 0;
1039 symbol->st_other = ELF::STV_DEFAULT;
1040 if (const DefinedAtom *da = llvm::dyn_cast<const DefinedAtom>(atom)){
1041 symbol->st_size = da->size();
1042 lld::DefinedAtom::ContentType ct;
1043 switch (ct = da->contentType()){
1044 case DefinedAtom::typeCode:
1045 symbol->st_value = addr;
1046 type = ELF::STT_FUNC;
1047 break;
1048 case DefinedAtom::typeData:
1049 symbol->st_value = addr;
1050 type = ELF::STT_OBJECT;
1051 break;
1052 case DefinedAtom::typeZeroFill:
1053 type = ELF::STT_COMMON;
1054 symbol->st_value = addr;
1055 break;
1056 default:
1057 type = ELF::STT_NOTYPE;
1058 }
1059 if (da->scope() == DefinedAtom::scopeTranslationUnit)
1060 binding = ELF::STB_LOCAL;
1061 else
1062 binding = ELF::STB_GLOBAL;
1063 } else if (const AbsoluteAtom *aa = llvm::dyn_cast<const AbsoluteAtom>(atom)){
1064 type = ELF::STT_OBJECT;
1065 symbol->st_shndx = ELF::SHN_ABS;
1066 switch (aa->scope()) {
1067 case AbsoluteAtom::scopeLinkageUnit:
1068 symbol->st_other = ELF::STV_HIDDEN;
1069 binding = ELF::STB_LOCAL;
1070 break;
1071 case AbsoluteAtom::scopeTranslationUnit:
1072 binding = ELF::STB_LOCAL;
1073 break;
1074 case AbsoluteAtom::scopeGlobal:
1075 binding = ELF::STB_GLOBAL;
1076 break;
1077 }
1078 symbol->st_value = aa->value();
1079 }
1080 else {
1081 symbol->st_value = 0;
1082 type = ELF::STT_NOTYPE;
1083 binding = ELF::STB_WEAK;
1084 }
1085 symbol->setBindingAndType(binding, type);
1086 _symbolTable.push_back(symbol);
1087 this->_fsize += sizeof(Elf_Sym);
1088 }
1089
1090 void setStringSection(ELFStringTable<target_endianness, is64Bits> *s) {
1091 _stringSection = s;
1092 }
1093
1094 void finalize() {
1095 // sh_info should be one greater than last symbol with STB_LOCAL binding
1096 // we sort the symbol table to keep all local symbols at the beginning
1097 std::stable_sort(_symbolTable.begin(), _symbolTable.end(),
1098 [](const Elf_Sym *A, const Elf_Sym *B) {
1099 return A->getBinding() < B->getBinding();
1100 });
1101 uint16_t shInfo = 0;
1102 for (auto i : _symbolTable) {
1103 if (i->getBinding() != ELF::STB_LOCAL)
1104 break;
1105 shInfo++;
1106 }
1107 this->_shInfo = shInfo;
1108 this->setLink(_stringSection->ordinal());
1109 }
1110
1111 void write(ELFWriter *writer,
1112 OwningPtr<FileOutputBuffer> &buffer) {
1113
1114 uint8_t *chunkBuffer = buffer->getBufferStart();
1115 uint8_t *dest = chunkBuffer + this->fileOffset();
1116 for (auto sti : _symbolTable) {
1117 memcpy(dest, sti, sizeof(Elf_Sym));
1118 dest += sizeof(Elf_Sym);
1119 }
1120 }
1121
1122private:
1123 ELFStringTable<target_endianness, is64Bits> *_stringSection;
1124 std::vector<Elf_Sym*> _symbolTable;
1125 llvm::BumpPtrAllocator _symbolAllocate;
1126 int64_t _link;
1127};
1128
1129/// \brief An ELFHeader represents the Elf[32/64]_Ehdr structure at the
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001130/// start of an ELF executable file.
1131template<support::endianness target_endianness, bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001132class ELFHeader : public Chunk<target_endianness, is64Bits> {
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001133public:
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001134 typedef object::Elf_Ehdr_Impl<target_endianness, is64Bits> Elf_Ehdr;
1135
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001136 ELFHeader()
1137 : Chunk<target_endianness, is64Bits>("elfhdr"
1138 , Chunk<target_endianness, is64Bits>::K_ELFHeader) {
1139 memset(_eh.e_ident, 0, llvm::ELF::EI_NIDENT);
1140 e_ident(ELF::EI_MAG0, 0x7f);
1141 e_ident(ELF::EI_MAG1, 'E');
1142 e_ident(ELF::EI_MAG2, 'L');
1143 e_ident(ELF::EI_MAG3, 'F');
1144 e_ehsize(sizeof(Elf_Ehdr));
1145 e_flags(2);
1146 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001147 void e_ident(int I, unsigned char C) { _eh.e_ident[I] = C; }
1148 void e_type(uint16_t type) { _eh.e_type = type; }
1149 void e_machine(uint16_t machine) { _eh.e_machine = machine; }
1150 void e_version(uint32_t version) { _eh.e_version = version; }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001151 void e_entry(int64_t entry) { _eh.e_entry = entry; }
1152 void e_phoff(int64_t phoff) { _eh.e_phoff = phoff; }
1153 void e_shoff(int64_t shoff) { _eh.e_shoff = shoff; }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001154 void e_flags(uint32_t flags) { _eh.e_flags = flags; }
1155 void e_ehsize(uint16_t ehsize) { _eh.e_ehsize = ehsize; }
1156 void e_phentsize(uint16_t phentsize) { _eh.e_phentsize = phentsize; }
1157 void e_phnum(uint16_t phnum) { _eh.e_phnum = phnum; }
1158 void e_shentsize(uint16_t shentsize) { _eh.e_shentsize = shentsize; }
1159 void e_shnum(uint16_t shnum) { _eh.e_shnum = shnum; }
1160 void e_shstrndx(uint16_t shstrndx) { _eh.e_shstrndx = shstrndx; }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001161 uint64_t fileSize() { return sizeof (Elf_Ehdr); }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001162
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001163 static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001164 return c->Kind() == Chunk<target_endianness, is64Bits>::K_ELFHeader;
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001165 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001166
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001167 void write(ELFWriter *writer,
1168 OwningPtr<FileOutputBuffer> &buffer) {
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001169
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001170 uint8_t *chunkBuffer = buffer->getBufferStart();
1171 uint8_t *atomContent = chunkBuffer + this->fileOffset();
1172 memcpy(atomContent, &_eh, fileSize());
1173 }
1174
1175 void finalize() { }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001176
1177private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001178 Elf_Ehdr _eh;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001179};
1180
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001181/// \brief An ELFProgramHeader represents the Elf[32/64]_Phdr structure at the
1182/// start of an ELF executable file.
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001183template<support::endianness target_endianness, bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001184class ELFProgramHeader : public Chunk<target_endianness, is64Bits> {
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001185public:
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001186 typedef object::Elf_Phdr<target_endianness, is64Bits> Elf_Phdr;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001187
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001188 ELFProgramHeader()
1189 : Chunk<target_endianness, is64Bits>("elfphdr"
1190 , Chunk<target_endianness, is64Bits>::K_ELFProgramHeader) { }
1191
1192 bool addSegment(Segment<target_endianness, is64Bits> *segment) {
1193 Elf_Phdr *phdr = nullptr;
1194 bool ret = false;
1195
1196 for (auto sei = segment->slices_begin(), see = segment->slices_end();
1197 sei != see; ++sei) {
1198 if (_phi == _ph.end()) {
1199 phdr = new(_allocator.Allocate<Elf_Phdr>()) Elf_Phdr;
1200 _ph.push_back(phdr);
1201 _phi = _ph.end();
1202 ret = true;
1203 } else {
1204 phdr = (*_phi);
1205 ++_phi;
1206 }
1207 phdr->p_type = segment->segmentType();
1208 phdr->p_offset = (*sei)->fileOffset();
1209 phdr->p_vaddr = (*sei)->virtualAddr();
1210 phdr->p_paddr = (*sei)->virtualAddr();
1211 phdr->p_filesz = (*sei)->fileSize();
1212 phdr->p_memsz = (*sei)->memSize();
1213 phdr->p_flags = segment->flags();
1214 phdr->p_align = (phdr->p_type == llvm::ELF::PT_LOAD) ?
1215 segment->pageSize() : (*sei)->align2();
1216 }
1217 return ret;
1218 }
1219
1220 void resetProgramHeaders() {
1221 _phi = _ph.begin();
1222 }
1223
1224 void setVAddr(uint64_t addr) {
1225 this->_start = llvm::RoundUpToAlignment(addr, 8);
1226 this->_fsize = this->_start - addr;
1227 }
1228
1229 uint64_t fileSize() { return this->_fsize + (sizeof (Elf_Phdr) * _ph.size()); }
1230
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001231 static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001232 return c->Kind() == Chunk<target_endianness, is64Bits>::K_ELFProgramHeader;
1233 }
1234
1235 void write(ELFWriter *writer,
1236 OwningPtr<FileOutputBuffer> &buffer) {
1237
1238 uint8_t *chunkBuffer = buffer->getBufferStart();
1239 uint8_t *dest = chunkBuffer + this->fileOffset();
1240 for (auto phi : _ph) {
1241 memcpy(dest, phi, sizeof(Elf_Phdr));
1242 dest += sizeof(Elf_Phdr);
1243 }
1244 }
1245
1246 void finalize() { }
1247
1248 int64_t entsize() {
1249 return sizeof(Elf_Phdr);
1250 }
1251
1252 int64_t numHeaders() {
1253 return _ph.size();
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001254 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001255
1256private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001257 std::vector<Elf_Phdr *> _ph;
1258 typedef typename std::vector<Elf_Phdr *>::iterator ph_iter;
1259 ph_iter _phi;
1260 llvm::BumpPtrAllocator _allocator;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001261};
1262
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001263/// \brief An ELFSectionHeader represents the Elf[32/64]_Shdr structure
1264/// at the end of the file
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001265template<support::endianness target_endianness, bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001266class ELFSectionHeader : public Chunk<target_endianness, is64Bits> {
1267public:
1268 typedef object::Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001269
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001270 ELFSectionHeader(int32_t order):Chunk<target_endianness, is64Bits>("shdr",
1271 Chunk<target_endianness, is64Bits>::K_ELFSectionHeader)
1272 {
1273 this->_fsize = 0;
1274 this->_align2 = 8;
1275 this->setOrder(order);
1276 // The first element in the list is always NULL
1277 Elf_Shdr *nullshdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
1278 ::memset(nullshdr, 0, sizeof (Elf_Shdr));
1279 _sectionInfo.push_back(nullshdr);
1280 this->_fsize += sizeof (Elf_Shdr);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001281 }
1282
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001283 uint16_t fileSize() {
1284 return sizeof(Elf_Shdr) * _sectionInfo.size();
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001285 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001286
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001287 void appendSection(MergedSections<target_endianness, is64Bits> *section) {
1288 Elf_Shdr *shdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
1289 shdr->sh_name = _stringSection->addString(section->name());
1290 shdr->sh_type = section->type();
1291 shdr->sh_flags = section->flags();
1292 shdr->sh_offset = section->fileOffset();
1293 shdr->sh_addr = section->virtualAddr();
1294 shdr->sh_size = section->memSize();
1295 shdr->sh_link = section->link();
1296 shdr->sh_info = section->shinfo();
1297 shdr->sh_addralign = section->align2();
1298 shdr->sh_entsize = section->entsize();
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001299 _sectionInfo.push_back(shdr);
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001300 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001301
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001302 void updateSection(Section<target_endianness, is64Bits> *section) {
1303 Elf_Shdr *shdr = _sectionInfo[section->ordinal()];
1304 shdr->sh_type = section->type();
1305 shdr->sh_flags = section->flags();
1306 shdr->sh_offset = section->fileOffset();
1307 shdr->sh_addr = section->virtualAddr();
1308 shdr->sh_size = section->fileSize();
1309 shdr->sh_link = section->link();
1310 shdr->sh_info = section->shinfo();
1311 shdr->sh_addralign = section->align2();
1312 shdr->sh_entsize = section->entsize();
1313 }
1314
1315 static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
1316 return c->getChunkKind() == Chunk<target_endianness, is64Bits>::K_ELFSectionHeader;
1317 }
1318
1319 void setStringSection(ELFStringTable<target_endianness, is64Bits> *s) {
1320 _stringSection = s;
1321 }
1322
1323 void write(ELFWriter *writer,
1324 OwningPtr<FileOutputBuffer> &buffer) {
1325
1326 uint8_t *chunkBuffer = buffer->getBufferStart();
1327 uint8_t *dest = chunkBuffer + this->fileOffset();
1328 for (auto shi : _sectionInfo) {
1329 memcpy(dest, shi, sizeof(Elf_Shdr));
1330 dest += sizeof(Elf_Shdr);
1331 }
1332 _stringSection->write(writer, buffer);
1333 }
1334
1335 void finalize() { }
1336
1337 int64_t entsize() {
1338 return sizeof(Elf_Shdr);
1339 }
1340
1341 int64_t numHeaders() {
1342 return _sectionInfo.size();
1343 }
1344
1345private:
1346 ELFStringTable<target_endianness, is64Bits> *_stringSection;
1347 std::vector<Elf_Shdr*> _sectionInfo;
1348 llvm::BumpPtrAllocator _sectionAllocate;
1349};
1350
1351
1352/// \brief The DefaultELFLayout class is used by the Writer to arrange
1353/// sections and segments in the order determined by the target ELF
1354/// format. The writer creates a single instance of the DefaultELFLayout
1355/// class
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001356template<support::endianness target_endianness, bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001357class DefaultELFLayout : public ELFLayout {
1358public:
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001359
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001360 // The order in which the sections appear in the output file
1361 // If its determined, that the layout needs to change
1362 // just changing the order of enumerations would essentially
1363 // change the layout in the output file
1364 enum DefaultSectionOrder {
1365 ORDER_NOT_DEFINED = 0,
1366 ORDER_INTERP,
1367 ORDER_NOTE,
1368 ORDER_HASH,
1369 ORDER_DYNAMIC_SYMBOLS,
1370 ORDER_DYNAMIC_STRINGS,
1371 ORDER_INIT,
1372 ORDER_TEXT,
1373 ORDER_PLT,
1374 ORDER_FINI,
1375 ORDER_RODATA,
1376 ORDER_EH_FRAME,
1377 ORDER_EH_FRAMEHDR,
1378 ORDER_CTORS,
1379 ORDER_DTORS,
1380 ORDER_DYNAMIC,
1381 ORDER_GOT,
1382 ORDER_GOT_PLT,
1383 ORDER_DATA,
1384 ORDER_BSS,
1385 ORDER_OTHER,
1386 ORDER_SECTION_STRINGS,
1387 ORDER_SYMBOL_TABLE,
1388 ORDER_STRING_TABLE,
1389 ORDER_SECTION_HEADERS
1390 };
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001391
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001392public:
1393
1394 // The Key used for creating Sections
1395 // The sections are created using
1396 // SectionName, [contentType, contentPermissions]
1397 typedef std::pair<StringRef,
1398 std::pair<int32_t, int32_t>> Key;
1399 typedef typename std::vector<Chunk<target_endianness, is64Bits> *>::iterator
1400 ChunkIter;
1401 // The key used for Segments
1402 // The segments are created using
1403 // SegmentName, Segment flags
1404 typedef std::pair<StringRef, int64_t> SegmentKey;
1405 // Merged Sections contain the map of Sectionnames to a vector of sections,
1406 // that have been merged to form a single section
1407 typedef std::map<StringRef, MergedSections<target_endianness, is64Bits> *>
1408 MergedSectionMapT;
1409 typedef typename std::vector
1410 <MergedSections<target_endianness, is64Bits> *>::iterator MergedSectionIter;
1411
1412 // HashKey for the Section
1413 class HashKey {
1414 public:
1415 int64_t operator() (const Key &k) const {
1416 // k.first = section Name
1417 // k.second = [contentType, Permissions]
1418 return llvm::hash_combine(k.first, k.second.first, k.second.second);
1419 }
1420 };
1421
1422 // HashKey for the Segment
1423 class SegmentHashKey {
1424 public:
1425 int64_t operator() (const SegmentKey &k) const {
1426 // k.first = SegmentName
1427 // k.second = SegmentFlags
1428 return llvm::hash_combine(k.first, k.second);
1429 }
1430 };
1431
1432 typedef std::unordered_map<Key,
1433 Section<target_endianness, is64Bits>*, HashKey> SectionMapT;
1434 typedef std::unordered_map<SegmentKey,
1435 Segment<target_endianness, is64Bits>*,
1436 SegmentHashKey> SegmentMapT;
1437
1438 DefaultELFLayout(const WriterOptionsELF &options):_options(options) { }
1439
1440 /// \brief Return the section order for a input section
1441 virtual SectionOrder getSectionOrder
1442 (const StringRef name,
1443 int32_t contentType,
1444 int32_t contentPermissions) {
1445 switch (contentType) {
1446 case DefinedAtom::typeCode:
1447 return llvm::StringSwitch<Reference::Kind>(name)
1448 .StartsWith(".eh_frame_hdr", ORDER_EH_FRAMEHDR)
1449 .StartsWith(".eh_frame", ORDER_EH_FRAME)
1450 .StartsWith(".init", ORDER_INIT)
1451 .StartsWith(".fini", ORDER_FINI)
1452 .StartsWith(".hash", ORDER_HASH)
1453 .Default(ORDER_TEXT);
1454
1455 case DefinedAtom::typeConstant:
1456 return ORDER_RODATA;
1457
1458 case DefinedAtom::typeData:
1459 return ORDER_DATA;
1460
1461 case DefinedAtom::typeZeroFill:
1462 return ORDER_BSS;
1463
1464 default:
1465 // If we get passed in a section push it to OTHER
1466 if (contentPermissions == DefinedAtom::perm___)
1467 return ORDER_OTHER;
1468
1469 return ORDER_NOT_DEFINED;
1470 }
1471 }
1472
1473 /// \brief This maps the input sections to the output section names
1474 StringRef getSectionName(const StringRef name,
1475 const int32_t contentType) {
1476 if (contentType == DefinedAtom::typeZeroFill)
1477 return ".bss";
1478 if (name.startswith(".text"))
1479 return ".text";
1480 if (name.startswith(".rodata"))
1481 return ".rodata";
1482 return name;
1483 }
1484
1485 /// \brief Gets the segment for a output section
1486 virtual ELFLayout::SegmentType getSegmentType(Section<target_endianness,
1487 is64Bits> *section) const {
1488 switch(section->order()) {
1489 case ORDER_INTERP:
1490 return llvm::ELF::PT_INTERP;
1491
1492 case ORDER_TEXT:
1493 case ORDER_HASH:
1494 case ORDER_DYNAMIC_SYMBOLS:
1495 case ORDER_DYNAMIC_STRINGS:
1496 case ORDER_INIT:
1497 case ORDER_PLT:
1498 case ORDER_FINI:
1499 case ORDER_RODATA:
1500 case ORDER_EH_FRAME:
1501 case ORDER_EH_FRAMEHDR:
1502 return llvm::ELF::PT_LOAD;
1503
1504 case ORDER_NOTE:
1505 return llvm::ELF::PT_NOTE;
1506
1507 case ORDER_DYNAMIC:
1508 return llvm::ELF::PT_DYNAMIC;
1509
1510 case ORDER_CTORS:
1511 case ORDER_DTORS:
1512 case ORDER_GOT:
1513 return llvm::ELF::PT_GNU_RELRO;
1514
1515 case ORDER_GOT_PLT:
1516 case ORDER_DATA:
1517 case ORDER_BSS:
1518 return llvm::ELF::PT_LOAD;
1519
1520 default:
1521 return llvm::ELF::PT_NULL;
1522 }
1523 }
1524
1525 /// \brief Returns true/false depending on whether the section has a Output
1526 // segment or not
1527 static bool hasOutputSegment(Section<target_endianness,
1528 is64Bits> *section) {
1529 switch(section->order()) {
1530 case ORDER_INTERP:
1531 case ORDER_HASH:
1532 case ORDER_DYNAMIC_SYMBOLS:
1533 case ORDER_DYNAMIC_STRINGS:
1534 case ORDER_INIT:
1535 case ORDER_PLT:
1536 case ORDER_TEXT:
1537 case ORDER_FINI:
1538 case ORDER_RODATA:
1539 case ORDER_EH_FRAME:
1540 case ORDER_EH_FRAMEHDR:
1541 case ORDER_NOTE:
1542 case ORDER_DYNAMIC:
1543 case ORDER_CTORS:
1544 case ORDER_DTORS:
1545 case ORDER_GOT:
1546 case ORDER_GOT_PLT:
1547 case ORDER_DATA:
1548 case ORDER_BSS:
1549 return true;
1550
1551 default:
1552 return false;
1553 }
1554 }
1555
1556 // Adds an atom to the section
1557 virtual error_code addAtom(const Atom *atom) {
1558 const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom);
1559 const StringRef sectionName =
1560 getSectionName(definedAtom->customSectionName(),
1561 definedAtom->contentType());
1562 const lld::DefinedAtom::ContentPermissions permissions =
1563 definedAtom->permissions();
1564 const lld::DefinedAtom::ContentType contentType =
1565 definedAtom->contentType();
1566 const Key key(sectionName, std::make_pair(contentType, permissions));
1567 const std::pair<Key, Section<target_endianness, is64Bits> *>
1568 currentSection(key, nullptr);
1569 std::pair<typename SectionMapT::iterator, bool>
1570 sectionInsert(_sectionMap.insert(currentSection));
1571 Section<target_endianness, is64Bits> *section;
1572 // the section is already in the map
1573 if (!sectionInsert.second) {
1574 section = sectionInsert.first->second;
1575 section->setContentPermissions(permissions);
1576 }
1577 else {
1578 SectionOrder section_order = getSectionOrder(sectionName,
1579 contentType,
1580 permissions);
1581 section = new (_allocator.Allocate
1582 <Section<target_endianness, is64Bits>>())
1583 Section<target_endianness, is64Bits>
1584 (sectionName, contentType,
1585 permissions, section_order);
1586 sectionInsert.first->second = section;
1587 section->setOrder(section_order);
1588 _sections.push_back(section);
1589 }
1590 section->appendAtom(atom);
1591 return error_code::success();
1592 }
1593
1594 // Merge sections with the same name into a MergedSections
1595 void mergeSimiliarSections() {
1596 MergedSections<target_endianness, is64Bits> *mergedSection;
1597
1598 for (auto &si : _sections) {
1599 const std::pair<StringRef, MergedSections<target_endianness, is64Bits> *>
1600 currentMergedSections(si->name(),
1601 nullptr);
1602 std::pair<typename MergedSectionMapT::iterator, bool>
1603 mergedSectionInsert
1604 (_mergedSectionMap.insert(currentMergedSections));
1605 if (!mergedSectionInsert.second) {
1606 mergedSection = mergedSectionInsert.first->second;
1607 }
1608 else {
1609 mergedSection = new (_allocator.Allocate
1610 <MergedSections<target_endianness, is64Bits>>())
1611 MergedSections<target_endianness, is64Bits>(si->name());
1612 _mergedSections.push_back(mergedSection);
1613 mergedSectionInsert.first->second = mergedSection;
1614 }
1615 mergedSection->appendSection(si);
1616 }
1617 }
1618
1619 void assignSectionsToSegments() {
1620 // sort the sections by their order as defined by the layout
1621 std::stable_sort(_sections.begin(), _sections.end(),
1622 [](Chunk<target_endianness, is64Bits> *A,
1623 Chunk<target_endianness, is64Bits> *B) {
1624 return A->order() < B->order();
1625 });
1626 // Merge all sections
1627 mergeSimiliarSections();
1628 // Set the ordinal after sorting the sections
1629 int ordinal = 1;
1630 for (auto &msi : _mergedSections) {
1631 (*msi).setOrdinal(ordinal);
1632 for (auto ai = (*msi).begin_sections(), ae = (*msi).end_sections();
1633 ai != ae; ++ai) {
1634 (*ai)->setOrdinal(ordinal);
1635 }
1636 ++ordinal;
1637 }
1638 Section<target_endianness, is64Bits> *section;
1639 Segment<target_endianness, is64Bits> *segment;
1640 for (auto msi = merged_sections_begin(), mse = merged_sections_end();
1641 msi != mse; ++msi) {
1642 for (auto ai = (*msi)->begin_sections(), ae = (*msi)->end_sections();
1643 ai != ae; ++ai) {
1644 if ((*ai)->kind() == Chunk<target_endianness, is64Bits>::K_ELFSection) {
1645 section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(*ai);
1646 if (!hasOutputSegment(section))
1647 continue;
1648 (*msi)->setHasSegment();
1649 section->setSegment(getSegmentType(section));
1650 const StringRef segmentName = section->segmentKindToStr();
1651 // Use the flags of the merged Section for the segment
1652 const SegmentKey key(segmentName, (*msi)->flags());
1653 const std::pair<SegmentKey, Segment<target_endianness, is64Bits> *>
1654 currentSegment(key, nullptr);
1655 std::pair<typename SegmentMapT::iterator, bool>
1656 segmentInsert(_segmentMap.insert(currentSegment));
1657
1658 if (!segmentInsert.second) {
1659 segment = segmentInsert.first->second;
1660 } else {
1661 segment = new (_allocator.Allocate
1662 <Segment<target_endianness, is64Bits>>())
1663 Segment<target_endianness, is64Bits>
1664 (segmentName, getSegmentType(section),
1665 _options);
1666 segmentInsert.first->second = segment;
1667 _segments.push_back(segment);
1668 }
1669 segment->append(section);
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001670 }
1671 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001672 }
1673 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001674
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001675 void addSection(Chunk<target_endianness, is64Bits> *c) {
1676 _sections.push_back(c);
1677 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001678
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001679 void assignFileOffsets() {
1680 std::sort(_segments.begin(),
1681 _segments.end(),
1682 Segment<target_endianness, is64Bits>::compareSegments);
1683 int ordinal = 0;
1684 // Compute the number of segments that might be needed, so that the
1685 // size of the program header can be computed
1686 uint64_t offset = 0;
1687 for (auto si : _segments) {
1688 si->setOrdinal(++ordinal);
1689 si->assignOffsets(offset);
1690 offset += si->fileSize();
1691 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001692 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001693
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001694 void setELFHeader(ELFHeader<target_endianness, is64Bits> *e) {
1695 _elfHeader = e;
1696 }
Hemant Kulkarni87dbac02012-11-13 21:34:45 +00001697
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001698 void setProgramHeader(ELFProgramHeader<target_endianness, is64Bits> *p) {
1699 _programHeader = p;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001700 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001701
1702 void assignVirtualAddress() {
1703 int32_t numSlices = 0;
1704 uint64_t virtualAddress = _options.baseAddress();
1705
1706 // Add the ELF Header
1707 if (_elfHeader) {
1708 _elfHeader->setFileOffset(0);
1709 _elfHeader->setVAddr(virtualAddress);
1710 }
1711 // Add the program header
1712 if (_programHeader) {
1713 _programHeader->setVAddr(uint64_t(virtualAddress + _elfHeader->fileSize()));
1714 _programHeader->setFileOffset(_elfHeader->fileSize());
1715 }
1716 bool newSegmentHeaderAdded = true;
1717 while (true) {
1718 for (auto si : _segments) {
1719 newSegmentHeaderAdded = _programHeader->addSegment(si);
1720 numSlices += si->numSlices();
1721 }
1722 if (!newSegmentHeaderAdded)
1723 break;
1724 uint64_t fileoffset = _elfHeader->fileSize() + _programHeader->fileSize();
1725 uint64_t address = virtualAddress;
1726 // Fix the offsets after adding the program header
1727 for (auto &si : _segments) {
1728 // Align the segment to a page boundary
1729 fileoffset = llvm::RoundUpToAlignment(fileoffset, _options.pageSize());
1730 si->assignOffsets(fileoffset);
1731 fileoffset = si->fileOffset() + si->fileSize();
1732 }
1733 // start assigning virtual addresses
1734 for (auto si = _segments.begin(); si != _segments.end(); ++si) {
1735 (*si)->setVAddr(virtualAddress);
1736 // The first segment has the virtualAddress set to the base address as
1737 // we have added the file header and the program header dont align the
1738 // first segment to the pagesize
1739 (*si)->assignVirtualAddress(address, (si == _segments.begin()));
1740 (*si)->setMemSize(address - virtualAddress);
1741 virtualAddress = llvm::RoundUpToAlignment(address, _options.pageSize());
1742 }
1743 _programHeader->resetProgramHeaders();
1744 }
1745 Section<target_endianness, is64Bits> *section;
1746 // Fix the offsets of all the atoms within a section
1747 for (auto &si : _sections) {
1748 section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(si);
1749 if (section &&
1750 DefaultELFLayout<target_endianness, is64Bits>::hasOutputSegment(section))
1751 section->assignOffsets(section->fileOffset());
1752 }
1753 // Set the size of the merged Sections
1754 for (auto msi = merged_sections_begin(), mse = merged_sections_end();
1755 msi != mse; ++msi) {
1756 uint64_t sectionfileoffset = 0;
1757 uint64_t startFileOffset = 0;
1758 uint64_t sectionsize = 0;
1759 bool isFirstSection = true;
1760 for (auto si = (*msi)->begin_sections(); si != (*msi)->end_sections(); ++si) {
1761 if (isFirstSection) {
1762 startFileOffset = (*si)->fileOffset();
1763 isFirstSection = false;
1764 }
1765 sectionfileoffset = (*si)->fileOffset();
1766 sectionsize = (*si)->fileSize();
1767 }
1768 sectionsize = (sectionfileoffset - startFileOffset) + sectionsize;
1769 (*msi)->setFileOffset(startFileOffset);
1770 (*msi)->setSize(sectionsize);
1771 }
1772 // Set the virtual addr of the merged Sections
1773 for (auto msi = merged_sections_begin(), mse = merged_sections_end();
1774 msi != mse; ++msi) {
1775 uint64_t sectionstartaddr = 0;
1776 uint64_t startaddr = 0;
1777 uint64_t sectionsize = 0;
1778 bool isFirstSection = true;
1779 for (auto si = (*msi)->begin_sections(), se = (*msi)->end_sections();
1780 si != se; ++si) {
1781 if (isFirstSection) {
1782 startaddr = (*si)->virtualAddr();
1783 isFirstSection = false;
1784 }
1785 sectionstartaddr = (*si)->virtualAddr();
1786 sectionsize = (*si)->memSize();
1787 }
1788 sectionsize = (sectionstartaddr - startaddr) + sectionsize;
1789 (*msi)->setMemSize(sectionsize);
1790 (*msi)->setAddr(startaddr);
1791 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001792 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001793
1794 void assignOffsetsForMiscSections() {
1795 uint64_t fileoffset = 0;
1796 uint64_t size = 0;
1797 for (auto si : _segments) {
1798 fileoffset = si->fileOffset();
1799 size = si->fileSize();
1800 }
1801 fileoffset = fileoffset + size;
1802 Section<target_endianness, is64Bits> *section;
1803 for (auto si : _sections) {
1804 section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(si);
1805 if (section &&
1806 DefaultELFLayout<target_endianness, is64Bits>::hasOutputSegment
1807 (section))
1808 continue;
1809 fileoffset = llvm::RoundUpToAlignment(fileoffset, si->align2());
1810 si->setFileOffset(fileoffset);
1811 si->setVAddr(0);
1812 fileoffset += si->fileSize();
1813 }
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001814 }
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001815
1816 void finalize() {
1817 for (auto &si : _sections) {
1818 si->finalize();
1819 }
1820 }
1821
1822 bool findAtomAddrByName(const StringRef name, uint64_t &addr) {
1823 Section<target_endianness, is64Bits> *section;
1824 for (auto ai = _sections.begin(); ai != _sections.end(); ++ai) {
1825 if ((*ai)->kind() == Chunk<target_endianness, is64Bits>::K_ELFSection) {
1826 section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(*ai);
1827 if (section->findAtomAddrByName(name, addr))
1828 return true;
1829 }
1830 }
1831 return false;
1832 }
1833
1834 MergedSectionIter merged_sections_begin() {
1835 return _mergedSections.begin();
1836 }
1837
1838 MergedSectionIter merged_sections_end() {
1839 return _mergedSections.end();
1840 }
1841
1842 ChunkIter sections_begin() {
1843 return _sections.begin();
1844 }
1845 ChunkIter sections_end() {
1846 return _sections.end();
1847 }
1848
1849 ChunkIter segments_begin() {
1850 return _segments.begin();
1851 }
1852
1853 ChunkIter segments_end() {
1854 return _segments.end();
1855 }
1856
1857 ELFHeader<target_endianness, is64Bits> *elfHeader() {
1858 return _elfHeader;
1859 }
1860
1861 ELFProgramHeader<target_endianness, is64Bits> *elfProgramHeader() {
1862 return _programHeader;
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001863 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001864
1865private:
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001866 SectionMapT _sectionMap;
1867 MergedSectionMapT _mergedSectionMap;
1868 SegmentMapT _segmentMap;
Sid Manningdd110202012-09-25 18:22:09 +00001869
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001870 std::vector<Chunk<target_endianness, is64Bits> *> _sections;
1871 std::vector<Segment<target_endianness, is64Bits> *> _segments;
1872 std::vector<MergedSections<target_endianness, is64Bits> *> _mergedSections;
1873 ELFHeader<target_endianness, is64Bits> *_elfHeader;
1874 ELFProgramHeader<target_endianness, is64Bits> *_programHeader;
1875 llvm::BumpPtrAllocator _allocator;
1876 const WriterOptionsELF &_options;
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001877};
1878
1879//===----------------------------------------------------------------------===//
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001880// ELFExecutableWriter Class
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001881//===----------------------------------------------------------------------===//
1882template<support::endianness target_endianness, bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001883class ELFExecutableWriter : public ELFWriter {
1884public:
1885 typedef object::Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
1886 typedef object::Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
1887
1888 ELFExecutableWriter(const WriterOptionsELF &options);
1889
1890private:
1891 // build the sections that need to be created
1892 void buildChunks(const lld::File &file);
1893 virtual error_code writeFile(const lld::File &File, StringRef path);
1894 void buildAtomToAddressMap();
1895 void buildSymbolTable ();
1896 void buildSectionHeaderTable();
1897 void assignSectionsWithNoSegments();
1898 void addAbsoluteUndefinedSymbols(const lld::File &File);
1899
1900 uint64_t addressOfAtom(const Atom *atom) {
1901 return _atomToAddressMap[atom];
1902 }
1903
1904 KindHandler *kindHandler() { return _referenceKindHandler.get(); }
1905
1906 void createDefaultSections();
1907
1908 const WriterOptionsELF &_options;
1909
1910 typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
1911 std::unique_ptr<KindHandler> _referenceKindHandler;
1912 AtomToAddress _atomToAddressMap;
1913 llvm::BumpPtrAllocator _chunkAllocate;
1914 DefaultELFLayout<target_endianness, is64Bits> *_layout;
1915 ELFHeader<target_endianness, is64Bits> *_elfHeader;
1916 ELFProgramHeader<target_endianness, is64Bits> *_programHeader;
1917 ELFSymbolTable<target_endianness, is64Bits> * _symtab;
1918 ELFStringTable<target_endianness, is64Bits> *_strtab;
1919 ELFStringTable<target_endianness, is64Bits> *_shstrtab;
1920 ELFSectionHeader<target_endianness, is64Bits> *_shdrtab;
1921};
1922
1923//===----------------------------------------------------------------------===//
1924// ELFExecutableWriter
1925//===----------------------------------------------------------------------===//
1926template<support::endianness target_endianness, bool is64Bits>
1927ELFExecutableWriter<target_endianness, is64Bits>
1928 ::ELFExecutableWriter(const WriterOptionsELF &options)
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001929 : _options(options)
Sid Manning42064e52012-10-09 02:20:47 +00001930 , _referenceKindHandler(KindHandler::makeHandler(_options.machine(),
1931 target_endianness))
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001932{
1933 _layout = new DefaultELFLayout<target_endianness, is64Bits>(options);
1934}
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001935
1936template<support::endianness target_endianness, bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001937void ELFExecutableWriter<target_endianness, is64Bits>
1938 ::buildChunks(const lld::File &file){
1939 for (const DefinedAtom *definedAtom : file.defined() ) {
1940 _layout->addAtom(definedAtom);
1941 }
1942}
1943
1944template<support::endianness target_endianness, bool is64Bits>
1945void ELFExecutableWriter<target_endianness, is64Bits>::buildSymbolTable () {
1946 Section<target_endianness, is64Bits> *section;
1947 for (auto si = _layout->sections_begin(); si != _layout->sections_end(); ++si) {
1948 if ((*si)->kind() != Chunk<target_endianness, is64Bits>::K_ELFSection)
1949 continue;
1950 section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(*si);
1951 for (auto ai = section->atoms_begin(); ai != section->atoms_end(); ++ai) {
1952 _symtab->addSymbol(ai->first, section->ordinal(), ai->second.second);
Hemant Kulkarni736f7fb2012-11-21 21:07:36 +00001953 }
1954 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001955}
1956
1957template<support::endianness target_endianness, bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001958void ELFExecutableWriter<target_endianness, is64Bits>::
1959 addAbsoluteUndefinedSymbols(const lld::File &file) {
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001960 for (const UndefinedAtom *a : file.undefined()) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001961 _symtab->addSymbol(a, ELF::SHN_UNDEF);
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001962 }
1963
1964 for (const AbsoluteAtom *a : file.absolute()) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001965 _symtab->addSymbol(a, ELF::SHN_ABS);
Hemant Kulkarni08e410292012-10-01 23:53:20 +00001966 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001967}
1968
Sid Manningdd110202012-09-25 18:22:09 +00001969template<support::endianness target_endianness, bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001970void ELFExecutableWriter<target_endianness, is64Bits>
Sid Manningdd110202012-09-25 18:22:09 +00001971 ::buildAtomToAddressMap () {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001972 Section<target_endianness, is64Bits> *section;
1973 for (auto si = _layout->sections_begin();
1974 si != _layout->sections_end(); ++si) {
1975 if ((*si)->kind() != Chunk<target_endianness, is64Bits>::K_ELFSection)
1976 continue;
1977 section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(*si);
1978 for (auto ai = section->atoms_begin(); ai != section->atoms_end(); ++ai) {
1979 _atomToAddressMap[ai->first] = (ai)->second.second;
Sid Manningdd110202012-09-25 18:22:09 +00001980 }
1981 }
Sid Manningdd110202012-09-25 18:22:09 +00001982}
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001983
1984template<support::endianness target_endianness, bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001985void ELFExecutableWriter<target_endianness, is64Bits>
1986 ::buildSectionHeaderTable() {
1987 for (auto msi = _layout->merged_sections_begin();
1988 msi != _layout->merged_sections_end(); ++msi) {
1989 if ((*msi)->kind() != Chunk<target_endianness, is64Bits>::K_ELFSection)
1990 continue;
1991 if ((*msi)->hasSegment())
1992 _shdrtab->appendSection(*msi);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001993 }
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00001994}
1995
1996template<support::endianness target_endianness, bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00001997void ELFExecutableWriter<target_endianness, is64Bits>
1998 ::assignSectionsWithNoSegments() {
1999 Section<target_endianness, is64Bits> *section;
2000 for (auto msi = _layout->merged_sections_begin();
2001 msi != _layout->merged_sections_end(); ++msi) {
2002 if ((*msi)->kind() != Chunk<target_endianness, is64Bits>::K_ELFSection)
2003 continue;
2004 if (!(*msi)->hasSegment())
2005 _shdrtab->appendSection(*msi);
2006 }
2007 _layout->assignOffsetsForMiscSections();
2008 for (auto si = _layout->sections_begin();
2009 si != _layout->sections_end(); ++si) {
2010 if ((*si)->kind() != Chunk<target_endianness, is64Bits>::K_ELFSection)
2011 continue;
2012 section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(*si);
2013 if (!DefaultELFLayout<target_endianness, is64Bits>::hasOutputSegment
2014 (section))
2015 _shdrtab->updateSection(section);
2016 }
2017}
2018
2019template<support::endianness target_endianness, bool is64Bits>
2020error_code ELFExecutableWriter<target_endianness, is64Bits>
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002021 ::writeFile(const lld::File &file, StringRef path) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002022 buildChunks(file);
2023 // Create the default sections like the symbol table, string table, and the
2024 // section string table
2025 createDefaultSections();
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002026
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002027 // Set the Layout
2028 _layout->assignSectionsToSegments();
2029 _layout->assignFileOffsets();
2030 _layout->assignVirtualAddress();
2031
2032 // Build the Atom To Address map for applying relocations
2033 buildAtomToAddressMap();
2034
2035 // Create symbol table and section string table
2036 buildSymbolTable();
2037
2038 // add other symbols
2039 addAbsoluteUndefinedSymbols(file);
2040
2041 // Finalize the layout by calling the finalize() functions
2042 _layout->finalize();
2043
2044 // build Section Header table
2045 buildSectionHeaderTable();
2046
2047 // assign Offsets and virtual addresses
2048 // for sections with no segments
2049 assignSectionsWithNoSegments();
2050
2051 uint64_t totalSize = _shdrtab->fileOffset() + _shdrtab->fileSize();
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002052
2053 OwningPtr<FileOutputBuffer> buffer;
2054 error_code ec = FileOutputBuffer::create(path,
2055 totalSize, buffer,
2056 FileOutputBuffer::F_executable);
2057 if (ec)
2058 return ec;
2059
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002060 for (auto si = _layout->sections_begin(); si != _layout->sections_end(); ++si)
2061 (*si)->write(this, buffer);
2062
2063 _elfHeader->e_ident(ELF::EI_CLASS, (_options.is64Bit() ? ELF::ELFCLASS64
2064 : ELF::ELFCLASS32));
2065 _elfHeader->e_ident(ELF::EI_DATA, (_options.endianness() == llvm::support::big)
2066 ? ELF::ELFDATA2MSB : ELF::ELFDATA2LSB);
2067 _elfHeader->e_ident(ELF::EI_VERSION, 1);
2068 _elfHeader->e_ident(ELF::EI_OSABI, 0);
2069 _elfHeader->e_type(_options.type());
2070 _elfHeader->e_machine(_options.machine());
2071 _elfHeader->e_version(1);
2072 _elfHeader->e_entry(0ULL);
2073 _elfHeader->e_phoff(_programHeader->fileOffset());
2074 _elfHeader->e_shoff(_shdrtab->fileOffset());
2075 _elfHeader->e_phentsize(_programHeader->entsize());
2076 _elfHeader->e_phnum(_programHeader->numHeaders());
2077 _elfHeader->e_shentsize(_shdrtab->entsize());
2078 _elfHeader->e_shnum(_shdrtab->numHeaders());
2079 _elfHeader->e_shstrndx(_shstrtab->ordinal());
2080 uint64_t virtualAddr = 0;
2081 _layout->findAtomAddrByName("_start", virtualAddr);
2082 _elfHeader->e_entry(virtualAddr);
2083 _elfHeader->write(this, buffer);
2084 _programHeader->write(this, buffer);
2085
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002086 return buffer->commit();
2087}
Nick Kledzikabb69812012-05-31 22:34:00 +00002088
Sid Manningdd110202012-09-25 18:22:09 +00002089template<support::endianness target_endianness, bool is64Bits>
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002090void ELFExecutableWriter<target_endianness, is64Bits>
2091 ::createDefaultSections() {
2092 _elfHeader = new ELFHeader<target_endianness, is64Bits>();
2093 _programHeader = new ELFProgramHeader<target_endianness, is64Bits>();
2094 _layout->setELFHeader(_elfHeader);
2095 _layout->setProgramHeader(_programHeader);
2096
2097 _symtab = new ELFSymbolTable<target_endianness, is64Bits>
2098 (".symtab",
2099 DefaultELFLayout<target_endianness, is64Bits>::ORDER_SYMBOL_TABLE);
2100 _strtab = new ELFStringTable<target_endianness, is64Bits>
2101 (".strtab",
2102 DefaultELFLayout<target_endianness, is64Bits>::ORDER_STRING_TABLE);
2103 _shstrtab = new ELFStringTable<target_endianness, is64Bits>
2104 (".shstrtab",
2105 DefaultELFLayout<target_endianness, is64Bits>::ORDER_SECTION_STRINGS);
2106 _shdrtab = new ELFSectionHeader<target_endianness, is64Bits>
2107 (DefaultELFLayout<target_endianness, is64Bits>::ORDER_SECTION_HEADERS);
2108 _layout->addSection(_symtab);
2109 _layout->addSection(_strtab);
2110 _layout->addSection(_shstrtab);
2111 _shdrtab->setStringSection(_shstrtab);
2112 _symtab->setStringSection(_strtab);
2113 _layout->addSection(_shdrtab);
Sid Manningdd110202012-09-25 18:22:09 +00002114}
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002115
Nick Kledzikabb69812012-05-31 22:34:00 +00002116} // namespace elf
2117
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002118Writer *createWriterELF(const WriterOptionsELF &options) {
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002119
2120 // Set the default layout to be the static executable layout
2121 // We would set the layout to a dynamic executable layout
2122 // if we came across any shared libraries in the process
2123
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002124 if (!options.is64Bit() && options.endianness() == llvm::support::little)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002125 return new lld::elf::ELFExecutableWriter<support::little, false>(options);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002126 else if (options.is64Bit() && options.endianness() == llvm::support::little)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002127 return new lld::elf::ELFExecutableWriter<support::little, true>(options);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002128 else if (!options.is64Bit() && options.endianness() == llvm::support::big)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002129 return new lld::elf::ELFExecutableWriter<support::big, false>(options);
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002130 else if (options.is64Bit() && options.endianness() == llvm::support::big)
Shankar Easwaran495d38b2012-12-27 02:26:30 +00002131 return new lld::elf::ELFExecutableWriter<support::big, true>(options);
Nick Kledzikabb69812012-05-31 22:34:00 +00002132
Hemant Kulkarni927bbc22012-09-14 16:11:34 +00002133 llvm_unreachable("Invalid Options!");
Nick Kledzikabb69812012-05-31 22:34:00 +00002134}
Nick Kledzikabb69812012-05-31 22:34:00 +00002135} // namespace lld