Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:42:51

0001 //===-- CompactUnwindInfo.h -------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLDB_SYMBOL_COMPACTUNWINDINFO_H
0010 #define LLDB_SYMBOL_COMPACTUNWINDINFO_H
0011 
0012 #include "lldb/Symbol/ObjectFile.h"
0013 #include "lldb/Symbol/UnwindPlan.h"
0014 #include "lldb/Utility/DataExtractor.h"
0015 #include "lldb/Utility/RangeMap.h"
0016 #include "lldb/lldb-private.h"
0017 #include <mutex>
0018 #include <vector>
0019 
0020 namespace lldb_private {
0021 
0022 // Compact Unwind info is an unwind format used on Darwin.  The unwind
0023 // instructions for typical compiler-generated functions can be expressed in a
0024 // 32-bit encoding. The format includes a two-level index so the unwind
0025 // information for a function can be found by two binary searches in the
0026 // section.  It can represent both stack frames that use a frame-pointer
0027 // register and frameless functions, on i386/x86_64 for instance.  When a
0028 // function is too complex to be represented in the compact unwind format, it
0029 // calls out to eh_frame unwind instructions.
0030 
0031 // On Mac OS X / iOS, a function will have either a compact unwind
0032 // representation or an eh_frame representation.  If lldb is going to benefit
0033 // from the compiler's description about saved register locations, it must be
0034 // able to read both sources of information.
0035 
0036 class CompactUnwindInfo {
0037 public:
0038   CompactUnwindInfo(ObjectFile &objfile, lldb::SectionSP &section);
0039 
0040   ~CompactUnwindInfo();
0041 
0042   bool GetUnwindPlan(Target &target, Address addr, UnwindPlan &unwind_plan);
0043 
0044   bool IsValid(const lldb::ProcessSP &process_sp);
0045 
0046 private:
0047   // The top level index entries of the compact unwind info
0048   //   (internal representation of struct
0049   //   unwind_info_section_header_index_entry)
0050   // There are relatively few of these (one per 500/1000 functions, depending
0051   // on format) so creating them on first scan will not be too costly.
0052   struct UnwindIndex {
0053     uint32_t function_offset = 0; // The offset of the first function covered by
0054                                   // this index
0055     uint32_t second_level = 0;    // The offset (inside unwind_info sect) to the
0056                                   // second level page for this index
0057     // (either UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED)
0058     uint32_t lsda_array_start = 0; // The offset (inside unwind_info sect) LSDA
0059                                    // array for this index
0060     uint32_t lsda_array_end =
0061         0; // The offset to the LSDA array for the NEXT index
0062     bool sentinal_entry = false; // There is an empty index at the end which
0063                                  // provides the upper bound of
0064     // function addresses that are described
0065 
0066     UnwindIndex() = default;
0067 
0068     bool operator<(const CompactUnwindInfo::UnwindIndex &rhs) const {
0069       return function_offset < rhs.function_offset;
0070     }
0071 
0072     bool operator==(const CompactUnwindInfo::UnwindIndex &rhs) const {
0073       return function_offset == rhs.function_offset;
0074     }
0075   };
0076 
0077   // An internal object used to store the information we retrieve about a
0078   // function -- the encoding bits and possibly the LSDA/personality function.
0079   struct FunctionInfo {
0080     uint32_t encoding = 0; // compact encoding 32-bit value for this function
0081     Address lsda_address; // the address of the LSDA data for this function
0082     Address personality_ptr_address; // the address where the personality
0083                                      // routine addr can be found
0084 
0085     uint32_t valid_range_offset_start = 0; // first offset that this encoding is
0086                                            // valid for (start of the function)
0087     uint32_t valid_range_offset_end =
0088         0; // the offset of the start of the next function
0089     FunctionInfo() = default;
0090   };
0091 
0092   struct UnwindHeader {
0093     uint32_t version;
0094     uint32_t common_encodings_array_offset = 0;
0095     uint32_t common_encodings_array_count = 0;
0096     uint32_t personality_array_offset = 0;
0097     uint32_t personality_array_count = 0;
0098 
0099     UnwindHeader() = default;
0100   };
0101 
0102   void ScanIndex(const lldb::ProcessSP &process_sp);
0103 
0104   bool GetCompactUnwindInfoForFunction(Target &target, Address address,
0105                                        FunctionInfo &unwind_info);
0106 
0107   lldb::offset_t
0108   BinarySearchRegularSecondPage(uint32_t entry_page_offset,
0109                                 uint32_t entry_count, uint32_t function_offset,
0110                                 uint32_t *entry_func_start_offset,
0111                                 uint32_t *entry_func_end_offset);
0112 
0113   uint32_t BinarySearchCompressedSecondPage(uint32_t entry_page_offset,
0114                                             uint32_t entry_count,
0115                                             uint32_t function_offset_to_find,
0116                                             uint32_t function_offset_base,
0117                                             uint32_t *entry_func_start_offset,
0118                                             uint32_t *entry_func_end_offset);
0119 
0120   uint32_t GetLSDAForFunctionOffset(uint32_t lsda_offset, uint32_t lsda_count,
0121                                     uint32_t function_offset);
0122 
0123   bool CreateUnwindPlan_x86_64(Target &target, FunctionInfo &function_info,
0124                                UnwindPlan &unwind_plan,
0125                                Address pc_or_function_start);
0126 
0127   bool CreateUnwindPlan_i386(Target &target, FunctionInfo &function_info,
0128                              UnwindPlan &unwind_plan,
0129                              Address pc_or_function_start);
0130 
0131   bool CreateUnwindPlan_arm64(Target &target, FunctionInfo &function_info,
0132                               UnwindPlan &unwind_plan,
0133                               Address pc_or_function_start);
0134 
0135   bool CreateUnwindPlan_armv7(Target &target, FunctionInfo &function_info,
0136                               UnwindPlan &unwind_plan,
0137                               Address pc_or_function_start);
0138 
0139   ObjectFile &m_objfile;
0140   lldb::SectionSP m_section_sp;
0141   lldb::WritableDataBufferSP
0142       m_section_contents_if_encrypted; // if the binary is
0143                                        // encrypted, read the
0144                                        // sect contents
0145   // out of live memory and cache them here
0146   std::mutex m_mutex;
0147   std::vector<UnwindIndex> m_indexes;
0148 
0149   LazyBool m_indexes_computed; // eLazyBoolYes once we've tried to parse the
0150                                // unwind info
0151   // eLazyBoolNo means we cannot parse the unwind info & should not retry
0152   // eLazyBoolCalculate means we haven't tried to parse it yet
0153 
0154   DataExtractor m_unwindinfo_data;
0155   bool m_unwindinfo_data_computed; // true once we've mapped in the unwindinfo
0156                                    // data
0157 
0158   UnwindHeader m_unwind_header;
0159 };
0160 
0161 } // namespace lldb_private
0162 
0163 #endif // LLDB_SYMBOL_COMPACTUNWINDINFO_H