1 //===- OutputSections.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 "OutputSections.h"
11 #include "Config.h"
12 #include "SymbolTable.h"
13 #include "Target.h"
14 
15 using namespace llvm;
16 using namespace llvm::object;
17 using namespace llvm::ELF;
18 
19 using namespace lld;
20 using namespace lld::elf2;
21 
22 template <bool Is64Bits>
23 OutputSectionBase<Is64Bits>::OutputSectionBase(StringRef Name, uint32_t sh_type,
24                                                uintX_t sh_flags)
25     : Name(Name) {
26   memset(&Header, 0, sizeof(HeaderT));
27   Header.sh_type = sh_type;
28   Header.sh_flags = sh_flags;
29 }
30 
31 template <class ELFT>
32 GotSection<ELFT>::GotSection()
33     : OutputSectionBase<ELFT::Is64Bits>(".got", llvm::ELF::SHT_PROGBITS,
34                                         llvm::ELF::SHF_ALLOC |
35                                             llvm::ELF::SHF_WRITE) {
36   this->Header.sh_addralign = this->getAddrSize();
37 }
38 
39 template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody *Sym) {
40   Sym->setGotIndex(Entries.size());
41   Entries.push_back(Sym);
42 }
43 
44 template <class ELFT>
45 typename GotSection<ELFT>::uintX_t
46 GotSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
47   return this->getVA() + B.getGotIndex() * this->getAddrSize();
48 }
49 
50 template <class ELFT>
51 PltSection<ELFT>::PltSection(const GotSection<ELFT> &GotSec)
52     : OutputSectionBase<ELFT::Is64Bits>(".plt", llvm::ELF::SHT_PROGBITS,
53                                         llvm::ELF::SHF_ALLOC |
54                                             llvm::ELF::SHF_EXECINSTR),
55       GotSec(GotSec) {
56   this->Header.sh_addralign = 16;
57 }
58 
59 template <class ELFT> void PltSection<ELFT>::writeTo(uint8_t *Buf) {
60   uintptr_t Start = reinterpret_cast<uintptr_t>(Buf);
61   for (const SymbolBody *E : Entries) {
62     uint64_t GotEntryAddr = GotSec.getEntryAddr(*E);
63     uintptr_t InstPos = reinterpret_cast<uintptr_t>(Buf);
64     uint64_t PltEntryAddr = (InstPos - Start) + this->getVA();
65     Target->writePltEntry(Buf, GotEntryAddr, PltEntryAddr);
66     Buf += 8;
67   }
68 }
69 
70 template <class ELFT> void PltSection<ELFT>::addEntry(SymbolBody *Sym) {
71   Sym->setPltIndex(Entries.size());
72   Entries.push_back(Sym);
73 }
74 
75 template <class ELFT>
76 typename PltSection<ELFT>::uintX_t
77 PltSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
78   return this->getVA() + B.getPltIndex() * EntrySize;
79 }
80 
81 template <class ELFT>
82 RelocationSection<ELFT>::RelocationSection(SymbolTableSection<ELFT> &DynSymSec,
83                                            const GotSection<ELFT> &GotSec,
84                                            bool IsRela)
85     : OutputSectionBase<ELFT::Is64Bits>(IsRela ? ".rela.dyn" : ".rel.dyn",
86                                         IsRela ? llvm::ELF::SHT_RELA
87                                                : llvm::ELF::SHT_REL,
88                                         llvm::ELF::SHF_ALLOC),
89       DynSymSec(DynSymSec), GotSec(GotSec), IsRela(IsRela) {
90   this->Header.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
91   this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
92 }
93 
94 template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
95   const unsigned EntrySize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
96   bool IsMips64EL = Relocs[0].C.getFile()->getObj().isMips64EL();
97   for (const DynamicReloc<ELFT> &Rel : Relocs) {
98     auto *P = reinterpret_cast<Elf_Rel *>(Buf);
99     Buf += EntrySize;
100 
101     const InputSection<ELFT> &C = Rel.C;
102     const Elf_Rel &RI = Rel.RI;
103     OutputSection<ELFT> *Out = C.getOutputSection();
104     uint32_t SymIndex = RI.getSymbol(IsMips64EL);
105     const SymbolBody *Body = C.getFile()->getSymbolBody(SymIndex);
106     uint32_t Type = RI.getType(IsMips64EL);
107     if (Target->relocNeedsGot(Type, *Body)) {
108       P->r_offset = GotSec.getEntryAddr(*Body);
109       P->setSymbolAndType(Body->getDynamicSymbolTableIndex(),
110                           Target->getGotReloc(), IsMips64EL);
111     } else {
112       P->r_offset = RI.r_offset + C.getOutputSectionOff() + Out->getVA();
113       P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), Type, IsMips64EL);
114       if (IsRela)
115         static_cast<Elf_Rela *>(P)->r_addend =
116             static_cast<const Elf_Rela &>(RI).r_addend;
117     }
118   }
119 }
120 
121 template <class ELFT> void RelocationSection<ELFT>::finalize() {
122   this->Header.sh_link = DynSymSec.getSectionIndex();
123   this->Header.sh_size = Relocs.size() * this->Header.sh_entsize;
124 }
125 
126 template <bool Is64Bits>
127 InterpSection<Is64Bits>::InterpSection()
128     : OutputSectionBase<Is64Bits>(".interp", llvm::ELF::SHT_PROGBITS,
129                                   llvm::ELF::SHF_ALLOC) {
130   this->Header.sh_size = Config->DynamicLinker.size() + 1;
131   this->Header.sh_addralign = 1;
132 }
133 
134 template <bool Is64Bits>
135 template <endianness E>
136 void OutputSectionBase<Is64Bits>::writeHeaderTo(
137     typename ELFFile<ELFType<E, Is64Bits>>::Elf_Shdr *SHdr) {
138   SHdr->sh_name = Header.sh_name;
139   SHdr->sh_type = Header.sh_type;
140   SHdr->sh_flags = Header.sh_flags;
141   SHdr->sh_addr = Header.sh_addr;
142   SHdr->sh_offset = Header.sh_offset;
143   SHdr->sh_size = Header.sh_size;
144   SHdr->sh_link = Header.sh_link;
145   SHdr->sh_info = Header.sh_info;
146   SHdr->sh_addralign = Header.sh_addralign;
147   SHdr->sh_entsize = Header.sh_entsize;
148 }
149 
150 template <bool Is64Bits> void InterpSection<Is64Bits>::writeTo(uint8_t *Buf) {
151   memcpy(Buf, Config->DynamicLinker.data(), Config->DynamicLinker.size());
152 }
153 
154 template <class ELFT>
155 HashTableSection<ELFT>::HashTableSection(SymbolTableSection<ELFT> &DynSymSec)
156     : OutputSectionBase<ELFT::Is64Bits>(".hash", llvm::ELF::SHT_HASH,
157                                         llvm::ELF::SHF_ALLOC),
158       DynSymSec(DynSymSec) {
159   this->Header.sh_entsize = sizeof(Elf_Word);
160   this->Header.sh_addralign = sizeof(Elf_Word);
161 }
162 
163 template <class ELFT> void HashTableSection<ELFT>::addSymbol(SymbolBody *S) {
164   StringRef Name = S->getName();
165   DynSymSec.addSymbol(Name);
166   Hashes.push_back(hash(Name));
167   S->setDynamicSymbolTableIndex(Hashes.size());
168 }
169 
170 template <class ELFT>
171 DynamicSection<ELFT>::DynamicSection(SymbolTable &SymTab,
172                                      HashTableSection<ELFT> &HashSec,
173                                      RelocationSection<ELFT> &RelaDynSec)
174     : OutputSectionBase<ELFT::Is64Bits>(".dynamic", llvm::ELF::SHT_DYNAMIC,
175                                         llvm::ELF::SHF_ALLOC |
176                                             llvm::ELF::SHF_WRITE),
177       HashSec(HashSec), DynSymSec(HashSec.getDynSymSec()),
178       DynStrSec(DynSymSec.getStrTabSec()), RelaDynSec(RelaDynSec),
179       SymTab(SymTab) {
180   typename Base::HeaderT &Header = this->Header;
181   Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
182   Header.sh_entsize = ELFT::Is64Bits ? 16 : 8;
183 }
184 
185 template <class ELFT> void DynamicSection<ELFT>::finalize() {
186   typename Base::HeaderT &Header = this->Header;
187   Header.sh_link = DynStrSec.getSectionIndex();
188 
189   unsigned NumEntries = 0;
190   if (RelaDynSec.hasRelocs()) {
191     ++NumEntries; // DT_RELA / DT_REL
192     ++NumEntries; // DT_RELASZ / DT_RELSZ
193     ++NumEntries; // DT_RELAENT / DT_RELENT
194   }
195   ++NumEntries; // DT_SYMTAB
196   ++NumEntries; // DT_SYMENT
197   ++NumEntries; // DT_STRTAB
198   ++NumEntries; // DT_STRSZ
199   ++NumEntries; // DT_HASH
200 
201   StringRef RPath = Config->RPath;
202   if (!RPath.empty()) {
203     ++NumEntries; // DT_RUNPATH
204     DynStrSec.add(RPath);
205   }
206 
207   const std::vector<std::unique_ptr<SharedFileBase>> &SharedFiles =
208       SymTab.getSharedFiles();
209   for (const std::unique_ptr<SharedFileBase> &File : SharedFiles)
210     DynStrSec.add(File->getName());
211   NumEntries += SharedFiles.size();
212 
213   ++NumEntries; // DT_NULL
214 
215   Header.sh_size = NumEntries * Header.sh_entsize;
216 }
217 
218 template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
219   typedef typename std::conditional<ELFT::Is64Bits, Elf64_Dyn, Elf32_Dyn>::type
220       Elf_Dyn;
221   auto *P = reinterpret_cast<Elf_Dyn *>(Buf);
222 
223   if (RelaDynSec.hasRelocs()) {
224     bool IsRela = RelaDynSec.isRela();
225     P->d_tag = IsRela ? DT_RELA : DT_REL;
226     P->d_un.d_ptr = RelaDynSec.getVA();
227     ++P;
228 
229     P->d_tag = IsRela ? DT_RELASZ : DT_RELSZ;
230     P->d_un.d_val = RelaDynSec.getSize();
231     ++P;
232 
233     P->d_tag = IsRela ? DT_RELAENT : DT_RELENT;
234     P->d_un.d_val = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
235     ++P;
236   }
237 
238   P->d_tag = DT_SYMTAB;
239   P->d_un.d_ptr = DynSymSec.getVA();
240   ++P;
241 
242   P->d_tag = DT_SYMENT;
243   P->d_un.d_ptr = sizeof(Elf_Sym);
244   ++P;
245 
246   P->d_tag = DT_STRTAB;
247   P->d_un.d_ptr = DynStrSec.getVA();
248   ++P;
249 
250   P->d_tag = DT_STRSZ;
251   P->d_un.d_val = DynStrSec.data().size();
252   ++P;
253 
254   P->d_tag = DT_HASH;
255   P->d_un.d_ptr = HashSec.getVA();
256   ++P;
257 
258   StringRef RPath = Config->RPath;
259   if (!RPath.empty()) {
260     P->d_tag = DT_RUNPATH;
261     P->d_un.d_val = DynStrSec.getFileOff(RPath);
262     ++P;
263   }
264 
265   const std::vector<std::unique_ptr<SharedFileBase>> &SharedFiles =
266       SymTab.getSharedFiles();
267   for (const std::unique_ptr<SharedFileBase> &File : SharedFiles) {
268     P->d_tag = DT_NEEDED;
269     P->d_un.d_val = DynStrSec.getFileOff(File->getName());
270     ++P;
271   }
272 
273   P->d_tag = DT_NULL;
274   P->d_un.d_val = 0;
275   ++P;
276 }
277 
278 template <class ELFT>
279 OutputSection<ELFT>::OutputSection(const PltSection<ELFT> &PltSec,
280                                    const GotSection<ELFT> &GotSec,
281                                    const OutputSection<ELFT> &BssSec,
282                                    StringRef Name, uint32_t sh_type,
283                                    uintX_t sh_flags)
284     : OutputSectionBase<ELFT::Is64Bits>(Name, sh_type, sh_flags),
285       PltSec(PltSec), GotSec(GotSec), BssSec(BssSec) {}
286 
287 template <class ELFT>
288 void OutputSection<ELFT>::addSection(InputSection<ELFT> *C) {
289   Sections.push_back(C);
290   C->setOutputSection(this);
291   uint32_t Align = C->getAlign();
292   if (Align > this->Header.sh_addralign)
293     this->Header.sh_addralign = Align;
294 
295   uintX_t Off = this->Header.sh_size;
296   Off = RoundUpToAlignment(Off, Align);
297   C->setOutputSectionOff(Off);
298   Off += C->getSize();
299   this->Header.sh_size = Off;
300 }
301 
302 template <class ELFT>
303 typename ELFFile<ELFT>::uintX_t
304 lld::elf2::getSymVA(const ELFSymbolBody<ELFT> &S,
305                     const OutputSection<ELFT> &BssSec) {
306   switch (S.kind()) {
307   case SymbolBody::DefinedSyntheticKind:
308     return cast<DefinedSynthetic<ELFT>>(S).Section.getVA() + S.Sym.st_value;
309   case SymbolBody::DefinedAbsoluteKind:
310     return S.Sym.st_value;
311   case SymbolBody::DefinedRegularKind: {
312     const auto &DR = cast<DefinedRegular<ELFT>>(S);
313     const InputSection<ELFT> *SC = &DR.Section;
314     OutputSection<ELFT> *OS = SC->getOutputSection();
315     return OS->getVA() + SC->getOutputSectionOff() + DR.Sym.st_value;
316   }
317   case SymbolBody::DefinedCommonKind:
318     return BssSec.getVA() + cast<DefinedCommon<ELFT>>(S).OffsetInBSS;
319   case SymbolBody::SharedKind:
320   case SymbolBody::UndefinedKind:
321     return 0;
322   case SymbolBody::LazyKind:
323     break;
324   }
325   llvm_unreachable("Lazy symbol reached writer");
326 }
327 
328 template <class ELFT>
329 typename ELFFile<ELFT>::uintX_t
330 lld::elf2::getLocalSymVA(const typename ELFFile<ELFT>::Elf_Sym *Sym,
331                          const ObjectFile<ELFT> &File) {
332   uint32_t SecIndex = Sym->st_shndx;
333 
334   if (SecIndex == SHN_XINDEX)
335     SecIndex = File.getObj().getExtendedSymbolTableIndex(
336         Sym, File.getSymbolTable(), File.getSymbolTableShndx());
337   ArrayRef<InputSection<ELFT> *> Sections = File.getSections();
338   InputSection<ELFT> *Section = Sections[SecIndex];
339   OutputSection<ELFT> *Out = Section->getOutputSection();
340   return Out->getVA() + Section->getOutputSectionOff() + Sym->st_value;
341 }
342 
343 template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
344   for (InputSection<ELFT> *C : Sections)
345     C->writeTo(Buf, BssSec, PltSec, GotSec);
346 }
347 
348 template <bool Is64Bits>
349 StringTableSection<Is64Bits>::StringTableSection(bool Dynamic)
350     : OutputSectionBase<Is64Bits>(Dynamic ? ".dynstr" : ".strtab",
351                                   llvm::ELF::SHT_STRTAB,
352                                   Dynamic ? (uintX_t)llvm::ELF::SHF_ALLOC : 0),
353       Dynamic(Dynamic) {
354   this->Header.sh_addralign = 1;
355 }
356 
357 template <bool Is64Bits>
358 void StringTableSection<Is64Bits>::writeTo(uint8_t *Buf) {
359   StringRef Data = StrTabBuilder.data();
360   memcpy(Buf, Data.data(), Data.size());
361 }
362 
363 bool lld::elf2::includeInSymtab(const SymbolBody &B) {
364   if (B.isLazy())
365     return false;
366   if (!B.isUsedInRegularObj())
367     return false;
368   uint8_t V = B.getMostConstrainingVisibility();
369   if (V != STV_DEFAULT && V != STV_PROTECTED)
370     return false;
371   return true;
372 }
373 
374 bool lld::elf2::includeInDynamicSymtab(const SymbolBody &B) {
375   if (Config->ExportDynamic || Config->Shared)
376     return true;
377   return B.isUsedInDynamicReloc();
378 }
379 
380 bool lld::elf2::shouldKeepInSymtab(StringRef SymName) {
381   if (Config->DiscardNone)
382     return true;
383 
384   // ELF defines dynamic locals as symbols which name starts with ".L".
385   return !(Config->DiscardLocals && SymName.startswith(".L"));
386 }
387 
388 template <class ELFT>
389 SymbolTableSection<ELFT>::SymbolTableSection(
390     SymbolTable &Table, StringTableSection<ELFT::Is64Bits> &StrTabSec,
391     const OutputSection<ELFT> &BssSec)
392     : OutputSectionBase<ELFT::Is64Bits>(
393           StrTabSec.isDynamic() ? ".dynsym" : ".symtab",
394           StrTabSec.isDynamic() ? llvm::ELF::SHT_DYNSYM : llvm::ELF::SHT_SYMTAB,
395           StrTabSec.isDynamic() ? (uintX_t)llvm::ELF::SHF_ALLOC : 0),
396       Table(Table), StrTabSec(StrTabSec), BssSec(BssSec) {
397   typedef OutputSectionBase<ELFT::Is64Bits> Base;
398   typename Base::HeaderT &Header = this->Header;
399 
400   Header.sh_entsize = sizeof(Elf_Sym);
401   Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
402 }
403 
404 template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
405   Buf += sizeof(Elf_Sym);
406 
407   // All symbols with STB_LOCAL binding precede the weak and global symbols.
408   // .dynsym only contains global symbols.
409   if (!Config->DiscardAll && !StrTabSec.isDynamic())
410     writeLocalSymbols(Buf);
411 
412   writeGlobalSymbols(Buf);
413 }
414 
415 template <class ELFT>
416 void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
417   // Iterate over all input object files to copy their local symbols
418   // to the output symbol table pointed by Buf.
419   for (const std::unique_ptr<ObjectFileBase> &FileB : Table.getObjectFiles()) {
420     auto &File = cast<ObjectFile<ELFT>>(*FileB);
421     Elf_Sym_Range Syms = File.getLocalSymbols();
422     for (const Elf_Sym &Sym : Syms) {
423       ErrorOr<StringRef> SymName = Sym.getName(File.getStringTable());
424       if (SymName && !shouldKeepInSymtab(*SymName))
425         continue;
426       auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
427       Buf += sizeof(*ESym);
428       ESym->st_name = (SymName) ? StrTabSec.getFileOff(*SymName) : 0;
429       ESym->st_size = Sym.st_size;
430       ESym->setBindingAndType(Sym.getBinding(), Sym.getType());
431       uint32_t SecIndex = Sym.st_shndx;
432       uintX_t VA = Sym.st_value;
433       if (SecIndex == SHN_ABS) {
434         ESym->st_shndx = SHN_ABS;
435       } else {
436         if (SecIndex == SHN_XINDEX)
437           SecIndex = File.getObj().getExtendedSymbolTableIndex(
438               &Sym, File.getSymbolTable(), File.getSymbolTableShndx());
439         ArrayRef<InputSection<ELFT> *> Sections = File.getSections();
440         const InputSection<ELFT> *Section = Sections[SecIndex];
441         const OutputSection<ELFT> *Out = Section->getOutputSection();
442         ESym->st_shndx = Out->getSectionIndex();
443         VA += Out->getVA() + Section->getOutputSectionOff();
444       }
445       ESym->st_value = VA;
446     }
447   }
448 }
449 
450 template <class ELFT>
451 void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *&Buf) {
452   // Write the internal symbol table contents to the output symbol table
453   // pointed by Buf.
454   for (const std::pair<StringRef, Symbol *> &P : Table.getSymbols()) {
455     StringRef Name = P.first;
456     Symbol *Sym = P.second;
457     SymbolBody *Body = Sym->Body;
458     if (!includeInSymtab(*Body))
459       continue;
460     if (StrTabSec.isDynamic() && !includeInDynamicSymtab(*Body))
461       continue;
462 
463     const auto &EBody = *cast<ELFSymbolBody<ELFT>>(Body);
464     const Elf_Sym &InputSym = EBody.Sym;
465     auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
466     Buf += sizeof(*ESym);
467     ESym->st_name = StrTabSec.getFileOff(Name);
468 
469     const OutputSection<ELFT> *Out = nullptr;
470     const InputSection<ELFT> *Section = nullptr;
471 
472     switch (EBody.kind()) {
473     case SymbolBody::DefinedSyntheticKind:
474       Out = &cast<DefinedSynthetic<ELFT>>(Body)->Section;
475       break;
476     case SymbolBody::DefinedRegularKind:
477       Section = &cast<DefinedRegular<ELFT>>(EBody).Section;
478       break;
479     case SymbolBody::DefinedCommonKind:
480       Out = &BssSec;
481       break;
482     case SymbolBody::UndefinedKind:
483     case SymbolBody::DefinedAbsoluteKind:
484     case SymbolBody::SharedKind:
485       break;
486     case SymbolBody::LazyKind:
487       llvm_unreachable("Lazy symbol got to output symbol table!");
488     }
489 
490     ESym->setBindingAndType(InputSym.getBinding(), InputSym.getType());
491     ESym->st_size = InputSym.st_size;
492     ESym->setVisibility(EBody.getMostConstrainingVisibility());
493     if (InputSym.isAbsolute()) {
494       ESym->st_shndx = SHN_ABS;
495       ESym->st_value = InputSym.st_value;
496     }
497 
498     if (Section)
499       Out = Section->getOutputSection();
500 
501     ESym->st_value = getSymVA(EBody, BssSec);
502 
503     if (Out)
504       ESym->st_shndx = Out->getSectionIndex();
505   }
506 }
507 
508 namespace lld {
509 namespace elf2 {
510 template class OutputSectionBase<false>;
511 template class OutputSectionBase<true>;
512 
513 template void OutputSectionBase<false>::writeHeaderTo<support::little>(
514     ELFFile<ELFType<support::little, false>>::Elf_Shdr *SHdr);
515 template void OutputSectionBase<true>::writeHeaderTo<support::little>(
516     ELFFile<ELFType<support::little, true>>::Elf_Shdr *SHdr);
517 template void OutputSectionBase<false>::writeHeaderTo<support::big>(
518     ELFFile<ELFType<support::big, false>>::Elf_Shdr *SHdr);
519 template void OutputSectionBase<true>::writeHeaderTo<support::big>(
520     ELFFile<ELFType<support::big, true>>::Elf_Shdr *SHdr);
521 
522 template class GotSection<ELF32LE>;
523 template class GotSection<ELF32BE>;
524 template class GotSection<ELF64LE>;
525 template class GotSection<ELF64BE>;
526 
527 template class PltSection<ELF32LE>;
528 template class PltSection<ELF32BE>;
529 template class PltSection<ELF64LE>;
530 template class PltSection<ELF64BE>;
531 
532 template class RelocationSection<ELF32LE>;
533 template class RelocationSection<ELF32BE>;
534 template class RelocationSection<ELF64LE>;
535 template class RelocationSection<ELF64BE>;
536 
537 template class InterpSection<false>;
538 template class InterpSection<true>;
539 
540 template class HashTableSection<ELF32LE>;
541 template class HashTableSection<ELF32BE>;
542 template class HashTableSection<ELF64LE>;
543 template class HashTableSection<ELF64BE>;
544 
545 template class DynamicSection<ELF32LE>;
546 template class DynamicSection<ELF32BE>;
547 template class DynamicSection<ELF64LE>;
548 template class DynamicSection<ELF64BE>;
549 
550 template class OutputSection<ELF32LE>;
551 template class OutputSection<ELF32BE>;
552 template class OutputSection<ELF64LE>;
553 template class OutputSection<ELF64BE>;
554 
555 template class StringTableSection<false>;
556 template class StringTableSection<true>;
557 
558 template class SymbolTableSection<ELF32LE>;
559 template class SymbolTableSection<ELF32BE>;
560 template class SymbolTableSection<ELF64LE>;
561 template class SymbolTableSection<ELF64BE>;
562 
563 template ELFFile<ELF32LE>::uintX_t
564 getSymVA(const ELFSymbolBody<ELF32LE> &, const OutputSection<ELF32LE> &);
565 
566 template ELFFile<ELF32BE>::uintX_t
567 getSymVA(const ELFSymbolBody<ELF32BE> &, const OutputSection<ELF32BE> &);
568 
569 template ELFFile<ELF64LE>::uintX_t
570 getSymVA(const ELFSymbolBody<ELF64LE> &, const OutputSection<ELF64LE> &);
571 
572 template ELFFile<ELF64BE>::uintX_t
573 getSymVA(const ELFSymbolBody<ELF64BE> &, const OutputSection<ELF64BE> &);
574 
575 template ELFFile<ELF32LE>::uintX_t
576 getLocalSymVA(const ELFFile<ELF32LE>::Elf_Sym *, const ObjectFile<ELF32LE> &);
577 
578 template ELFFile<ELF32BE>::uintX_t
579 getLocalSymVA(const ELFFile<ELF32BE>::Elf_Sym *, const ObjectFile<ELF32BE> &);
580 
581 template ELFFile<ELF64LE>::uintX_t
582 getLocalSymVA(const ELFFile<ELF64LE>::Elf_Sym *, const ObjectFile<ELF64LE> &);
583 
584 template ELFFile<ELF64BE>::uintX_t
585 getLocalSymVA(const ELFFile<ELF64BE>::Elf_Sym *, const ObjectFile<ELF64BE> &);
586 }
587 }
588