| 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 | |
| Simon Atanasyan | 860fbf0 | 2016-02-25 21:33:56 +0000 | [diff] [blame] | 17 | #include "llvm/Support/Endian.h" |
| 18 | |
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 19 | using namespace llvm; |
| 20 | using namespace llvm::ELF; |
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 21 | using namespace llvm::object; |
| Simon Atanasyan | 860fbf0 | 2016-02-25 21:33:56 +0000 | [diff] [blame] | 22 | using namespace llvm::support::endian; |
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 23 | |
| 24 | using namespace lld; |
| Rafael Espindola | e0df00b | 2016-02-28 00:25:54 +0000 | [diff] [blame] | 25 | using namespace lld::elf; |
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 26 | |
| 27 | template <class ELFT> |
| Rui Ueyama | f714955 | 2016-03-11 18:46:51 +0000 | [diff] [blame] | 28 | InputSectionBase<ELFT>::InputSectionBase(elf::ObjectFile<ELFT> *File, |
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 29 | const Elf_Shdr *Header, |
| 30 | Kind SectionKind) |
| Rui Ueyama | 0b28952 | 2016-02-25 18:43:51 +0000 | [diff] [blame] | 31 | : Header(Header), File(File), SectionKind(SectionKind), Repl(this) { |
| Rui Ueyama | 8fc070d | 2016-02-24 00:23:15 +0000 | [diff] [blame] | 32 | // The garbage collector sets sections' Live bits. |
| 33 | // If GC is disabled, all sections are considered live by default. |
| Rui Ueyama | 733153d | 2016-02-24 18:33:35 +0000 | [diff] [blame] | 34 | Live = !Config->GcSections; |
| Rui Ueyama | 5ac5891 | 2016-02-24 00:38:18 +0000 | [diff] [blame] | 35 | |
| 36 | // The ELF spec states that a value of 0 means the section has |
| 37 | // no alignment constraits. |
| Rui Ueyama | 733153d | 2016-02-24 18:33:35 +0000 | [diff] [blame] | 38 | Align = std::max<uintX_t>(Header->sh_addralign, 1); |
| Rui Ueyama | 8fc070d | 2016-02-24 00:23:15 +0000 | [diff] [blame] | 39 | } |
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 40 | |
| Simon Atanasyan | 13f6da1 | 2016-03-31 21:26:23 +0000 | [diff] [blame] | 41 | template <class ELFT> size_t InputSectionBase<ELFT>::getSize() const { |
| 42 | if (auto *D = dyn_cast<InputSection<ELFT>>(this)) |
| 43 | if (D->getThunksSize() > 0) |
| 44 | return D->getThunkOff() + D->getThunksSize(); |
| 45 | return Header->sh_size; |
| 46 | } |
| 47 | |
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 48 | template <class ELFT> StringRef InputSectionBase<ELFT>::getSectionName() const { |
| Rafael Espindola | 75714f6 | 2016-03-03 22:24:39 +0000 | [diff] [blame] | 49 | return check(File->getObj().getSectionName(this->Header)); |
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 50 | } |
| 51 | |
| 52 | template <class ELFT> |
| 53 | ArrayRef<uint8_t> InputSectionBase<ELFT>::getSectionData() const { |
| Rafael Espindola | 75714f6 | 2016-03-03 22:24:39 +0000 | [diff] [blame] | 54 | return check(this->File->getObj().getSectionContents(this->Header)); |
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 55 | } |
| 56 | |
| 57 | template <class ELFT> |
| Rui Ueyama | 9328b2c | 2016-03-14 23:16:09 +0000 | [diff] [blame] | 58 | typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) { |
| Rafael Espindola | db9bf4d | 2015-11-11 16:50:37 +0000 | [diff] [blame] | 59 | switch (SectionKind) { |
| 60 | case Regular: |
| 61 | return cast<InputSection<ELFT>>(this)->OutSecOff + Offset; |
| Rafael Espindola | 0c6a4f1 | 2015-11-11 19:54:14 +0000 | [diff] [blame] | 62 | case EHFrame: |
| 63 | return cast<EHInputSection<ELFT>>(this)->getOffset(Offset); |
| Rafael Espindola | db9bf4d | 2015-11-11 16:50:37 +0000 | [diff] [blame] | 64 | case Merge: |
| 65 | return cast<MergeInputSection<ELFT>>(this)->getOffset(Offset); |
| Simon Atanasyan | 1d7df40 | 2015-12-20 10:57:34 +0000 | [diff] [blame] | 66 | case MipsReginfo: |
| Rui Ueyama | 58a636a | 2016-01-06 22:01:25 +0000 | [diff] [blame] | 67 | // MIPS .reginfo sections are consumed by the linker, |
| 68 | // so it should never be copied to output. |
| 69 | llvm_unreachable("MIPS .reginfo reached writeTo()."); |
| Rafael Espindola | db9bf4d | 2015-11-11 16:50:37 +0000 | [diff] [blame] | 70 | } |
| George Rimar | 777f963 | 2016-03-12 08:31:34 +0000 | [diff] [blame] | 71 | llvm_unreachable("invalid section kind"); |
| Rafael Espindola | db9bf4d | 2015-11-11 16:50:37 +0000 | [diff] [blame] | 72 | } |
| 73 | |
| 74 | template <class ELFT> |
| Rafael Espindola | ccfe3cb | 2016-04-04 14:04:16 +0000 | [diff] [blame] | 75 | typename ELFT::uint |
| 76 | InputSectionBase<ELFT>::getOffset(const DefinedRegular<ELFT> &Sym) { |
| 77 | return getOffset(Sym.Value); |
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 78 | } |
| 79 | |
| Rui Ueyama | 1250464 | 2015-10-27 21:51:13 +0000 | [diff] [blame] | 80 | // Returns a section that Rel relocation is pointing to. |
| 81 | template <class ELFT> |
| 82 | InputSectionBase<ELFT> * |
| Rui Ueyama | d7e4a28 | 2016-02-24 00:23:13 +0000 | [diff] [blame] | 83 | InputSectionBase<ELFT>::getRelocTarget(const Elf_Rel &Rel) const { |
| Rui Ueyama | 1250464 | 2015-10-27 21:51:13 +0000 | [diff] [blame] | 84 | // Global symbol |
| 85 | uint32_t SymIndex = Rel.getSymbol(Config->Mips64EL); |
| Rafael Espindola | 67d72c0 | 2016-03-11 12:06:30 +0000 | [diff] [blame] | 86 | SymbolBody &B = File->getSymbolBody(SymIndex).repl(); |
| 87 | if (auto *D = dyn_cast<DefinedRegular<ELFT>>(&B)) |
| Rui Ueyama | 54945f6 | 2016-03-13 20:34:34 +0000 | [diff] [blame] | 88 | if (D->Section) |
| 89 | return D->Section->Repl; |
| Rui Ueyama | 1250464 | 2015-10-27 21:51:13 +0000 | [diff] [blame] | 90 | return nullptr; |
| 91 | } |
| 92 | |
| 93 | template <class ELFT> |
| 94 | InputSectionBase<ELFT> * |
| Rui Ueyama | d7e4a28 | 2016-02-24 00:23:13 +0000 | [diff] [blame] | 95 | InputSectionBase<ELFT>::getRelocTarget(const Elf_Rela &Rel) const { |
| Rui Ueyama | 1250464 | 2015-10-27 21:51:13 +0000 | [diff] [blame] | 96 | return getRelocTarget(reinterpret_cast<const Elf_Rel &>(Rel)); |
| 97 | } |
| 98 | |
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 99 | template <class ELFT> |
| Rui Ueyama | f714955 | 2016-03-11 18:46:51 +0000 | [diff] [blame] | 100 | InputSection<ELFT>::InputSection(elf::ObjectFile<ELFT> *F, |
| 101 | const Elf_Shdr *Header) |
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 102 | : InputSectionBase<ELFT>(F, Header, Base::Regular) {} |
| 103 | |
| 104 | template <class ELFT> |
| 105 | bool InputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) { |
| 106 | return S->SectionKind == Base::Regular; |
| 107 | } |
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 108 | |
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 109 | template <class ELFT> |
| George Rimar | 58941ee | 2016-02-25 08:23:37 +0000 | [diff] [blame] | 110 | InputSectionBase<ELFT> *InputSection<ELFT>::getRelocatedSection() { |
| 111 | assert(this->Header->sh_type == SHT_RELA || this->Header->sh_type == SHT_REL); |
| 112 | ArrayRef<InputSectionBase<ELFT> *> Sections = this->File->getSections(); |
| 113 | return Sections[this->Header->sh_info]; |
| 114 | } |
| 115 | |
| Simon Atanasyan | 13f6da1 | 2016-03-31 21:26:23 +0000 | [diff] [blame] | 116 | template <class ELFT> void InputSection<ELFT>::addThunk(SymbolBody &Body) { |
| 117 | Body.ThunkIndex = Thunks.size(); |
| 118 | Thunks.push_back(&Body); |
| 119 | } |
| 120 | |
| 121 | template <class ELFT> uint64_t InputSection<ELFT>::getThunkOff() const { |
| 122 | return this->Header->sh_size; |
| 123 | } |
| 124 | |
| 125 | template <class ELFT> uint64_t InputSection<ELFT>::getThunksSize() const { |
| 126 | return Thunks.size() * Target->ThunkSize; |
| 127 | } |
| 128 | |
| George Rimar | 58941ee | 2016-02-25 08:23:37 +0000 | [diff] [blame] | 129 | // This is used for -r. We can't use memcpy to copy relocations because we need |
| 130 | // to update symbol table offset and section index for each relocation. So we |
| 131 | // copy relocations one by one. |
| 132 | template <class ELFT> |
| Rui Ueyama | fc467e7 | 2016-03-13 05:06:50 +0000 | [diff] [blame] | 133 | template <class RelTy> |
| Rafael Espindola | 0f7ccc3 | 2016-04-05 14:47:28 +0000 | [diff] [blame] | 134 | void InputSection<ELFT>::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { |
| George Rimar | 58941ee | 2016-02-25 08:23:37 +0000 | [diff] [blame] | 135 | InputSectionBase<ELFT> *RelocatedSection = getRelocatedSection(); |
| 136 | |
| Rui Ueyama | fc467e7 | 2016-03-13 05:06:50 +0000 | [diff] [blame] | 137 | for (const RelTy &Rel : Rels) { |
| George Rimar | 58941ee | 2016-02-25 08:23:37 +0000 | [diff] [blame] | 138 | uint32_t SymIndex = Rel.getSymbol(Config->Mips64EL); |
| 139 | uint32_t Type = Rel.getType(Config->Mips64EL); |
| Rafael Espindola | 67d72c0 | 2016-03-11 12:06:30 +0000 | [diff] [blame] | 140 | SymbolBody &Body = this->File->getSymbolBody(SymIndex).repl(); |
| George Rimar | 58941ee | 2016-02-25 08:23:37 +0000 | [diff] [blame] | 141 | |
| Rui Ueyama | fc467e7 | 2016-03-13 05:06:50 +0000 | [diff] [blame] | 142 | RelTy *P = reinterpret_cast<RelTy *>(Buf); |
| 143 | Buf += sizeof(RelTy); |
| George Rimar | 58941ee | 2016-02-25 08:23:37 +0000 | [diff] [blame] | 144 | |
| George Rimar | 58941ee | 2016-02-25 08:23:37 +0000 | [diff] [blame] | 145 | P->r_offset = RelocatedSection->getOffset(Rel.r_offset); |
| Rafael Espindola | 67d72c0 | 2016-03-11 12:06:30 +0000 | [diff] [blame] | 146 | P->setSymbolAndType(Body.DynsymIndex, Type, Config->Mips64EL); |
| George Rimar | 58941ee | 2016-02-25 08:23:37 +0000 | [diff] [blame] | 147 | } |
| 148 | } |
| 149 | |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 150 | // Page(Expr) is the page address of the expression Expr, defined |
| 151 | // as (Expr & ~0xFFF). (This applies even if the machine page size |
| 152 | // supported by the platform has a different value.) |
| 153 | static uint64_t getAArch64Page(uint64_t Expr) { |
| 154 | return Expr & (~static_cast<uint64_t>(0xFFF)); |
| Rafael Espindola | 163974d | 2016-03-29 23:05:59 +0000 | [diff] [blame] | 155 | } |
| 156 | |
| George Rimar | 58941ee | 2016-02-25 08:23:37 +0000 | [diff] [blame] | 157 | template <class ELFT> |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 158 | static typename ELFT::uint |
| 159 | getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P, |
| 160 | const SymbolBody &Body, uint8_t *BufLoc, |
| 161 | const elf::ObjectFile<ELFT> &File, RelExpr Expr) { |
| Rafael Espindola | 3f5d634 | 2016-04-18 12:07:13 +0000 | [diff] [blame] | 162 | typedef typename ELFT::uint uintX_t; |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 163 | switch (Expr) { |
| 164 | case R_TLSLD: |
| Rafael Espindola | 3f5d634 | 2016-04-18 12:07:13 +0000 | [diff] [blame] | 165 | return Out<ELFT>::Got->getTlsIndexOff() + A - |
| 166 | Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t); |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 167 | case R_TLSLD_PC: |
| 168 | return Out<ELFT>::Got->getTlsIndexVA() + A - P; |
| 169 | case R_THUNK: |
| 170 | return Body.getThunkVA<ELFT>(); |
| 171 | case R_PPC_TOC: |
| 172 | return getPPC64TocBase() + A; |
| 173 | case R_TLSGD: |
| Rafael Espindola | 3f5d634 | 2016-04-18 12:07:13 +0000 | [diff] [blame] | 174 | return Out<ELFT>::Got->getGlobalDynOffset(Body) + A - |
| 175 | Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t); |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 176 | case R_TLSGD_PC: |
| 177 | return Out<ELFT>::Got->getGlobalDynAddr(Body) + A - P; |
| 178 | case R_PLT: |
| 179 | return Body.getPltVA<ELFT>() + A; |
| 180 | case R_PLT_PC: |
| 181 | case R_PPC_PLT_OPD: |
| 182 | return Body.getPltVA<ELFT>() + A - P; |
| 183 | case R_SIZE: |
| 184 | return Body.getSize<ELFT>() + A; |
| Rafael Espindola | 3f5d634 | 2016-04-18 12:07:13 +0000 | [diff] [blame] | 185 | case R_GOTREL: |
| 186 | return Body.getVA<ELFT>(A) - Out<ELFT>::Got->getVA(); |
| 187 | case R_GOT_FROM_END: |
| 188 | return Body.getGotOffset<ELFT>() + A - |
| 189 | Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t); |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 190 | case R_GOT: |
| 191 | case R_RELAX_TLS_GD_TO_IE: |
| 192 | return Body.getGotVA<ELFT>() + A; |
| 193 | case R_GOT_PAGE_PC: |
| 194 | return getAArch64Page(Body.getGotVA<ELFT>() + A) - getAArch64Page(P); |
| 195 | case R_GOT_PC: |
| 196 | case R_RELAX_TLS_GD_TO_IE_PC: |
| 197 | return Body.getGotVA<ELFT>() + A - P; |
| Rafael Espindola | 3f5d634 | 2016-04-18 12:07:13 +0000 | [diff] [blame] | 198 | case R_GOTONLY_PC: |
| 199 | return Out<ELFT>::Got->getVA() + A - P; |
| 200 | case R_TLS: |
| Rafael Espindola | ece62b9 | 2016-04-18 12:44:33 +0000 | [diff] [blame] | 201 | return Body.getVA<ELFT>(A) - Out<ELFT>::TlsPhdr->p_memsz; |
| Rafael Espindola | 3f5d634 | 2016-04-18 12:07:13 +0000 | [diff] [blame] | 202 | case R_NEG_TLS: |
| 203 | return Out<ELF32LE>::TlsPhdr->p_memsz - Body.getVA<ELFT>(A); |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 204 | case R_ABS: |
| 205 | case R_RELAX_TLS_GD_TO_LE: |
| 206 | case R_RELAX_TLS_IE_TO_LE: |
| 207 | case R_RELAX_TLS_LD_TO_LE: |
| 208 | return Body.getVA<ELFT>(A); |
| 209 | case R_MIPS_GP0: |
| Simon Atanasyan | 604aee1 | 2016-03-13 15:37:38 +0000 | [diff] [blame] | 210 | // We need to adjust SymVA value in case of R_MIPS_GPREL16/32 |
| 211 | // relocations because they use the following expression to calculate |
| 212 | // the relocation's result for local symbol: S + A + GP0 - G. |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 213 | return Body.getVA<ELFT>(A) + File.getMipsGp0(); |
| Rafael Espindola | 58cd5db | 2016-04-19 22:46:03 +0000 | [diff] [blame^] | 214 | case R_GOT_OFF: |
| 215 | return Body.getGotOffset<ELFT>() + A; |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 216 | case R_MIPS_GOT_LOCAL: |
| Simon Atanasyan | 604aee1 | 2016-03-13 15:37:38 +0000 | [diff] [blame] | 217 | // If relocation against MIPS local symbol requires GOT entry, this entry |
| 218 | // should be initialized by 'page address'. This address is high 16-bits |
| Rafael Espindola | abc9a12 | 2016-03-30 12:45:58 +0000 | [diff] [blame] | 219 | // of sum the symbol's value and the addend. |
| Rafael Espindola | 58cd5db | 2016-04-19 22:46:03 +0000 | [diff] [blame^] | 220 | return Out<ELFT>::Got->getMipsLocalPageOffset(Body.getVA<ELFT>(A)); |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 221 | case R_MIPS_GOT: |
| Simon Atanasyan | 604aee1 | 2016-03-13 15:37:38 +0000 | [diff] [blame] | 222 | // For non-local symbols GOT entries should contain their full |
| 223 | // addresses. But if such symbol cannot be preempted, we do not |
| 224 | // have to put them into the "global" part of GOT and use dynamic |
| 225 | // linker to determine their actual addresses. That is why we |
| 226 | // create GOT entries for them in the "local" part of GOT. |
| Rafael Espindola | 58cd5db | 2016-04-19 22:46:03 +0000 | [diff] [blame^] | 227 | return Out<ELFT>::Got->getMipsLocalEntryOffset(Body.getVA<ELFT>(A)); |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 228 | case R_PPC_OPD: { |
| 229 | uint64_t SymVA = Body.getVA<ELFT>(A); |
| 230 | // If we have an undefined weak symbol, we might get here with a symbol |
| 231 | // address of zero. That could overflow, but the code must be unreachable, |
| 232 | // so don't bother doing anything at all. |
| 233 | if (!SymVA) |
| 234 | return 0; |
| 235 | if (Out<ELF64BE>::Opd) { |
| 236 | // If this is a local call, and we currently have the address of a |
| 237 | // function-descriptor, get the underlying code address instead. |
| 238 | uint64_t OpdStart = Out<ELF64BE>::Opd->getVA(); |
| 239 | uint64_t OpdEnd = OpdStart + Out<ELF64BE>::Opd->getSize(); |
| 240 | bool InOpd = OpdStart <= SymVA && SymVA < OpdEnd; |
| 241 | if (InOpd) |
| 242 | SymVA = read64be(&Out<ELF64BE>::OpdBuf[SymVA - OpdStart]); |
| 243 | } |
| 244 | return SymVA - P; |
| 245 | } |
| 246 | case R_PC: |
| 247 | return Body.getVA<ELFT>(A) - P; |
| 248 | case R_PAGE_PC: |
| 249 | return getAArch64Page(Body.getVA<ELFT>(A)) - getAArch64Page(P); |
| 250 | } |
| 251 | llvm_unreachable("Invalid expression"); |
| Simon Atanasyan | 604aee1 | 2016-03-13 15:37:38 +0000 | [diff] [blame] | 252 | } |
| 253 | |
| Rafael Espindola | 69082f0 | 2016-03-18 18:11:26 +0000 | [diff] [blame] | 254 | template <class ELFT> |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 255 | void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd) { |
| 256 | const unsigned Bits = sizeof(uintX_t) * 8; |
| 257 | for (const Relocation &Rel : Relocations) { |
| 258 | uintX_t Offset = Rel.Offset; |
| Rafael Espindola | 69082f0 | 2016-03-18 18:11:26 +0000 | [diff] [blame] | 259 | uint8_t *BufLoc = Buf + Offset; |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 260 | uint32_t Type = Rel.Type; |
| 261 | uintX_t A = Rel.Addend; |
| 262 | |
| Rafael Espindola | 69082f0 | 2016-03-18 18:11:26 +0000 | [diff] [blame] | 263 | uintX_t AddrLoc = OutSec->getVA() + Offset; |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 264 | RelExpr Expr = Rel.Expr; |
| 265 | uint64_t SymVA = SignExtend64<Bits>( |
| 266 | getSymVA<ELFT>(Type, A, AddrLoc, *Rel.Sym, BufLoc, *File, Expr)); |
| Rafael Espindola | 69082f0 | 2016-03-18 18:11:26 +0000 | [diff] [blame] | 267 | |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 268 | if (Expr == R_RELAX_TLS_IE_TO_LE) { |
| 269 | Target->relaxTlsIeToLe(BufLoc, Type, SymVA); |
| 270 | continue; |
| 271 | } |
| 272 | if (Expr == R_RELAX_TLS_LD_TO_LE) { |
| 273 | Target->relaxTlsLdToLe(BufLoc, Type, SymVA); |
| 274 | continue; |
| 275 | } |
| 276 | if (Expr == R_RELAX_TLS_GD_TO_LE) { |
| 277 | Target->relaxTlsGdToLe(BufLoc, Type, SymVA); |
| 278 | continue; |
| 279 | } |
| 280 | if (Expr == R_RELAX_TLS_GD_TO_IE_PC || Expr == R_RELAX_TLS_GD_TO_IE) { |
| 281 | Target->relaxTlsGdToIe(BufLoc, Type, SymVA); |
| Rafael Espindola | 69082f0 | 2016-03-18 18:11:26 +0000 | [diff] [blame] | 282 | continue; |
| 283 | } |
| 284 | |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 285 | if (Expr == R_PPC_PLT_OPD) { |
| 286 | uint32_t Nop = 0x60000000; |
| 287 | if (BufLoc + 8 <= BufEnd && read32be(BufLoc + 4) == Nop) |
| 288 | write32be(BufLoc + 4, 0xe8410028); // ld %r2, 40(%r1) |
| Rafael Espindola | 69082f0 | 2016-03-18 18:11:26 +0000 | [diff] [blame] | 289 | } |
| 290 | |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 291 | Target->relocateOne(BufLoc, Type, SymVA); |
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 292 | } |
| 293 | } |
| 294 | |
| Rui Ueyama | 15ef5e1 | 2015-10-07 19:18:16 +0000 | [diff] [blame] | 295 | template <class ELFT> void InputSection<ELFT>::writeTo(uint8_t *Buf) { |
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 296 | if (this->Header->sh_type == SHT_NOBITS) |
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 297 | return; |
| George Rimar | 58941ee | 2016-02-25 08:23:37 +0000 | [diff] [blame] | 298 | ELFFile<ELFT> &EObj = this->File->getObj(); |
| 299 | |
| Rui Ueyama | f43d150 | 2016-03-30 00:43:49 +0000 | [diff] [blame] | 300 | // If -r is given, then an InputSection may be a relocation section. |
| George Rimar | 58941ee | 2016-02-25 08:23:37 +0000 | [diff] [blame] | 301 | if (this->Header->sh_type == SHT_RELA) { |
| Rui Ueyama | f43d150 | 2016-03-30 00:43:49 +0000 | [diff] [blame] | 302 | copyRelocations(Buf + OutSecOff, EObj.relas(this->Header)); |
| George Rimar | 58941ee | 2016-02-25 08:23:37 +0000 | [diff] [blame] | 303 | return; |
| 304 | } |
| 305 | if (this->Header->sh_type == SHT_REL) { |
| Rui Ueyama | f43d150 | 2016-03-30 00:43:49 +0000 | [diff] [blame] | 306 | copyRelocations(Buf + OutSecOff, EObj.rels(this->Header)); |
| George Rimar | 58941ee | 2016-02-25 08:23:37 +0000 | [diff] [blame] | 307 | return; |
| 308 | } |
| 309 | |
| Rui Ueyama | f43d150 | 2016-03-30 00:43:49 +0000 | [diff] [blame] | 310 | // Copy section contents from source object file to output file. |
| 311 | ArrayRef<uint8_t> Data = this->getSectionData(); |
| Rui Ueyama | 55c3f89 | 2015-10-15 01:58:40 +0000 | [diff] [blame] | 312 | memcpy(Buf + OutSecOff, Data.data(), Data.size()); |
| Rafael Espindola | 4ea0021 | 2015-09-21 22:01:00 +0000 | [diff] [blame] | 313 | |
| Rafael Espindola | 69082f0 | 2016-03-18 18:11:26 +0000 | [diff] [blame] | 314 | // Iterate over all relocation sections that apply to this section. |
| Rui Ueyama | f43d150 | 2016-03-30 00:43:49 +0000 | [diff] [blame] | 315 | uint8_t *BufEnd = Buf + OutSecOff + Data.size(); |
| Rafael Espindola | 22ef956 | 2016-04-13 01:40:19 +0000 | [diff] [blame] | 316 | this->relocate(Buf, BufEnd); |
| Simon Atanasyan | 13f6da1 | 2016-03-31 21:26:23 +0000 | [diff] [blame] | 317 | |
| 318 | // The section might have a data/code generated by the linker and need |
| 319 | // to be written after the section. Usually these are thunks - small piece |
| 320 | // of code used to jump between "incompatible" functions like PIC and non-PIC |
| 321 | // or if the jump target too far and its address does not fit to the short |
| 322 | // jump istruction. |
| 323 | if (!Thunks.empty()) { |
| 324 | Buf += OutSecOff + getThunkOff(); |
| 325 | for (const SymbolBody *S : Thunks) { |
| 326 | Target->writeThunk(Buf, S->getVA<ELFT>()); |
| 327 | Buf += Target->ThunkSize; |
| 328 | } |
| 329 | } |
| Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 330 | } |
| 331 | |
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 332 | template <class ELFT> |
| Rui Ueyama | 0b28952 | 2016-02-25 18:43:51 +0000 | [diff] [blame] | 333 | void InputSection<ELFT>::replace(InputSection<ELFT> *Other) { |
| 334 | this->Align = std::max(this->Align, Other->Align); |
| 335 | Other->Repl = this->Repl; |
| 336 | Other->Live = false; |
| 337 | } |
| 338 | |
| 339 | template <class ELFT> |
| Rafael Espindola | 0c6a4f1 | 2015-11-11 19:54:14 +0000 | [diff] [blame] | 340 | SplitInputSection<ELFT>::SplitInputSection( |
| Rui Ueyama | f714955 | 2016-03-11 18:46:51 +0000 | [diff] [blame] | 341 | elf::ObjectFile<ELFT> *File, const Elf_Shdr *Header, |
| Rafael Espindola | 0c6a4f1 | 2015-11-11 19:54:14 +0000 | [diff] [blame] | 342 | typename InputSectionBase<ELFT>::Kind SectionKind) |
| 343 | : InputSectionBase<ELFT>(File, Header, SectionKind) {} |
| 344 | |
| 345 | template <class ELFT> |
| Rui Ueyama | f714955 | 2016-03-11 18:46:51 +0000 | [diff] [blame] | 346 | EHInputSection<ELFT>::EHInputSection(elf::ObjectFile<ELFT> *F, |
| Rafael Espindola | 0c6a4f1 | 2015-11-11 19:54:14 +0000 | [diff] [blame] | 347 | const Elf_Shdr *Header) |
| Rui Ueyama | da73532 | 2015-12-24 10:08:54 +0000 | [diff] [blame] | 348 | : SplitInputSection<ELFT>(F, Header, InputSectionBase<ELFT>::EHFrame) { |
| 349 | // Mark .eh_frame sections as live by default because there are |
| 350 | // usually no relocations that point to .eh_frames. Otherwise, |
| George Rimar | e9e1d32 | 2016-02-18 15:17:01 +0000 | [diff] [blame] | 351 | // the garbage collector would drop all .eh_frame sections. |
| Rui Ueyama | da73532 | 2015-12-24 10:08:54 +0000 | [diff] [blame] | 352 | this->Live = true; |
| 353 | } |
| Rafael Espindola | 0c6a4f1 | 2015-11-11 19:54:14 +0000 | [diff] [blame] | 354 | |
| 355 | template <class ELFT> |
| 356 | bool EHInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) { |
| 357 | return S->SectionKind == InputSectionBase<ELFT>::EHFrame; |
| 358 | } |
| 359 | |
| 360 | template <class ELFT> |
| Rui Ueyama | 9328b2c | 2016-03-14 23:16:09 +0000 | [diff] [blame] | 361 | typename ELFT::uint EHInputSection<ELFT>::getOffset(uintX_t Offset) { |
| George Rimar | 6ab275c | 2015-12-25 09:51:42 +0000 | [diff] [blame] | 362 | // The file crtbeginT.o has relocations pointing to the start of an empty |
| 363 | // .eh_frame that is known to be the first in the link. It does that to |
| 364 | // identify the start of the output .eh_frame. Handle this special case. |
| 365 | if (this->getSectionHdr()->sh_size == 0) |
| 366 | return Offset; |
| Rafael Espindola | 0c6a4f1 | 2015-11-11 19:54:14 +0000 | [diff] [blame] | 367 | std::pair<uintX_t, uintX_t> *I = this->getRangeAndSize(Offset).first; |
| 368 | uintX_t Base = I->second; |
| George Rimar | 4b40ebc | 2015-11-13 13:44:59 +0000 | [diff] [blame] | 369 | if (Base == uintX_t(-1)) |
| Rafael Espindola | 0c6a4f1 | 2015-11-11 19:54:14 +0000 | [diff] [blame] | 370 | return -1; // Not in the output |
| 371 | |
| 372 | uintX_t Addend = Offset - I->first; |
| 373 | return Base + Addend; |
| 374 | } |
| 375 | |
| 376 | template <class ELFT> |
| Rafael Espindola | 36a73d2 | 2016-03-11 16:32:46 +0000 | [diff] [blame] | 377 | MergeInputSection<ELFT>::MergeInputSection(elf::ObjectFile<ELFT> *F, |
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 378 | const Elf_Shdr *Header) |
| Rafael Espindola | 0c6a4f1 | 2015-11-11 19:54:14 +0000 | [diff] [blame] | 379 | : SplitInputSection<ELFT>(F, Header, InputSectionBase<ELFT>::Merge) {} |
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 380 | |
| 381 | template <class ELFT> |
| 382 | bool MergeInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) { |
| Rafael Espindola | 0c6a4f1 | 2015-11-11 19:54:14 +0000 | [diff] [blame] | 383 | return S->SectionKind == InputSectionBase<ELFT>::Merge; |
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 384 | } |
| 385 | |
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 386 | template <class ELFT> |
| Rui Ueyama | 9328b2c | 2016-03-14 23:16:09 +0000 | [diff] [blame] | 387 | std::pair<std::pair<typename ELFT::uint, typename ELFT::uint> *, |
| 388 | typename ELFT::uint> |
| Rafael Espindola | 0c6a4f1 | 2015-11-11 19:54:14 +0000 | [diff] [blame] | 389 | SplitInputSection<ELFT>::getRangeAndSize(uintX_t Offset) { |
| Rafael Espindola | f82ed2a | 2015-10-24 22:51:01 +0000 | [diff] [blame] | 390 | ArrayRef<uint8_t> D = this->getSectionData(); |
| Rui Ueyama | 7ba639b | 2015-10-25 16:25:04 +0000 | [diff] [blame] | 391 | StringRef Data((const char *)D.data(), D.size()); |
| Rafael Espindola | f82ed2a | 2015-10-24 22:51:01 +0000 | [diff] [blame] | 392 | uintX_t Size = Data.size(); |
| 393 | if (Offset >= Size) |
| George Rimar | 777f963 | 2016-03-12 08:31:34 +0000 | [diff] [blame] | 394 | fatal("entry is past the end of the section"); |
| Rafael Espindola | f82ed2a | 2015-10-24 22:51:01 +0000 | [diff] [blame] | 395 | |
| 396 | // Find the element this offset points to. |
| 397 | auto I = std::upper_bound( |
| Rafael Espindola | d04c12a | 2015-11-11 15:20:45 +0000 | [diff] [blame] | 398 | Offsets.begin(), Offsets.end(), Offset, |
| Rafael Espindola | 1fe2d1e | 2015-11-11 15:55:00 +0000 | [diff] [blame] | 399 | [](const uintX_t &A, const std::pair<uintX_t, uintX_t> &B) { |
| Rafael Espindola | f82ed2a | 2015-10-24 22:51:01 +0000 | [diff] [blame] | 400 | return A < B.first; |
| 401 | }); |
| Rafael Espindola | 3299499 | 2015-11-11 15:40:37 +0000 | [diff] [blame] | 402 | uintX_t End = I == Offsets.end() ? Data.size() : I->first; |
| Rafael Espindola | f82ed2a | 2015-10-24 22:51:01 +0000 | [diff] [blame] | 403 | --I; |
| Rafael Espindola | 0c6a4f1 | 2015-11-11 19:54:14 +0000 | [diff] [blame] | 404 | return std::make_pair(&*I, End); |
| 405 | } |
| 406 | |
| 407 | template <class ELFT> |
| Rui Ueyama | 9328b2c | 2016-03-14 23:16:09 +0000 | [diff] [blame] | 408 | typename ELFT::uint MergeInputSection<ELFT>::getOffset(uintX_t Offset) { |
| George Rimar | 4b40ebc | 2015-11-13 13:44:59 +0000 | [diff] [blame] | 409 | std::pair<std::pair<uintX_t, uintX_t> *, uintX_t> T = |
| Rafael Espindola | 0c6a4f1 | 2015-11-11 19:54:14 +0000 | [diff] [blame] | 410 | this->getRangeAndSize(Offset); |
| 411 | std::pair<uintX_t, uintX_t> *I = T.first; |
| 412 | uintX_t End = T.second; |
| Rafael Espindola | f82ed2a | 2015-10-24 22:51:01 +0000 | [diff] [blame] | 413 | uintX_t Start = I->first; |
| 414 | |
| 415 | // Compute the Addend and if the Base is cached, return. |
| 416 | uintX_t Addend = Offset - Start; |
| Rafael Espindola | 3299499 | 2015-11-11 15:40:37 +0000 | [diff] [blame] | 417 | uintX_t &Base = I->second; |
| Rafael Espindola | 1fe2d1e | 2015-11-11 15:55:00 +0000 | [diff] [blame] | 418 | if (Base != uintX_t(-1)) |
| Rafael Espindola | f82ed2a | 2015-10-24 22:51:01 +0000 | [diff] [blame] | 419 | return Base + Addend; |
| 420 | |
| Hal Finkel | f950595 | 2015-11-25 23:54:53 +0000 | [diff] [blame] | 421 | // Map the base to the offset in the output section and cache it. |
| Rafael Espindola | 0c6a4f1 | 2015-11-11 19:54:14 +0000 | [diff] [blame] | 422 | ArrayRef<uint8_t> D = this->getSectionData(); |
| 423 | StringRef Data((const char *)D.data(), D.size()); |
| Rafael Espindola | f82ed2a | 2015-10-24 22:51:01 +0000 | [diff] [blame] | 424 | StringRef Entry = Data.substr(Start, End - Start); |
| 425 | Base = |
| 426 | static_cast<MergeOutputSection<ELFT> *>(this->OutSec)->getOffset(Entry); |
| 427 | return Base + Addend; |
| Rafael Espindola | 5d83ccd | 2015-08-13 19:18:30 +0000 | [diff] [blame] | 428 | } |
| 429 | |
| Simon Atanasyan | 1d7df40 | 2015-12-20 10:57:34 +0000 | [diff] [blame] | 430 | template <class ELFT> |
| Rui Ueyama | f714955 | 2016-03-11 18:46:51 +0000 | [diff] [blame] | 431 | MipsReginfoInputSection<ELFT>::MipsReginfoInputSection(elf::ObjectFile<ELFT> *F, |
| Rui Ueyama | 70eed36 | 2016-01-06 22:42:43 +0000 | [diff] [blame] | 432 | const Elf_Shdr *Hdr) |
| 433 | : InputSectionBase<ELFT>(F, Hdr, InputSectionBase<ELFT>::MipsReginfo) { |
| 434 | // Initialize this->Reginfo. |
| Simon Atanasyan | 1d7df40 | 2015-12-20 10:57:34 +0000 | [diff] [blame] | 435 | ArrayRef<uint8_t> D = this->getSectionData(); |
| Rui Ueyama | 70eed36 | 2016-01-06 22:42:43 +0000 | [diff] [blame] | 436 | if (D.size() != sizeof(Elf_Mips_RegInfo<ELFT>)) |
| George Rimar | 777f963 | 2016-03-12 08:31:34 +0000 | [diff] [blame] | 437 | fatal("invalid size of .reginfo section"); |
| Rui Ueyama | 70eed36 | 2016-01-06 22:42:43 +0000 | [diff] [blame] | 438 | Reginfo = reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>(D.data()); |
| Simon Atanasyan | 57830b6 | 2015-12-25 13:02:13 +0000 | [diff] [blame] | 439 | } |
| 440 | |
| Simon Atanasyan | 1d7df40 | 2015-12-20 10:57:34 +0000 | [diff] [blame] | 441 | template <class ELFT> |
| 442 | bool MipsReginfoInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) { |
| 443 | return S->SectionKind == InputSectionBase<ELFT>::MipsReginfo; |
| 444 | } |
| 445 | |
| Rafael Espindola | e0df00b | 2016-02-28 00:25:54 +0000 | [diff] [blame] | 446 | template class elf::InputSectionBase<ELF32LE>; |
| 447 | template class elf::InputSectionBase<ELF32BE>; |
| 448 | template class elf::InputSectionBase<ELF64LE>; |
| 449 | template class elf::InputSectionBase<ELF64BE>; |
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 450 | |
| Rafael Espindola | e0df00b | 2016-02-28 00:25:54 +0000 | [diff] [blame] | 451 | template class elf::InputSection<ELF32LE>; |
| 452 | template class elf::InputSection<ELF32BE>; |
| 453 | template class elf::InputSection<ELF64LE>; |
| 454 | template class elf::InputSection<ELF64BE>; |
| Rafael Espindola | c159c96 | 2015-10-19 21:00:02 +0000 | [diff] [blame] | 455 | |
| Rafael Espindola | e0df00b | 2016-02-28 00:25:54 +0000 | [diff] [blame] | 456 | template class elf::EHInputSection<ELF32LE>; |
| 457 | template class elf::EHInputSection<ELF32BE>; |
| 458 | template class elf::EHInputSection<ELF64LE>; |
| 459 | template class elf::EHInputSection<ELF64BE>; |
| Rafael Espindola | 0c6a4f1 | 2015-11-11 19:54:14 +0000 | [diff] [blame] | 460 | |
| Rafael Espindola | e0df00b | 2016-02-28 00:25:54 +0000 | [diff] [blame] | 461 | template class elf::MergeInputSection<ELF32LE>; |
| 462 | template class elf::MergeInputSection<ELF32BE>; |
| 463 | template class elf::MergeInputSection<ELF64LE>; |
| 464 | template class elf::MergeInputSection<ELF64BE>; |
| Simon Atanasyan | 1d7df40 | 2015-12-20 10:57:34 +0000 | [diff] [blame] | 465 | |
| Rafael Espindola | e0df00b | 2016-02-28 00:25:54 +0000 | [diff] [blame] | 466 | template class elf::MipsReginfoInputSection<ELF32LE>; |
| 467 | template class elf::MipsReginfoInputSection<ELF32BE>; |
| 468 | template class elf::MipsReginfoInputSection<ELF64LE>; |
| 469 | template class elf::MipsReginfoInputSection<ELF64BE>; |