| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 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" | 
| Rafael Espindola | 192e1fa | 2015-08-06 15:08:23 +0000 | [diff] [blame] | 12 | #include "Error.h" | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 13 | #include "Symbols.h" | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 14 | #include "llvm/ADT/STLExtras.h" | 
|  | 15 |  | 
|  | 16 | using namespace llvm::ELF; | 
|  | 17 |  | 
|  | 18 | using namespace lld; | 
|  | 19 | using namespace lld::elf2; | 
|  | 20 |  | 
| Rafael Espindola | 3c9cb4b | 2015-08-05 12:03:34 +0000 | [diff] [blame] | 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 |  | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 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(); | 
| Rafael Espindola | 832b93f | 2015-08-24 20:06:32 +0000 | [diff] [blame] | 42 | Chunks.resize(Size); | 
|  | 43 | unsigned I = 0; | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 44 | for (const Elf_Shdr &Sec : ELFObj->sections()) { | 
| Rafael Espindola | cde2513 | 2015-08-13 14:45:44 +0000 | [diff] [blame] | 45 | switch (Sec.sh_type) { | 
|  | 46 | case SHT_SYMTAB: | 
| Rafael Espindola | d8340da | 2015-08-10 15:12:17 +0000 | [diff] [blame] | 47 | Symtab = &Sec; | 
| Rafael Espindola | cde2513 | 2015-08-13 14:45:44 +0000 | [diff] [blame] | 48 | break; | 
| Rafael Espindola | 2034822 | 2015-08-24 21:43:25 +0000 | [diff] [blame] | 49 | case SHT_SYMTAB_SHNDX: { | 
|  | 50 | ErrorOr<ArrayRef<Elf_Word>> ErrorOrTable = ELFObj->getSHNDXTable(Sec); | 
|  | 51 | error(ErrorOrTable); | 
|  | 52 | SymtabSHNDX = *ErrorOrTable; | 
|  | 53 | break; | 
|  | 54 | } | 
| Rafael Espindola | cde2513 | 2015-08-13 14:45:44 +0000 | [diff] [blame] | 55 | case SHT_STRTAB: | 
|  | 56 | case SHT_NULL: | 
| Rafael Espindola | cde2513 | 2015-08-13 14:45:44 +0000 | [diff] [blame] | 57 | break; | 
| Michael J. Spencer | 67bc8d6 | 2015-08-27 23:15:56 +0000 | [diff] [blame] | 58 | case SHT_RELA: | 
|  | 59 | case SHT_REL: { | 
|  | 60 | uint32_t RelocatedSectionIndex = Sec.sh_info; | 
|  | 61 | if (RelocatedSectionIndex >= Size) | 
|  | 62 | error("Invalid relocated section index"); | 
|  | 63 | SectionChunk<ELFT> *RelocatedSection = Chunks[RelocatedSectionIndex]; | 
|  | 64 | if (!RelocatedSection) | 
|  | 65 | error("Unsupported relocation reference"); | 
|  | 66 | RelocatedSection->RelocSections.push_back(&Sec); | 
|  | 67 | break; | 
|  | 68 | } | 
| Rafael Espindola | cde2513 | 2015-08-13 14:45:44 +0000 | [diff] [blame] | 69 | default: | 
| Michael J. Spencer | 67bc8d6 | 2015-08-27 23:15:56 +0000 | [diff] [blame] | 70 | Chunks[I] = new (Alloc) SectionChunk<ELFT>(this, &Sec); | 
| Rafael Espindola | cde2513 | 2015-08-13 14:45:44 +0000 | [diff] [blame] | 71 | break; | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 72 | } | 
| Rafael Espindola | 832b93f | 2015-08-24 20:06:32 +0000 | [diff] [blame] | 73 | ++I; | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 74 | } | 
|  | 75 | } | 
|  | 76 |  | 
|  | 77 | template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSymbols() { | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 78 | ErrorOr<StringRef> StringTableOrErr = | 
|  | 79 | ELFObj->getStringTableForSymtab(*Symtab); | 
|  | 80 | error(StringTableOrErr.getError()); | 
|  | 81 | StringRef StringTable = *StringTableOrErr; | 
|  | 82 |  | 
| Rafael Espindola | 1a9344f | 2015-08-07 17:16:28 +0000 | [diff] [blame] | 83 | Elf_Sym_Range Syms = ELFObj->symbols(Symtab); | 
| Reid Kleckner | f7b85e0 | 2015-08-11 20:06:51 +0000 | [diff] [blame] | 84 | uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end()); | 
| Rafael Espindola | 7c38818 | 2015-08-11 16:30:34 +0000 | [diff] [blame] | 85 | uint32_t FirstNonLocal = Symtab->sh_info; | 
|  | 86 | if (FirstNonLocal > NumSymbols) | 
|  | 87 | error("Invalid sh_info in symbol table"); | 
|  | 88 | Syms = llvm::make_range(Syms.begin() + FirstNonLocal, Syms.end()); | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 89 | SymbolBodies.reserve(NumSymbols); | 
| Rafael Espindola | 3031851 | 2015-08-04 14:00:56 +0000 | [diff] [blame] | 90 | for (const Elf_Sym &Sym : Syms) | 
|  | 91 | SymbolBodies.push_back(createSymbolBody(StringTable, &Sym)); | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 92 | } | 
|  | 93 |  | 
|  | 94 | template <class ELFT> | 
|  | 95 | SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable, | 
|  | 96 | const Elf_Sym *Sym) { | 
|  | 97 | ErrorOr<StringRef> NameOrErr = Sym->getName(StringTable); | 
|  | 98 | error(NameOrErr.getError()); | 
|  | 99 | StringRef Name = *NameOrErr; | 
| Rafael Espindola | 2034822 | 2015-08-24 21:43:25 +0000 | [diff] [blame] | 100 |  | 
|  | 101 | uint32_t SecIndex = Sym->st_shndx; | 
| Rafael Espindola | 51d4690 | 2015-08-28 21:26:51 +0000 | [diff] [blame^] | 102 | switch (SecIndex) { | 
|  | 103 | case SHN_ABS: | 
| Rafael Espindola | 0e0c190 | 2015-08-27 12:40:06 +0000 | [diff] [blame] | 104 | return new (Alloc) DefinedAbsolute<ELFT>(Name, *Sym); | 
| Rafael Espindola | 51d4690 | 2015-08-28 21:26:51 +0000 | [diff] [blame^] | 105 | case SHN_UNDEF: | 
|  | 106 | return new (Alloc) Undefined<ELFT>(Name, *Sym); | 
|  | 107 | case SHN_COMMON: | 
|  | 108 | return new (Alloc) DefinedCommon<ELFT>(Name, *Sym); | 
|  | 109 | case SHN_XINDEX: | 
| Rafael Espindola | 2034822 | 2015-08-24 21:43:25 +0000 | [diff] [blame] | 110 | SecIndex = ELFObj->getExtendedSymbolTableIndex(Sym, Symtab, SymtabSHNDX); | 
| Rafael Espindola | 51d4690 | 2015-08-28 21:26:51 +0000 | [diff] [blame^] | 111 | break; | 
|  | 112 | } | 
| Rafael Espindola | 2034822 | 2015-08-24 21:43:25 +0000 | [diff] [blame] | 113 |  | 
| Rafael Espindola | 5cd113d | 2015-08-24 22:00:25 +0000 | [diff] [blame] | 114 | if (SecIndex >= Chunks.size() || | 
|  | 115 | (SecIndex != 0 && !Chunks[SecIndex])) | 
|  | 116 | error("Invalid section index"); | 
|  | 117 |  | 
| Rafael Espindola | b13df65 | 2015-08-11 17:33:02 +0000 | [diff] [blame] | 118 | switch (Sym->getBinding()) { | 
|  | 119 | default: | 
|  | 120 | error("unexpected binding"); | 
|  | 121 | case STB_GLOBAL: | 
| Rafael Espindola | 3a63f3f | 2015-08-28 20:19:34 +0000 | [diff] [blame] | 122 | case STB_WEAK: | 
| Rafael Espindola | 832b93f | 2015-08-24 20:06:32 +0000 | [diff] [blame] | 123 | return new (Alloc) DefinedRegular<ELFT>(Name, *Sym, *Chunks[SecIndex]); | 
| Rafael Espindola | b13df65 | 2015-08-11 17:33:02 +0000 | [diff] [blame] | 124 | } | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 125 | } | 
|  | 126 |  | 
|  | 127 | namespace lld { | 
|  | 128 | namespace elf2 { | 
|  | 129 | template class elf2::ObjectFile<llvm::object::ELF32LE>; | 
|  | 130 | template class elf2::ObjectFile<llvm::object::ELF32BE>; | 
|  | 131 | template class elf2::ObjectFile<llvm::object::ELF64LE>; | 
|  | 132 | template class elf2::ObjectFile<llvm::object::ELF64BE>; | 
|  | 133 | } | 
|  | 134 | } |