Path: blob/main/contrib/llvm-project/lld/MachO/UnwindInfoSection.cpp
34869 views
//===- UnwindInfoSection.cpp ----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "UnwindInfoSection.h"9#include "InputSection.h"10#include "Layout.h"11#include "OutputSection.h"12#include "OutputSegment.h"13#include "SymbolTable.h"14#include "Symbols.h"15#include "SyntheticSections.h"16#include "Target.h"1718#include "lld/Common/ErrorHandler.h"19#include "lld/Common/Memory.h"20#include "llvm/ADT/DenseMap.h"21#include "llvm/ADT/STLExtras.h"22#include "llvm/BinaryFormat/MachO.h"23#include "llvm/Support/Parallel.h"2425#include "mach-o/compact_unwind_encoding.h"2627#include <numeric>2829using namespace llvm;30using namespace llvm::MachO;31using namespace llvm::support::endian;32using namespace lld;33using namespace lld::macho;3435#define COMMON_ENCODINGS_MAX 12736#define COMPACT_ENCODINGS_MAX 2563738#define SECOND_LEVEL_PAGE_BYTES 409639#define SECOND_LEVEL_PAGE_WORDS (SECOND_LEVEL_PAGE_BYTES / sizeof(uint32_t))40#define REGULAR_SECOND_LEVEL_ENTRIES_MAX \41((SECOND_LEVEL_PAGE_BYTES - \42sizeof(unwind_info_regular_second_level_page_header)) / \43sizeof(unwind_info_regular_second_level_entry))44#define COMPRESSED_SECOND_LEVEL_ENTRIES_MAX \45((SECOND_LEVEL_PAGE_BYTES - \46sizeof(unwind_info_compressed_second_level_page_header)) / \47sizeof(uint32_t))4849#define COMPRESSED_ENTRY_FUNC_OFFSET_BITS 2450#define COMPRESSED_ENTRY_FUNC_OFFSET_MASK \51UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(~0)5253static_assert(static_cast<uint32_t>(UNWIND_X86_64_DWARF_SECTION_OFFSET) ==54static_cast<uint32_t>(UNWIND_ARM64_DWARF_SECTION_OFFSET) &&55static_cast<uint32_t>(UNWIND_X86_64_DWARF_SECTION_OFFSET) ==56static_cast<uint32_t>(UNWIND_X86_DWARF_SECTION_OFFSET));5758constexpr uint64_t DWARF_SECTION_OFFSET = UNWIND_X86_64_DWARF_SECTION_OFFSET;5960// Compact Unwind format is a Mach-O evolution of DWARF Unwind that61// optimizes space and exception-time lookup. Most DWARF unwind62// entries can be replaced with Compact Unwind entries, but the ones63// that cannot are retained in DWARF form.64//65// This comment will address macro-level organization of the pre-link66// and post-link compact unwind tables. For micro-level organization67// pertaining to the bitfield layout of the 32-bit compact unwind68// entries, see libunwind/include/mach-o/compact_unwind_encoding.h69//70// Important clarifying factoids:71//72// * __LD,__compact_unwind is the compact unwind format for compiler73// output and linker input. It is never a final output. It could be74// an intermediate output with the `-r` option which retains relocs.75//76// * __TEXT,__unwind_info is the compact unwind format for final77// linker output. It is never an input.78//79// * __TEXT,__eh_frame is the DWARF format for both linker input and output.80//81// * __TEXT,__unwind_info entries are divided into 4 KiB pages (2nd82// level) by ascending address, and the pages are referenced by an83// index (1st level) in the section header.84//85// * Following the headers in __TEXT,__unwind_info, the bulk of the86// section contains a vector of compact unwind entries87// `{functionOffset, encoding}` sorted by ascending `functionOffset`.88// Adjacent entries with the same encoding can be folded to great89// advantage, achieving a 3-order-of-magnitude reduction in the90// number of entries.91//92// Refer to the definition of unwind_info_section_header in93// compact_unwind_encoding.h for an overview of the format we are encoding94// here.9596// TODO(gkm): how do we align the 2nd-level pages?9798// The various fields in the on-disk representation of each compact unwind99// entry.100#define FOR_EACH_CU_FIELD(DO) \101DO(Ptr, functionAddress) \102DO(uint32_t, functionLength) \103DO(compact_unwind_encoding_t, encoding) \104DO(Ptr, personality) \105DO(Ptr, lsda)106107CREATE_LAYOUT_CLASS(CompactUnwind, FOR_EACH_CU_FIELD);108109#undef FOR_EACH_CU_FIELD110111// LLD's internal representation of a compact unwind entry.112struct CompactUnwindEntry {113uint64_t functionAddress;114uint32_t functionLength;115compact_unwind_encoding_t encoding;116Symbol *personality;117InputSection *lsda;118};119120using EncodingMap = DenseMap<compact_unwind_encoding_t, size_t>;121122struct SecondLevelPage {123uint32_t kind;124size_t entryIndex;125size_t entryCount;126size_t byteCount;127std::vector<compact_unwind_encoding_t> localEncodings;128EncodingMap localEncodingIndexes;129};130131// UnwindInfoSectionImpl allows us to avoid cluttering our header file with a132// lengthy definition of UnwindInfoSection.133class UnwindInfoSectionImpl final : public UnwindInfoSection {134public:135UnwindInfoSectionImpl() : cuLayout(target->wordSize) {}136uint64_t getSize() const override { return unwindInfoSize; }137void prepare() override;138void finalize() override;139void writeTo(uint8_t *buf) const override;140141private:142void prepareRelocations(ConcatInputSection *);143void relocateCompactUnwind(std::vector<CompactUnwindEntry> &);144void encodePersonalities();145Symbol *canonicalizePersonality(Symbol *);146147uint64_t unwindInfoSize = 0;148SmallVector<decltype(symbols)::value_type, 0> symbolsVec;149CompactUnwindLayout cuLayout;150std::vector<std::pair<compact_unwind_encoding_t, size_t>> commonEncodings;151EncodingMap commonEncodingIndexes;152// The entries here will be in the same order as their originating symbols153// in symbolsVec.154std::vector<CompactUnwindEntry> cuEntries;155// Indices into the cuEntries vector.156std::vector<size_t> cuIndices;157std::vector<Symbol *> personalities;158SmallDenseMap<std::pair<InputSection *, uint64_t /* addend */>, Symbol *>159personalityTable;160// Indices into cuEntries for CUEs with a non-null LSDA.161std::vector<size_t> entriesWithLsda;162// Map of cuEntries index to an index within the LSDA array.163DenseMap<size_t, uint32_t> lsdaIndex;164std::vector<SecondLevelPage> secondLevelPages;165uint64_t level2PagesOffset = 0;166// The highest-address function plus its size. The unwinder needs this to167// determine the address range that is covered by unwind info.168uint64_t cueEndBoundary = 0;169};170171UnwindInfoSection::UnwindInfoSection()172: SyntheticSection(segment_names::text, section_names::unwindInfo) {173align = 4;174}175176// Record function symbols that may need entries emitted in __unwind_info, which177// stores unwind data for address ranges.178//179// Note that if several adjacent functions have the same unwind encoding and180// personality function and no LSDA, they share one unwind entry. For this to181// work, functions without unwind info need explicit "no unwind info" unwind182// entries -- else the unwinder would think they have the unwind info of the183// closest function with unwind info right before in the image. Thus, we add184// function symbols for each unique address regardless of whether they have185// associated unwind info.186void UnwindInfoSection::addSymbol(const Defined *d) {187if (d->unwindEntry())188allEntriesAreOmitted = false;189// We don't yet know the final output address of this symbol, but we know that190// they are uniquely determined by a combination of the isec and value, so191// we use that as the key here.192auto p = symbols.insert({{d->isec(), d->value}, d});193// If we have multiple symbols at the same address, only one of them can have194// an associated unwind entry.195if (!p.second && d->unwindEntry()) {196assert(p.first->second == d || !p.first->second->unwindEntry());197p.first->second = d;198}199}200201void UnwindInfoSectionImpl::prepare() {202// This iteration needs to be deterministic, since prepareRelocations may add203// entries to the GOT. Hence the use of a MapVector for204// UnwindInfoSection::symbols.205for (const Defined *d : make_second_range(symbols))206if (d->unwindEntry()) {207if (d->unwindEntry()->getName() == section_names::compactUnwind) {208prepareRelocations(d->unwindEntry());209} else {210// We don't have to add entries to the GOT here because FDEs have211// explicit GOT relocations, so Writer::scanRelocations() will add those212// GOT entries. However, we still need to canonicalize the personality213// pointers (like prepareRelocations() does for CU entries) in order214// to avoid overflowing the 3-personality limit.215FDE &fde = cast<ObjFile>(d->getFile())->fdes[d->unwindEntry()];216fde.personality = canonicalizePersonality(fde.personality);217}218}219}220221// Compact unwind relocations have different semantics, so we handle them in a222// separate code path from regular relocations. First, we do not wish to add223// rebase opcodes for __LD,__compact_unwind, because that section doesn't224// actually end up in the final binary. Second, personality pointers always225// reside in the GOT and must be treated specially.226void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) {227assert(!isec->shouldOmitFromOutput() &&228"__compact_unwind section should not be omitted");229230// FIXME: Make this skip relocations for CompactUnwindEntries that231// point to dead-stripped functions. That might save some amount of232// work. But since there are usually just few personality functions233// that are referenced from many places, at least some of them likely234// live, it wouldn't reduce number of got entries.235for (size_t i = 0; i < isec->relocs.size(); ++i) {236Reloc &r = isec->relocs[i];237assert(target->hasAttr(r.type, RelocAttrBits::UNSIGNED));238// Since compact unwind sections aren't part of the inputSections vector,239// they don't get canonicalized by scanRelocations(), so we have to do the240// canonicalization here.241if (auto *referentIsec = r.referent.dyn_cast<InputSection *>())242r.referent = referentIsec->canonical();243244// Functions and LSDA entries always reside in the same object file as the245// compact unwind entries that references them, and thus appear as section246// relocs. There is no need to prepare them. We only prepare relocs for247// personality functions.248if (r.offset != cuLayout.personalityOffset)249continue;250251if (auto *s = r.referent.dyn_cast<Symbol *>()) {252// Personality functions are nearly always system-defined (e.g.,253// ___gxx_personality_v0 for C++) and relocated as dylib symbols. When an254// application provides its own personality function, it might be255// referenced by an extern Defined symbol reloc, or a local section reloc.256if (auto *defined = dyn_cast<Defined>(s)) {257// XXX(vyng) This is a special case for handling duplicate personality258// symbols. Note that LD64's behavior is a bit different and it is259// inconsistent with how symbol resolution usually work260//261// So we've decided not to follow it. Instead, simply pick the symbol262// with the same name from the symbol table to replace the local one.263//264// (See discussions/alternatives already considered on D107533)265if (!defined->isExternal())266if (Symbol *sym = symtab->find(defined->getName()))267if (!sym->isLazy())268r.referent = s = sym;269}270if (auto *undefined = dyn_cast<Undefined>(s)) {271treatUndefinedSymbol(*undefined, isec, r.offset);272// treatUndefinedSymbol() can replace s with a DylibSymbol; re-check.273if (isa<Undefined>(s))274continue;275}276277// Similar to canonicalizePersonality(), but we also register a GOT entry.278if (auto *defined = dyn_cast<Defined>(s)) {279// Check if we have created a synthetic symbol at the same address.280Symbol *&personality =281personalityTable[{defined->isec(), defined->value}];282if (personality == nullptr) {283personality = defined;284in.got->addEntry(defined);285} else if (personality != defined) {286r.referent = personality;287}288continue;289}290291assert(isa<DylibSymbol>(s));292in.got->addEntry(s);293continue;294}295296if (auto *referentIsec = r.referent.dyn_cast<InputSection *>()) {297assert(!isCoalescedWeak(referentIsec));298// Personality functions can be referenced via section relocations299// if they live in the same object file. Create placeholder synthetic300// symbols for them in the GOT. If the corresponding symbol is already301// in the GOT, use that to avoid creating a duplicate entry. All GOT302// entries needed by non-unwind sections will have already been added303// by this point.304Symbol *&s = personalityTable[{referentIsec, r.addend}];305if (s == nullptr) {306Defined *const *gotEntry =307llvm::find_if(referentIsec->symbols, [&](Defined const *d) {308return d->value == static_cast<uint64_t>(r.addend) &&309d->isInGot();310});311if (gotEntry != referentIsec->symbols.end()) {312s = *gotEntry;313} else {314// This runs after dead stripping, so the noDeadStrip argument does315// not matter.316s = make<Defined>("<internal>", /*file=*/nullptr, referentIsec,317r.addend, /*size=*/0, /*isWeakDef=*/false,318/*isExternal=*/false, /*isPrivateExtern=*/false,319/*includeInSymtab=*/true,320/*isReferencedDynamically=*/false,321/*noDeadStrip=*/false);322s->used = true;323in.got->addEntry(s);324}325}326r.referent = s;327r.addend = 0;328}329}330}331332Symbol *UnwindInfoSectionImpl::canonicalizePersonality(Symbol *personality) {333if (auto *defined = dyn_cast_or_null<Defined>(personality)) {334// Check if we have created a synthetic symbol at the same address.335Symbol *&synth = personalityTable[{defined->isec(), defined->value}];336if (synth == nullptr)337synth = defined;338else if (synth != defined)339return synth;340}341return personality;342}343344// We need to apply the relocations to the pre-link compact unwind section345// before converting it to post-link form. There should only be absolute346// relocations here: since we are not emitting the pre-link CU section, there347// is no source address to make a relative location meaningful.348void UnwindInfoSectionImpl::relocateCompactUnwind(349std::vector<CompactUnwindEntry> &cuEntries) {350parallelFor(0, symbolsVec.size(), [&](size_t i) {351CompactUnwindEntry &cu = cuEntries[i];352const Defined *d = symbolsVec[i].second;353cu.functionAddress = d->getVA();354if (!d->unwindEntry())355return;356357// If we have DWARF unwind info, create a slimmed-down CU entry that points358// to it.359if (d->unwindEntry()->getName() == section_names::ehFrame) {360// The unwinder will look for the DWARF entry starting at the hint,361// assuming the hint points to a valid CFI record start. If it362// fails to find the record, it proceeds in a linear search through the363// contiguous CFI records from the hint until the end of the section.364// Ideally, in the case where the offset is too large to be encoded, we365// would instead encode the largest possible offset to a valid CFI record,366// but since we don't keep track of that, just encode zero -- the start of367// the section is always the start of a CFI record.368uint64_t dwarfOffsetHint =369d->unwindEntry()->outSecOff <= DWARF_SECTION_OFFSET370? d->unwindEntry()->outSecOff371: 0;372cu.encoding = target->modeDwarfEncoding | dwarfOffsetHint;373const FDE &fde = cast<ObjFile>(d->getFile())->fdes[d->unwindEntry()];374cu.functionLength = fde.funcLength;375// Omit the DWARF personality from compact-unwind entry so that we376// don't need to encode it.377cu.personality = nullptr;378cu.lsda = fde.lsda;379return;380}381382assert(d->unwindEntry()->getName() == section_names::compactUnwind);383384auto buf =385reinterpret_cast<const uint8_t *>(d->unwindEntry()->data.data()) -386target->wordSize;387cu.functionLength =388support::endian::read32le(buf + cuLayout.functionLengthOffset);389cu.encoding = support::endian::read32le(buf + cuLayout.encodingOffset);390for (const Reloc &r : d->unwindEntry()->relocs) {391if (r.offset == cuLayout.personalityOffset)392cu.personality = r.referent.get<Symbol *>();393else if (r.offset == cuLayout.lsdaOffset)394cu.lsda = r.getReferentInputSection();395}396});397}398399// There should only be a handful of unique personality pointers, so we can400// encode them as 2-bit indices into a small array.401void UnwindInfoSectionImpl::encodePersonalities() {402for (size_t idx : cuIndices) {403CompactUnwindEntry &cu = cuEntries[idx];404if (cu.personality == nullptr)405continue;406// Linear search is fast enough for a small array.407auto it = find(personalities, cu.personality);408uint32_t personalityIndex; // 1-based index409if (it != personalities.end()) {410personalityIndex = std::distance(personalities.begin(), it) + 1;411} else {412personalities.push_back(cu.personality);413personalityIndex = personalities.size();414}415cu.encoding |=416personalityIndex << llvm::countr_zero(417static_cast<compact_unwind_encoding_t>(UNWIND_PERSONALITY_MASK));418}419if (personalities.size() > 3)420error("too many personalities (" + Twine(personalities.size()) +421") for compact unwind to encode");422}423424static bool canFoldEncoding(compact_unwind_encoding_t encoding) {425// From compact_unwind_encoding.h:426// UNWIND_X86_64_MODE_STACK_IND:427// A "frameless" (RBP not used as frame pointer) function large constant428// stack size. This case is like the previous, except the stack size is too429// large to encode in the compact unwind encoding. Instead it requires that430// the function contains "subq $nnnnnnnn,RSP" in its prolog. The compact431// encoding contains the offset to the nnnnnnnn value in the function in432// UNWIND_X86_64_FRAMELESS_STACK_SIZE.433// Since this means the unwinder has to look at the `subq` in the function434// of the unwind info's unwind address, two functions that have identical435// unwind info can't be folded if it's using this encoding since both436// entries need unique addresses.437static_assert(static_cast<uint32_t>(UNWIND_X86_64_MODE_STACK_IND) ==438static_cast<uint32_t>(UNWIND_X86_MODE_STACK_IND));439if ((target->cpuType == CPU_TYPE_X86_64 || target->cpuType == CPU_TYPE_X86) &&440(encoding & UNWIND_MODE_MASK) == UNWIND_X86_64_MODE_STACK_IND) {441// FIXME: Consider passing in the two function addresses and getting442// their two stack sizes off the `subq` and only returning false if they're443// actually different.444return false;445}446return true;447}448449// Scan the __LD,__compact_unwind entries and compute the space needs of450// __TEXT,__unwind_info and __TEXT,__eh_frame.451void UnwindInfoSectionImpl::finalize() {452if (symbols.empty())453return;454455// At this point, the address space for __TEXT,__text has been456// assigned, so we can relocate the __LD,__compact_unwind entries457// into a temporary buffer. Relocation is necessary in order to sort458// the CU entries by function address. Sorting is necessary so that459// we can fold adjacent CU entries with identical encoding+personality460// and without any LSDA. Folding is necessary because it reduces the461// number of CU entries by as much as 3 orders of magnitude!462cuEntries.resize(symbols.size());463// The "map" part of the symbols MapVector was only needed for deduplication464// in addSymbol(). Now that we are done adding, move the contents to a plain465// std::vector for indexed access.466symbolsVec = symbols.takeVector();467relocateCompactUnwind(cuEntries);468469// Rather than sort & fold the 32-byte entries directly, we create a470// vector of indices to entries and sort & fold that instead.471cuIndices.resize(cuEntries.size());472std::iota(cuIndices.begin(), cuIndices.end(), 0);473llvm::sort(cuIndices, [&](size_t a, size_t b) {474return cuEntries[a].functionAddress < cuEntries[b].functionAddress;475});476477// Record the ending boundary before we fold the entries.478cueEndBoundary = cuEntries[cuIndices.back()].functionAddress +479cuEntries[cuIndices.back()].functionLength;480481// Fold adjacent entries with matching encoding+personality and without LSDA482// We use three iterators on the same cuIndices to fold in-situ:483// (1) `foldBegin` is the first of a potential sequence of matching entries484// (2) `foldEnd` is the first non-matching entry after `foldBegin`.485// The semi-open interval [ foldBegin .. foldEnd ) contains a range486// entries that can be folded into a single entry and written to ...487// (3) `foldWrite`488auto foldWrite = cuIndices.begin();489for (auto foldBegin = cuIndices.begin(); foldBegin < cuIndices.end();) {490auto foldEnd = foldBegin;491// Common LSDA encodings (e.g. for C++ and Objective-C) contain offsets from492// a base address. The base address is normally not contained directly in493// the LSDA, and in that case, the personality function treats the starting494// address of the function (which is computed by the unwinder) as the base495// address and interprets the LSDA accordingly. The unwinder computes the496// starting address of a function as the address associated with its CU497// entry. For this reason, we cannot fold adjacent entries if they have an498// LSDA, because folding would make the unwinder compute the wrong starting499// address for the functions with the folded entries, which in turn would500// cause the personality function to misinterpret the LSDA for those501// functions. In the very rare case where the base address is encoded502// directly in the LSDA, two functions at different addresses would503// necessarily have different LSDAs, so their CU entries would not have been504// folded anyway.505while (++foldEnd < cuIndices.end() &&506cuEntries[*foldBegin].encoding == cuEntries[*foldEnd].encoding &&507!cuEntries[*foldBegin].lsda && !cuEntries[*foldEnd].lsda &&508// If we've gotten to this point, we don't have an LSDA, which should509// also imply that we don't have a personality function, since in all510// likelihood a personality function needs the LSDA to do anything511// useful. It can be technically valid to have a personality function512// and no LSDA though (e.g. the C++ personality __gxx_personality_v0513// is just a no-op without LSDA), so we still check for personality514// function equivalence to handle that case.515cuEntries[*foldBegin].personality ==516cuEntries[*foldEnd].personality &&517canFoldEncoding(cuEntries[*foldEnd].encoding))518;519*foldWrite++ = *foldBegin;520foldBegin = foldEnd;521}522cuIndices.erase(foldWrite, cuIndices.end());523524encodePersonalities();525526// Count frequencies of the folded encodings527EncodingMap encodingFrequencies;528for (size_t idx : cuIndices)529encodingFrequencies[cuEntries[idx].encoding]++;530531// Make a vector of encodings, sorted by descending frequency532for (const auto &frequency : encodingFrequencies)533commonEncodings.emplace_back(frequency);534llvm::sort(commonEncodings,535[](const std::pair<compact_unwind_encoding_t, size_t> &a,536const std::pair<compact_unwind_encoding_t, size_t> &b) {537if (a.second == b.second)538// When frequencies match, secondarily sort on encoding539// to maintain parity with validate-unwind-info.py540return a.first > b.first;541return a.second > b.second;542});543544// Truncate the vector to 127 elements.545// Common encoding indexes are limited to 0..126, while encoding546// indexes 127..255 are local to each second-level page547if (commonEncodings.size() > COMMON_ENCODINGS_MAX)548commonEncodings.resize(COMMON_ENCODINGS_MAX);549550// Create a map from encoding to common-encoding-table index551for (size_t i = 0; i < commonEncodings.size(); i++)552commonEncodingIndexes[commonEncodings[i].first] = i;553554// Split folded encodings into pages, where each page is limited by ...555// (a) 4 KiB capacity556// (b) 24-bit difference between first & final function address557// (c) 8-bit compact-encoding-table index,558// for which 0..126 references the global common-encodings table,559// and 127..255 references a local per-second-level-page table.560// First we try the compact format and determine how many entries fit.561// If more entries fit in the regular format, we use that.562for (size_t i = 0; i < cuIndices.size();) {563size_t idx = cuIndices[i];564secondLevelPages.emplace_back();565SecondLevelPage &page = secondLevelPages.back();566page.entryIndex = i;567uint64_t functionAddressMax =568cuEntries[idx].functionAddress + COMPRESSED_ENTRY_FUNC_OFFSET_MASK;569size_t n = commonEncodings.size();570size_t wordsRemaining =571SECOND_LEVEL_PAGE_WORDS -572sizeof(unwind_info_compressed_second_level_page_header) /573sizeof(uint32_t);574while (wordsRemaining >= 1 && i < cuIndices.size()) {575idx = cuIndices[i];576const CompactUnwindEntry *cuPtr = &cuEntries[idx];577if (cuPtr->functionAddress >= functionAddressMax)578break;579if (commonEncodingIndexes.count(cuPtr->encoding) ||580page.localEncodingIndexes.count(cuPtr->encoding)) {581i++;582wordsRemaining--;583} else if (wordsRemaining >= 2 && n < COMPACT_ENCODINGS_MAX) {584page.localEncodings.emplace_back(cuPtr->encoding);585page.localEncodingIndexes[cuPtr->encoding] = n++;586i++;587wordsRemaining -= 2;588} else {589break;590}591}592page.entryCount = i - page.entryIndex;593594// If this is not the final page, see if it's possible to fit more entries595// by using the regular format. This can happen when there are many unique596// encodings, and we saturated the local encoding table early.597if (i < cuIndices.size() &&598page.entryCount < REGULAR_SECOND_LEVEL_ENTRIES_MAX) {599page.kind = UNWIND_SECOND_LEVEL_REGULAR;600page.entryCount = std::min(REGULAR_SECOND_LEVEL_ENTRIES_MAX,601cuIndices.size() - page.entryIndex);602i = page.entryIndex + page.entryCount;603} else {604page.kind = UNWIND_SECOND_LEVEL_COMPRESSED;605}606}607608for (size_t idx : cuIndices) {609lsdaIndex[idx] = entriesWithLsda.size();610if (cuEntries[idx].lsda)611entriesWithLsda.push_back(idx);612}613614// compute size of __TEXT,__unwind_info section615level2PagesOffset = sizeof(unwind_info_section_header) +616commonEncodings.size() * sizeof(uint32_t) +617personalities.size() * sizeof(uint32_t) +618// The extra second-level-page entry is for the sentinel619(secondLevelPages.size() + 1) *620sizeof(unwind_info_section_header_index_entry) +621entriesWithLsda.size() *622sizeof(unwind_info_section_header_lsda_index_entry);623unwindInfoSize =624level2PagesOffset + secondLevelPages.size() * SECOND_LEVEL_PAGE_BYTES;625}626627// All inputs are relocated and output addresses are known, so write!628629void UnwindInfoSectionImpl::writeTo(uint8_t *buf) const {630assert(!cuIndices.empty() && "call only if there is unwind info");631632// section header633auto *uip = reinterpret_cast<unwind_info_section_header *>(buf);634uip->version = 1;635uip->commonEncodingsArraySectionOffset = sizeof(unwind_info_section_header);636uip->commonEncodingsArrayCount = commonEncodings.size();637uip->personalityArraySectionOffset =638uip->commonEncodingsArraySectionOffset +639(uip->commonEncodingsArrayCount * sizeof(uint32_t));640uip->personalityArrayCount = personalities.size();641uip->indexSectionOffset = uip->personalityArraySectionOffset +642(uip->personalityArrayCount * sizeof(uint32_t));643uip->indexCount = secondLevelPages.size() + 1;644645// Common encodings646auto *i32p = reinterpret_cast<uint32_t *>(&uip[1]);647for (const auto &encoding : commonEncodings)648*i32p++ = encoding.first;649650// Personalities651for (const Symbol *personality : personalities)652*i32p++ = personality->getGotVA() - in.header->addr;653654// FIXME: LD64 checks and warns aboutgaps or overlapse in cuEntries address655// ranges. We should do the same too656657// Level-1 index658uint32_t lsdaOffset =659uip->indexSectionOffset +660uip->indexCount * sizeof(unwind_info_section_header_index_entry);661uint64_t l2PagesOffset = level2PagesOffset;662auto *iep = reinterpret_cast<unwind_info_section_header_index_entry *>(i32p);663for (const SecondLevelPage &page : secondLevelPages) {664size_t idx = cuIndices[page.entryIndex];665iep->functionOffset = cuEntries[idx].functionAddress - in.header->addr;666iep->secondLevelPagesSectionOffset = l2PagesOffset;667iep->lsdaIndexArraySectionOffset =668lsdaOffset + lsdaIndex.lookup(idx) *669sizeof(unwind_info_section_header_lsda_index_entry);670iep++;671l2PagesOffset += SECOND_LEVEL_PAGE_BYTES;672}673// Level-1 sentinel674// XXX(vyng): Note that LD64 adds +1 here.675// Unsure whether it's a bug or it's their workaround for something else.676// See comments from https://reviews.llvm.org/D138320.677iep->functionOffset = cueEndBoundary - in.header->addr;678iep->secondLevelPagesSectionOffset = 0;679iep->lsdaIndexArraySectionOffset =680lsdaOffset + entriesWithLsda.size() *681sizeof(unwind_info_section_header_lsda_index_entry);682iep++;683684// LSDAs685auto *lep =686reinterpret_cast<unwind_info_section_header_lsda_index_entry *>(iep);687for (size_t idx : entriesWithLsda) {688const CompactUnwindEntry &cu = cuEntries[idx];689lep->lsdaOffset = cu.lsda->getVA(/*off=*/0) - in.header->addr;690lep->functionOffset = cu.functionAddress - in.header->addr;691lep++;692}693694// Level-2 pages695auto *pp = reinterpret_cast<uint32_t *>(lep);696for (const SecondLevelPage &page : secondLevelPages) {697if (page.kind == UNWIND_SECOND_LEVEL_COMPRESSED) {698uintptr_t functionAddressBase =699cuEntries[cuIndices[page.entryIndex]].functionAddress;700auto *p2p =701reinterpret_cast<unwind_info_compressed_second_level_page_header *>(702pp);703p2p->kind = page.kind;704p2p->entryPageOffset =705sizeof(unwind_info_compressed_second_level_page_header);706p2p->entryCount = page.entryCount;707p2p->encodingsPageOffset =708p2p->entryPageOffset + p2p->entryCount * sizeof(uint32_t);709p2p->encodingsCount = page.localEncodings.size();710auto *ep = reinterpret_cast<uint32_t *>(&p2p[1]);711for (size_t i = 0; i < page.entryCount; i++) {712const CompactUnwindEntry &cue =713cuEntries[cuIndices[page.entryIndex + i]];714auto it = commonEncodingIndexes.find(cue.encoding);715if (it == commonEncodingIndexes.end())716it = page.localEncodingIndexes.find(cue.encoding);717*ep++ = (it->second << COMPRESSED_ENTRY_FUNC_OFFSET_BITS) |718(cue.functionAddress - functionAddressBase);719}720if (!page.localEncodings.empty())721memcpy(ep, page.localEncodings.data(),722page.localEncodings.size() * sizeof(uint32_t));723} else {724auto *p2p =725reinterpret_cast<unwind_info_regular_second_level_page_header *>(pp);726p2p->kind = page.kind;727p2p->entryPageOffset =728sizeof(unwind_info_regular_second_level_page_header);729p2p->entryCount = page.entryCount;730auto *ep = reinterpret_cast<uint32_t *>(&p2p[1]);731for (size_t i = 0; i < page.entryCount; i++) {732const CompactUnwindEntry &cue =733cuEntries[cuIndices[page.entryIndex + i]];734*ep++ = cue.functionAddress;735*ep++ = cue.encoding;736}737}738pp += SECOND_LEVEL_PAGE_WORDS;739}740}741742UnwindInfoSection *macho::makeUnwindInfoSection() {743return make<UnwindInfoSectionImpl>();744}745746747