1 //===- UnwindInfoSection.cpp ----------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "UnwindInfoSection.h" 10 #include "ConcatOutputSection.h" 11 #include "Config.h" 12 #include "InputSection.h" 13 #include "OutputSection.h" 14 #include "OutputSegment.h" 15 #include "SymbolTable.h" 16 #include "Symbols.h" 17 #include "SyntheticSections.h" 18 #include "Target.h" 19 20 #include "lld/Common/ErrorHandler.h" 21 #include "lld/Common/Memory.h" 22 #include "llvm/ADT/STLExtras.h" 23 #include "llvm/ADT/SmallVector.h" 24 #include "llvm/BinaryFormat/MachO.h" 25 26 using namespace llvm; 27 using namespace llvm::MachO; 28 using namespace lld; 29 using namespace lld::macho; 30 31 #define COMMON_ENCODINGS_MAX 127 32 #define COMPACT_ENCODINGS_MAX 256 33 34 #define SECOND_LEVEL_PAGE_BYTES 4096 35 #define SECOND_LEVEL_PAGE_WORDS (SECOND_LEVEL_PAGE_BYTES / sizeof(uint32_t)) 36 #define REGULAR_SECOND_LEVEL_ENTRIES_MAX \ 37 ((SECOND_LEVEL_PAGE_BYTES - \ 38 sizeof(unwind_info_regular_second_level_page_header)) / \ 39 sizeof(unwind_info_regular_second_level_entry)) 40 #define COMPRESSED_SECOND_LEVEL_ENTRIES_MAX \ 41 ((SECOND_LEVEL_PAGE_BYTES - \ 42 sizeof(unwind_info_compressed_second_level_page_header)) / \ 43 sizeof(uint32_t)) 44 45 #define COMPRESSED_ENTRY_FUNC_OFFSET_BITS 24 46 #define COMPRESSED_ENTRY_FUNC_OFFSET_MASK \ 47 UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(~0) 48 49 // Compact Unwind format is a Mach-O evolution of DWARF Unwind that 50 // optimizes space and exception-time lookup. Most DWARF unwind 51 // entries can be replaced with Compact Unwind entries, but the ones 52 // that cannot are retained in DWARF form. 53 // 54 // This comment will address macro-level organization of the pre-link 55 // and post-link compact unwind tables. For micro-level organization 56 // pertaining to the bitfield layout of the 32-bit compact unwind 57 // entries, see libunwind/include/mach-o/compact_unwind_encoding.h 58 // 59 // Important clarifying factoids: 60 // 61 // * __LD,__compact_unwind is the compact unwind format for compiler 62 // output and linker input. It is never a final output. It could be 63 // an intermediate output with the `-r` option which retains relocs. 64 // 65 // * __TEXT,__unwind_info is the compact unwind format for final 66 // linker output. It is never an input. 67 // 68 // * __TEXT,__eh_frame is the DWARF format for both linker input and output. 69 // 70 // * __TEXT,__unwind_info entries are divided into 4 KiB pages (2nd 71 // level) by ascending address, and the pages are referenced by an 72 // index (1st level) in the section header. 73 // 74 // * Following the headers in __TEXT,__unwind_info, the bulk of the 75 // section contains a vector of compact unwind entries 76 // `{functionOffset, encoding}` sorted by ascending `functionOffset`. 77 // Adjacent entries with the same encoding can be folded to great 78 // advantage, achieving a 3-order-of-magnitude reduction in the 79 // number of entries. 80 // 81 // * The __TEXT,__unwind_info format can accommodate up to 127 unique 82 // encodings for the space-efficient compressed format. In practice, 83 // fewer than a dozen unique encodings are used by C++ programs of 84 // all sizes. Therefore, we don't even bother implementing the regular 85 // non-compressed format. Time will tell if anyone in the field ever 86 // overflows the 127-encodings limit. 87 // 88 // Refer to the definition of unwind_info_section_header in 89 // compact_unwind_encoding.h for an overview of the format we are encoding 90 // here. 91 92 // TODO(gkm): prune __eh_frame entries superseded by __unwind_info, PR50410 93 // TODO(gkm): how do we align the 2nd-level pages? 94 95 using EncodingMap = llvm::DenseMap<compact_unwind_encoding_t, size_t>; 96 97 struct SecondLevelPage { 98 uint32_t kind; 99 size_t entryIndex; 100 size_t entryCount; 101 size_t byteCount; 102 std::vector<compact_unwind_encoding_t> localEncodings; 103 EncodingMap localEncodingIndexes; 104 }; 105 106 template <class Ptr> class UnwindInfoSectionImpl : public UnwindInfoSection { 107 public: 108 void prepareRelocations(ConcatInputSection *) override; 109 void finalize() override; 110 void writeTo(uint8_t *buf) const override; 111 112 private: 113 std::vector<std::pair<compact_unwind_encoding_t, size_t>> commonEncodings; 114 EncodingMap commonEncodingIndexes; 115 // Indices of personality functions within the GOT. 116 std::vector<uint32_t> personalities; 117 SmallDenseMap<std::pair<InputSection *, uint64_t /* addend */>, Symbol *> 118 personalityTable; 119 std::vector<unwind_info_section_header_lsda_index_entry> lsdaEntries; 120 // Map of function offset (from the image base) to an index within the LSDA 121 // array. 122 llvm::DenseMap<uint32_t, uint32_t> functionToLsdaIndex; 123 std::vector<CompactUnwindEntry<Ptr>> cuVector; 124 std::vector<CompactUnwindEntry<Ptr> *> cuPtrVector; 125 std::vector<SecondLevelPage> secondLevelPages; 126 uint64_t level2PagesOffset = 0; 127 }; 128 129 // Compact unwind relocations have different semantics, so we handle them in a 130 // separate code path from regular relocations. First, we do not wish to add 131 // rebase opcodes for __LD,__compact_unwind, because that section doesn't 132 // actually end up in the final binary. Second, personality pointers always 133 // reside in the GOT and must be treated specially. 134 template <class Ptr> 135 void UnwindInfoSectionImpl<Ptr>::prepareRelocations(ConcatInputSection *isec) { 136 assert(isec->segname == segment_names::ld && 137 isec->name == section_names::compactUnwind); 138 assert(!isec->shouldOmitFromOutput() && 139 "__compact_unwind section should not be omitted"); 140 141 // FIXME: Make this skip relocations for CompactUnwindEntries that 142 // point to dead-stripped functions. That might save some amount of 143 // work. But since there are usually just few personality functions 144 // that are referenced from many places, at least some of them likely 145 // live, it wouldn't reduce number of got entries. 146 for (size_t i = 0; i < isec->relocs.size(); ++i) { 147 Reloc &r = isec->relocs[i]; 148 assert(target->hasAttr(r.type, RelocAttrBits::UNSIGNED)); 149 if (r.offset % sizeof(CompactUnwindEntry<Ptr>) != 150 offsetof(CompactUnwindEntry<Ptr>, personality)) 151 continue; 152 153 Reloc &rFunc = isec->relocs[++i]; 154 assert(r.offset == 155 rFunc.offset + offsetof(CompactUnwindEntry<Ptr>, personality)); 156 rFunc.referent.get<InputSection *>()->hasPersonality = true; 157 158 if (auto *s = r.referent.dyn_cast<Symbol *>()) { 159 if (auto *undefined = dyn_cast<Undefined>(s)) { 160 treatUndefinedSymbol(*undefined); 161 // treatUndefinedSymbol() can replace s with a DylibSymbol; re-check. 162 if (isa<Undefined>(s)) 163 continue; 164 } 165 if (auto *defined = dyn_cast<Defined>(s)) { 166 // Check if we have created a synthetic symbol at the same address. 167 Symbol *&personality = 168 personalityTable[{defined->isec, defined->value}]; 169 if (personality == nullptr) { 170 personality = defined; 171 in.got->addEntry(defined); 172 } else if (personality != defined) { 173 r.referent = personality; 174 } 175 continue; 176 } 177 assert(isa<DylibSymbol>(s)); 178 in.got->addEntry(s); 179 continue; 180 } 181 182 if (auto *referentIsec = r.referent.dyn_cast<InputSection *>()) { 183 assert(!isCoalescedWeak(referentIsec)); 184 // Personality functions can be referenced via section relocations 185 // if they live in the same object file. Create placeholder synthetic 186 // symbols for them in the GOT. 187 Symbol *&s = personalityTable[{referentIsec, r.addend}]; 188 if (s == nullptr) { 189 // This runs after dead stripping, so the noDeadStrip argument does not 190 // matter. 191 s = make<Defined>("<internal>", /*file=*/nullptr, referentIsec, 192 r.addend, /*size=*/0, /*isWeakDef=*/false, 193 /*isExternal=*/false, /*isPrivateExtern=*/false, 194 /*isThumb=*/false, /*isReferencedDynamically=*/false, 195 /*noDeadStrip=*/false); 196 in.got->addEntry(s); 197 } 198 r.referent = s; 199 r.addend = 0; 200 } 201 } 202 } 203 204 // Unwind info lives in __DATA, and finalization of __TEXT will occur before 205 // finalization of __DATA. Moreover, the finalization of unwind info depends on 206 // the exact addresses that it references. So it is safe for compact unwind to 207 // reference addresses in __TEXT, but not addresses in any other segment. 208 static ConcatInputSection *checkTextSegment(InputSection *isec) { 209 if (isec->segname != segment_names::text) 210 error("compact unwind references address in " + toString(isec) + 211 " which is not in segment __TEXT"); 212 // __text should always be a ConcatInputSection. 213 return cast<ConcatInputSection>(isec); 214 } 215 216 // We need to apply the relocations to the pre-link compact unwind section 217 // before converting it to post-link form. There should only be absolute 218 // relocations here: since we are not emitting the pre-link CU section, there 219 // is no source address to make a relative location meaningful. 220 template <class Ptr> 221 static void 222 relocateCompactUnwind(ConcatOutputSection *compactUnwindSection, 223 std::vector<CompactUnwindEntry<Ptr>> &cuVector) { 224 for (const ConcatInputSection *isec : compactUnwindSection->inputs) { 225 assert(isec->parent == compactUnwindSection); 226 227 uint8_t *buf = 228 reinterpret_cast<uint8_t *>(cuVector.data()) + isec->outSecOff; 229 memcpy(buf, isec->data.data(), isec->data.size()); 230 231 for (const Reloc &r : isec->relocs) { 232 uint64_t referentVA = 0; 233 if (auto *referentSym = r.referent.dyn_cast<Symbol *>()) { 234 if (!isa<Undefined>(referentSym)) { 235 assert(referentSym->isInGot()); 236 if (auto *defined = dyn_cast<Defined>(referentSym)) 237 checkTextSegment(defined->isec); 238 // At this point in the link, we may not yet know the final address of 239 // the GOT, so we just encode the index. We make it a 1-based index so 240 // that we can distinguish the null pointer case. 241 referentVA = referentSym->gotIndex + 1; 242 } 243 } else if (auto *referentIsec = r.referent.dyn_cast<InputSection *>()) { 244 ConcatInputSection *concatIsec = checkTextSegment(referentIsec); 245 if (concatIsec->shouldOmitFromOutput()) 246 referentVA = UINT64_MAX; // Tombstone value 247 else 248 referentVA = referentIsec->getVA(r.addend); 249 } 250 251 writeAddress(buf + r.offset, referentVA, r.length); 252 } 253 } 254 } 255 256 // There should only be a handful of unique personality pointers, so we can 257 // encode them as 2-bit indices into a small array. 258 template <class Ptr> 259 void encodePersonalities( 260 const std::vector<CompactUnwindEntry<Ptr> *> &cuPtrVector, 261 std::vector<uint32_t> &personalities) { 262 for (CompactUnwindEntry<Ptr> *cu : cuPtrVector) { 263 if (cu->personality == 0) 264 continue; 265 // Linear search is fast enough for a small array. 266 auto it = find(personalities, cu->personality); 267 uint32_t personalityIndex; // 1-based index 268 if (it != personalities.end()) { 269 personalityIndex = std::distance(personalities.begin(), it) + 1; 270 } else { 271 personalities.push_back(cu->personality); 272 personalityIndex = personalities.size(); 273 } 274 cu->encoding |= 275 personalityIndex << countTrailingZeros( 276 static_cast<compact_unwind_encoding_t>(UNWIND_PERSONALITY_MASK)); 277 } 278 if (personalities.size() > 3) 279 error("too many personalities (" + std::to_string(personalities.size()) + 280 ") for compact unwind to encode"); 281 } 282 283 // Scan the __LD,__compact_unwind entries and compute the space needs of 284 // __TEXT,__unwind_info and __TEXT,__eh_frame 285 template <class Ptr> void UnwindInfoSectionImpl<Ptr>::finalize() { 286 if (compactUnwindSection == nullptr) 287 return; 288 289 // At this point, the address space for __TEXT,__text has been 290 // assigned, so we can relocate the __LD,__compact_unwind entries 291 // into a temporary buffer. Relocation is necessary in order to sort 292 // the CU entries by function address. Sorting is necessary so that 293 // we can fold adjacent CU entries with identical 294 // encoding+personality+lsda. Folding is necessary because it reduces 295 // the number of CU entries by as much as 3 orders of magnitude! 296 compactUnwindSection->finalize(); 297 assert(compactUnwindSection->getSize() % sizeof(CompactUnwindEntry<Ptr>) == 298 0); 299 size_t cuCount = 300 compactUnwindSection->getSize() / sizeof(CompactUnwindEntry<Ptr>); 301 cuVector.resize(cuCount); 302 relocateCompactUnwind(compactUnwindSection, cuVector); 303 304 // Rather than sort & fold the 32-byte entries directly, we create a 305 // vector of pointers to entries and sort & fold that instead. 306 cuPtrVector.reserve(cuCount); 307 for (CompactUnwindEntry<Ptr> &cuEntry : cuVector) 308 cuPtrVector.emplace_back(&cuEntry); 309 llvm::sort(cuPtrVector, [](const CompactUnwindEntry<Ptr> *a, 310 const CompactUnwindEntry<Ptr> *b) { 311 return a->functionAddress < b->functionAddress; 312 }); 313 314 // Dead-stripped functions get a functionAddress of UINT64_MAX in 315 // relocateCompactUnwind(). Filter them out here. 316 // FIXME: This doesn't yet collect associated data like LSDAs kept 317 // alive only by a now-removed CompactUnwindEntry or other comdat-like 318 // data (`kindNoneGroupSubordinate*` in ld64). 319 CompactUnwindEntry<Ptr> tombstone; 320 tombstone.functionAddress = static_cast<Ptr>(UINT64_MAX); 321 cuPtrVector.erase( 322 std::lower_bound(cuPtrVector.begin(), cuPtrVector.end(), &tombstone, 323 [](const CompactUnwindEntry<Ptr> *a, 324 const CompactUnwindEntry<Ptr> *b) { 325 return a->functionAddress < b->functionAddress; 326 }), 327 cuPtrVector.end()); 328 329 // Fold adjacent entries with matching encoding+personality+lsda 330 // We use three iterators on the same cuPtrVector to fold in-situ: 331 // (1) `foldBegin` is the first of a potential sequence of matching entries 332 // (2) `foldEnd` is the first non-matching entry after `foldBegin`. 333 // The semi-open interval [ foldBegin .. foldEnd ) contains a range 334 // entries that can be folded into a single entry and written to ... 335 // (3) `foldWrite` 336 auto foldWrite = cuPtrVector.begin(); 337 for (auto foldBegin = cuPtrVector.begin(); foldBegin < cuPtrVector.end();) { 338 auto foldEnd = foldBegin; 339 while (++foldEnd < cuPtrVector.end() && 340 (*foldBegin)->encoding == (*foldEnd)->encoding && 341 (*foldBegin)->personality == (*foldEnd)->personality && 342 (*foldBegin)->lsda == (*foldEnd)->lsda) 343 ; 344 *foldWrite++ = *foldBegin; 345 foldBegin = foldEnd; 346 } 347 cuPtrVector.erase(foldWrite, cuPtrVector.end()); 348 349 encodePersonalities(cuPtrVector, personalities); 350 351 // Count frequencies of the folded encodings 352 EncodingMap encodingFrequencies; 353 for (const CompactUnwindEntry<Ptr> *cuPtrEntry : cuPtrVector) 354 encodingFrequencies[cuPtrEntry->encoding]++; 355 356 // Make a vector of encodings, sorted by descending frequency 357 for (const auto &frequency : encodingFrequencies) 358 commonEncodings.emplace_back(frequency); 359 llvm::sort(commonEncodings, 360 [](const std::pair<compact_unwind_encoding_t, size_t> &a, 361 const std::pair<compact_unwind_encoding_t, size_t> &b) { 362 if (a.second == b.second) 363 // When frequencies match, secondarily sort on encoding 364 // to maintain parity with validate-unwind-info.py 365 return a.first > b.first; 366 return a.second > b.second; 367 }); 368 369 // Truncate the vector to 127 elements. 370 // Common encoding indexes are limited to 0..126, while encoding 371 // indexes 127..255 are local to each second-level page 372 if (commonEncodings.size() > COMMON_ENCODINGS_MAX) 373 commonEncodings.resize(COMMON_ENCODINGS_MAX); 374 375 // Create a map from encoding to common-encoding-table index 376 for (size_t i = 0; i < commonEncodings.size(); i++) 377 commonEncodingIndexes[commonEncodings[i].first] = i; 378 379 // Split folded encodings into pages, where each page is limited by ... 380 // (a) 4 KiB capacity 381 // (b) 24-bit difference between first & final function address 382 // (c) 8-bit compact-encoding-table index, 383 // for which 0..126 references the global common-encodings table, 384 // and 127..255 references a local per-second-level-page table. 385 // First we try the compact format and determine how many entries fit. 386 // If more entries fit in the regular format, we use that. 387 for (size_t i = 0; i < cuPtrVector.size();) { 388 secondLevelPages.emplace_back(); 389 SecondLevelPage &page = secondLevelPages.back(); 390 page.entryIndex = i; 391 uintptr_t functionAddressMax = 392 cuPtrVector[i]->functionAddress + COMPRESSED_ENTRY_FUNC_OFFSET_MASK; 393 size_t n = commonEncodings.size(); 394 size_t wordsRemaining = 395 SECOND_LEVEL_PAGE_WORDS - 396 sizeof(unwind_info_compressed_second_level_page_header) / 397 sizeof(uint32_t); 398 while (wordsRemaining >= 1 && i < cuPtrVector.size()) { 399 const CompactUnwindEntry<Ptr> *cuPtr = cuPtrVector[i]; 400 if (cuPtr->functionAddress >= functionAddressMax) { 401 break; 402 } else if (commonEncodingIndexes.count(cuPtr->encoding) || 403 page.localEncodingIndexes.count(cuPtr->encoding)) { 404 i++; 405 wordsRemaining--; 406 } else if (wordsRemaining >= 2 && n < COMPACT_ENCODINGS_MAX) { 407 page.localEncodings.emplace_back(cuPtr->encoding); 408 page.localEncodingIndexes[cuPtr->encoding] = n++; 409 i++; 410 wordsRemaining -= 2; 411 } else { 412 break; 413 } 414 } 415 page.entryCount = i - page.entryIndex; 416 417 // If this is not the final page, see if it's possible to fit more 418 // entries by using the regular format. This can happen when there 419 // are many unique encodings, and we we saturated the local 420 // encoding table early. 421 if (i < cuPtrVector.size() && 422 page.entryCount < REGULAR_SECOND_LEVEL_ENTRIES_MAX) { 423 page.kind = UNWIND_SECOND_LEVEL_REGULAR; 424 page.entryCount = std::min(REGULAR_SECOND_LEVEL_ENTRIES_MAX, 425 cuPtrVector.size() - page.entryIndex); 426 i = page.entryIndex + page.entryCount; 427 } else { 428 page.kind = UNWIND_SECOND_LEVEL_COMPRESSED; 429 } 430 } 431 432 for (const CompactUnwindEntry<Ptr> *cu : cuPtrVector) { 433 uint32_t functionOffset = cu->functionAddress - in.header->addr; 434 functionToLsdaIndex[functionOffset] = lsdaEntries.size(); 435 if (cu->lsda != 0) 436 lsdaEntries.push_back( 437 {functionOffset, static_cast<uint32_t>(cu->lsda - in.header->addr)}); 438 } 439 440 // compute size of __TEXT,__unwind_info section 441 level2PagesOffset = 442 sizeof(unwind_info_section_header) + 443 commonEncodings.size() * sizeof(uint32_t) + 444 personalities.size() * sizeof(uint32_t) + 445 // The extra second-level-page entry is for the sentinel 446 (secondLevelPages.size() + 1) * 447 sizeof(unwind_info_section_header_index_entry) + 448 lsdaEntries.size() * sizeof(unwind_info_section_header_lsda_index_entry); 449 unwindInfoSize = 450 level2PagesOffset + secondLevelPages.size() * SECOND_LEVEL_PAGE_BYTES; 451 } 452 453 // All inputs are relocated and output addresses are known, so write! 454 455 template <class Ptr> 456 void UnwindInfoSectionImpl<Ptr>::writeTo(uint8_t *buf) const { 457 // section header 458 auto *uip = reinterpret_cast<unwind_info_section_header *>(buf); 459 uip->version = 1; 460 uip->commonEncodingsArraySectionOffset = sizeof(unwind_info_section_header); 461 uip->commonEncodingsArrayCount = commonEncodings.size(); 462 uip->personalityArraySectionOffset = 463 uip->commonEncodingsArraySectionOffset + 464 (uip->commonEncodingsArrayCount * sizeof(uint32_t)); 465 uip->personalityArrayCount = personalities.size(); 466 uip->indexSectionOffset = uip->personalityArraySectionOffset + 467 (uip->personalityArrayCount * sizeof(uint32_t)); 468 uip->indexCount = secondLevelPages.size() + 1; 469 470 // Common encodings 471 auto *i32p = reinterpret_cast<uint32_t *>(&uip[1]); 472 for (const auto &encoding : commonEncodings) 473 *i32p++ = encoding.first; 474 475 // Personalities 476 for (const uint32_t &personality : personalities) 477 *i32p++ = 478 in.got->addr + (personality - 1) * target->wordSize - in.header->addr; 479 480 // Level-1 index 481 uint32_t lsdaOffset = 482 uip->indexSectionOffset + 483 uip->indexCount * sizeof(unwind_info_section_header_index_entry); 484 uint64_t l2PagesOffset = level2PagesOffset; 485 auto *iep = reinterpret_cast<unwind_info_section_header_index_entry *>(i32p); 486 for (const SecondLevelPage &page : secondLevelPages) { 487 iep->functionOffset = 488 cuPtrVector[page.entryIndex]->functionAddress - in.header->addr; 489 iep->secondLevelPagesSectionOffset = l2PagesOffset; 490 iep->lsdaIndexArraySectionOffset = 491 lsdaOffset + functionToLsdaIndex.lookup(iep->functionOffset) * 492 sizeof(unwind_info_section_header_lsda_index_entry); 493 iep++; 494 l2PagesOffset += SECOND_LEVEL_PAGE_BYTES; 495 } 496 // Level-1 sentinel 497 const CompactUnwindEntry<Ptr> &cuEnd = cuVector.back(); 498 iep->functionOffset = cuEnd.functionAddress + cuEnd.functionLength; 499 iep->secondLevelPagesSectionOffset = 0; 500 iep->lsdaIndexArraySectionOffset = 501 lsdaOffset + 502 lsdaEntries.size() * sizeof(unwind_info_section_header_lsda_index_entry); 503 iep++; 504 505 // LSDAs 506 size_t lsdaBytes = 507 lsdaEntries.size() * sizeof(unwind_info_section_header_lsda_index_entry); 508 if (lsdaBytes > 0) 509 memcpy(iep, lsdaEntries.data(), lsdaBytes); 510 511 // Level-2 pages 512 auto *pp = reinterpret_cast<uint32_t *>(reinterpret_cast<uint8_t *>(iep) + 513 lsdaBytes); 514 for (const SecondLevelPage &page : secondLevelPages) { 515 if (page.kind == UNWIND_SECOND_LEVEL_COMPRESSED) { 516 uintptr_t functionAddressBase = 517 cuPtrVector[page.entryIndex]->functionAddress; 518 auto *p2p = 519 reinterpret_cast<unwind_info_compressed_second_level_page_header *>( 520 pp); 521 p2p->kind = page.kind; 522 p2p->entryPageOffset = 523 sizeof(unwind_info_compressed_second_level_page_header); 524 p2p->entryCount = page.entryCount; 525 p2p->encodingsPageOffset = 526 p2p->entryPageOffset + p2p->entryCount * sizeof(uint32_t); 527 p2p->encodingsCount = page.localEncodings.size(); 528 auto *ep = reinterpret_cast<uint32_t *>(&p2p[1]); 529 for (size_t i = 0; i < page.entryCount; i++) { 530 const CompactUnwindEntry<Ptr> *cuep = cuPtrVector[page.entryIndex + i]; 531 auto it = commonEncodingIndexes.find(cuep->encoding); 532 if (it == commonEncodingIndexes.end()) 533 it = page.localEncodingIndexes.find(cuep->encoding); 534 *ep++ = (it->second << COMPRESSED_ENTRY_FUNC_OFFSET_BITS) | 535 (cuep->functionAddress - functionAddressBase); 536 } 537 if (page.localEncodings.size() != 0) 538 memcpy(ep, page.localEncodings.data(), 539 page.localEncodings.size() * sizeof(uint32_t)); 540 } else { 541 auto *p2p = 542 reinterpret_cast<unwind_info_regular_second_level_page_header *>(pp); 543 p2p->kind = page.kind; 544 p2p->entryPageOffset = 545 sizeof(unwind_info_regular_second_level_page_header); 546 p2p->entryCount = page.entryCount; 547 auto *ep = reinterpret_cast<uint32_t *>(&p2p[1]); 548 for (size_t i = 0; i < page.entryCount; i++) { 549 const CompactUnwindEntry<Ptr> *cuep = cuPtrVector[page.entryIndex + i]; 550 *ep++ = cuep->functionAddress; 551 *ep++ = cuep->encoding; 552 } 553 } 554 pp += SECOND_LEVEL_PAGE_WORDS; 555 } 556 } 557 558 UnwindInfoSection *macho::makeUnwindInfoSection() { 559 if (target->wordSize == 8) 560 return make<UnwindInfoSectionImpl<uint64_t>>(); 561 else 562 return make<UnwindInfoSectionImpl<uint32_t>>(); 563 } 564