blob: ec07df776c0c5549eebc12bd57747541ccd78c2b [file] [log] [blame]
Shankar Easwaran6d9921f2013-01-21 20:09:55 +00001//===- lib/ReaderWriter/ELF/ELFSectionChunks.h -----------------------------===//
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#ifndef LLD_READER_WRITER_ELF_SECTION_CHUNKS_H_
11#define LLD_READER_WRITER_ELF_SECTION_CHUNKS_H_
12
13#include "lld/Core/DefinedAtom.h"
14#include "lld/Core/range.h"
15
16#include "llvm/ADT/ArrayRef.h"
17#include "llvm/ADT/OwningPtr.h"
18#include "llvm/ADT/StringRef.h"
19
20#include "llvm/Object/ELF.h"
21
22#include "llvm/Support/Allocator.h"
23#include "llvm/Support/Debug.h"
24#include "llvm/Support/ELF.h"
25#include "llvm/Support/ErrorHandling.h"
26#include "llvm/Support/FileOutputBuffer.h"
27
28#include "ELFChunk.h"
29#include "ELFLayout.h"
30#include "ELFWriter.h"
31
32namespace lld {
33namespace elf {
34
35/// \brief A section contains a set of atoms that have similiar properties
36/// The atoms that have similiar properties are merged to form a section
37template<class ELFT>
38class Section : public Chunk<ELFT> {
39public:
40 // The Kind of section that the object represents
41 enum SectionKind {
42 K_Default,
43 K_Target, // The section is handed over to the target
44 K_SymbolTable,
45 K_StringTable,
46 };
47 // Create a section object, the section is set to the default type if the
48 // caller doesnot set it
49 Section(const llvm::StringRef sectionName,
50 const int32_t contentType,
51 const int32_t contentPermissions,
52 const int32_t order,
53 const SectionKind kind = K_Default);
54
55 /// return the section kind
56 inline SectionKind sectionKind() const {
57 return _sectionKind;
58 }
59
60 /// Align the offset to the required modulus defined by the atom alignment
61 uint64_t alignOffset(uint64_t offset, DefinedAtom::Alignment &atomAlign);
62
63 // \brief Append an atom to a Section. The atom gets pushed into a vector
64 // contains the atom, the atom file offset, the atom virtual address
65 // the atom file offset is aligned appropriately as set by the Reader
66 void appendAtom(const Atom *atom);
67
68 /// \brief Set the virtual address of each Atom in the Section. This
69 /// routine gets called after the linker fixes up the virtual address
70 /// of the section
71 inline void assignVirtualAddress(uint64_t &addr) {
72 for (auto &ai : _atoms) {
73 ai._virtualAddr = addr + ai._fileOffset;
74 }
75 addr += this->memSize();
76 }
77
78 /// \brief Set the file offset of each Atom in the section. This routine
79 /// gets called after the linker fixes up the section offset
80 inline void assignOffsets(uint64_t offset) {
81 for (auto &ai : _atoms) {
82 ai._fileOffset = offset + ai._fileOffset;
83 }
84 }
85
86 /// \brief Find the Atom address given a name, this is needed to to properly
87 /// apply relocation. The section class calls this to find the atom address
88 /// to fix the relocation
89 inline bool findAtomAddrByName(const llvm::StringRef name, uint64_t &addr) {
90 for (auto ai : _atoms) {
91 if (ai._atom->name() == name) {
92 addr = ai._virtualAddr;
93 return true;
94 }
95 }
96 return false;
97 }
98
99 /// \brief Does the Atom occupy any disk space
100 inline bool occupiesNoDiskSpace() const {
101 return _contentType == DefinedAtom::typeZeroFill;
102 }
103
104 /// \brief The permission of the section is the most permissive permission
105 /// of all atoms that the section contains
106 inline void setContentPermissions(int32_t perm) {
107 _contentPermissions = std::max(perm, _contentPermissions);
108 }
109
110 /// \brief Get the section flags, defined by the permissions of the section
111 int64_t flags();
112
113 /// \brief Return the section type, the returned value is recorded in the
114 /// sh_type field of the Section Header
115 int type();
116
117 /// \brief convert the segment type to a String for diagnostics
118 /// and printing purposes
119 llvm::StringRef segmentKindToStr() const;
120
121 /// \brief Return the raw flags, we need this to sort segments
122 inline int64_t atomflags() const {
123 return _contentPermissions;
124 }
125
126 /// \brief Returns the section link field, the returned value is
127 /// recorded in the sh_link field of the Section Header
128 inline int link() const {
129 return _link;
130 }
131
132 inline void setLink(int32_t link) {
133 _link = link;
134 }
135
136 /// \brief Returns the section entsize field, the returned value is
137 /// recorded in the sh_entsize field of the Section Header
138 inline int entsize() const {
139 return _entSize;
140 }
141
142 /// \brief Returns the shinfo field, the returned value is
143 /// recorded in the sh_info field of the Section Header
144 inline int shinfo() const {
145 return _shInfo;
146 }
147
148 /// \brief Records the segmentType, that this section belongs to
149 inline void setSegment(const ELFLayout::SegmentType segmentType) {
150 _segmentType = segmentType;
151 }
152
153 /// \brief for LLVM style RTTI information
154 static inline bool classof(const Chunk<ELFT> *c) {
155 return c->kind() == Chunk<ELFT>::K_ELFSection;
156 }
157
158 /// \brief Finalize the section contents before writing
159 inline void finalize() { }
160
161 /// \brief Write the section and the atom contents to the buffer
162 void write(ELFWriter *writer,
163 llvm::OwningPtr<llvm::FileOutputBuffer> &buffer);
164
165 /// Atom Iterators
166 typedef typename std::vector<AtomLayout>::iterator atom_iter;
167
168 range<atom_iter> atoms() { return _atoms; }
169
170protected:
171 int32_t _contentType;
172 int32_t _contentPermissions;
173 SectionKind _sectionKind;
174 std::vector<AtomLayout> _atoms;
175 ELFLayout::SegmentType _segmentType;
176 int64_t _entSize;
177 int64_t _shInfo;
178 int64_t _link;
179};
180
181// Create a section object, the section is set to the default type if the
182// caller doesnot set it
183template<class ELFT>
184Section<ELFT>::Section(const StringRef sectionName,
185 const int32_t contentType,
186 const int32_t contentPermissions,
187 const int32_t order,
188 const SectionKind kind)
189 : Chunk<ELFT>(sectionName, Chunk<ELFT>::K_ELFSection)
190 , _contentType(contentType)
191 , _contentPermissions(contentPermissions)
192 , _sectionKind(kind)
193 , _entSize(0)
194 , _shInfo(0)
195 , _link(0) {
196 this->setOrder(order);
197}
198
199/// Align the offset to the required modulus defined by the atom alignment
200template<class ELFT>
201uint64_t
202Section<ELFT>::alignOffset(uint64_t offset, DefinedAtom::Alignment &atomAlign) {
203 uint64_t requiredModulus = atomAlign.modulus;
204 uint64_t align2 = 1u << atomAlign.powerOf2;
205 uint64_t currentModulus = (offset % align2);
206 uint64_t retOffset = offset;
207 if (currentModulus != requiredModulus) {
208 if (requiredModulus > currentModulus)
209 retOffset += requiredModulus - currentModulus;
210 else
211 retOffset += align2 + requiredModulus - currentModulus;
212 }
213 return retOffset;
214}
215
216// \brief Append an atom to a Section. The atom gets pushed into a vector
217// contains the atom, the atom file offset, the atom virtual address
218// the atom file offset is aligned appropriately as set by the Reader
219template<class ELFT>
220void
221Section<ELFT>::appendAtom(const Atom *atom) {
222 Atom::Definition atomType = atom->definition();
223 const DefinedAtom *definedAtom = cast<DefinedAtom>(atom);
224
225 DefinedAtom::Alignment atomAlign = definedAtom->alignment();
226 uint64_t align2 = 1u << atomAlign.powerOf2;
227 // Align the atom to the required modulus/ align the file offset and the
228 // memory offset seperately this is required so that BSS symbols are handled
229 // properly as the BSS symbols only occupy memory size and not file size
230 uint64_t fOffset = alignOffset(this->fileSize(), atomAlign);
231 uint64_t mOffset = alignOffset(this->memSize(), atomAlign);
232 switch (atomType) {
233 case Atom::definitionRegular:
234 switch(definedAtom->contentType()) {
235 case DefinedAtom::typeCode:
236 case DefinedAtom::typeData:
237 case DefinedAtom::typeConstant:
238 _atoms.push_back(AtomLayout(atom, fOffset, 0));
239 this->_fsize = fOffset + definedAtom->size();
240 this->_msize = mOffset + definedAtom->size();
241 break;
242 case DefinedAtom::typeZeroFill:
243 _atoms.push_back(AtomLayout(atom, mOffset, 0));
244 this->_msize = mOffset + definedAtom->size();
245 break;
246 default:
247 this->_fsize = fOffset + definedAtom->size();
248 this->_msize = mOffset + definedAtom->size();
249 break;
250 }
251 break;
252 default:
253 llvm_unreachable("Expecting only definedAtoms being passed here");
254 break;
255 }
256 // Set the section alignment to the largest alignment
257 // std::max doesnot support uint64_t
258 if (this->_align2 < align2)
259 this->_align2 = align2;
260}
261
262/// \brief Get the section flags, defined by the permissions of the section
263template<class ELFT>
264int64_t
265Section<ELFT>::flags() {
266 switch (_contentPermissions) {
267 case DefinedAtom::perm___:
268 return 0;
269
270 case DefinedAtom::permR__:
271 return llvm::ELF::SHF_ALLOC;
272
273 case DefinedAtom::permR_X:
274 return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR;
275
276 case DefinedAtom::permRW_:
277 case DefinedAtom::permRW_L:
278 return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE;
279
280 case DefinedAtom::permRWX:
281 return llvm::ELF::SHF_ALLOC |
282 llvm::ELF::SHF_WRITE |
283 llvm::ELF::SHF_EXECINSTR;
284
285 default:
286 break;
287 }
288 return llvm::ELF::SHF_ALLOC;
289}
290
291/// \brief Return the section type, the returned value is recorded in the
292/// sh_type field of the Section Header
293
294template<class ELFT>
295int
296Section<ELFT>::type() {
297 switch (_contentType) {
298 case DefinedAtom::typeCode:
299 case DefinedAtom::typeData:
300 case DefinedAtom::typeConstant:
301 return llvm::ELF::SHT_PROGBITS;
302
303 case DefinedAtom::typeZeroFill:
304 return llvm::ELF::SHT_NOBITS;
305
306 // Case to handle section types
307 // Symtab, String Table ...
308 default:
309 return _contentType;
310 }
311}
312
313/// \brief convert the segment type to a String for diagnostics
314/// and printing purposes
315template<class ELFT>
316StringRef
317Section<ELFT>::segmentKindToStr() const {
318 switch(_segmentType) {
319 case llvm::ELF::PT_INTERP:
320 return "INTERP";
321 case llvm::ELF::PT_LOAD:
322 return "LOAD";
323 case llvm::ELF::PT_GNU_EH_FRAME:
324 return "EH_FRAME";
325 case llvm::ELF::PT_NOTE:
326 return "NOTE";
327 case llvm::ELF::PT_DYNAMIC:
328 return "DYNAMIC";
329 case llvm::ELF::PT_GNU_RELRO:
330 return "RELRO";
331 case llvm::ELF::PT_NULL:
332 return "NULL";
333 default:
334 return "UNKNOWN";
335 }
336}
337
338/// \brief Write the section and the atom contents to the buffer
339template<class ELFT>
340void
341Section<ELFT>::write(ELFWriter *writer,
342 llvm::OwningPtr<llvm::FileOutputBuffer> &buffer) {
343 uint8_t *chunkBuffer = buffer->getBufferStart();
344 for (auto &ai : _atoms) {
345 const DefinedAtom *definedAtom = cast<DefinedAtom>(ai._atom);
346 if (definedAtom->contentType() == DefinedAtom::typeZeroFill)
347 continue;
348 // Copy raw content of atom to file buffer.
349 llvm::ArrayRef<uint8_t> content = definedAtom->rawContent();
350 uint64_t contentSize = content.size();
351 if (contentSize == 0)
352 continue;
353 uint8_t *atomContent = chunkBuffer + ai._fileOffset;
354 std::copy_n(content.data(), contentSize, atomContent);
355 for (const auto ref : *definedAtom) {
356 uint32_t offset = ref->offsetInAtom();
357 uint64_t targetAddress = 0;
358 assert(ref->target() != nullptr && "Found the target to be NULL");
359 targetAddress = writer->addressOfAtom(ref->target());
360 uint64_t fixupAddress = writer->addressOfAtom(ai._atom) + offset;
361 // apply the relocation
362 writer->kindHandler()->applyFixup(ref->kind(),
363 ref->addend(),
364 &atomContent[offset],
365 fixupAddress,
366 targetAddress);
367 }
368 }
369}
370
371/// \brief A MergedSections represents a set of sections grouped by the same
372/// name. The output file that gets written by the linker has sections grouped
373/// by similiar names
374template<class ELFT>
375class MergedSections {
376public:
377 // Iterators
378 typedef typename std::vector<Chunk<ELFT> *>::iterator ChunkIter;
379
380 MergedSections(llvm::StringRef name);
381
382 // Appends a section into the list of sections that are part of this Merged
383 // Section
384 void appendSection(Chunk<ELFT> *c);
385
386 // Set the MergedSections is associated with a segment
387 inline void setHasSegment() { _hasSegment = true; }
388
389 /// Sets the ordinal
390 inline void setOrdinal(uint64_t ordinal) {
391 _ordinal = ordinal;
392 }
393
394 /// Sets the Memory size
395 inline void setMemSize(uint64_t memsz) {
396 _memSize = memsz;
397 }
398
399 /// Sets the size fo the merged Section
400 inline void setSize(uint64_t fsiz) {
401 _size = fsiz;
402 }
403
404 // The offset of the first section contained in the merged section is
405 // contained here
406 inline void setFileOffset(uint64_t foffset) {
407 _fileOffset = foffset;
408 }
409
410 // Sets the starting address of the section
411 inline void setAddr(uint64_t addr) {
412 _virtualAddr = addr;
413 }
414
415 inline range<ChunkIter> sections() { return _sections; }
416
417 // The below functions returns the properties of the MergeSection
418 inline bool hasSegment() const { return _hasSegment; }
419
420 inline llvm::StringRef name() const { return _name; }
421
422 inline int64_t shinfo() const { return _shInfo; }
423
424 inline uint64_t align2() const { return _align2; }
425
426 inline int64_t link() const { return _link; }
427
428 inline int64_t type() const { return _type; }
429
430 inline uint64_t virtualAddr() const { return _virtualAddr; }
431
432 inline int64_t ordinal() const { return _ordinal; }
433
434 inline int64_t kind() const { return _kind; }
435
436 inline uint64_t fileSize() const { return _size; }
437
438 inline int64_t entsize() const { return _entSize; }
439
440 inline uint64_t fileOffset() const { return _fileOffset; }
441
442 inline int64_t flags() const { return _flags; }
443
444 inline uint64_t memSize() { return _memSize; }
445
446private:
447 llvm::StringRef _name;
448 bool _hasSegment;
449 uint64_t _ordinal;
450 int64_t _flags;
451 uint64_t _size;
452 uint64_t _memSize;
453 uint64_t _fileOffset;
454 uint64_t _virtualAddr;
455 int64_t _shInfo;
456 int64_t _entSize;
457 int64_t _link;
458 uint64_t _align2;
459 int64_t _kind;
460 int64_t _type;
461 std::vector<Chunk<ELFT> *> _sections;
462};
463
464/// MergedSections
465template<class ELFT>
466MergedSections<ELFT>::MergedSections(StringRef name)
467 : _name(name)
468 ,_hasSegment(false)
469 ,_ordinal(0)
470 ,_flags(0)
471 ,_size(0)
472 ,_memSize(0)
473 ,_fileOffset(0)
474 ,_virtualAddr(0)
475 ,_shInfo(0)
476 ,_entSize(0)
477 ,_link(0)
478 ,_align2(0)
479 ,_kind(0)
480 ,_type(0) { }
481
482
483template<class ELFT>
484void
485MergedSections<ELFT>::appendSection(Chunk<ELFT> *c) {
486 if (c->align2() > _align2)
487 _align2 = c->align2();
488 if (const auto section = dyn_cast<Section<ELFT>>(c)) {
489 _link = section->link();
490 _shInfo = section->shinfo();
491 _entSize = section->entsize();
492 _type = section->type();
493 if (_flags < section->flags())
494 _flags = section->flags();
495 }
496 _kind = c->kind();
497 _sections.push_back(c);
498}
499
500/// \brief The class represents the ELF String Table
501template<class ELFT>
502class ELFStringTable : public Section<ELFT> {
503public:
504 ELFStringTable(const char *str, int32_t order);
505
506 static inline bool classof(const Chunk<ELFT> *c) {
507 return c->kind() == Section<ELFT>::K_StringTable;
508 }
509
510 uint64_t addString(const llvm::StringRef symname);
511
512 void write(ELFWriter *writer,
513 llvm::OwningPtr<llvm::FileOutputBuffer> &buffer);
514
515 inline void finalize() { }
516
517private:
518 std::vector<llvm::StringRef> _strings;
519};
520
521template<class ELFT>
522ELFStringTable<ELFT>::ELFStringTable(const char *str,
523 int32_t order)
524 : Section<ELFT>(
525 str,
526 llvm::ELF::SHT_STRTAB,
527 DefinedAtom::perm___,
528 order,
529 Section<ELFT>::K_StringTable) {
530 // the string table has a NULL entry for which
531 // add an empty string
532 _strings.push_back("");
533 this->_fsize = 1;
534 this->_align2 = 1;
535 this->setOrder(order);
536}
537
538template<class ELFT>
539uint64_t
540ELFStringTable<ELFT>::addString(const StringRef symname) {
541 _strings.push_back(symname);
542 uint64_t offset = this->_fsize;
543 this->_fsize += symname.size() + 1;
544 return offset;
545}
546
547template<class ELFT>
548void
549ELFStringTable<ELFT>::write(ELFWriter *writer,
550 llvm::OwningPtr<llvm::FileOutputBuffer> &buffer) {
551 uint8_t *chunkBuffer = buffer->getBufferStart();
552 uint8_t *dest = chunkBuffer + this->fileOffset();
553 for (auto si : _strings) {
554 memcpy(dest, si.data(), si.size());
555 dest += si.size();
556 memcpy(dest, "", 1);
557 dest += 1;
558 }
559}
560
561/// \brief The ELFSymbolTable class represents the symbol table in a ELF file
562template<class ELFT>
563class ELFSymbolTable : public Section<ELFT> {
564public:
565 typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
566
567 ELFSymbolTable(const char *str, int32_t order);
568
569 void addSymbol(const Atom *atom, int32_t sectionIndex, uint64_t addr = 0);
570
571 void finalize();
572
573 void write(ELFWriter *writer,
574 llvm::OwningPtr<llvm::FileOutputBuffer> &buffer);
575
576 static inline bool classof(const Chunk<ELFT> *c) {
577 return c->kind() == Section<ELFT>::K_SymbolTable;
578 }
579
580 inline void setStringSection(ELFStringTable<ELFT> *s) {
581 _stringSection = s;
582 }
583
584private:
585 ELFStringTable<ELFT> *_stringSection;
586 std::vector<Elf_Sym*> _symbolTable;
587 llvm::BumpPtrAllocator _symbolAllocate;
588 int64_t _link;
589};
590
591/// ELF Symbol Table
592template<class ELFT>
593ELFSymbolTable<ELFT>::ELFSymbolTable(const char *str,
594 int32_t order)
595 : Section<ELFT>(
596 str,
597 llvm::ELF::SHT_SYMTAB,
598 0,
599 order,
600 Section<ELFT>::K_SymbolTable) {
601 this->setOrder(order);
602 Elf_Sym *symbol = new (_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
603 memset((void *)symbol, 0, sizeof(Elf_Sym));
604 _symbolTable.push_back(symbol);
605 this->_entSize = sizeof(Elf_Sym);
606 this->_fsize = sizeof(Elf_Sym);
607 this->_align2 = sizeof(void *);
608}
609
610template<class ELFT>
611void
612ELFSymbolTable<ELFT>::addSymbol(const Atom *atom,
613 int32_t sectionIndex,
614 uint64_t addr) {
615 Elf_Sym *symbol = new(_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
616 unsigned char binding = 0, type = 0;
617 symbol->st_name = _stringSection->addString(atom->name());
618 symbol->st_size = 0;
619 symbol->st_shndx = sectionIndex;
620 symbol->st_value = 0;
621 symbol->st_other = llvm::ELF::STV_DEFAULT;
622 if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom)){
623 symbol->st_size = da->size();
624 lld::DefinedAtom::ContentType ct;
625 switch (ct = da->contentType()){
626 case DefinedAtom::typeCode:
627 symbol->st_value = addr;
628 type = llvm::ELF::STT_FUNC;
629 break;
630 case DefinedAtom::typeData:
631 case DefinedAtom::typeConstant:
632 symbol->st_value = addr;
633 type = llvm::ELF::STT_OBJECT;
634 break;
635 case DefinedAtom::typeZeroFill:
636 type = llvm::ELF::STT_OBJECT;
637 symbol->st_value = addr;
638 break;
639 default:
640 type = llvm::ELF::STT_NOTYPE;
641 }
642 if (da->scope() == DefinedAtom::scopeTranslationUnit)
643 binding = llvm::ELF::STB_LOCAL;
644 else
645 binding = llvm::ELF::STB_GLOBAL;
646 } else if (const AbsoluteAtom *aa = dyn_cast<const AbsoluteAtom>(atom)){
647 type = llvm::ELF::STT_OBJECT;
648 symbol->st_shndx = llvm::ELF::SHN_ABS;
649 switch (aa->scope()) {
650 case AbsoluteAtom::scopeLinkageUnit:
651 symbol->st_other = llvm::ELF::STV_HIDDEN;
652 binding = llvm::ELF::STB_LOCAL;
653 break;
654 case AbsoluteAtom::scopeTranslationUnit:
655 binding = llvm::ELF::STB_LOCAL;
656 break;
657 case AbsoluteAtom::scopeGlobal:
658 binding = llvm::ELF::STB_GLOBAL;
659 break;
660 }
661 symbol->st_value = addr;
662 } else {
663 symbol->st_value = 0;
664 type = llvm::ELF::STT_NOTYPE;
665 binding = llvm::ELF::STB_WEAK;
666 }
667 symbol->setBindingAndType(binding, type);
668 _symbolTable.push_back(symbol);
669 this->_fsize += sizeof(Elf_Sym);
670}
671
672template<class ELFT>
673void
674ELFSymbolTable<ELFT>::finalize() {
675 // sh_info should be one greater than last symbol with STB_LOCAL binding
676 // we sort the symbol table to keep all local symbols at the beginning
677 std::stable_sort(_symbolTable.begin(), _symbolTable.end(),
678 [](const Elf_Sym *A, const Elf_Sym *B) {
679 return A->getBinding() < B->getBinding();
680 });
681 uint16_t shInfo = 0;
682 for (auto i : _symbolTable) {
683 if (i->getBinding() != llvm::ELF::STB_LOCAL)
684 break;
685 shInfo++;
686 }
687 this->_shInfo = shInfo;
688 this->setLink(_stringSection->ordinal());
689}
690
691template<class ELFT>
692void
693ELFSymbolTable<ELFT>::write(ELFWriter *writer,
694 llvm::OwningPtr<llvm::FileOutputBuffer> &buffer) {
695 uint8_t *chunkBuffer = buffer->getBufferStart();
696 uint8_t *dest = chunkBuffer + this->fileOffset();
697 for (auto sti : _symbolTable) {
698 memcpy(dest, sti, sizeof(Elf_Sym));
699 dest += sizeof(Elf_Sym);
700 }
701}
702
703} // elf
704} // lld
705
706#endif //LLD_READER_WRITER_ELF_SECTION_CHUNKS_H_