1 //===- UnwindInfoSection.h ------------------------------------------------===//
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 #ifndef LLD_MACHO_UNWIND_INFO_H
10 #define LLD_MACHO_UNWIND_INFO_H
11 
12 #include "MergedOutputSection.h"
13 #include "SyntheticSections.h"
14 
15 #include "mach-o/compact_unwind_encoding.h"
16 #include "llvm/ADT/DenseMap.h"
17 
18 #include <vector>
19 
20 // In 2020, we mostly care about 64-bit targets: x86_64 and arm64
21 struct CompactUnwindEntry64 {
22   uint64_t functionAddress;
23   uint32_t functionLength;
24   compact_unwind_encoding_t encoding;
25   uint64_t personality;
26   uint64_t lsda;
27 };
28 
29 // FIXME(gkm): someday we might care about 32-bit targets: x86 & arm
30 struct CompactUnwindEntry32 {
31   uint32_t functionAddress;
32   uint32_t functionLength;
33   compact_unwind_encoding_t encoding;
34   uint32_t personality;
35   uint32_t lsda;
36 };
37 
38 namespace lld {
39 namespace macho {
40 
41 class UnwindInfoSection : public SyntheticSection {
42 public:
43   UnwindInfoSection();
getSize()44   uint64_t getSize() const override { return unwindInfoSize; }
45   bool isNeeded() const override;
46   void finalize() override;
47   void writeTo(uint8_t *buf) const override;
setCompactUnwindSection(MergedOutputSection * cuSection)48   void setCompactUnwindSection(MergedOutputSection *cuSection) {
49     compactUnwindSection = cuSection;
50   }
51 
52 private:
53   std::vector<std::pair<compact_unwind_encoding_t, size_t>> commonEncodings;
54   std::vector<uint32_t> personalities;
55   std::vector<unwind_info_section_header_lsda_index_entry> lsdaEntries;
56   std::vector<CompactUnwindEntry64> cuVector;
57   std::vector<const CompactUnwindEntry64 *> cuPtrVector;
58   std::vector<std::vector<const CompactUnwindEntry64 *>::const_iterator>
59       pageBounds;
60   MergedOutputSection *compactUnwindSection = nullptr;
61   uint64_t level2PagesOffset = 0;
62   uint64_t unwindInfoSize = 0;
63 };
64 
65 #define UNWIND_INFO_COMMON_ENCODINGS_MAX 127
66 
67 #define UNWIND_INFO_SECOND_LEVEL_PAGE_SIZE 4096
68 #define UNWIND_INFO_REGULAR_SECOND_LEVEL_ENTRIES_MAX                           \
69   ((UNWIND_INFO_SECOND_LEVEL_PAGE_SIZE -                                       \
70     sizeof(unwind_info_regular_second_level_page_header)) /                    \
71    sizeof(unwind_info_regular_second_level_entry))
72 #define UNWIND_INFO_COMPRESSED_SECOND_LEVEL_ENTRIES_MAX                        \
73   ((UNWIND_INFO_SECOND_LEVEL_PAGE_SIZE -                                       \
74     sizeof(unwind_info_compressed_second_level_page_header)) /                 \
75    sizeof(uint32_t))
76 
77 #define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET_BITS 24
78 #define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET_MASK                          \
79   UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(~0)
80 
81 } // namespace macho
82 } // namespace lld
83 
84 #endif
85