Lines Matching +full:partitions +full:- +full:table +full:- +full:offset

1 //===- SyntheticSections.cpp ----------------------------------------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file contains linker-synthesized sections. Currently,
14 //===----------------------------------------------------------------------===//
63 return config->is64 ? read64(buf) : read32(buf); in readUint()
67 if (config->is64) in writeUint()
87 // With this feature, you can identify LLD-generated binaries easily
88 // by "readelf --string-dump .comment <file>".
93 sec->splitIntoPieces(); in createCommentSection()
102 this->entsize = sizeof(Elf_Mips_ABIFlags); in MipsAbiFlagsSection()
115 if (sec->type != SHT_MIPS_ABIFLAGS) in create()
117 sec->markDead(); in create()
120 std::string filename = toString(sec->file); in create()
121 const size_t size = sec->content().size(); in create()
131 reinterpret_cast<const Elf_Mips_ABIFlags *>(sec->content().data()); in create()
132 if (s->version != 0) { in create()
134 Twine(s->version)); in create()
140 flags.isa_level = std::max(flags.isa_level, s->isa_level); in create()
141 flags.isa_rev = std::max(flags.isa_rev, s->isa_rev); in create()
142 flags.isa_ext = std::max(flags.isa_ext, s->isa_ext); in create()
143 flags.gpr_size = std::max(flags.gpr_size, s->gpr_size); in create()
144 flags.cpr1_size = std::max(flags.cpr1_size, s->cpr1_size); in create()
145 flags.cpr2_size = std::max(flags.cpr2_size, s->cpr2_size); in create()
146 flags.ases |= s->ases; in create()
147 flags.flags1 |= s->flags1; in create()
148 flags.flags2 |= s->flags2; in create()
149 flags.fp_abi = elf::getMipsFpAbiFlag(flags.fp_abi, s->fp_abi, filename); in create()
162 this->entsize = sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo); in MipsOptionsSection()
167 options->kind = ODK_REGINFO; in writeTo()
168 options->size = getSize(); in writeTo()
170 if (!config->relocatable) in writeTo()
171 reginfo.ri_gp_value = in.mipsGot->getGp(); in writeTo()
183 if (sec->type == SHT_MIPS_OPTIONS) in create()
191 sec->markDead(); in create()
193 std::string filename = toString(sec->file); in create()
194 ArrayRef<uint8_t> d = sec->content(); in create()
203 if (opt->kind == ODK_REGINFO) { in create()
204 reginfo.ri_gprmask |= opt->getRegInfo().ri_gprmask; in create()
205 sec->getFile<ELFT>()->mipsGp0 = opt->getRegInfo().ri_gp_value; in create()
209 if (!opt->size) in create()
211 d = d.slice(opt->size); in create()
223 this->entsize = sizeof(Elf_Mips_RegInfo); in MipsReginfoSection()
227 if (!config->relocatable) in writeTo()
228 reginfo.ri_gp_value = in.mipsGot->getGp(); in writeTo()
240 if (sec->type == SHT_MIPS_REGINFO) in create()
248 sec->markDead(); in create()
250 if (sec->content().size() != sizeof(Elf_Mips_RegInfo)) { in create()
251 error(toString(sec->file) + ": invalid size of .reginfo section"); in create()
255 auto *r = reinterpret_cast<const Elf_Mips_RegInfo *>(sec->content().data()); in create()
256 reginfo.ri_gprmask |= r->ri_gprmask; in create()
257 sec->getFile<ELFT>()->mipsGp0 = r->ri_gp_value; in create()
265 StringRef s = saver().save(config->dynamicLinker); in createInterpSection()
277 in.symTab->addSymbol(s); in addSyntheticLocal()
279 if (config->emachine == EM_ARM && !config->isLE && config->armBe8 && in addSyntheticLocal()
289 switch (config->buildId) { in getHashSize()
298 return config->buildIdVector.size(); in getHashSize()
304 // This class represents a linker-synthesized .note.gnu.property section.
318 config->wordsize, ".note.gnu.property") {} in GnuPropertySection()
322 write32(buf + 4, getSize() - 16); // Content size in writeTo()
326 uint32_t featureAndType = config->emachine == EM_AARCH64 in writeTo()
330 unsigned offset = 16; in writeTo() local
331 if (config->andFeatures != 0) { in writeTo()
332 write32(buf + offset + 0, featureAndType); // Feature type in writeTo()
333 write32(buf + offset + 4, 4); // Feature size in writeTo()
334 write32(buf + offset + 8, config->andFeatures); // Feature flags in writeTo()
335 if (config->is64) in writeTo()
336 write32(buf + offset + 12, 0); // Padding in writeTo()
337 offset += 16; in writeTo()
341 write32(buf + offset + 0, GNU_PROPERTY_AARCH64_FEATURE_PAUTH); in writeTo()
342 write32(buf + offset + 4, ctx.aarch64PauthAbiCoreInfo.size()); in writeTo()
343 memcpy(buf + offset + 8, ctx.aarch64PauthAbiCoreInfo.data(), in writeTo()
350 if (config->andFeatures != 0) in getSize()
351 contentSize += config->is64 ? 16 : 12; in getSize()
359 : SyntheticSection(SHF_ALLOC, SHT_NOTE, 4, ".note.gnu.build-id"), in BuildIdSection()
377 this->bss = true; in BssSection()
378 this->size = size; in BssSection()
391 if (firstRelI != (unsigned)-1) in addCie()
392 personality = &cie.sec->file->getRelocTargetSym(rels[firstRelI]); in addCie()
400 rec->cie = &cie; in addCie()
406 // There is one FDE per function. Returns a non-null pointer to the function
415 // ld.gold with -r. ld.gold may discard only functions and leave their in isFdeLive()
418 if (firstRelI == (unsigned)-1) in isFdeLive()
422 Symbol &b = sec->file->getRelocTargetSym(rel); in isFdeLive()
424 // FDEs for garbage-collected or merged-by-ICF sections, or sections in in isFdeLive()
427 if (!d->folded && d->section && d->section->partition == partition) in isFdeLive()
439 for (EhSectionPiece &cie : sec->cies) in addRecords()
441 for (EhSectionPiece &fde : sec->fdes) { in addRecords()
443 CieRecord *rec = offsetToCie[fde.inputOff + 4 - id]; in addRecords()
449 rec->fdes.push_back(&fde); in addRecords()
456 if (!sec->isLive()) in addSectionAux()
459 sec->template relsOrRelas<ELFT>(/*supportsCrel=*/false); in addSectionAux()
477 if (!ciesWithLSDA.contains(fde.inputOff + 4 - id)) in iterateFDEWithLSDAAux()
482 if (auto *s = dyn_cast_or_null<InputSection>(d->section)) in iterateFDEWithLSDAAux()
494 sec->template relsOrRelas<ELFT>(/*supportsCrel=*/false); in iterateFDEWithLSDA()
504 // Fix the size field. -4 since size does not include the size field itself. in writeCieFde()
505 write32(buf, d.size() - 4); in writeCieFde()
509 assert(!this->size); // Not finalized. in finalizeContents()
511 switch (config->ekind) { in finalizeContents()
534 rec->cie->outputOff = off; in finalizeContents()
535 off += rec->cie->size; in finalizeContents()
537 for (EhSectionPiece *fde : rec->fdes) { in finalizeContents()
538 fde->outputOff = off; in finalizeContents()
539 off += fde->size; in finalizeContents()
544 // Call Frame Information records. glibc unwind-dw2-fde.c in finalizeContents()
549 this->size = off; in finalizeContents()
552 // Returns data for .eh_frame_hdr. .eh_frame_hdr is a binary search table
556 uint8_t *buf = Out::bufferStart + getParent()->offset + outSecOff; in getFdeData()
559 uint64_t va = getPartition().ehFrameHdr->getVA(); in getFdeData()
561 uint8_t enc = getFdeEncoding(rec->cie); in getFdeData()
562 for (EhSectionPiece *fde : rec->fdes) { in getFdeData()
563 uint64_t pc = getFdePc(buf, fde->outputOff, enc); in getFdeData()
564 uint64_t fdeVA = getParent()->addr + fde->outputOff; in getFdeData()
565 if (!isInt<32>(pc - va)) { in getFdeData()
566 errorOrWarn(toString(fde->sec) + ": PC offset is too large: 0x" + in getFdeData()
567 Twine::utohexstr(pc - va)); in getFdeData()
570 ret.push_back({uint32_t(pc - va), uint32_t(fdeVA - va)}); in getFdeData()
613 // stored at FDE + 8 byte. And this offset is within in getFdePc()
618 return config->is64 ? addr : uint32_t(addr); in getFdePc()
620 return addr + getParent()->addr + off + outSecOff; in getFdePc()
627 size_t cieOffset = rec->cie->outputOff; in writeTo()
628 writeCieFde(buf + cieOffset, rec->cie->data()); in writeTo()
630 for (EhSectionPiece *fde : rec->fdes) { in writeTo()
631 size_t off = fde->outputOff; in writeTo()
632 writeCieFde(buf + off, fde->data()); in writeTo()
634 // FDE's second word should have the offset to an associated CIE. in writeTo()
636 write32(buf + off + 4, off + 4 - cieOffset); in writeTo()
644 target->relocateAlloc(*s, buf); in writeTo()
646 if (getPartition().ehFrameHdr && getPartition().ehFrameHdr->getParent()) in writeTo()
647 getPartition().ehFrameHdr->write(); in writeTo()
652 target->gotEntrySize, ".got") { in GotSection()
653 numEntries = target->gotHeaderEntriesNum; in GotSection()
658 assert(sym.auxIdx == symAux.size() - 1); in addEntry()
663 assert(sym.auxIdx == symAux.size() - 1); in addTlsDescEntry()
670 assert(sym.auxIdx == symAux.size() - 1); in addDynTlsEntry()
677 // Reserves TLS entries for a TLS module ID and a TLS block offset.
680 if (tlsIndexOff != uint32_t(-1)) in addTlsIndex()
682 tlsIndexOff = numEntries * config->wordsize; in addTlsIndex()
688 return sym.getTlsDescIdx() * config->wordsize; in getTlsDescOffset()
696 return this->getVA() + b.getTlsGdIdx() * config->wordsize; in getGlobalDynAddr()
700 return b.getTlsGdIdx() * config->wordsize; in getGlobalDynOffset()
704 if (config->emachine == EM_PPC64 && in finalizeContents()
705 numEntries <= target->gotHeaderEntriesNum && !ElfSym::globalOffsetTable) in finalizeContents()
708 size = numEntries * config->wordsize; in finalizeContents()
714 return hasGotOffRel || numEntries > target->gotHeaderEntriesNum; in isNeeded()
721 target->writeGotHeader(buf); in writeTo()
722 target->relocateAlloc(*this, buf); in writeTo()
779 // If there are relocation-only entries in the GOT, TLS entries in getIndexedEntriesNum()
781 // by 16-bit index so count both reloc-only and TLS entries. in getIndexedEntriesNum()
788 if (f.mipsGotIndex == uint32_t(-1)) { in getGot()
791 f.mipsGotIndex = gots.size() - 1; in getGot()
799 const FileGot &g = gots[f->mipsGotIndex]; in getPageEntryOffset()
802 uint64_t secAddr = getMipsPageAddr(outSec->addr); in getPageEntryOffset()
804 index = g.pagesMap.lookup(outSec).firstIndex + (symAddr - secAddr) / 0xffff; in getPageEntryOffset()
808 return index * config->wordsize; in getPageEntryOffset()
813 const FileGot &g = gots[f->mipsGotIndex]; in getSymEntryOffset()
815 if (sym->isTls()) in getSymEntryOffset()
816 return g.tls.lookup(sym) * config->wordsize; in getSymEntryOffset()
817 if (sym->isPreemptible) in getSymEntryOffset()
818 return g.global.lookup(sym) * config->wordsize; in getSymEntryOffset()
819 return g.local16.lookup({sym, addend}) * config->wordsize; in getSymEntryOffset()
823 const FileGot &g = gots[f->mipsGotIndex]; in getTlsIndexOffset()
824 return g.dynTlsSymbols.lookup(nullptr) * config->wordsize; in getTlsIndexOffset()
829 const FileGot &g = gots[f->mipsGotIndex]; in getGlobalDynOffset()
831 return g.dynTlsSymbols.lookup(sym) * config->wordsize; in getGlobalDynOffset()
864 if (count * config->wordsize > config->mipsGotSize) in tryMergeGots()
874 size = headerEntriesNum * config->wordsize; in updateAllocSize()
876 size += g.getEntriesNum() * config->wordsize; in updateAllocSize()
886 // For each GOT move non-preemptible symbols from the `Global` in build()
887 // to `Local16` list. Preemptible symbol might become non-preemptible in build()
891 if (!p.first->isPreemptible) in build()
894 return !p.first->isPreemptible; in build()
898 // For each GOT remove "reloc-only" entry if there is "global" in build()
900 // using 32-bit value at the end of 16-bit entries. in build()
909 // Evaluate number of "reloc-only" entries in the resulting GOT. in build()
910 // To do that put all unique "reloc-only" and "global" entries in build()
914 set_union(primGot->relocs, got.global); in build()
915 set_union(primGot->relocs, got.relocs); in build()
925 for (SectionCommand *cmd : os->commands) { in build()
927 for (InputSection *isec : isd->sections) { in build()
928 uint64_t off = alignToPowerOf2(secSize, isec->addralign); in build()
929 secSize = off + isec->getSize(); in build()
944 file->mipsGotIndex = 0; in build()
956 file->mipsGotIndex = mergedGots.size() - 1; in build()
961 // Reduce number of "reloc-only" entries in the primary GOT in build()
964 primGot->relocs.remove_if([&](const std::pair<Symbol *, size_t> &p) { in build()
965 return primGot->global.count(p.first); in build()
976 // to store page addresses of local symbols. We assume the worst case - in build()
999 for (auto &p : primGot->global) { in build()
1000 if (p.first->auxIdx == 0) in build()
1001 p.first->allocateAux(); in build()
1004 for (auto &p : primGot->relocs) { in build()
1005 if (p.first->auxIdx == 0) in build()
1006 p.first->allocateAux(); in build()
1015 uint64_t offset = p.second * config->wordsize; in build() local
1017 // for the TP-relative offset as we don't know how much other data will in build()
1019 if (s->isPreemptible || config->shared) in build()
1020 mainPart->relaDyn->addReloc({target->tlsGotRel, this, offset, in build()
1026 uint64_t offset = p.second * config->wordsize; in build() local
1028 if (!config->shared) in build()
1030 mainPart->relaDyn->addReloc({target->tlsModuleIndexRel, this, offset}); in build()
1034 // S->isPreemptible is not sufficient (this happens e.g. for in build()
1035 // thread-locals that have been marked as local through a linker script) in build()
1036 if (!s->isPreemptible && !config->shared) in build()
1038 mainPart->relaDyn->addSymbolReloc(target->tlsModuleIndexRel, *this, in build()
1039 offset, *s); in build()
1040 // However, we can skip writing the TLS offset reloc for non-preemptible in build()
1042 if (!s->isPreemptible) in build()
1044 offset += config->wordsize; in build()
1045 mainPart->relaDyn->addSymbolReloc(target->tlsOffsetRel, *this, offset, in build()
1050 // Do not create dynamic relocations for non-TLS in build()
1057 uint64_t offset = p.second * config->wordsize; in build() local
1058 mainPart->relaDyn->addSymbolReloc(target->relativeRel, *this, offset, in build()
1061 if (!config->isPic) in build()
1068 uint64_t offset = (l.second.firstIndex + pi) * config->wordsize; in build() local
1069 mainPart->relaDyn->addReloc({target->relativeRel, this, offset, l.first, in build()
1074 uint64_t offset = p.second * config->wordsize; in build() local
1075 mainPart->relaDyn->addReloc({target->relativeRel, this, offset, in build()
1085 return !config->relocatable; in isNeeded()
1092 if (!f || f->mipsGotIndex == uint32_t(-1) || f->mipsGotIndex == 0) in getGp()
1093 return ElfSym::mipsGp->getVA(0); in getGp()
1094 return getVA() + gots[f->mipsGotIndex].startIndex * config->wordsize + 0x7ff0; in getGp()
1112 writeUint(buf + config->wordsize, (uint64_t)1 << (config->wordsize * 8 - 1)); in writeTo()
1117 va = s->getVA(a); in writeTo()
1118 writeUint(buf + i * config->wordsize, va); in writeTo()
1124 uint64_t firstPageAddr = getMipsPageAddr(l.first->addr); in writeTo()
1128 // Local, global, TLS, reloc-only entries. in writeTo()
1131 // To calculate the adjustments use offsets for thread-local storage. in writeTo()
1132 // http://web.archive.org/web/20190324223224/https://www.linux-mips.org/wiki/NPTL in writeTo()
1144 p.first->isPreemptible || config->shared ? 0 : -0x7000); in writeTo()
1146 if (p.first == nullptr && !config->shared) in writeTo()
1148 else if (p.first && !p.first->isPreemptible) { in writeTo()
1152 if (!config->shared) in writeTo()
1154 write(p.second + 1, p.first, -0x8000); in writeTo()
1160 // On PowerPC the .plt section is used to hold the table of function addresses
1163 // consistent across both 64-bit PowerPC ABIs as well as the 32-bit PowerPC ABI.
1165 : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize, in GotPltSection()
1167 if (config->emachine == EM_PPC) { in GotPltSection()
1169 } else if (config->emachine == EM_PPC64) { in GotPltSection()
1176 assert(sym.auxIdx == symAux.size() - 1 && in addEntry()
1182 return (target->gotPltHeaderEntriesNum + entries.size()) * in getSize()
1183 target->gotEntrySize; in getSize()
1187 target->writeGotPltHeader(buf); in writeTo()
1188 buf += target->gotPltHeaderEntriesNum * target->gotEntrySize; in writeTo()
1190 target->writeGotPlt(buf, *b); in writeTo()
1191 buf += target->gotEntrySize; in writeTo()
1203 if (config->emachine == EM_ARM) in getIgotPltName()
1208 if (config->emachine == EM_PPC64) in getIgotPltName()
1218 config->emachine == EM_PPC64 ? SHT_NOBITS : SHT_PROGBITS, in IgotPltSection()
1219 target->gotEntrySize, getIgotPltName()) {} in IgotPltSection()
1227 return entries.size() * target->gotEntrySize; in getSize()
1232 target->writeIgotPlt(buf, *b); in writeTo()
1233 buf += target->gotEntrySize; in writeTo()
1246 // Adds a string to the string table. If `hashIt` is true we hash and check for
1254 return r.first->second; in addString()
1258 unsigned ret = this->size; in addString()
1259 this->size = this->size + s.size() + 1; in addString()
1273 // non-VER_NDX_LOCAL-non-VER_NDX_GLOBAL definitions, plus 1.
1281 : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_DYNAMIC, config->wordsize, in DynamicSection()
1283 this->entsize = ELFT::Is64Bits ? 16 : 8; in DynamicSection()
1286 // which passes -z rodynamic. in DynamicSection()
1288 // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf in DynamicSection()
1289 if (config->emachine == EM_MIPS || config->zRodynamic) in DynamicSection()
1290 this->flags = SHF_ALLOC; in DynamicSection()
1295 // - part.relaDyn
1296 // - in.relaPlt: this is included if a linker script places .rela.plt inside
1302 if (in.relaPlt->getParent() == relaDyn.getParent()) in addRelaSz()
1303 size += in.relaPlt->getSize(); in addRelaSz()
1311 static uint64_t addPltRelSz() { return in.relaPlt->getSize(); } in addPltRelSz()
1328 for (StringRef s : config->filterList) in computeContents()
1329 addInt(DT_FILTER, part.dynStrTab->addString(s)); in computeContents()
1330 for (StringRef s : config->auxiliaryList) in computeContents()
1331 addInt(DT_AUXILIARY, part.dynStrTab->addString(s)); in computeContents()
1333 if (!config->rpath.empty()) in computeContents()
1334 addInt(config->enableNewDtags ? DT_RUNPATH : DT_RPATH, in computeContents()
1335 part.dynStrTab->addString(config->rpath)); in computeContents()
1338 if (file->isNeeded) in computeContents()
1339 addInt(DT_NEEDED, part.dynStrTab->addString(file->soName)); in computeContents()
1342 if (!config->soName.empty()) in computeContents()
1343 addInt(DT_SONAME, part.dynStrTab->addString(config->soName)); in computeContents()
1345 if (!config->soName.empty()) in computeContents()
1346 addInt(DT_NEEDED, part.dynStrTab->addString(config->soName)); in computeContents()
1347 addInt(DT_SONAME, part.dynStrTab->addString(part.name)); in computeContents()
1353 if (config->bsymbolic == BsymbolicKind::All) in computeContents()
1355 if (config->zGlobal) in computeContents()
1357 if (config->zInitfirst) in computeContents()
1359 if (config->zInterpose) in computeContents()
1361 if (config->zNodefaultlib) in computeContents()
1363 if (config->zNodelete) in computeContents()
1365 if (config->zNodlopen) in computeContents()
1367 if (config->pie) in computeContents()
1369 if (config->zNow) { in computeContents()
1373 if (config->zOrigin) { in computeContents()
1377 if (!config->zText) in computeContents()
1379 if (ctx.hasTlsIe && config->shared) in computeContents()
1393 // debugger this information. Such systems may choose make .dynamic read-only. in computeContents()
1394 // If the target is such a system (used -z rodynamic) don't write DT_DEBUG. in computeContents()
1395 if (!config->shared && !config->relocatable && !config->zRodynamic) in computeContents()
1398 if (part.relaDyn->isNeeded()) { in computeContents()
1399 addInSec(part.relaDyn->dynamicTag, *part.relaDyn); in computeContents()
1400 entries.emplace_back(part.relaDyn->sizeDynamicTag, in computeContents()
1403 bool isRela = config->isRela; in computeContents()
1410 if (config->emachine != EM_MIPS) { in computeContents()
1411 size_t numRelativeRels = part.relaDyn->getRelativeRelocCount(); in computeContents()
1412 if (config->zCombreloc && numRelativeRels) in computeContents()
1416 if (part.relrDyn && part.relrDyn->getParent() && in computeContents()
1417 !part.relrDyn->relocs.empty()) { in computeContents()
1418 addInSec(config->useAndroidRelrTags ? DT_ANDROID_RELR : DT_RELR, in computeContents()
1420 addInt(config->useAndroidRelrTags ? DT_ANDROID_RELRSZ : DT_RELRSZ, in computeContents()
1421 part.relrDyn->getParent()->size); in computeContents()
1422 addInt(config->useAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT, in computeContents()
1425 if (part.relrAuthDyn && part.relrAuthDyn->getParent() && in computeContents()
1426 !part.relrAuthDyn->relocs.empty()) { in computeContents()
1428 addInt(DT_AARCH64_AUTH_RELRSZ, part.relrAuthDyn->getParent()->size); in computeContents()
1431 if (isMain && in.relaPlt->isNeeded()) { in computeContents()
1434 switch (config->emachine) { in computeContents()
1445 if (llvm::find_if(in.relaPlt->relocs, [](const DynamicReloc &r) { in computeContents()
1446 return r.type == target->pltRel && in computeContents()
1447 r.sym->stOther & STO_AARCH64_VARIANT_PCS; in computeContents()
1448 }) != in.relaPlt->relocs.end()) in computeContents()
1453 if (llvm::any_of(in.relaPlt->relocs, [](const DynamicReloc &r) { in computeContents()
1454 return r.type == target->pltRel && in computeContents()
1455 (r.sym->stOther & STO_RISCV_VARIANT_CC); in computeContents()
1463 addInt(DT_PLTREL, config->isRela ? DT_RELA : DT_REL); in computeContents()
1466 if (config->emachine == EM_AARCH64) { in computeContents()
1467 if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) in computeContents()
1469 if (config->zPacPlt) in computeContents()
1473 addInt(DT_AARCH64_MEMTAG_MODE, config->androidMemtagMode == NT_MEMTAG_LEVEL_ASYNC); in computeContents()
1474 addInt(DT_AARCH64_MEMTAG_HEAP, config->androidMemtagHeap); in computeContents()
1475 addInt(DT_AARCH64_MEMTAG_STACK, config->androidMemtagStack); in computeContents()
1476 if (mainPart->memtagGlobalDescriptors->isNeeded()) { in computeContents()
1477 addInSec(DT_AARCH64_MEMTAG_GLOBALS, *mainPart->memtagGlobalDescriptors); in computeContents()
1479 mainPart->memtagGlobalDescriptors->getSize()); in computeContents()
1487 addInt(DT_STRSZ, part.dynStrTab->getSize()); in computeContents()
1488 if (!config->zText) in computeContents()
1490 if (part.gnuHashTab && part.gnuHashTab->getParent()) in computeContents()
1492 if (part.hashTab && part.hashTab->getParent()) in computeContents()
1497 addInt(DT_PREINIT_ARRAY, Out::preinitArray->addr); in computeContents()
1498 addInt(DT_PREINIT_ARRAYSZ, Out::preinitArray->size); in computeContents()
1501 addInt(DT_INIT_ARRAY, Out::initArray->addr); in computeContents()
1502 addInt(DT_INIT_ARRAYSZ, Out::initArray->size); in computeContents()
1505 addInt(DT_FINI_ARRAY, Out::finiArray->addr); in computeContents()
1506 addInt(DT_FINI_ARRAYSZ, Out::finiArray->size); in computeContents()
1509 if (Symbol *b = symtab.find(config->init)) in computeContents()
1510 if (b->isDefined()) in computeContents()
1511 addInt(DT_INIT, b->getVA()); in computeContents()
1512 if (Symbol *b = symtab.find(config->fini)) in computeContents()
1513 if (b->isDefined()) in computeContents()
1514 addInt(DT_FINI, b->getVA()); in computeContents()
1517 if (part.verSym && part.verSym->isNeeded()) in computeContents()
1519 if (part.verDef && part.verDef->isLive()) { in computeContents()
1523 if (part.verNeed && part.verNeed->isNeeded()) { in computeContents()
1527 if (!f->vernauxs.empty()) in computeContents()
1532 if (config->emachine == EM_MIPS) { in computeContents()
1535 addInt(DT_MIPS_BASE_ADDRESS, target->getImageBase()); in computeContents()
1536 addInt(DT_MIPS_SYMTABNO, part.dynSymTab->getNumSymbols()); in computeContents()
1537 addInt(DT_MIPS_LOCAL_GOTNO, in.mipsGot->getLocalEntriesNum()); in computeContents()
1539 if (const Symbol *b = in.mipsGot->getFirstGlobalEntry()) in computeContents()
1540 addInt(DT_MIPS_GOTSYM, b->dynsymIndex); in computeContents()
1542 addInt(DT_MIPS_GOTSYM, part.dynSymTab->getNumSymbols()); in computeContents()
1545 if (!config->pie) in computeContents()
1547 // Store the offset to the .rld_map section in computeContents()
1550 in.mipsRldMap->getVA() - (getVA() + entries.size() * entsize)); in computeContents()
1555 // glibc assumes the old-style BSS PLT layout which we don't support. in computeContents()
1556 if (config->emachine == EM_PPC) in computeContents()
1560 if (config->emachine == EM_PPC64 && in.plt->isNeeded()) { in computeContents()
1563 addInt(DT_PPC64_GLINK, in.plt->getVA() + target->pltHeaderSize - 32); in computeContents()
1566 if (config->emachine == EM_PPC64) in computeContents()
1567 addInt(DT_PPC64_OPT, getPPC64TargetInfo()->ppc64DynamicSectionOpt); in computeContents()
1574 if (OutputSection *sec = getPartition().dynStrTab->getParent()) in finalizeContents()
1575 getParent()->link = sec->sectionIndex; in finalizeContents()
1576 this->size = computeContents().size() * this->entsize; in finalizeContents()
1583 p->d_tag = kv.first; in writeTo()
1584 p->d_un.d_val = kv.second; in writeTo()
1590 return inputSec->getVA(offsetInSec); in getOffset()
1603 uint64_t ca = InputSection::getRelocTargetVA(inputSec->file, type, addend, in computeAddend()
1605 return config->is64 ? ca : SignExtend64<32>(ca); in computeAddend()
1609 return getMipsPageAddr(outputSec->addr) + addend; in computeAddend()
1618 size_t index = symTab->getSymbolIndex(*sym); in getSymIndex()
1619 assert((index != 0 || (type != target->gotRel && type != target->pltRel) || in getSymIndex()
1620 !mainPart->dynSymTab->getParent()) && in getSymIndex()
1621 "GOT or PLT relocation must refer to symbol in dynamic symbol table"); in getSymIndex()
1630 : SyntheticSection(SHF_ALLOC, type, config->wordsize, name), in RelocationBaseSection()
1638 R_ADDEND, addendRelType ? *addendRelType : target->noneRel); in addSymbolReloc()
1666 const RelType relativeRel = target->relativeRel; in partitionRels()
1669 [=](auto &r) { return r.type == relativeRel; }) - in partitionRels()
1679 if (symTab && symTab->getParent()) in finalizeContents()
1680 getParent()->link = symTab->getParent()->sectionIndex; in finalizeContents()
1682 getParent()->link = 0; in finalizeContents()
1684 if (in.relaPlt.get() == this && in.gotPlt->getParent()) { in finalizeContents()
1685 getParent()->flags |= ELF::SHF_INFO_LINK; in finalizeContents()
1686 getParent()->info = in.gotPlt->getParent()->sectionIndex; in finalizeContents()
1704 [t = target->iRelativeRel](auto &r) { return r.type != t; }); in computeRels()
1713 // Non-relative relocations are few, so don't bother with parallelSort. in computeRels()
1723 : RelocationBaseSection(name, config->isRela ? SHT_RELA : SHT_REL, in RelocationSection()
1724 config->isRela ? DT_RELA : DT_REL, in RelocationSection()
1725 config->isRela ? DT_RELASZ : DT_RELSZ, combreloc, in RelocationSection()
1727 this->entsize = config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); in RelocationSection()
1734 p->r_offset = rel.r_offset; in writeTo()
1735 p->setSymbolAndType(rel.r_sym, rel.type, config->isMips64EL); in writeTo()
1736 if (config->isRela) in writeTo()
1737 p->r_addend = rel.addend; in writeTo()
1738 buf += config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); in writeTo()
1747 : (config->useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR), in RelrBaseSection()
1748 config->wordsize, isAArch64Auth ? ".relr.auth.dyn" : ".relr.dyn"), in RelrBaseSection()
1765 name, config->isRela ? SHT_ANDROID_RELA : SHT_ANDROID_REL, in AndroidPackedRelocationSection()
1766 config->isRela ? DT_ANDROID_RELA : DT_ANDROID_REL, in AndroidPackedRelocationSection()
1767 config->isRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ, in AndroidPackedRelocationSection()
1769 this->entsize = 1; in AndroidPackedRelocationSection()
1774 // This function computes the contents of an Android-format packed relocation in updateAllocSize()
1784 // the r_offset field. By sorting relocations by offset, grouping them by in updateAllocSize()
1786 // previous offset, each 8-byte relocation can be compressed to as little as 1 in updateAllocSize()
1787 // byte (or less with run-length encoding). This relocation packer was able to in updateAllocSize()
1792 // 'APS2' followed by a sequence of SLEB128-encoded integers. The first two in updateAllocSize()
1798 // - the number of relocations in the relocation group in updateAllocSize()
1799 // - flags for the relocation group in updateAllocSize()
1800 // - (if RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG is set) the r_offset delta in updateAllocSize()
1802 // - (if RELOCATION_GROUPED_BY_INFO_FLAG is set) the value of the r_info in updateAllocSize()
1804 // - (if RELOCATION_GROUP_HAS_ADDEND_FLAG and in updateAllocSize()
1811 // - (if RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG is not set) the r_offset in updateAllocSize()
1813 // - (if RELOCATION_GROUPED_BY_INFO_FLAG is not set) the value of the r_info in updateAllocSize()
1815 // - (if RELOCATION_GROUP_HAS_ADDEND_FLAG is set and in updateAllocSize()
1826 // offset (we set this to zero because the first relocation group will in updateAllocSize()
1838 r.r_addend = config->isRela ? rel.computeAddend() : 0; in updateAllocSize()
1840 if (r.getType(config->isMips64EL) == target->relativeRel) in updateAllocSize()
1852 // format allows these groups to be encoded using a sort of run-length in updateAllocSize()
1853 // encoding, but each group will cost 7 bytes in addition to the offset from in updateAllocSize()
1862 } while (i != e && (i - 1)->r_offset + config->wordsize == i->r_offset); in updateAllocSize()
1871 // For non-relative relocations, we would like to: in updateAllocSize()
1872 // 1. Have relocations with the same symbol offset to be consecutive, so in updateAllocSize()
1873 // that the runtime linker can speed-up symbol lookup by implementing an in updateAllocSize()
1874 // 1-entry cache. in updateAllocSize()
1877 // Since the symbol offset is the high bits in r_info, sorting by r_info in updateAllocSize()
1893 // based on r_info. However, we can approximate this trade-off by the number in updateAllocSize()
1899 // For Rela, the addend for most non-relative relocations is zero, and thus we in updateAllocSize()
1906 while (j != e && i->r_info == j->r_info && in updateAllocSize()
1907 (!config->isRela || i->r_addend == j->r_addend)) in updateAllocSize()
1909 if (j - i < 3 || (config->isRela && i->r_addend != 0)) in updateAllocSize()
1916 // Sort ungrouped relocations by offset to minimize the encoded length. in updateAllocSize()
1922 config->isRela ? RELOCATION_GROUP_HAS_ADDEND_FLAG : 0; in updateAllocSize()
1924 uint64_t offset = 0; in updateAllocSize() local
1927 // Emit the run-length encoding for the groups of adjacent relative in updateAllocSize()
1929 // format. The first is used to set the current offset to the start of the in updateAllocSize()
1937 add(g[0].r_offset - offset); in updateAllocSize()
1938 add(target->relativeRel); in updateAllocSize()
1939 if (config->isRela) { in updateAllocSize()
1940 add(g[0].r_addend - addend); in updateAllocSize()
1945 add(g.size() - 1); in updateAllocSize()
1948 add(config->wordsize); in updateAllocSize()
1949 add(target->relativeRel); in updateAllocSize()
1950 if (config->isRela) { in updateAllocSize()
1952 add(i.r_addend - addend); in updateAllocSize()
1957 offset = g.back().r_offset; in updateAllocSize()
1964 add(target->relativeRel); in updateAllocSize()
1966 add(r.r_offset - offset); in updateAllocSize()
1967 offset = r.r_offset; in updateAllocSize()
1968 if (config->isRela) { in updateAllocSize()
1969 add(r.r_addend - addend); in updateAllocSize()
1975 // Grouped non-relatives. in updateAllocSize()
1981 add(r.r_offset - offset); in updateAllocSize()
1982 offset = r.r_offset; in updateAllocSize()
1987 // Finally the ungrouped non-relative relocations. in updateAllocSize()
1992 add(r.r_offset - offset); in updateAllocSize()
1993 offset = r.r_offset; in updateAllocSize()
1995 if (config->isRela) { in updateAllocSize()
1996 add(r.r_addend - addend); in updateAllocSize()
2005 relocData.append(oldSize - relocData.size(), 0); in updateAllocSize()
2010 // turn can affect the sizes of the LEB-encoded integers stored in this in updateAllocSize()
2018 this->entsize = config->wordsize; in RelrSection()
2025 // Proposal for adding SHT_RELR sections to generic-abi is here: in updateAllocSize()
2026 // https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg in updateAllocSize()
2039 // Excluding the least significant bit in the bitmap, each non-zero bit in in updateAllocSize()
2044 // a single bitmap can encode up to 31 relocations in a 32-bit object, and in updateAllocSize()
2045 // 63 relocations in a 64-bit object. in updateAllocSize()
2055 // Same as Config->Wordsize but faster because this is a compile-time in updateAllocSize()
2061 const size_t nBits = wordsize * 8 - 1; in updateAllocSize()
2081 uint64_t d = offsets[i] - base; in updateAllocSize()
2096 log(".relr.dyn needs " + Twine(oldSize - relrRelocs.size()) + in updateAllocSize()
2107 config->wordsize, in SymbolTableBaseSection()
2113 // See "Global Offset Table" in Chapter 5 in the following document
2115 // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
2118 // Sort entries related to non-local preemptible symbols by GOT indexes. in sortMipsSymbols()
2120 if (l.sym->isInGot() && r.sym->isInGot()) in sortMipsSymbols()
2121 return l.sym->getGotIdx() < r.sym->getGotIdx(); in sortMipsSymbols()
2122 if (!l.sym->isInGot() && !r.sym->isInGot()) in sortMipsSymbols()
2124 return !l.sym->isInGot(); in sortMipsSymbols()
2129 getParent()->link = sec->sectionIndex; in finalizeContents()
2131 if (this->type != SHT_DYNSYM) { in finalizeContents()
2139 // Section's Info field has the index of the first non-local symbol. in finalizeContents()
2141 getParent()->info = 1; in finalizeContents()
2144 // NB: It also sorts Symbols to meet the GNU hash table requirements. in finalizeContents()
2145 getPartition().gnuHashTab->addSymbols(symbols); in finalizeContents()
2146 } else if (config->emachine == EM_MIPS) { in finalizeContents()
2151 // themselves. All other partitions use a lookup table. in finalizeContents()
2152 if (this == mainPart->dynSymTab.get()) { in finalizeContents()
2155 s.sym->dynsymIndex = ++i; in finalizeContents()
2170 [](const SymbolTableEntry &s) { return s.sym->isLocal(); }); in sortSymTabSymbols()
2171 size_t numLocals = e - symbols.begin(); in sortSymTabSymbols()
2172 getParent()->info = numLocals + 1; in sortSymTabSymbols()
2181 arr[s.sym->file].push_back(s); in sortSymTabSymbols()
2191 assert(this->type != SHT_DYNSYM || !b->isLocal()); in addSymbol()
2192 symbols.push_back({b, strTabSec.addString(b->getName(), false)}); in addSymbol()
2196 if (this == mainPart->dynSymTab.get()) in getSymbolIndex()
2199 // Initializes symbol lookup tables lazily. This is used only for -r, in getSymbolIndex()
2200 // --emit-relocs and dynsyms in partitions other than the main one. in getSymbolIndex()
2205 if (e.sym->type == STT_SECTION) in getSymbolIndex()
2206 sectionIndexMap[e.sym->getOutputSection()] = ++i; in getSymbolIndex()
2222 this->entsize = sizeof(Elf_Sym); in SymbolTableSection()
2226 if (config->relocatable) in getCommonSec()
2228 return dyn_cast_or_null<BssSection>(d->section); in getCommonSec()
2233 assert(!(sym->hasFlag(NEEDS_COPY) && sym->isObject())); in getSymSectionIndex()
2234 if (!isa<Defined>(sym) || sym->hasFlag(NEEDS_COPY)) in getSymSectionIndex()
2236 if (const OutputSection *os = sym->getOutputSection()) in getSymSectionIndex()
2237 return os->sectionIndex >= SHN_LORESERVE ? (uint32_t)SHN_XINDEX in getSymSectionIndex()
2238 : os->sectionIndex; in getSymSectionIndex()
2242 // Write the internal symbol table contents to the output symbol table.
2251 bool isDefinedHere = type == SHT_SYMTAB || sym->partition == partition; in writeTo()
2254 eSym->st_name = ent.strTabOffset; in writeTo()
2255 eSym->setBindingAndType(sym->binding, sym->type); in writeTo()
2256 eSym->st_other = sym->stOther; in writeTo()
2259 // When -r is specified, a COMMON symbol is not allocated. Its st_shndx in writeTo()
2261 eSym->st_shndx = SHN_COMMON; in writeTo()
2262 eSym->st_value = commonSec->addralign; in writeTo()
2263 eSym->st_size = cast<Defined>(sym)->size; in writeTo()
2267 eSym->st_shndx = shndx; in writeTo()
2268 eSym->st_value = sym->getVA(); in writeTo()
2274 eSym->st_size = shndx != SHN_UNDEF ? cast<Defined>(sym)->size : 0; in writeTo()
2276 eSym->st_shndx = 0; in writeTo()
2277 eSym->st_value = 0; in writeTo()
2278 eSym->st_size = 0; in writeTo()
2287 // dynamic linker distinguish such symbols and MIPS lazy-binding stubs. in writeTo()
2288 // https://sourceware.org/ml/binutils/2008-07/txt00000.txt in writeTo()
2289 if (config->emachine == EM_MIPS) { in writeTo()
2294 if (sym->isInPlt() && sym->hasFlag(NEEDS_COPY)) in writeTo()
2295 eSym->st_other |= STO_MIPS_PLT; in writeTo()
2297 // We already set the less-significant bit for symbols in writeTo()
2301 // clear that bit for non-dynamic symbol table, so tools in writeTo()
2304 if (sym->isDefined() && in writeTo()
2305 ((sym->stOther & STO_MIPS_MICROMIPS) || sym->hasFlag(NEEDS_COPY))) { in writeTo()
2307 eSym->st_value &= ~1; in writeTo()
2308 eSym->st_other |= STO_MIPS_MICROMIPS; in writeTo()
2311 if (config->relocatable) in writeTo()
2314 eSym->st_other |= STO_MIPS_PIC; in writeTo()
2322 this->entsize = 4; in SymtabShndxSection()
2330 for (const SymbolTableEntry &entry : in.symTab->getSymbols()) { in writeTo()
2332 write32(buf, entry.sym->getOutputSection()->sectionIndex); in writeTo()
2344 for (SectionCommand *cmd : script->sectionCommands) in isNeeded()
2351 getParent()->link = in.symTab->getParent()->sectionIndex; in finalizeContents()
2355 return in.symTab->getNumSymbols() * 4; in getSize()
2358 // .hash and .gnu.hash sections contain on-disk hash tables that map
2359 // symbol names to their dynamic symbol table indices. Their purpose
2383 // and better version of .hash. .hash is just an on-disk hash table, but
2384 // .gnu.hash has a bloom filter in addition to a hash table to skip
2386 // about .gnu.hash, you want to specify --hash-style=gnu. Otherwise, a
2387 // safe bet is to specify --hash-style=both for backward compatibility.
2389 : SyntheticSection(SHF_ALLOC, SHT_GNU_HASH, config->wordsize, ".gnu.hash") { in GnuHashTableSection()
2393 if (OutputSection *sec = getPartition().dynSymTab->getParent()) in finalizeContents()
2394 getParent()->link = sec->sectionIndex; in finalizeContents()
2402 maskWords = NextPowerOf2(numBits / (config->wordsize * 8)); in finalizeContents()
2406 size += config->wordsize * maskWords; // Bloom filter in finalizeContents()
2414 write32(buf + 4, getPartition().dynSymTab->getNumSymbols() - symbols.size()); in writeTo()
2419 // Write the 2-bit bloom filter. in writeTo()
2420 const unsigned c = config->is64 ? 64 : 32; in writeTo()
2424 size_t i = (sym.hash / c) & (maskWords - 1); in writeTo()
2425 uint64_t val = readUint(buf + i * config->wordsize); in writeTo()
2428 writeUint(buf + i * config->wordsize, val); in writeTo()
2430 buf += config->wordsize * maskWords; in writeTo()
2432 // Write the hash table. in writeTo()
2434 uint32_t oldBucket = -1; in writeTo()
2440 uint32_t hash = i->hash; in writeTo()
2441 bool isLastInChain = (i + 1) == e || i->bucketIdx != (i + 1)->bucketIdx; in writeTo()
2445 if (i->bucketIdx == oldBucket) in writeTo()
2448 // value table. in writeTo()
2449 write32(buckets + i->bucketIdx, in writeTo()
2450 getPartition().dynSymTab->getSymbolIndex(*i->sym)); in writeTo()
2451 oldBucket = i->bucketIdx; in writeTo()
2455 // Add symbols to this symbol hash table. Note that this function
2456 // destructively sort a given vector -- which is needed because
2457 // GNU-style hash table places some sorting requirements.
2463 return !s.sym->isDefined() || s.sym->partition != partition; in addSymbols()
2466 // We chose load factor 4 for the on-disk hash table. For each hash in addSymbols()
2471 // Note that we don't want to create a zero-sized hash table because in addSymbols()
2473 // table. If that's the case, we create a hash table with one unused in addSymbols()
2475 nBuckets = std::max<size_t>((v.end() - mid) / 4, 1); in addSymbols()
2482 uint32_t hash = hashGnu(b->getName()); in addSymbols()
2499 this->entsize = 4; in HashTableSection()
2505 if (OutputSection *sec = symTab->getParent()) in finalizeContents()
2506 getParent()->link = sec->sectionIndex; in finalizeContents()
2509 numEntries += symTab->getNumSymbols(); // The chain entries. in finalizeContents()
2512 numEntries += symTab->getNumSymbols(); in finalizeContents()
2513 this->size = numEntries * 4; in finalizeContents()
2518 unsigned numSymbols = symTab->getNumSymbols(); in writeTo()
2527 for (const SymbolTableEntry &s : symTab->getSymbols()) { in writeTo()
2529 StringRef name = sym->getName(); in writeTo()
2530 unsigned i = sym->dynsymIndex; in writeTo()
2539 headerSize(target->pltHeaderSize) { in PltSection()
2541 if (config->emachine == EM_PPC64) { in PltSection()
2548 if ((config->emachine == EM_386 || config->emachine == EM_X86_64) && in PltSection()
2549 (config->andFeatures & GNU_PROPERTY_X86_FEATURE_1_IBT)) in PltSection()
2554 if (config->emachine == EM_SPARCV9) in PltSection()
2555 this->flags |= SHF_WRITE; in PltSection()
2561 target->writePltHeader(buf); in writeTo()
2565 target->writePlt(buf + off, *sym, getVA() + off); in writeTo()
2566 off += target->pltEntrySize; in writeTo()
2571 assert(sym.auxIdx == symAux.size() - 1); in addEntry()
2577 return headerSize + entries.size() * target->pltEntrySize; in getSize()
2581 // For -z retpolineplt, .iplt needs the .plt header. in isNeeded()
2582 return !entries.empty() || (config->zRetpolineplt && in.iplt->isNeeded()); in isNeeded()
2588 target->addPltHeaderSymbols(*this); in addSymbols()
2592 target->addPltSymbols(*this, off); in addSymbols()
2593 off += target->pltEntrySize; in addSymbols()
2599 if (config->emachine == EM_PPC || config->emachine == EM_PPC64) { in IpltSection()
2608 target->writeIplt(buf + off, *sym, getVA() + off); in writeTo()
2609 off += target->ipltEntrySize; in writeTo()
2614 return entries.size() * target->ipltEntrySize; in getSize()
2618 assert(sym.auxIdx == symAux.size() - 1); in addEntry()
2627 target->addPltSymbols(*this, off); in addSymbols()
2628 off += target->pltEntrySize; in addSymbols()
2642 return headerSize + entries.size() * target->pltEntrySize + footerSize; in getSize()
2645 // This is an x86-only extra PLT section and used only when a security
2676 // .got.plt AND code to resolve a dynamic symbol lazily. With the 2-PLT scheme,
2680 // Lazy symbol resolution in the 2-PLT scheme works in the usual way, except
2684 // In other words, this is how the 2-PLT scheme works. Application code is
2694 // There is an open question as to whether the 2-PLT scheme was desirable or
2695 // not. We could have simply extended the PLT entry size to 32-bytes to
2697 // 2-PLT scheme. One reason to split PLT was, by doing that, we could keep hot
2701 // That said, the 2-PLT scheme is a part of the ABI, debuggers and other tools
2707 target->writeIBTPlt(buf, in.plt->getNumEntries()); in writeTo()
2712 return 16 + in.plt->getNumEntries() * target->pltEntrySize; in getSize()
2715 bool IBTPltSection::isNeeded() const { return in.plt->getNumEntries() > 0; } in isNeeded()
2725 h = h * 67 + toLower(c) - 113; in computeGdbHash()
2729 // 4-byte alignment ensures that values in the hash lookup table and the name
2730 // table are aligned.
2744 /* Abbrev table size */ 4 + in getDebugNamesHeaderSize()
2750 readEntry(uint64_t &offset, const DWARFDebugNames::NameIndex &ni, in readEntry() argument
2754 ie->poolOffset = offset; in readEntry()
2756 uint64_t ulebVal = namesExtractor.getULEB128(&offset, &err); in readEntry()
2765 ie->abbrevCode = static_cast<uint32_t>(ulebVal); in readEntry()
2766 auto it = ni.getAbbrevs().find_as(ie->abbrevCode); in readEntry()
2769 "abbrev code not found in abbrev table: %" PRIu32, in readEntry()
2770 ie->abbrevCode); in readEntry()
2773 for (DWARFDebugNames::AttributeEncoding a : it->Attributes) { in readEntry()
2776 attr.attrValue = namesExtractor.getU32(&offset, &err); in readEntry()
2778 ie->parentOffset = entriesBase + attr.attrValue; in readEntry()
2786 attr.attrValue = namesExtractor.getU8(&offset, &err); in readEntry()
2792 attr.attrValue = namesExtractor.getU16(&offset, &err); in readEntry()
2798 attr.attrValue = namesExtractor.getU32(&offset, &err); in readEntry()
2805 "unrecognized form encoding %d in abbrev table", a.Form); in readEntry()
2815 ie->attrValues.push_back(attr); in readEntry()
2818 ie->attrValues.push_back(cuAttr); in readEntry()
2869 uint64_t offset = locs.EntriesBase + entryOffsets[i]; in parseDebugNames() local
2870 while (offset < namesSec.Data.size() && namesSec.Data[offset] != 0) { in parseDebugNames()
2873 readEntry(offset, ni, locs.EntriesBase, namesExtractor, namesSec); in parseDebugNames()
2881 if (offset >= namesSec.Data.size()) in parseDebugNames()
2913 TimeTraceScope timeScope("Merge .debug_names", "hdr and abbrev table"); in computeHdrAndAbbrevTable()
2947 // Create the merged abbrev table, uniquifyinng the input abbrev tables and in computeHdrAndAbbrevTable()
2948 // computing mapping from old (per-cu) abbrev codes to new (merged) abbrev in computeHdrAndAbbrevTable()
2981 newCode = existing->code; in computeHdrAndAbbrevTable()
2988 abbrev2->code = newCode; in computeHdrAndAbbrevTable()
2995 // Compute the merged abbrev table. in computeHdrAndAbbrevTable()
2998 encodeULEB128(abbrev->code, os); in computeHdrAndAbbrevTable()
2999 encodeULEB128(abbrev->tag, os); in computeHdrAndAbbrevTable()
3000 for (DWARFDebugNames::AttributeEncoding a : abbrev->attributes) { in computeHdrAndAbbrevTable()
3006 os.write(0); // abbrev table end in computeHdrAndAbbrevTable()
3021 // Collect and de-duplicate all the names (preserving all the entries). in computeEntryPool()
3025 bit_floor(std::min<size_t>(config->threadCount, numShards)); in computeEntryPool()
3026 const size_t shift = 32 - countr_zero(numShards); in computeEntryPool()
3040 if ((shardId & (concurrency - 1)) != threadId) in computeEntryPool()
3049 // canonicalization) to have correct merged offset value and size. in computeEntryPool()
3061 nameVec[it->second].indexEntries.append(std::move(ne.indexEntries)); in computeEntryPool()
3071 uint32_t offset = 0; in computeEntryPool() local
3073 ne.entryOffset = offset; in computeEntryPool()
3075 ie.poolOffset = offset; in computeEntryPool()
3076 offset += getULEB128Size(ie.abbrevCode); in computeEntryPool()
3078 offset += value.attrSize; in computeEntryPool()
3080 ++offset; // index entry sentinel in computeEntryPool()
3082 offsets[shard] = offset; in computeEntryPool()
3087 uint32_t offset = offsets[shard - 1]; in computeEntryPool() local
3089 ne.entryOffset += offset; in computeEntryPool()
3091 ie.poolOffset += offset; in computeEntryPool()
3103 // corresponds to position in the merged table vector). in computeEntryPool()
3104 const Abbrev *abbrev = abbrevTable[ie.abbrevCode - 1]; in computeEntryPool()
3105 for (const auto &[a, v] : zip_equal(abbrev->attributes, ie.attrValues)) in computeEntryPool()
3107 v.attrValue = ie.parentEntry->poolOffset; in computeEntryPool()
3116 return {offsets[numShards - 1], num}; in computeEntryPool()
3129 if (!(s->flags & SHF_ALLOC) && s->name == ".debug_names") { in init()
3130 s->markDead(); in init()
3132 files.insert(isec->file); in init()
3150 // Compute section header (except unit_length), abbrev table, and entry pool. in init()
3159 hdr.UnitLength = size - 4; in init()
3178 if (Error e = inputChunk.llvmDebugNames->extract()) { in DebugNamesSection()
3188 // relocations. Record the section offset to be relocated by in DebugNamesSection()
3198 for (uint32_t &offset : entryOffsets) in DebugNamesSection()
3199 offset = endian::readNext<uint32_t, ELFT::Endianness, unaligned>(p); in DebugNamesSection()
3221 invokeOnRelocs(*sec, getNameRelocs, *sec->file, relocs.get()[i]); in finalizeContents()
3229 // Relocate string offsets in the name table with .debug_str + X relocations. in finalizeContents()
3260 // Write the hash lookup table. in writeTo()
3278 endian::writeNext<uint32_t, ELFT::Endianness>(buf, e->hashValue); in writeTo()
3280 // Write the name table. The name entries are ordered by bucket_idx and in writeTo()
3281 // correspond one-to-one with the hash lookup table. in writeTo()
3286 endian::writeNext<uint32_t, ELFT::Endianness>(buf, ne->stringOffset); in writeTo()
3291 endian::writeNext<uint32_t, ELFT::Endianness>(buf, ne->entryOffset); in writeTo()
3293 // Write the abbrev table. in writeTo()
3296 // Write the entry pool. Unlike the name table, the name entries follow the in writeTo()
3322 assert(uint64_t(buf - beginBuf) == size); in writeTo()
3328 // Returns the desired size of an on-disk hash table for a .gdb_index section.
3338 ret.push_back({cu->getOffset(), cu->getLength() + 4}); in readCuList()
3348 if (Error e = cu->tryExtractDIEsIfNeeded(false)) { in readAddressAreas()
3352 Expected<DWARFAddressRangesVector> ranges = cu->collectAddressRanges(); in readAddressAreas()
3358 ArrayRef<InputSectionBase *> sections = sec->file->getSections(); in readAddressAreas()
3360 if (r.SectionIndex == -1ULL) in readAddressAreas()
3364 if (s && s != &InputSection::discarded && s->isLive()) in readAddressAreas()
3385 DWARFDebugPubTable table; in readPubNamesAndTypes() local
3386 table.extract(data, /*GnuStyle=*/true, [&](Error e) { in readPubNamesAndTypes()
3387 warn(toString(pub->sec) + ": " + toString(std::move(e))); in readPubNamesAndTypes()
3389 for (const DWARFDebugPubTable::Set &set : table.getData()) { in readPubNamesAndTypes()
3396 return cu.cuOffset < set.Offset; in readPubNamesAndTypes()
3397 }) - in readPubNamesAndTypes()
3425 // multi-threading as the number of symbols can be in the order of millions. in createSymbols()
3429 llvm::bit_floor(std::min<size_t>(config->threadCount, numShards)); in createSymbols()
3430 const size_t shift = 32 - llvm::countr_zero(numShards); in createSymbols()
3439 if ((shardId & (concurrency - 1)) != threadId) in createSymbols()
3448 symbols[shardId][it->second].cuVector.push_back(v); in createSymbols()
3480 errorOrWarn("--gdb-index: constant pool size (" + Twine(off) + in createSymbols()
3486 // Returns a newly-created .gdb_index section.
3493 // note that isec->data() may uncompress the full content, which should be in create()
3503 if (s->name == ".debug_gnu_pubnames" || s->name == ".debug_gnu_pubtypes") in create()
3504 s->markDead(); in create()
3505 else if (isec->name == ".debug_info") in create()
3506 files.insert(isec->file); in create()
3508 // Drop .rel[a].debug_gnu_pub{names,types} for --emit-relocs. in create()
3511 if (InputSectionBase *rel = isec->getRelocatedSection()) in create()
3512 return !rel->isLive(); in create()
3513 return !s->isLive(); in create()
3526 // If the are multiple compile units .debug_info (very rare ld -r --unique), in create()
3535 ret->chunks = std::move(chunks); in create()
3536 std::tie(ret->symbols, ret->size) = createSymbols(nameAttrs, ret->chunks); in create()
3539 ret->size += sizeof(GdbIndexHeader) + ret->computeSymtabSize() * 8; in create()
3540 for (GdbChunk &chunk : ret->chunks) in create()
3541 ret->size += in create()
3551 hdr->version = 7; in writeTo()
3555 hdr->cuListOff = buf - start; in writeTo()
3558 write64le(buf, chunk.sec->outSecOff + cu.cuOffset); in writeTo()
3565 hdr->cuTypesOff = buf - start; in writeTo()
3566 hdr->addressAreaOff = buf - start; in writeTo()
3571 const uint64_t baseAddr = e.section->repl->getVA(0); in writeTo()
3580 // Write the on-disk open-addressing hash table containing symbols. in writeTo()
3581 hdr->symtabOff = buf - start; in writeTo()
3583 uint32_t mask = symtabSize - 1; in writeTo()
3600 hdr->constantPoolOff = buf - start; in writeTo()
3629 // .eh_frame_hdr contains a binary search table of pointers to FDEs.
3630 // Each entry of the search table consists of two values,
3634 uint8_t *buf = Out::bufferStart + getParent()->offset + outSecOff; in write()
3636 SmallVector<FdeData, 0> fdes = getPartition().ehFrame->getFdeData(); in write()
3643 getPartition().ehFrame->getParent()->addr - this->getVA() - 4); in write()
3656 return 12 + getPartition().ehFrame->numFdes * 8; in getSize()
3660 return isLive() && getPartition().ehFrame->isNeeded(); in isNeeded()
3670 if (!config->soName.empty()) in getFileDefName()
3671 return config->soName; in getFileDefName()
3672 return config->outputFile; in getFileDefName()
3676 fileDefNameOff = getPartition().dynStrTab->addString(getFileDefName()); in finalizeContents()
3678 verDefNameOffs.push_back(getPartition().dynStrTab->addString(v.name)); in finalizeContents()
3680 if (OutputSection *sec = getPartition().dynStrTab->getParent()) in finalizeContents()
3681 getParent()->link = sec->sectionIndex; in finalizeContents()
3685 // https://sourceware.org/ml/binutils/2014-11/msg00355.html in finalizeContents()
3686 getParent()->info = getVerDefNum(); in finalizeContents()
3724 // .gnu.version is a table where each entry is 2 byte long.
3728 this->entsize = 2; in VersionTableSection()
3734 getParent()->link = getPartition().dynSymTab->getParent()->sectionIndex; in finalizeContents()
3738 return (getPartition().dynSymTab->getSymbols().size() + 1) * 2; in getSize()
3743 for (const SymbolTableEntry &s : getPartition().dynSymTab->getSymbols()) { in writeTo()
3746 assert(!s.sym->isLazy()); in writeTo()
3747 write16(buf, s.sym->versionId); in writeTo()
3754 (getPartition().verDef || getPartition().verNeed->isNeeded()); in isNeeded()
3758 auto &file = cast<SharedFile>(*ss->file); in addVerneed()
3759 if (ss->versionId == VER_NDX_GLOBAL) in addVerneed()
3769 if (file.vernauxs[ss->versionId] == 0) in addVerneed()
3770 file.vernauxs[ss->versionId] = ++SharedFile::vernauxNum + getVerDefNum(); in addVerneed()
3772 ss->versionId = file.vernauxs[ss->versionId]; in addVerneed()
3782 if (f->vernauxs.empty()) in finalizeContents()
3786 vn.nameStrTab = getPartition().dynStrTab->addString(f->soName); in finalizeContents()
3787 bool isLibc = config->relrGlibc && f->soName.starts_with("libc.so."); in finalizeContents()
3789 for (unsigned i = 0; i != f->vernauxs.size(); ++i) { in finalizeContents()
3790 if (f->vernauxs[i] == 0) in finalizeContents()
3793 reinterpret_cast<const typename ELFT::Verdef *>(f->verdefs[i]); in finalizeContents()
3794 StringRef ver(f->getStringTable().data() + verdef->getAux()->vda_name); in finalizeContents()
3797 vn.vernauxs.push_back({verdef->vd_hash, f->vernauxs[i], in finalizeContents()
3798 getPartition().dynStrTab->addString(ver)}); in finalizeContents()
3804 getPartition().dynStrTab->addString(ver)}); in finalizeContents()
3808 if (OutputSection *sec = getPartition().dynStrTab->getParent()) in finalizeContents()
3809 getParent()->link = sec->sectionIndex; in finalizeContents()
3810 getParent()->info = verneeds.size(); in finalizeContents()
3820 verneed->vn_version = 1; in writeTo()
3821 verneed->vn_cnt = vn.vernauxs.size(); in writeTo()
3822 verneed->vn_file = vn.nameStrTab; in writeTo()
3823 verneed->vn_aux = in writeTo()
3824 reinterpret_cast<char *>(vernaux) - reinterpret_cast<char *>(verneed); in writeTo()
3825 verneed->vn_next = sizeof(Elf_Verneed); in writeTo()
3830 vernaux->vna_hash = vna.hash; in writeTo()
3831 vernaux->vna_flags = 0; in writeTo()
3832 vernaux->vna_other = vna.verneedIndex; in writeTo()
3833 vernaux->vna_name = vna.nameStrTab; in writeTo()
3834 vernaux->vna_next = sizeof(Elf_Vernaux); in writeTo()
3838 vernaux[-1].vna_next = 0; in writeTo()
3840 verneed[-1].vn_next = 0; in writeTo()
3853 ms->parent = this; in addSection()
3855 assert(addralign == ms->addralign || !(ms->flags & SHF_STRINGS)); in addSection()
3856 addralign = std::max(addralign, ms->addralign); in addSection()
3869 // Add all string pieces to the string table builder to create section in finalizeContents()
3872 for (size_t i = 0, e = sec->pieces.size(); i != e; ++i) in finalizeContents()
3873 if (sec->pieces[i].live) in finalizeContents()
3874 builder.add(sec->getData(i)); in finalizeContents()
3876 // Fix the string table content. After this, the contents will never change. in finalizeContents()
3879 // finalize() fixed tail-optimized strings, so we can now get in finalizeContents()
3880 // offsets of strings. Get an offset for each string and save it in finalizeContents()
3883 for (size_t i = 0, e = sec->pieces.size(); i != e; ++i) in finalizeContents()
3884 if (sec->pieces[i].live) in finalizeContents()
3885 sec->pieces[i].outputOff = builder.getOffset(sec->getData(i)); in finalizeContents()
3895 // millions. So, we use multi-threading.
3902 // Initializes string table builders. in finalizeContents()
3909 llvm::bit_floor(std::min<size_t>(config->threadCount, numShards)); in finalizeContents()
3914 for (size_t i = 0, e = sec->pieces.size(); i != e; ++i) { in finalizeContents()
3915 if (!sec->pieces[i].live) in finalizeContents()
3917 size_t shardId = getShardId(sec->pieces[i].hash); in finalizeContents()
3918 if ((shardId & (concurrency - 1)) == threadId) in finalizeContents()
3919 sec->pieces[i].outputOff = shards[shardId].add(sec->getData(i)); in finalizeContents()
3924 // Compute an in-section offset for each shard. in finalizeContents()
3938 for (size_t i = 0, e = sec->pieces.size(); i != e; ++i) in finalizeContents()
3939 if (sec->pieces[i].live) in finalizeContents()
3940 sec->pieces[i].outputOff += in finalizeContents()
3941 shardOffsets[getShardId(sec->pieces[i].hash)]; in finalizeContents()
3950 for (InputSectionBase *sec : file->getSections()) { in splitSections()
3954 s->splitIntoPieces(); in splitSections()
3956 eh->split<ELFT>(); in splitSections()
3964 EhFrameSection &eh = *sec->getPartition().ehFrame; in combineEhSections()
3965 sec->parent = &eh; in combineEhSections()
3966 eh.addralign = std::max(eh.addralign, sec->addralign); in combineEhSections()
3968 llvm::append_range(eh.dependentSections, sec->dependentSections); in combineEhSections()
3971 if (!mainPart->armExidx) in combineEhSections()
3976 if (!s->isLive() || s->partition == 255) in combineEhSections()
3978 Partition &part = s->getPartition(); in combineEhSections()
3979 return s->kind() == SectionBase::Regular && part.armExidx && in combineEhSections()
3980 part.armExidx->addSection(cast<InputSection>(s)); in combineEhSections()
3985 : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize, in MipsRldMapSection()
3990 config->wordsize, ".ARM.exidx") {} in ARMExidxSyntheticSection()
3993 for (InputSection *d : isec->dependentSections) in findExidxSection()
3994 if (d->type == SHT_ARM_EXIDX && d->isLive()) in findExidxSection()
4000 return (isec->flags & SHF_ALLOC) && (isec->flags & SHF_EXECINSTR) && in isValidExidxSectionDep()
4001 isec->getSize() > 0; in isValidExidxSectionDep()
4005 if (isec->type == SHT_ARM_EXIDX) { in addSection()
4006 if (InputSection *dep = isec->getLinkOrderDep()) in addSection()
4022 // FIXME: we do not output a relocation section when --emit-relocs is used in addSection()
4023 // as we do not have relocation sections for linker generated table entries in addSection()
4027 if (config->emitRelocs && isec->type == SHT_REL) in addSection()
4028 if (InputSectionBase *ex = isec->getRelocatedSection()) in addSection()
4029 if (isa<InputSection>(ex) && ex->type == SHT_ARM_EXIDX) in addSection()
4036 // special EXIDX_CANTUNWIND bit-pattern.
4042 // section Prev, where Cur follows Prev in the table. This can be done if the
4047 // Get the last table Entry from the previous .ARM.exidx section. If Prev is in isDuplicateArmExidxSec()
4051 prevUnwind = read32(prev->content().data() + prev->content().size() - 4); in isDuplicateArmExidxSec()
4055 // We consider the unwind instructions of an .ARM.exidx table entry in isDuplicateArmExidxSec()
4057 // - Both are the special EXIDX_CANTUNWIND. in isDuplicateArmExidxSec()
4058 // - Both are the same inline unwind instructions. in isDuplicateArmExidxSec()
4067 for (uint32_t offset = 4; offset < (uint32_t)cur->content().size(); offset +=8) { in isDuplicateArmExidxSec() local
4068 uint32_t curUnwind = read32(cur->content().data() + offset); in isDuplicateArmExidxSec()
4072 // All table entries in this .ARM.exidx Section can be merged into the in isDuplicateArmExidxSec()
4077 // The .ARM.exidx table must be sorted in ascending order of the address of the
4078 // functions the table describes. std::optionally duplicate adjacent table
4082 // mergeable .ARM.exidx table entries are removed from it.
4084 // Ensure that any fixed-point iterations after the first see the original set in finalizeContents()
4088 else if (config->enableNonContiguousRegions) in finalizeContents()
4096 auto isDiscarded = [](const InputSection *isec) { return !isec->isLive(); }; in finalizeContents()
4102 if (!isec->isLive()) in finalizeContents()
4106 int64_t off = static_cast<int64_t>(isec->getVA() - getVA()); in finalizeContents()
4116 OutputSection *aOut = a->getParent(); in finalizeContents()
4117 OutputSection *bOut = b->getParent(); in finalizeContents()
4120 return aOut->addr < bOut->addr; in finalizeContents()
4121 return a->outSecOff < b->outSecOff; in finalizeContents()
4126 if (config->mergeArmExidx) { in finalizeContents()
4141 // offset is within the SyntheticSection. in finalizeContents()
4142 size_t offset = 0; in finalizeContents() local
4146 d->outSecOff = offset; in finalizeContents()
4147 d->parent = getParent(); in finalizeContents()
4148 offset += d->getSize(); in finalizeContents()
4150 offset += 8; in finalizeContents()
4154 size = offset + 8; in finalizeContents()
4161 // To write the .ARM.exidx table from the ExecutableSections we have three cases
4169 // the table to terminate the address range of the final entry.
4175 uint64_t offset = 0; in writeTo() local
4177 assert(isec->getParent() != nullptr); in writeTo()
4179 for (int dataOffset = 0; dataOffset != (int)d->content().size(); in writeTo()
4181 write32(buf + offset + dataOffset, in writeTo()
4182 read32(d->content().data() + dataOffset)); in writeTo()
4185 d->outSecOff = offset + outSecOff; in writeTo()
4186 target->relocateAlloc(*d, buf + offset); in writeTo()
4187 offset += d->getSize(); in writeTo()
4190 write32(buf + offset + 0, 0x0); in writeTo()
4191 write32(buf + offset + 4, 0x1); in writeTo()
4192 uint64_t s = isec->getVA(); in writeTo()
4193 uint64_t p = getVA() + offset; in writeTo()
4194 target->relocateNoSym(buf + offset, R_ARM_PREL31, s - p); in writeTo()
4195 offset += 8; in writeTo()
4199 write32(buf + offset + 0, 0x0); in writeTo()
4200 write32(buf + offset + 4, 0x1); in writeTo()
4201 uint64_t s = sentinel->getVA(sentinel->getSize()); in writeTo()
4202 uint64_t p = getVA() + offset; in writeTo()
4203 target->relocateNoSym(buf + offset, R_ARM_PREL31, s - p); in writeTo()
4204 assert(size == offset + 8); in writeTo()
4209 [](InputSection *isec) { return isec->isLive(); }); in isNeeded()
4214 config->emachine == EM_PPC64 ? 16 : 4, ".text.thunk") { in ThunkSection()
4215 this->parent = os; in ThunkSection()
4216 this->outSecOff = off; in ThunkSection()
4227 t->addSymbols(*this); in addThunk()
4232 t->writeTo(buf + t->offset); in writeTo()
4239 return t->getTargetInputSection(); in getTargetInputSection()
4245 off = alignToPowerOf2(off, t->alignment); in assignOffsets()
4246 t->setOffset(off); in assignOffsets()
4247 uint32_t size = t->size(); in assignOffsets()
4248 t->getThunkTargetSym()->size = size; in assignOffsets()
4262 for (SectionCommand *cmd : getParent()->commands) in isNeeded()
4264 for (InputSection *isec : isd->sections) in isNeeded()
4271 // PPC32 may create multiple GOT sections for -fPIC/-fPIE, one per file in in finalizeContents()
4275 for (SectionCommand *cmd : getParent()->commands) in finalizeContents()
4277 for (InputSection *isec : isd->sections) { in finalizeContents()
4278 // isec->file may be nullptr for MergeSyntheticSection. in finalizeContents()
4279 if (isec != this && isec->file) in finalizeContents()
4280 isec->file->ppc32Got2 = isec; in finalizeContents()
4285 // If linking position-dependent code then the table will store the addresses
4287 // position-independent code the section has type SHT_NOBITS since it will be
4291 config->isPic ? SHT_NOBITS : SHT_PROGBITS, 8, in PPC64LongBranchTargetSection()
4296 return getVA() + entry_index.find({sym, addend})->second * 8; in getEntryVA()
4306 return res.first->second; in addEntry()
4314 // If linking non-pic we have the final addresses of the targets and they get in writeTo()
4315 // written to the table directly. For pic the dynamic linker will allocate in writeTo()
4317 if (config->isPic) in writeTo()
4323 assert(sym->getVA()); in writeTo()
4324 // Need calls to branch to the local entry-point since a long-branch in writeTo()
4325 // must be a local-call. in writeTo()
4326 write64(buf, sym->getVA(addend) + in writeTo()
4327 getPPC64GlobalEntryToLocalEntryOffset(sym->stOther)); in writeTo()
4337 // creation. Because of this, if we don't create any long-branch thunks we end in isNeeded()
4343 // MIPS non-PIC executable gets ABI version 1. in getAbiVersion()
4344 if (config->emachine == EM_MIPS) { in getAbiVersion()
4345 if (!config->isPic && !config->relocatable && in getAbiVersion()
4346 (config->eflags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC) in getAbiVersion()
4351 if (config->emachine == EM_AMDGPU && !ctx.objectFiles.empty()) { in getAbiVersion()
4352 uint8_t ver = ctx.objectFiles[0]->abiVersion; in getAbiVersion()
4354 if (file->abiVersion != ver) in getAbiVersion()
4366 eHdr->e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32; in writeEhdr()
4367 eHdr->e_ident[EI_DATA] = in writeEhdr()
4369 eHdr->e_ident[EI_VERSION] = EV_CURRENT; in writeEhdr()
4370 eHdr->e_ident[EI_OSABI] = config->osabi; in writeEhdr()
4371 eHdr->e_ident[EI_ABIVERSION] = getAbiVersion(); in writeEhdr()
4372 eHdr->e_machine = config->emachine; in writeEhdr()
4373 eHdr->e_version = EV_CURRENT; in writeEhdr()
4374 eHdr->e_flags = config->eflags; in writeEhdr()
4375 eHdr->e_ehsize = sizeof(typename ELFT::Ehdr); in writeEhdr()
4376 eHdr->e_phnum = part.phdrs.size(); in writeEhdr()
4377 eHdr->e_shentsize = sizeof(typename ELFT::Shdr); in writeEhdr()
4379 if (!config->relocatable) { in writeEhdr()
4380 eHdr->e_phoff = sizeof(typename ELFT::Ehdr); in writeEhdr()
4381 eHdr->e_phentsize = sizeof(typename ELFT::Phdr); in writeEhdr()
4386 // Write the program header table. in writePhdrs()
4389 hBuf->p_type = p->p_type; in writePhdrs()
4390 hBuf->p_flags = p->p_flags; in writePhdrs()
4391 hBuf->p_offset = p->p_offset; in writePhdrs()
4392 hBuf->p_vaddr = p->p_vaddr; in writePhdrs()
4393 hBuf->p_paddr = p->p_paddr; in writePhdrs()
4394 hBuf->p_filesz = p->p_filesz; in writePhdrs()
4395 hBuf->p_memsz = p->p_memsz; in writePhdrs()
4396 hBuf->p_align = p->p_align; in writePhdrs()
4414 // Loadable partitions are always ET_DYN. in writeTo()
4416 eHdr->e_type = ET_DYN; in writeTo()
4437 return 12 * (partitions.size() - 1); in getSize()
4441 for (size_t i = 1; i != partitions.size(); ++i) in finalizeContents()
4442 partitions[i].nameStrTab = mainPart->dynStrTab->addString(partitions[i].name); in finalizeContents()
4447 for (size_t i = 1; i != partitions.size(); ++i) { in writeTo()
4448 write32(buf, mainPart->dynStrTab->getVA() + partitions[i].nameStrTab - va); in writeTo()
4449 write32(buf + 4, partitions[i].elfHeader->getVA() - (va + 4)); in writeTo()
4451 SyntheticSection *next = i == partitions.size() - 1 in writeTo()
4453 : partitions[i + 1].elfHeader.get(); in writeTo()
4454 write32(buf + 8, next->getVA() - partitions[i].elfHeader->getVA()); in writeTo()
4493 return !config->relocatable && !config->shared && in needsInterpSection()
4494 !config->dynamicLinker.empty() && script->needsInterpSection(); in needsInterpSection()
4498 return config->emachine == EM_AARCH64 && in hasMemtag()
4499 config->androidMemtagMode != ELF::NT_MEMTAG_LEVEL_NONE; in hasMemtag()
4504 // - A dynamic loader to process relocations, and
4505 // - Dynamic entries.
4506 // This restriction could be removed in future by re-using some of the ideas
4510 (config->relocatable || config->shared || needsInterpSection()); in canHaveMemtagGlobals()
4527 value |= config->androidMemtagMode; in writeTo()
4528 if (config->androidMemtagHeap) in writeTo()
4530 // Note, MTE stack is an ABI break. Attempting to run an MTE stack-enabled in writeTo()
4532 if (config->androidMemtagStack) in writeTo()
4545 write32(buf + 4, config->packageMetadata.size() + 1); in writeTo()
4548 memcpy(buf + 16, config->packageMetadata.data(), in writeTo()
4549 config->packageMetadata.size()); in writeTo()
4554 alignTo(config->packageMetadata.size() + 1, 4); in getSize()
4558 // it to `*(buf + offset)` if `buf` is non-null.
4559 static size_t computeOrWriteULEB128(uint64_t v, uint8_t *buf, size_t offset) { in computeOrWriteULEB128() argument
4561 return encodeULEB128(v, buf + offset); in computeOrWriteULEB128()
4565 // https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#83encoding-of
4577 const uint64_t addr = sym->getVA(); in createMemtagGlobalDescriptors()
4578 const uint64_t size = sym->getSize(); in createMemtagGlobalDescriptors()
4581 errorOrWarn("address of the tagged symbol \"" + sym->getName() + in createMemtagGlobalDescriptors()
4585 errorOrWarn("address of the tagged symbol \"" + sym->getName() + in createMemtagGlobalDescriptors()
4587 "\" is not granule (16-byte) aligned"); in createMemtagGlobalDescriptors()
4589 errorOrWarn("size of the tagged symbol \"" + sym->getName() + in createMemtagGlobalDescriptors()
4592 errorOrWarn("size of the tagged symbol \"" + sym->getName() + in createMemtagGlobalDescriptors()
4594 ") is not granule (16-byte) aligned"); in createMemtagGlobalDescriptors()
4597 const uint64_t stepToEncode = ((addr - lastGlobalEnd) / kMemtagGranuleSize) in createMemtagGlobalDescriptors()
4603 sectionSize += computeOrWriteULEB128(sizeToEncode - 1, buf, sectionSize); in createMemtagGlobalDescriptors()
4615 return s1->getVA() < s2->getVA(); in updateAllocSize()
4629 for (SectionCommand *cmd : script->sectionCommands) in findSection()
4631 if (osd->osec.name == name) in findSection()
4632 return &osd->osec; in findSection()
4639 if (!s || s->isDefined() || s->isCommon()) in addOptionalRegular()
4642 s->resolve(Defined{ctx.internalFile, StringRef(), STB_GLOBAL, stOther, in addOptionalRegular()
4645 s->isUsedInRegularObj = true; in addOptionalRegular()
4661 for (size_t i = 1; i <= partitions.size(); ++i) { in createSyntheticSections()
4663 sec->partition = i; in createSyntheticSections()
4673 Out::programHeaders->addralign = config->wordsize; in createSyntheticSections()
4675 if (config->strip != StripPolicy::All) { in createSyntheticSections()
4687 bool hasDataRelRo = script->hasSectionsCommand && findSection(".data.rel.ro"); in createSyntheticSections()
4692 // Add MIPS-specific sections. in createSyntheticSections()
4693 if (config->emachine == EM_MIPS) { in createSyntheticSections()
4694 if (!config->shared && config->hasDynSymTab) { in createSyntheticSections()
4706 StringRef relaDynName = config->isRela ? ".rela.dyn" : ".rel.dyn"; in createSyntheticSections()
4708 const unsigned threadCount = config->threadCount; in createSyntheticSections()
4709 for (Partition &part : partitions) { in createSyntheticSections()
4717 part.elfHeader->name = part.name; in createSyntheticSections()
4725 if (config->buildId != BuildIdKind::None) { in createSyntheticSections()
4730 // dynSymTab is always present to simplify sym->includeInDynsym() in in createSyntheticSections()
4736 if (config->relocatable) in createSyntheticSections()
4750 if (config->androidPackDynRelocs) in createSyntheticSections()
4755 relaDynName, config->zCombreloc, threadCount); in createSyntheticSections()
4757 if (config->hasDynSymTab) { in createSyntheticSections()
4771 if (config->gnuHash) { in createSyntheticSections()
4776 if (config->sysvHash) { in createSyntheticSections()
4786 if (config->relrPackDynRelocs) { in createSyntheticSections()
4794 if (config->ehFrameHdr) { in createSyntheticSections()
4801 if (config->emachine == EM_ARM) { in createSyntheticSections()
4807 if (!config->packageMetadata.empty()) { in createSyntheticSections()
4813 if (partitions.size() != 1) { in createSyntheticSections()
4815 // so that it is sorted after all other partitions. It also has other in createSyntheticSections()
4818 std::make_unique<BssSection>(".part.end", config->maxPageSize, 1); in createSyntheticSections()
4819 in.partEnd->partition = 255; in createSyntheticSections()
4825 in.partIndex->getSize()); in createSyntheticSections()
4831 if (config->emachine == EM_MIPS) { in createSyntheticSections()
4839 if (config->emachine == EM_PPC) { in createSyntheticSections()
4844 if (config->emachine == EM_PPC64) { in createSyntheticSections()
4855 if (config->zRelro && in createSyntheticSections()
4856 ((script->phdrsCommands.empty() && !script->hasSectionsCommand) || in createSyntheticSections()
4857 script->seenRelroEnd)) { in createSyntheticSections()
4862 if (config->emachine == EM_ARM) { in createSyntheticSections()
4869 if (ElfSym::globalOffsetTable && config->emachine != EM_MIPS) { in createSyntheticSections()
4870 if (target->gotBaseSymInGotPlt) in createSyntheticSections()
4871 in.gotPlt->hasGotPltOffRel = true; in createSyntheticSections()
4873 in.got->hasGotOffRel = true; in createSyntheticSections()
4879 config->isRela ? ".rela.plt" : ".rel.plt", /*sort=*/false, in createSyntheticSections()
4883 if ((config->emachine == EM_386 || config->emachine == EM_X86_64) && in createSyntheticSections()
4884 (config->andFeatures & GNU_PROPERTY_X86_FEATURE_1_IBT)) { in createSyntheticSections()
4889 if (config->emachine == EM_PPC) in createSyntheticSections()
4897 if (config->andFeatures || !ctx.aarch64PauthAbiCoreInfo.empty()) in createSyntheticSections()
4900 if (config->debugNames) { in createSyntheticSections()
4905 if (config->gdbIndex) { in createSyntheticSections()
4910 // .note.GNU-stack is always added when we are creating a re-linkable in createSyntheticSections()
4912 // section to control the executable-ness of the stack area, but that in createSyntheticSections()
4913 // is irrelevant these days. Stack area should always be non-executable in createSyntheticSections()
4915 if (config->relocatable) in createSyntheticSections()
4929 std::vector<Partition> elf::partitions; member in elf