| 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 | 53d5cea | 2015-09-21 17:47:00 +0000 | [diff] [blame] | 25 | InputSection<ELFT>::InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header) | 
| Michael J. Spencer | 67bc8d6 | 2015-08-27 23:15:56 +0000 | [diff] [blame] | 26 | : File(F), Header(Header) {} | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 27 |  | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 28 | template <class ELFT> | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 29 | template <bool isRela> | 
|  | 30 | void InputSection<ELFT>::relocate( | 
| Hal Finkel | 87bbd5f | 2015-10-12 21:19:18 +0000 | [diff] [blame] | 31 | uint8_t *Buf, uint8_t *BufEnd, | 
|  | 32 | iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels, | 
| Rui Ueyama | 15ef5e1 | 2015-10-07 19:18:16 +0000 | [diff] [blame] | 33 | const ObjectFile<ELFT> &File, uintX_t BaseAddr) { | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 34 | typedef Elf_Rel_Impl<ELFT, isRela> RelType; | 
| Rafael Espindola | e1901cc | 2015-09-24 15:11:50 +0000 | [diff] [blame] | 35 | bool IsMips64EL = File.getObj().isMips64EL(); | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 36 | for (const RelType &RI : Rels) { | 
|  | 37 | uint32_t SymIndex = RI.getSymbol(IsMips64EL); | 
|  | 38 | uint32_t Type = RI.getType(IsMips64EL); | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 39 |  | 
|  | 40 | // Handle relocations for local symbols -- they never get | 
|  | 41 | // resolved so we don't allocate a SymbolBody. | 
|  | 42 | const Elf_Shdr *SymTab = File.getSymbolTable(); | 
|  | 43 | if (SymIndex < SymTab->sh_info) { | 
| Rui Ueyama | bb3c336 | 2015-10-12 20:28:23 +0000 | [diff] [blame] | 44 | uintX_t SymVA = getLocalRelTarget(File, RI); | 
| Hal Finkel | 87bbd5f | 2015-10-12 21:19:18 +0000 | [diff] [blame] | 45 | Target->relocateOne(Buf, BufEnd, reinterpret_cast<const void *>(&RI), | 
|  | 46 | Type, BaseAddr, SymVA); | 
| Rui Ueyama | bb3c336 | 2015-10-12 20:28:23 +0000 | [diff] [blame] | 47 | continue; | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 48 | } | 
|  | 49 |  | 
| Rui Ueyama | bb3c336 | 2015-10-12 20:28:23 +0000 | [diff] [blame] | 50 | SymbolBody &Body = *File.getSymbolBody(SymIndex)->repl(); | 
|  | 51 | uintX_t SymVA = getSymVA<ELFT>(Body); | 
|  | 52 | if (Target->relocNeedsPlt(Type, Body)) { | 
|  | 53 | SymVA = Out<ELFT>::Plt->getEntryAddr(Body); | 
| Rafael Espindola | 227556e | 2015-10-14 16:15:46 +0000 | [diff] [blame] | 54 | Type = Target->getPLTRefReloc(Type); | 
| Rui Ueyama | bb3c336 | 2015-10-12 20:28:23 +0000 | [diff] [blame] | 55 | } else if (Target->relocNeedsGot(Type, Body)) { | 
|  | 56 | SymVA = Out<ELFT>::Got->getEntryAddr(Body); | 
|  | 57 | Type = Target->getGotRefReloc(); | 
|  | 58 | } else if (Target->relocPointsToGot(Type)) { | 
|  | 59 | SymVA = Out<ELFT>::Got->getVA(); | 
|  | 60 | Type = Target->getPCRelReloc(); | 
|  | 61 | } else if (isa<SharedSymbol<ELFT>>(Body)) { | 
|  | 62 | continue; | 
|  | 63 | } | 
| Hal Finkel | 87bbd5f | 2015-10-12 21:19:18 +0000 | [diff] [blame] | 64 | Target->relocateOne(Buf, BufEnd, reinterpret_cast<const void *>(&RI), Type, | 
| Rui Ueyama | af21d92 | 2015-10-08 20:06:07 +0000 | [diff] [blame] | 65 | BaseAddr, SymVA); | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 66 | } | 
|  | 67 | } | 
|  | 68 |  | 
| Rui Ueyama | 15ef5e1 | 2015-10-07 19:18:16 +0000 | [diff] [blame] | 69 | template <class ELFT> void InputSection<ELFT>::writeTo(uint8_t *Buf) { | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 70 | if (Header->sh_type == SHT_NOBITS) | 
|  | 71 | return; | 
|  | 72 | // Copy section contents from source object file to output file. | 
| Rafael Espindola | e1901cc | 2015-09-24 15:11:50 +0000 | [diff] [blame] | 73 | ArrayRef<uint8_t> Data = *File->getObj().getSectionContents(Header); | 
| Rui Ueyama | 55c3f89 | 2015-10-15 01:58:40 +0000 | [diff] [blame^] | 74 | memcpy(Buf + OutSecOff, Data.data(), Data.size()); | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 75 |  | 
| Rafael Espindola | e1901cc | 2015-09-24 15:11:50 +0000 | [diff] [blame] | 76 | ELFFile<ELFT> &EObj = File->getObj(); | 
| Rui Ueyama | 55c3f89 | 2015-10-15 01:58:40 +0000 | [diff] [blame^] | 77 | uint8_t *Base = Buf + OutSecOff; | 
|  | 78 | uintX_t BaseAddr = OutSec->getVA() + OutSecOff; | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 79 | // Iterate over all relocation sections that apply to this section. | 
|  | 80 | for (const Elf_Shdr *RelSec : RelocSections) { | 
|  | 81 | if (RelSec->sh_type == SHT_RELA) | 
| Hal Finkel | 87bbd5f | 2015-10-12 21:19:18 +0000 | [diff] [blame] | 82 | relocate(Base, Base + Data.size(), EObj.relas(RelSec), *File, BaseAddr); | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 83 | else | 
| Hal Finkel | 87bbd5f | 2015-10-12 21:19:18 +0000 | [diff] [blame] | 84 | relocate(Base, Base + Data.size(), EObj.rels(RelSec), *File, BaseAddr); | 
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 85 | } | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 86 | } | 
|  | 87 |  | 
| Rafael Espindola | 53d5cea | 2015-09-21 17:47:00 +0000 | [diff] [blame] | 88 | template <class ELFT> StringRef InputSection<ELFT>::getSectionName() const { | 
| Rafael Espindola | e1901cc | 2015-09-24 15:11:50 +0000 | [diff] [blame] | 89 | ErrorOr<StringRef> Name = File->getObj().getSectionName(Header); | 
| Rafael Espindola | 5d83ccd | 2015-08-13 19:18:30 +0000 | [diff] [blame] | 90 | error(Name); | 
|  | 91 | return *Name; | 
|  | 92 | } | 
|  | 93 |  | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 94 | namespace lld { | 
|  | 95 | namespace elf2 { | 
| Rafael Espindola | 53d5cea | 2015-09-21 17:47:00 +0000 | [diff] [blame] | 96 | template class InputSection<object::ELF32LE>; | 
|  | 97 | template class InputSection<object::ELF32BE>; | 
|  | 98 | template class InputSection<object::ELF64LE>; | 
|  | 99 | template class InputSection<object::ELF64BE>; | 
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 100 | } | 
|  | 101 | } |