Lines Matching +full:page +full:- +full:size

1 //===- UnwindInfoSection.cpp ----------------------------------------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
26 #include "mach-o/compact_unwind_encoding.h"
42 ((SECOND_LEVEL_PAGE_BYTES - \
46 ((SECOND_LEVEL_PAGE_BYTES - \
61 // Compact Unwind format is a Mach-O evolution of DWARF Unwind that
62 // optimizes space and exception-time lookup. Most DWARF unwind
66 // This comment will address macro-level organization of the pre-link
67 // and post-link compact unwind tables. For micro-level organization
68 // pertaining to the bitfield layout of the 32-bit compact unwind
69 // entries, see libunwind/include/mach-o/compact_unwind_encoding.h
75 // an intermediate output with the `-r` option which retains relocs.
90 // advantage, achieving a 3-order-of-magnitude reduction in the
97 // TODO(gkm): how do we align the 2nd-level pages?
99 // The various fields in the on-disk representation of each compact unwind
136 UnwindInfoSectionImpl() : cuLayout(target->wordSize) {} in UnwindInfoSectionImpl()
161 // Indices into cuEntries for CUEs with a non-null LSDA.
167 // The highest-address function plus its size. The unwinder needs this to
183 // entries -- else the unwinder would think they have the unwind info of the
188 if (d->unwindEntry()) in addSymbol()
193 auto p = symbols.insert({{d->isec(), d->value}, d}); in addSymbol()
196 if (!p.second && d->unwindEntry()) { in addSymbol()
197 assert(p.first->second == d || !p.first->second->unwindEntry()); in addSymbol()
198 p.first->second = d; in addSymbol()
207 if (d->unwindEntry()) { in prepare()
208 if (d->unwindEntry()->getName() == section_names::compactUnwind) { in prepare()
209 prepareRelocations(d->unwindEntry()); in prepare()
215 // to avoid overflowing the 3-personality limit. in prepare()
216 FDE &fde = cast<ObjFile>(d->getFile())->fdes[d->unwindEntry()]; in prepare()
228 assert(!isec->shouldOmitFromOutput() && in prepareRelocations()
232 // point to dead-stripped functions. That might save some amount of in prepareRelocations()
236 for (size_t i = 0; i < isec->relocs.size(); ++i) { in prepareRelocations()
237 Reloc &r = isec->relocs[i]; in prepareRelocations()
238 assert(target->hasAttr(r.type, RelocAttrBits::UNSIGNED)); in prepareRelocations()
243 r.referent = referentIsec->canonical(); in prepareRelocations()
253 // Personality functions are nearly always system-defined (e.g., in prepareRelocations()
266 if (!defined->isExternal()) in prepareRelocations()
267 if (Symbol *sym = symtab->find(defined->getName())) in prepareRelocations()
268 if (!sym->isLazy()) in prepareRelocations()
273 // treatUndefinedSymbol() can replace s with a DylibSymbol; re-check. in prepareRelocations()
282 personalityTable[{defined->isec(), defined->value}]; in prepareRelocations()
285 in.got->addEntry(defined); in prepareRelocations()
293 in.got->addEntry(s); in prepareRelocations()
303 // entries needed by non-unwind sections will have already been added in prepareRelocations()
308 llvm::find_if(referentIsec->symbols, [&](Defined const *d) { in prepareRelocations()
309 return d->value == static_cast<uint64_t>(r.addend) && in prepareRelocations()
310 d->isInGot(); in prepareRelocations()
312 if (gotEntry != referentIsec->symbols.end()) { in prepareRelocations()
318 r.addend, /*size=*/0, /*isWeakDef=*/false, in prepareRelocations()
323 s->used = true; in prepareRelocations()
324 in.got->addEntry(s); in prepareRelocations()
336 Symbol *&synth = personalityTable[{defined->isec(), defined->value}]; in canonicalizePersonality()
345 // We need to apply the relocations to the pre-link compact unwind section
346 // before converting it to post-link form. There should only be absolute
347 // relocations here: since we are not emitting the pre-link CU section, there
351 parallelFor(0, symbolsVec.size(), [&](size_t i) { in relocateCompactUnwind()
354 cu.functionAddress = d->getVA(); in relocateCompactUnwind()
355 if (!d->unwindEntry()) in relocateCompactUnwind()
358 // If we have DWARF unwind info, create a slimmed-down CU entry that points in relocateCompactUnwind()
360 if (d->unwindEntry()->getName() == section_names::ehFrame) { in relocateCompactUnwind()
367 // but since we don't keep track of that, just encode zero -- the start of in relocateCompactUnwind()
370 d->unwindEntry()->outSecOff <= DWARF_SECTION_OFFSET in relocateCompactUnwind()
371 ? d->unwindEntry()->outSecOff in relocateCompactUnwind()
373 cu.encoding = target->modeDwarfEncoding | dwarfOffsetHint; in relocateCompactUnwind()
374 const FDE &fde = cast<ObjFile>(d->getFile())->fdes[d->unwindEntry()]; in relocateCompactUnwind()
376 // Omit the DWARF personality from compact-unwind entry so that we in relocateCompactUnwind()
383 assert(d->unwindEntry()->getName() == section_names::compactUnwind); in relocateCompactUnwind()
386 reinterpret_cast<const uint8_t *>(d->unwindEntry()->data.data()) - in relocateCompactUnwind()
387 target->wordSize; in relocateCompactUnwind()
391 for (const Reloc &r : d->unwindEntry()->relocs) { in relocateCompactUnwind()
401 // encode them as 2-bit indices into a small array.
409 uint32_t personalityIndex; // 1-based index in encodePersonalities()
414 personalityIndex = personalities.size(); in encodePersonalities()
420 if (personalities.size() > 3) in encodePersonalities()
421 error("too many personalities (" + Twine(personalities.size()) + in encodePersonalities()
429 // stack size. This case is like the previous, except the stack size is too in canFoldEncoding()
440 if ((target->cpuType == CPU_TYPE_X86_64 || target->cpuType == CPU_TYPE_X86) && in canFoldEncoding()
463 cuEntries.resize(symbols.size()); in finalize()
470 // Rather than sort & fold the 32-byte entries directly, we create a in finalize()
472 cuIndices.resize(cuEntries.size()); in finalize()
483 // We use three iterators on the same cuIndices to fold in-situ: in finalize()
485 // (2) `foldEnd` is the first non-matching entry after `foldBegin`. in finalize()
486 // The semi-open interval [ foldBegin .. foldEnd ) contains a range in finalize()
492 // Common LSDA encodings (e.g. for C++ and Objective-C) contain offsets from in finalize()
514 // is just a no-op without LSDA), so we still check for personality in finalize()
540 // to maintain parity with validate-unwind-info.py in finalize()
547 // indexes 127..255 are local to each second-level page in finalize()
548 if (commonEncodings.size() > COMMON_ENCODINGS_MAX) in finalize()
551 // Create a map from encoding to common-encoding-table index in finalize()
552 for (size_t i = 0; i < commonEncodings.size(); i++) in finalize()
555 // Split folded encodings into pages, where each page is limited by ... in finalize()
557 // (b) 24-bit difference between first & final function address in finalize()
558 // (c) 8-bit compact-encoding-table index, in finalize()
559 // for which 0..126 references the global common-encodings table, in finalize()
560 // and 127..255 references a local per-second-level-page table. in finalize()
563 for (size_t i = 0; i < cuIndices.size();) { in finalize()
566 SecondLevelPage &page = secondLevelPages.back(); in finalize() local
567 page.entryIndex = i; in finalize()
570 size_t n = commonEncodings.size(); in finalize()
572 SECOND_LEVEL_PAGE_WORDS - in finalize()
575 while (wordsRemaining >= 1 && i < cuIndices.size()) { in finalize()
578 if (cuPtr->functionAddress >= functionAddressMax) in finalize()
580 if (commonEncodingIndexes.count(cuPtr->encoding) || in finalize()
581 page.localEncodingIndexes.count(cuPtr->encoding)) { in finalize()
583 wordsRemaining--; in finalize()
585 page.localEncodings.emplace_back(cuPtr->encoding); in finalize()
586 page.localEncodingIndexes[cuPtr->encoding] = n++; in finalize()
588 wordsRemaining -= 2; in finalize()
593 page.entryCount = i - page.entryIndex; in finalize()
595 // If this is not the final page, see if it's possible to fit more entries in finalize()
598 if (i < cuIndices.size() && in finalize()
599 page.entryCount < REGULAR_SECOND_LEVEL_ENTRIES_MAX) { in finalize()
600 page.kind = UNWIND_SECOND_LEVEL_REGULAR; in finalize()
601 page.entryCount = std::min(REGULAR_SECOND_LEVEL_ENTRIES_MAX, in finalize()
602 cuIndices.size() - page.entryIndex); in finalize()
603 i = page.entryIndex + page.entryCount; in finalize()
605 page.kind = UNWIND_SECOND_LEVEL_COMPRESSED; in finalize()
610 lsdaIndex[idx] = entriesWithLsda.size(); in finalize()
615 // compute size of __TEXT,__unwind_info section in finalize()
617 commonEncodings.size() * sizeof(uint32_t) + in finalize()
618 personalities.size() * sizeof(uint32_t) + in finalize()
619 // The extra second-level-page entry is for the sentinel in finalize()
620 (secondLevelPages.size() + 1) * in finalize()
622 entriesWithLsda.size() * in finalize()
625 level2PagesOffset + secondLevelPages.size() * SECOND_LEVEL_PAGE_BYTES; in finalize()
635 uip->version = 1; in writeTo()
636 uip->commonEncodingsArraySectionOffset = sizeof(unwind_info_section_header); in writeTo()
637 uip->commonEncodingsArrayCount = commonEncodings.size(); in writeTo()
638 uip->personalityArraySectionOffset = in writeTo()
639 uip->commonEncodingsArraySectionOffset + in writeTo()
640 (uip->commonEncodingsArrayCount * sizeof(uint32_t)); in writeTo()
641 uip->personalityArrayCount = personalities.size(); in writeTo()
642 uip->indexSectionOffset = uip->personalityArraySectionOffset + in writeTo()
643 (uip->personalityArrayCount * sizeof(uint32_t)); in writeTo()
644 uip->indexCount = secondLevelPages.size() + 1; in writeTo()
653 *i32p++ = personality->getGotVA() - in.header->addr; in writeTo()
658 // Level-1 index in writeTo()
660 uip->indexSectionOffset + in writeTo()
661 uip->indexCount * sizeof(unwind_info_section_header_index_entry); in writeTo()
664 for (const SecondLevelPage &page : secondLevelPages) { in writeTo() local
665 size_t idx = cuIndices[page.entryIndex]; in writeTo()
666 iep->functionOffset = cuEntries[idx].functionAddress - in.header->addr; in writeTo()
667 iep->secondLevelPagesSectionOffset = l2PagesOffset; in writeTo()
668 iep->lsdaIndexArraySectionOffset = in writeTo()
674 // Level-1 sentinel in writeTo()
678 iep->functionOffset = cueEndBoundary - in.header->addr; in writeTo()
679 iep->secondLevelPagesSectionOffset = 0; in writeTo()
680 iep->lsdaIndexArraySectionOffset = in writeTo()
681 lsdaOffset + entriesWithLsda.size() * in writeTo()
690 lep->lsdaOffset = cu.lsda->getVA(/*off=*/0) - in.header->addr; in writeTo()
691 lep->functionOffset = cu.functionAddress - in.header->addr; in writeTo()
695 // Level-2 pages in writeTo()
697 for (const SecondLevelPage &page : secondLevelPages) { in writeTo() local
698 if (page.kind == UNWIND_SECOND_LEVEL_COMPRESSED) { in writeTo()
700 cuEntries[cuIndices[page.entryIndex]].functionAddress; in writeTo()
704 p2p->kind = page.kind; in writeTo()
705 p2p->entryPageOffset = in writeTo()
707 p2p->entryCount = page.entryCount; in writeTo()
708 p2p->encodingsPageOffset = in writeTo()
709 p2p->entryPageOffset + p2p->entryCount * sizeof(uint32_t); in writeTo()
710 p2p->encodingsCount = page.localEncodings.size(); in writeTo()
712 for (size_t i = 0; i < page.entryCount; i++) { in writeTo()
714 cuEntries[cuIndices[page.entryIndex + i]]; in writeTo()
717 it = page.localEncodingIndexes.find(cue.encoding); in writeTo()
718 *ep++ = (it->second << COMPRESSED_ENTRY_FUNC_OFFSET_BITS) | in writeTo()
719 (cue.functionAddress - functionAddressBase); in writeTo()
721 if (!page.localEncodings.empty()) in writeTo()
722 memcpy(ep, page.localEncodings.data(), in writeTo()
723 page.localEncodings.size() * sizeof(uint32_t)); in writeTo()
727 p2p->kind = page.kind; in writeTo()
728 p2p->entryPageOffset = in writeTo()
730 p2p->entryCount = page.entryCount; in writeTo()
732 for (size_t i = 0; i < page.entryCount; i++) { in writeTo()
734 cuEntries[cuIndices[page.entryIndex + i]]; in writeTo()