Lines Matching +full:page +full:- +full:level

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.
83 // level) by ascending address, and the pages are referenced by an
84 // index (1st level) in the section header.
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) {}
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())
193 auto p = symbols.insert({{d->isec(), d->value}, d});
196 if (!p.second && d->unwindEntry()) {
197 assert(p.first->second == d || !p.first->second->unwindEntry());
198 p.first->second = d;
207 if (d->unwindEntry()) {
208 if (d->unwindEntry()->getName() == section_names::compactUnwind) {
209 prepareRelocations(d->unwindEntry());
215 // to avoid overflowing the 3-personality limit.
216 FDE &fde = cast<ObjFile>(d->getFile())->fdes[d->unwindEntry()];
228 assert(!isec->shouldOmitFromOutput() &&
232 // point to dead-stripped functions. That might save some amount of
236 for (size_t i = 0; i < isec->relocs.size(); ++i) {
237 Reloc &r = isec->relocs[i];
238 assert(target->hasAttr(r.type, RelocAttrBits::UNSIGNED));
243 r.referent = referentIsec->canonical();
253 // Personality functions are nearly always system-defined (e.g.,
266 if (!defined->isExternal())
267 if (Symbol *sym = symtab->find(defined->getName()))
268 if (!sym->isLazy())
273 // treatUndefinedSymbol() can replace s with a DylibSymbol; re-check.
282 personalityTable[{defined->isec(), defined->value}];
285 in.got->addEntry(defined);
293 in.got->addEntry(s);
303 // entries needed by non-unwind sections will have already been added
308 llvm::find_if(referentIsec->symbols, [&](Defined const *d) {
309 return d->value == static_cast<uint64_t>(r.addend) &&
310 d->isInGot();
312 if (gotEntry != referentIsec->symbols.end()) {
323 s->used = true;
324 in.got->addEntry(s);
336 Symbol *&synth = personalityTable[{defined->isec(), defined->value}];
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
354 cu.functionAddress = d->getVA();
355 if (!d->unwindEntry())
358 // If we have DWARF unwind info, create a slimmed-down CU entry that points
360 if (d->unwindEntry()->getName() == section_names::ehFrame) {
367 // but since we don't keep track of that, just encode zero -- the start of
370 d->unwindEntry()->outSecOff <= DWARF_SECTION_OFFSET
371 ? d->unwindEntry()->outSecOff
373 cu.encoding = target->modeDwarfEncoding | dwarfOffsetHint;
374 const FDE &fde = cast<ObjFile>(d->getFile())->fdes[d->unwindEntry()];
376 // Omit the DWARF personality from compact-unwind entry so that we
383 assert(d->unwindEntry()->getName() == section_names::compactUnwind);
386 reinterpret_cast<const uint8_t *>(d->unwindEntry()->data.data()) -
387 target->wordSize;
391 for (const Reloc &r : d->unwindEntry()->relocs) {
401 // encode them as 2-bit indices into a small array.
409 uint32_t personalityIndex; // 1-based index
440 if ((target->cpuType == CPU_TYPE_X86_64 || target->cpuType == CPU_TYPE_X86) &&
470 // Rather than sort & fold the 32-byte entries directly, we create a
483 // We use three iterators on the same cuIndices to fold in-situ:
485 // (2) `foldEnd` is the first non-matching entry after `foldBegin`.
486 // The semi-open interval [ foldBegin .. foldEnd ) contains a range
492 // Common LSDA encodings (e.g. for C++ and Objective-C) contain offsets from
514 // is just a no-op without LSDA), so we still check for personality
540 // to maintain parity with validate-unwind-info.py
547 // indexes 127..255 are local to each second-level page
551 // Create a map from encoding to common-encoding-table index
555 // Split folded encodings into pages, where each page is limited by ...
557 // (b) 24-bit difference between first & final function address
558 // (c) 8-bit compact-encoding-table index,
559 // for which 0..126 references the global common-encodings table,
560 // and 127..255 references a local per-second-level-page table.
566 SecondLevelPage &page = secondLevelPages.back();
567 page.entryIndex = i;
572 SECOND_LEVEL_PAGE_WORDS -
578 if (cuPtr->functionAddress >= functionAddressMax)
580 if (commonEncodingIndexes.count(cuPtr->encoding) ||
581 page.localEncodingIndexes.count(cuPtr->encoding)) {
583 wordsRemaining--;
585 page.localEncodings.emplace_back(cuPtr->encoding);
586 page.localEncodingIndexes[cuPtr->encoding] = n++;
588 wordsRemaining -= 2;
593 page.entryCount = i - page.entryIndex;
595 // If this is not the final page, see if it's possible to fit more entries
599 page.entryCount < REGULAR_SECOND_LEVEL_ENTRIES_MAX) {
600 page.kind = UNWIND_SECOND_LEVEL_REGULAR;
601 page.entryCount = std::min(REGULAR_SECOND_LEVEL_ENTRIES_MAX,
602 cuIndices.size() - page.entryIndex);
603 i = page.entryIndex + page.entryCount;
605 page.kind = UNWIND_SECOND_LEVEL_COMPRESSED;
619 // The extra second-level-page entry is for the sentinel
635 uip->version = 1;
636 uip->commonEncodingsArraySectionOffset = sizeof(unwind_info_section_header);
637 uip->commonEncodingsArrayCount = commonEncodings.size();
638 uip->personalityArraySectionOffset =
639 uip->commonEncodingsArraySectionOffset +
640 (uip->commonEncodingsArrayCount * sizeof(uint32_t));
641 uip->personalityArrayCount = personalities.size();
642 uip->indexSectionOffset = uip->personalityArraySectionOffset +
643 (uip->personalityArrayCount * sizeof(uint32_t));
644 uip->indexCount = secondLevelPages.size() + 1;
653 *i32p++ = personality->getGotVA() - in.header->addr;
658 // Level-1 index
660 uip->indexSectionOffset +
661 uip->indexCount * sizeof(unwind_info_section_header_index_entry);
664 for (const SecondLevelPage &page : secondLevelPages) {
665 size_t idx = cuIndices[page.entryIndex];
666 iep->functionOffset = cuEntries[idx].functionAddress - in.header->addr;
667 iep->secondLevelPagesSectionOffset = l2PagesOffset;
668 iep->lsdaIndexArraySectionOffset =
674 // Level-1 sentinel
678 iep->functionOffset = cueEndBoundary - in.header->addr;
679 iep->secondLevelPagesSectionOffset = 0;
680 iep->lsdaIndexArraySectionOffset =
690 lep->lsdaOffset = cu.lsda->getVA(/*off=*/0) - in.header->addr;
691 lep->functionOffset = cu.functionAddress - in.header->addr;
695 // Level-2 pages
697 for (const SecondLevelPage &page : secondLevelPages) {
698 if (page.kind == UNWIND_SECOND_LEVEL_COMPRESSED) {
700 cuEntries[cuIndices[page.entryIndex]].functionAddress;
704 p2p->kind = page.kind;
705 p2p->entryPageOffset =
707 p2p->entryCount = page.entryCount;
708 p2p->encodingsPageOffset =
709 p2p->entryPageOffset + p2p->entryCount * sizeof(uint32_t);
710 p2p->encodingsCount = page.localEncodings.size();
712 for (size_t i = 0; i < page.entryCount; i++) {
714 cuEntries[cuIndices[page.entryIndex + i]];
717 it = page.localEncodingIndexes.find(cue.encoding);
718 *ep++ = (it->second << COMPRESSED_ENTRY_FUNC_OFFSET_BITS) |
719 (cue.functionAddress - functionAddressBase);
721 if (!page.localEncodings.empty())
722 memcpy(ep, page.localEncodings.data(),
723 page.localEncodings.size() * sizeof(uint32_t));
727 p2p->kind = page.kind;
728 p2p->entryPageOffset =
730 p2p->entryCount = page.entryCount;
732 for (size_t i = 0; i < page.entryCount; i++) {
734 cuEntries[cuIndices[page.entryIndex + i]];