1 //===- InputFiles.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 "InputFiles.h"
11 #include "Chunks.h"
12 #include "Error.h"
13 #include "Symbols.h"
14 #include "llvm/ADT/STLExtras.h"
15 
16 using namespace llvm::ELF;
17 
18 using namespace lld;
19 using namespace lld::elf2;
20 
21 template <class ELFT>
22 bool ObjectFile<ELFT>::isCompatibleWith(const ObjectFileBase &Other) const {
23   if (kind() != Other.kind())
24     return false;
25   return getObj()->getHeader()->e_machine ==
26          cast<ObjectFile<ELFT>>(Other).getObj()->getHeader()->e_machine;
27 }
28 
29 template <class ELFT> void elf2::ObjectFile<ELFT>::parse() {
30   // Parse a memory buffer as a ELF file.
31   std::error_code EC;
32   ELFObj = llvm::make_unique<ELFFile<ELFT>>(MB.getBuffer(), EC);
33   error(EC);
34 
35   // Read section and symbol tables.
36   initializeChunks();
37   initializeSymbols();
38 }
39 
40 template <class ELFT> void elf2::ObjectFile<ELFT>::initializeChunks() {
41   uint64_t Size = ELFObj->getNumSections();
42   Chunks.resize(Size);
43   unsigned I = 0;
44   for (const Elf_Shdr &Sec : ELFObj->sections()) {
45     switch (Sec.sh_type) {
46     case SHT_SYMTAB:
47       Symtab = &Sec;
48       break;
49     case SHT_SYMTAB_SHNDX: {
50       ErrorOr<ArrayRef<Elf_Word>> ErrorOrTable = ELFObj->getSHNDXTable(Sec);
51       error(ErrorOrTable);
52       SymtabSHNDX = *ErrorOrTable;
53       break;
54     }
55     case SHT_STRTAB:
56     case SHT_NULL:
57     case SHT_RELA:
58     case SHT_REL:
59       break;
60     default:
61       Chunks[I] = new (Alloc) SectionChunk<ELFT>(this->getObj(), &Sec);
62       break;
63     }
64     ++I;
65   }
66 }
67 
68 template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSymbols() {
69   ErrorOr<StringRef> StringTableOrErr =
70       ELFObj->getStringTableForSymtab(*Symtab);
71   error(StringTableOrErr.getError());
72   StringRef StringTable = *StringTableOrErr;
73 
74   Elf_Sym_Range Syms = ELFObj->symbols(Symtab);
75   uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
76   uint32_t FirstNonLocal = Symtab->sh_info;
77   if (FirstNonLocal > NumSymbols)
78     error("Invalid sh_info in symbol table");
79   Syms = llvm::make_range(Syms.begin() + FirstNonLocal, Syms.end());
80   SymbolBodies.reserve(NumSymbols);
81   for (const Elf_Sym &Sym : Syms)
82     SymbolBodies.push_back(createSymbolBody(StringTable, &Sym));
83 }
84 
85 template <class ELFT>
86 SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable,
87                                                      const Elf_Sym *Sym) {
88   ErrorOr<StringRef> NameOrErr = Sym->getName(StringTable);
89   error(NameOrErr.getError());
90   StringRef Name = *NameOrErr;
91 
92   uint32_t SecIndex = Sym->st_shndx;
93   if (SecIndex == SHN_XINDEX)
94     SecIndex = ELFObj->getExtendedSymbolTableIndex(Sym, Symtab, SymtabSHNDX);
95 
96   if (SecIndex >= Chunks.size() ||
97       (SecIndex != 0 && !Chunks[SecIndex]))
98     error("Invalid section index");
99 
100   switch (Sym->getBinding()) {
101   default:
102     error("unexpected binding");
103   case STB_GLOBAL:
104     if (Sym->isUndefined())
105       return new (Alloc) Undefined<ELFT>(Name, *Sym);
106     return new (Alloc) DefinedRegular<ELFT>(Name, *Sym, *Chunks[SecIndex]);
107   case STB_WEAK:
108     if (Sym->isUndefined())
109       return new (Alloc) UndefinedWeak<ELFT>(Name, *Sym);
110     return new (Alloc) DefinedWeak<ELFT>(Name, *Sym, *Chunks[SecIndex]);
111   }
112 }
113 
114 namespace lld {
115 namespace elf2 {
116 template class elf2::ObjectFile<llvm::object::ELF32LE>;
117 template class elf2::ObjectFile<llvm::object::ELF32BE>;
118 template class elf2::ObjectFile<llvm::object::ELF64LE>;
119 template class elf2::ObjectFile<llvm::object::ELF64BE>;
120 }
121 }
122