| Rafael Espindola | 9d06ab6 | 2015-09-22 00:01:39 +0000 | [diff] [blame] | 1 | //===- InputSection.cpp ---------------------------------------------------===// | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 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 |  | 
| Rafael Espindola | 9d06ab6 | 2015-09-22 00:01:39 +0000 | [diff] [blame] | 10 | #include "InputSection.h" | 
| Rafael Espindola | 551dfd8 | 2015-09-25 19:24:57 +0000 | [diff] [blame] | 11 | #include "Config.h" | 
| Rafael Espindola | 192e1fa | 2015-08-06 15:08:23 +0000 | [diff] [blame] | 12 | #include "Error.h" | 
| Michael J. Spencer | 67bc8d6 | 2015-08-27 23:15:56 +0000 | [diff] [blame] | 13 | #include "InputFiles.h" | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 14 | #include "OutputSections.h" | 
| Rafael Espindola | 01205f7 | 2015-09-22 18:19:46 +0000 | [diff] [blame] | 15 | #include "Target.h" | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 16 |  | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 17 | using namespace llvm; | 
|  | 18 | using namespace llvm::ELF; | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 19 | using namespace llvm::object; | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 20 |  | 
|  | 21 | using namespace lld; | 
|  | 22 | using namespace lld::elf2; | 
|  | 23 |  | 
|  | 24 | template <class ELFT> | 
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 25 | InputSectionBase<ELFT>::InputSectionBase(ObjectFile<ELFT> *File, | 
|  | 26 | const Elf_Shdr *Header, | 
|  | 27 | Kind SectionKind) | 
|  | 28 | : Header(Header), File(File), SectionKind(SectionKind) {} | 
|  | 29 |  | 
|  | 30 | template <class ELFT> StringRef InputSectionBase<ELFT>::getSectionName() const { | 
|  | 31 | ErrorOr<StringRef> Name = File->getObj().getSectionName(this->Header); | 
|  | 32 | error(Name); | 
|  | 33 | return *Name; | 
|  | 34 | } | 
|  | 35 |  | 
|  | 36 | template <class ELFT> | 
|  | 37 | ArrayRef<uint8_t> InputSectionBase<ELFT>::getSectionData() const { | 
|  | 38 | ErrorOr<ArrayRef<uint8_t>> Ret = | 
|  | 39 | this->File->getObj().getSectionContents(this->Header); | 
|  | 40 | error(Ret); | 
|  | 41 | return *Ret; | 
|  | 42 | } | 
|  | 43 |  | 
|  | 44 | template <class ELFT> | 
|  | 45 | typename ELFFile<ELFT>::uintX_t | 
| Rafael Espindola | 48225b4 | 2015-10-23 19:55:11 +0000 | [diff] [blame] | 46 | InputSectionBase<ELFT>::getOffset(const Elf_Sym &Sym) { | 
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 47 | if (auto *S = dyn_cast<InputSection<ELFT>>(this)) | 
|  | 48 | return S->OutSecOff + Sym.st_value; | 
|  | 49 | return cast<MergeInputSection<ELFT>>(this)->getOffset(Sym.st_value); | 
|  | 50 | } | 
|  | 51 |  | 
| Rui Ueyama | 1250464 | 2015-10-27 21:51:13 +0000 | [diff] [blame] | 52 | // Returns a section that Rel relocation is pointing to. | 
|  | 53 | template <class ELFT> | 
|  | 54 | InputSectionBase<ELFT> * | 
|  | 55 | InputSectionBase<ELFT>::getRelocTarget(const Elf_Rel &Rel) { | 
|  | 56 | // Global symbol | 
|  | 57 | uint32_t SymIndex = Rel.getSymbol(Config->Mips64EL); | 
|  | 58 | if (SymbolBody *B = File->getSymbolBody(SymIndex)) | 
|  | 59 | if (auto *D = dyn_cast<DefinedRegular<ELFT>>(B->repl())) | 
|  | 60 | return &D->Section; | 
|  | 61 | // Local symbol | 
|  | 62 | if (const Elf_Sym *Sym = File->getLocalSymbol(SymIndex)) | 
|  | 63 | if (InputSectionBase<ELFT> *Sec = File->getSection(*Sym)) | 
|  | 64 | return Sec; | 
|  | 65 | return nullptr; | 
|  | 66 | } | 
|  | 67 |  | 
|  | 68 | template <class ELFT> | 
|  | 69 | InputSectionBase<ELFT> * | 
|  | 70 | InputSectionBase<ELFT>::getRelocTarget(const Elf_Rela &Rel) { | 
|  | 71 | return getRelocTarget(reinterpret_cast<const Elf_Rel &>(Rel)); | 
|  | 72 | } | 
|  | 73 |  | 
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 74 | template <class ELFT> | 
| Rafael Espindola | 53d5cea | 2015-09-21 17:47:00 +0000 | [diff] [blame] | 75 | InputSection<ELFT>::InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header) | 
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 76 | : InputSectionBase<ELFT>(F, Header, Base::Regular) {} | 
|  | 77 |  | 
|  | 78 | template <class ELFT> | 
|  | 79 | bool InputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) { | 
|  | 80 | return S->SectionKind == Base::Regular; | 
|  | 81 | } | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 82 |  | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 83 | template <class ELFT> | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 84 | template <bool isRela> | 
|  | 85 | void InputSection<ELFT>::relocate( | 
| Hal Finkel | 87bbd5f | 2015-10-12 21:19:18 +0000 | [diff] [blame] | 86 | uint8_t *Buf, uint8_t *BufEnd, | 
|  | 87 | iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels, | 
| Rui Ueyama | 15ef5e1 | 2015-10-07 19:18:16 +0000 | [diff] [blame] | 88 | const ObjectFile<ELFT> &File, uintX_t BaseAddr) { | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 89 | typedef Elf_Rel_Impl<ELFT, isRela> RelType; | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 90 | for (const RelType &RI : Rels) { | 
| Rui Ueyama | 6455852 | 2015-10-16 22:51:43 +0000 | [diff] [blame] | 91 | uint32_t SymIndex = RI.getSymbol(Config->Mips64EL); | 
|  | 92 | uint32_t Type = RI.getType(Config->Mips64EL); | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 93 |  | 
|  | 94 | // Handle relocations for local symbols -- they never get | 
|  | 95 | // resolved so we don't allocate a SymbolBody. | 
|  | 96 | const Elf_Shdr *SymTab = File.getSymbolTable(); | 
|  | 97 | if (SymIndex < SymTab->sh_info) { | 
| Hal Finkel | 230c5c5 | 2015-10-16 22:37:32 +0000 | [diff] [blame] | 98 | uintX_t SymVA = getLocalRelTarget(File, RI); | 
| Rui Ueyama | 96f0e0b | 2015-10-23 02:40:46 +0000 | [diff] [blame] | 99 | Target->relocateOne(Buf + RI.r_offset, BufEnd, Type, | 
|  | 100 | BaseAddr + RI.r_offset, SymVA); | 
| Rui Ueyama | bb3c336 | 2015-10-12 20:28:23 +0000 | [diff] [blame] | 101 | continue; | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 102 | } | 
|  | 103 |  | 
| Rui Ueyama | bb3c336 | 2015-10-12 20:28:23 +0000 | [diff] [blame] | 104 | SymbolBody &Body = *File.getSymbolBody(SymIndex)->repl(); | 
|  | 105 | uintX_t SymVA = getSymVA<ELFT>(Body); | 
|  | 106 | if (Target->relocNeedsPlt(Type, Body)) { | 
|  | 107 | SymVA = Out<ELFT>::Plt->getEntryAddr(Body); | 
| Rafael Espindola | 227556e | 2015-10-14 16:15:46 +0000 | [diff] [blame] | 108 | Type = Target->getPLTRefReloc(Type); | 
| Rui Ueyama | bb3c336 | 2015-10-12 20:28:23 +0000 | [diff] [blame] | 109 | } else if (Target->relocNeedsGot(Type, Body)) { | 
|  | 110 | SymVA = Out<ELFT>::Got->getEntryAddr(Body); | 
|  | 111 | Type = Target->getGotRefReloc(); | 
|  | 112 | } else if (Target->relocPointsToGot(Type)) { | 
|  | 113 | SymVA = Out<ELFT>::Got->getVA(); | 
|  | 114 | Type = Target->getPCRelReloc(); | 
| George Rimar | bc590fe | 2015-10-28 16:48:58 +0000 | [diff] [blame^] | 115 | } else if (!Target->relocNeedsCopy(Type, Body) && | 
|  | 116 | isa<SharedSymbol<ELFT>>(Body)) { | 
| Rui Ueyama | bb3c336 | 2015-10-12 20:28:23 +0000 | [diff] [blame] | 117 | continue; | 
|  | 118 | } | 
| Rui Ueyama | 96f0e0b | 2015-10-23 02:40:46 +0000 | [diff] [blame] | 119 | Target->relocateOne(Buf + RI.r_offset, BufEnd, Type, BaseAddr + RI.r_offset, | 
| Rafael Espindola | 932efcf | 2015-10-19 20:24:44 +0000 | [diff] [blame] | 120 | SymVA + getAddend<ELFT>(RI)); | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 121 | } | 
|  | 122 | } | 
|  | 123 |  | 
| Rui Ueyama | 15ef5e1 | 2015-10-07 19:18:16 +0000 | [diff] [blame] | 124 | template <class ELFT> void InputSection<ELFT>::writeTo(uint8_t *Buf) { | 
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 125 | if (this->Header->sh_type == SHT_NOBITS) | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 126 | return; | 
|  | 127 | // Copy section contents from source object file to output file. | 
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 128 | ArrayRef<uint8_t> Data = this->getSectionData(); | 
| Rui Ueyama | 55c3f89 | 2015-10-15 01:58:40 +0000 | [diff] [blame] | 129 | memcpy(Buf + OutSecOff, Data.data(), Data.size()); | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 130 |  | 
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 131 | ELFFile<ELFT> &EObj = this->File->getObj(); | 
| Rui Ueyama | 55c3f89 | 2015-10-15 01:58:40 +0000 | [diff] [blame] | 132 | uint8_t *Base = Buf + OutSecOff; | 
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 133 | uintX_t BaseAddr = this->OutSec->getVA() + OutSecOff; | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 134 | // Iterate over all relocation sections that apply to this section. | 
|  | 135 | for (const Elf_Shdr *RelSec : RelocSections) { | 
|  | 136 | if (RelSec->sh_type == SHT_RELA) | 
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 137 | relocate(Base, Base + Data.size(), EObj.relas(RelSec), *this->File, | 
|  | 138 | BaseAddr); | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 139 | else | 
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 140 | relocate(Base, Base + Data.size(), EObj.rels(RelSec), *this->File, | 
|  | 141 | BaseAddr); | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 142 | } | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 143 | } | 
|  | 144 |  | 
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 145 | template <class ELFT> | 
|  | 146 | MergeInputSection<ELFT>::MergeInputSection(ObjectFile<ELFT> *F, | 
|  | 147 | const Elf_Shdr *Header) | 
|  | 148 | : InputSectionBase<ELFT>(F, Header, Base::Merge) {} | 
|  | 149 |  | 
|  | 150 | template <class ELFT> | 
|  | 151 | bool MergeInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) { | 
|  | 152 | return S->SectionKind == Base::Merge; | 
|  | 153 | } | 
|  | 154 |  | 
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 155 | template <class ELFT> | 
|  | 156 | typename MergeInputSection<ELFT>::uintX_t | 
| Rafael Espindola | 48225b4 | 2015-10-23 19:55:11 +0000 | [diff] [blame] | 157 | MergeInputSection<ELFT>::getOffset(uintX_t Offset) { | 
| Rafael Espindola | f82ed2a | 2015-10-24 22:51:01 +0000 | [diff] [blame] | 158 | ArrayRef<uint8_t> D = this->getSectionData(); | 
| Rui Ueyama | 7ba639b | 2015-10-25 16:25:04 +0000 | [diff] [blame] | 159 | StringRef Data((const char *)D.data(), D.size()); | 
| Rafael Espindola | f82ed2a | 2015-10-24 22:51:01 +0000 | [diff] [blame] | 160 | uintX_t Size = Data.size(); | 
|  | 161 | if (Offset >= Size) | 
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 162 | error("Entry is past the end of the section"); | 
| Rafael Espindola | f82ed2a | 2015-10-24 22:51:01 +0000 | [diff] [blame] | 163 |  | 
|  | 164 | // Find the element this offset points to. | 
|  | 165 | auto I = std::upper_bound( | 
|  | 166 | this->Offsets.begin(), this->Offsets.end(), Offset, | 
|  | 167 | [](const uintX_t &A, const std::pair<uintX_t, uintX_t> &B) { | 
|  | 168 | return A < B.first; | 
|  | 169 | }); | 
|  | 170 | size_t End = I == this->Offsets.end() ? Data.size() : I->first; | 
|  | 171 | --I; | 
|  | 172 | uintX_t Start = I->first; | 
|  | 173 |  | 
|  | 174 | // Compute the Addend and if the Base is cached, return. | 
|  | 175 | uintX_t Addend = Offset - Start; | 
|  | 176 | uintX_t &Base = I->second; | 
|  | 177 | if (Base != uintX_t(-1)) | 
|  | 178 | return Base + Addend; | 
|  | 179 |  | 
|  | 180 | // Map the base to the offset in the output section and cashe it. | 
|  | 181 | StringRef Entry = Data.substr(Start, End - Start); | 
|  | 182 | Base = | 
|  | 183 | static_cast<MergeOutputSection<ELFT> *>(this->OutSec)->getOffset(Entry); | 
|  | 184 | return Base + Addend; | 
| Rafael Espindola | 5d83ccd | 2015-08-13 19:18:30 +0000 | [diff] [blame] | 185 | } | 
|  | 186 |  | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 187 | namespace lld { | 
|  | 188 | namespace elf2 { | 
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 189 | template class InputSectionBase<object::ELF32LE>; | 
|  | 190 | template class InputSectionBase<object::ELF32BE>; | 
|  | 191 | template class InputSectionBase<object::ELF64LE>; | 
|  | 192 | template class InputSectionBase<object::ELF64BE>; | 
|  | 193 |  | 
| Rafael Espindola | 53d5cea | 2015-09-21 17:47:00 +0000 | [diff] [blame] | 194 | template class InputSection<object::ELF32LE>; | 
|  | 195 | template class InputSection<object::ELF32BE>; | 
|  | 196 | template class InputSection<object::ELF64LE>; | 
|  | 197 | template class InputSection<object::ELF64BE>; | 
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 198 |  | 
|  | 199 | template class MergeInputSection<object::ELF32LE>; | 
|  | 200 | template class MergeInputSection<object::ELF32BE>; | 
|  | 201 | template class MergeInputSection<object::ELF64LE>; | 
|  | 202 | template class MergeInputSection<object::ELF64BE>; | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 203 | } | 
|  | 204 | } |