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