1 //===- InputSection.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 "InputSection.h"
11 #include "Config.h"
12 #include "Error.h"
13 #include "InputFiles.h"
14 #include "OutputSections.h"
15 #include "Target.h"
16 
17 using namespace llvm;
18 using namespace llvm::ELF;
19 using namespace llvm::object;
20 
21 using namespace lld;
22 using namespace lld::elf2;
23 
24 template <class ELFT>
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
46 InputSectionBase<ELFT>::getOffset(uintX_t Offset) {
47   switch (SectionKind) {
48   case Regular:
49     return cast<InputSection<ELFT>>(this)->OutSecOff + Offset;
50   case EHFrame:
51     return cast<EHInputSection<ELFT>>(this)->getOffset(Offset);
52   case Merge:
53     return cast<MergeInputSection<ELFT>>(this)->getOffset(Offset);
54   }
55   llvm_unreachable("Invalid section kind");
56 }
57 
58 template <class ELFT>
59 typename ELFFile<ELFT>::uintX_t
60 InputSectionBase<ELFT>::getOffset(const Elf_Sym &Sym) {
61   return getOffset(Sym.st_value);
62 }
63 
64 // Returns a section that Rel relocation is pointing to.
65 template <class ELFT>
66 InputSectionBase<ELFT> *
67 InputSectionBase<ELFT>::getRelocTarget(const Elf_Rel &Rel) {
68   // Global symbol
69   uint32_t SymIndex = Rel.getSymbol(Config->Mips64EL);
70   if (SymbolBody *B = File->getSymbolBody(SymIndex))
71     if (auto *D = dyn_cast<DefinedRegular<ELFT>>(B->repl()))
72       return &D->Section;
73   // Local symbol
74   if (const Elf_Sym *Sym = File->getLocalSymbol(SymIndex))
75     if (InputSectionBase<ELFT> *Sec = File->getSection(*Sym))
76       return Sec;
77   return nullptr;
78 }
79 
80 template <class ELFT>
81 InputSectionBase<ELFT> *
82 InputSectionBase<ELFT>::getRelocTarget(const Elf_Rela &Rel) {
83   return getRelocTarget(reinterpret_cast<const Elf_Rel &>(Rel));
84 }
85 
86 template <class ELFT>
87 InputSection<ELFT>::InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header)
88     : InputSectionBase<ELFT>(F, Header, Base::Regular) {}
89 
90 template <class ELFT>
91 bool InputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
92   return S->SectionKind == Base::Regular;
93 }
94 
95 template <class ELFT>
96 template <bool isRela>
97 void InputSectionBase<ELFT>::relocate(
98     uint8_t *Buf, uint8_t *BufEnd,
99     iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels) {
100   typedef Elf_Rel_Impl<ELFT, isRela> RelType;
101   for (const RelType &RI : Rels) {
102     uint32_t SymIndex = RI.getSymbol(Config->Mips64EL);
103     uint32_t Type = RI.getType(Config->Mips64EL);
104     uintX_t Offset = getOffset(RI.r_offset);
105     if (Offset == (uintX_t)-1)
106       continue;
107 
108     uint8_t *BufLoc = Buf + Offset;
109     uintX_t AddrLoc = OutSec->getVA() + Offset;
110 
111     if (Target->isTlsLocalDynamicReloc(Type)) {
112       Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc,
113                           Out<ELFT>::Got->getVA() +
114                               Out<ELFT>::LocalModuleTlsIndexOffset +
115                               getAddend<ELFT>(RI));
116       continue;
117     }
118 
119     // Handle relocations for local symbols -- they never get
120     // resolved so we don't allocate a SymbolBody.
121     const Elf_Shdr *SymTab = File->getSymbolTable();
122     if (SymIndex < SymTab->sh_info) {
123       uintX_t SymVA = getLocalRelTarget(*File, RI);
124       Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA);
125       continue;
126     }
127 
128     SymbolBody &Body = *File->getSymbolBody(SymIndex)->repl();
129 
130     if (Target->isTlsGlobalDynamicReloc(Type)) {
131       Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc,
132                           Out<ELFT>::Got->getEntryAddr(Body) +
133                               getAddend<ELFT>(RI));
134       continue;
135     }
136 
137     uintX_t SymVA = getSymVA<ELFT>(Body);
138     if (Target->relocNeedsPlt(Type, Body)) {
139       SymVA = Out<ELFT>::Plt->getEntryAddr(Body);
140       Type = Target->getPltRefReloc(Type);
141     } else if (Target->relocNeedsGot(Type, Body)) {
142       SymVA = Out<ELFT>::Got->getEntryAddr(Body);
143       Type = Body.isTLS() ? Target->getTlsGotReloc() : Target->getGotRefReloc();
144     } else if (Target->relocPointsToGot(Type)) {
145       SymVA = Out<ELFT>::Got->getVA();
146       Type = Target->getPCRelReloc();
147     } else if (!Target->relocNeedsCopy(Type, Body) &&
148                isa<SharedSymbol<ELFT>>(Body)) {
149       continue;
150     }
151     Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc,
152                         SymVA + getAddend<ELFT>(RI));
153   }
154 }
155 
156 template <class ELFT> void InputSection<ELFT>::writeTo(uint8_t *Buf) {
157   if (this->Header->sh_type == SHT_NOBITS)
158     return;
159   // Copy section contents from source object file to output file.
160   ArrayRef<uint8_t> Data = this->getSectionData();
161   memcpy(Buf + OutSecOff, Data.data(), Data.size());
162 
163   ELFFile<ELFT> &EObj = this->File->getObj();
164   uint8_t *BufEnd = Buf + OutSecOff + Data.size();
165   // Iterate over all relocation sections that apply to this section.
166   for (const Elf_Shdr *RelSec : this->RelocSections) {
167     if (RelSec->sh_type == SHT_RELA)
168       this->relocate(Buf, BufEnd, EObj.relas(RelSec));
169     else
170       this->relocate(Buf, BufEnd, EObj.rels(RelSec));
171   }
172 }
173 
174 template <class ELFT>
175 SplitInputSection<ELFT>::SplitInputSection(
176     ObjectFile<ELFT> *File, const Elf_Shdr *Header,
177     typename InputSectionBase<ELFT>::Kind SectionKind)
178     : InputSectionBase<ELFT>(File, Header, SectionKind) {}
179 
180 template <class ELFT>
181 EHInputSection<ELFT>::EHInputSection(ObjectFile<ELFT> *F,
182                                      const Elf_Shdr *Header)
183     : SplitInputSection<ELFT>(F, Header, InputSectionBase<ELFT>::EHFrame) {}
184 
185 template <class ELFT>
186 bool EHInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
187   return S->SectionKind == InputSectionBase<ELFT>::EHFrame;
188 }
189 
190 template <class ELFT>
191 typename EHInputSection<ELFT>::uintX_t
192 EHInputSection<ELFT>::getOffset(uintX_t Offset) {
193   std::pair<uintX_t, uintX_t> *I = this->getRangeAndSize(Offset).first;
194   uintX_t Base = I->second;
195   if (Base == uintX_t(-1))
196     return -1; // Not in the output
197 
198   uintX_t Addend = Offset - I->first;
199   return Base + Addend;
200 }
201 
202 template <class ELFT>
203 MergeInputSection<ELFT>::MergeInputSection(ObjectFile<ELFT> *F,
204                                            const Elf_Shdr *Header)
205     : SplitInputSection<ELFT>(F, Header, InputSectionBase<ELFT>::Merge) {}
206 
207 template <class ELFT>
208 bool MergeInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
209   return S->SectionKind == InputSectionBase<ELFT>::Merge;
210 }
211 
212 template <class ELFT>
213 std::pair<std::pair<typename ELFFile<ELFT>::uintX_t,
214                     typename ELFFile<ELFT>::uintX_t> *,
215           typename ELFFile<ELFT>::uintX_t>
216 SplitInputSection<ELFT>::getRangeAndSize(uintX_t Offset) {
217   ArrayRef<uint8_t> D = this->getSectionData();
218   StringRef Data((const char *)D.data(), D.size());
219   uintX_t Size = Data.size();
220   if (Offset >= Size)
221     error("Entry is past the end of the section");
222 
223   // Find the element this offset points to.
224   auto I = std::upper_bound(
225       Offsets.begin(), Offsets.end(), Offset,
226       [](const uintX_t &A, const std::pair<uintX_t, uintX_t> &B) {
227         return A < B.first;
228       });
229   uintX_t End = I == Offsets.end() ? Data.size() : I->first;
230   --I;
231   return std::make_pair(&*I, End);
232 }
233 
234 template <class ELFT>
235 typename MergeInputSection<ELFT>::uintX_t
236 MergeInputSection<ELFT>::getOffset(uintX_t Offset) {
237   std::pair<std::pair<uintX_t, uintX_t> *, uintX_t> T =
238       this->getRangeAndSize(Offset);
239   std::pair<uintX_t, uintX_t> *I = T.first;
240   uintX_t End = T.second;
241   uintX_t Start = I->first;
242 
243   // Compute the Addend and if the Base is cached, return.
244   uintX_t Addend = Offset - Start;
245   uintX_t &Base = I->second;
246   if (Base != uintX_t(-1))
247     return Base + Addend;
248 
249   // Map the base to the offset in the output section and cashe it.
250   ArrayRef<uint8_t> D = this->getSectionData();
251   StringRef Data((const char *)D.data(), D.size());
252   StringRef Entry = Data.substr(Start, End - Start);
253   Base =
254       static_cast<MergeOutputSection<ELFT> *>(this->OutSec)->getOffset(Entry);
255   return Base + Addend;
256 }
257 
258 namespace lld {
259 namespace elf2 {
260 template class InputSectionBase<object::ELF32LE>;
261 template class InputSectionBase<object::ELF32BE>;
262 template class InputSectionBase<object::ELF64LE>;
263 template class InputSectionBase<object::ELF64BE>;
264 
265 template class InputSection<object::ELF32LE>;
266 template class InputSection<object::ELF32BE>;
267 template class InputSection<object::ELF64LE>;
268 template class InputSection<object::ELF64BE>;
269 
270 template class EHInputSection<object::ELF32LE>;
271 template class EHInputSection<object::ELF32BE>;
272 template class EHInputSection<object::ELF64LE>;
273 template class EHInputSection<object::ELF64BE>;
274 
275 template class MergeInputSection<object::ELF32LE>;
276 template class MergeInputSection<object::ELF32BE>;
277 template class MergeInputSection<object::ELF64LE>;
278 template class MergeInputSection<object::ELF64BE>;
279 }
280 }
281