1278332Semaste//===-- CompactUnwindInfo.h -------------------------------------*- C++ -*-===// 2278332Semaste// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6278332Semaste// 7278332Semaste//===----------------------------------------------------------------------===// 8278332Semaste 9278332Semaste#ifndef liblldb_CompactUnwindInfo_h_ 10278332Semaste#define liblldb_CompactUnwindInfo_h_ 11278332Semaste 12278332Semaste#include "lldb/Symbol/ObjectFile.h" 13278332Semaste#include "lldb/Symbol/UnwindPlan.h" 14321369Sdim#include "lldb/Utility/DataExtractor.h" 15353358Sdim#include "lldb/Utility/RangeMap.h" 16278332Semaste#include "lldb/lldb-private.h" 17353358Sdim#include <mutex> 18353358Sdim#include <vector> 19278332Semaste 20278332Semastenamespace lldb_private { 21278332Semaste 22314564Sdim// Compact Unwind info is an unwind format used on Darwin. The unwind 23341825Sdim// instructions for typical compiler-generated functions can be expressed in a 24341825Sdim// 32-bit encoding. The format includes a two-level index so the unwind 25341825Sdim// information for a function can be found by two binary searches in the 26341825Sdim// section. It can represent both stack frames that use a frame-pointer 27341825Sdim// register and frameless functions, on i386/x86_64 for instance. When a 28341825Sdim// function is too complex to be represented in the compact unwind format, it 29341825Sdim// calls out to eh_frame unwind instructions. 30278332Semaste 31314564Sdim// On Mac OS X / iOS, a function will have either a compact unwind 32341825Sdim// representation or an eh_frame representation. If lldb is going to benefit 33341825Sdim// from the compiler's description about saved register locations, it must be 34341825Sdim// able to read both sources of information. 35278332Semaste 36314564Sdimclass CompactUnwindInfo { 37278332Semastepublic: 38314564Sdim CompactUnwindInfo(ObjectFile &objfile, lldb::SectionSP §ion); 39278332Semaste 40314564Sdim ~CompactUnwindInfo(); 41278332Semaste 42314564Sdim bool GetUnwindPlan(Target &target, Address addr, UnwindPlan &unwind_plan); 43278332Semaste 44314564Sdim bool IsValid(const lldb::ProcessSP &process_sp); 45278332Semaste 46278332Semasteprivate: 47314564Sdim // The top level index entries of the compact unwind info 48314564Sdim // (internal representation of struct 49314564Sdim // unwind_info_section_header_index_entry) 50341825Sdim // There are relatively few of these (one per 500/1000 functions, depending 51341825Sdim // on format) so creating them on first scan will not be too costly. 52314564Sdim struct UnwindIndex { 53314564Sdim uint32_t function_offset; // The offset of the first function covered by 54314564Sdim // this index 55314564Sdim uint32_t second_level; // The offset (inside unwind_info sect) to the second 56314564Sdim // level page for this index 57314564Sdim // (either UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED) 58314564Sdim uint32_t lsda_array_start; // The offset (inside unwind_info sect) LSDA 59314564Sdim // array for this index 60314564Sdim uint32_t lsda_array_end; // The offset to the LSDA array for the NEXT index 61314564Sdim bool sentinal_entry; // There is an empty index at the end which provides 62314564Sdim // the upper bound of 63314564Sdim // function addresses that are described 64278332Semaste 65314564Sdim UnwindIndex() 66314564Sdim : function_offset(0), second_level(0), lsda_array_start(0), 67314564Sdim lsda_array_end(0), sentinal_entry(false) {} 68278332Semaste 69314564Sdim bool operator<(const CompactUnwindInfo::UnwindIndex &rhs) const { 70314564Sdim return function_offset < rhs.function_offset; 71314564Sdim } 72278332Semaste 73314564Sdim bool operator==(const CompactUnwindInfo::UnwindIndex &rhs) const { 74314564Sdim return function_offset == rhs.function_offset; 75314564Sdim } 76314564Sdim }; 77278332Semaste 78314564Sdim // An internal object used to store the information we retrieve about a 79341825Sdim // function -- the encoding bits and possibly the LSDA/personality function. 80314564Sdim struct FunctionInfo { 81314564Sdim uint32_t encoding; // compact encoding 32-bit value for this function 82314564Sdim Address lsda_address; // the address of the LSDA data for this function 83314564Sdim Address personality_ptr_address; // the address where the personality 84314564Sdim // routine addr can be found 85278332Semaste 86314564Sdim uint32_t valid_range_offset_start; // first offset that this encoding is 87314564Sdim // valid for (start of the function) 88314564Sdim uint32_t 89314564Sdim valid_range_offset_end; // the offset of the start of the next function 90314564Sdim FunctionInfo() 91314564Sdim : encoding(0), lsda_address(), personality_ptr_address(), 92314564Sdim valid_range_offset_start(0), valid_range_offset_end(0) {} 93314564Sdim }; 94278332Semaste 95314564Sdim struct UnwindHeader { 96314564Sdim uint32_t version; 97314564Sdim uint32_t common_encodings_array_offset; 98314564Sdim uint32_t common_encodings_array_count; 99314564Sdim uint32_t personality_array_offset; 100314564Sdim uint32_t personality_array_count; 101278332Semaste 102314564Sdim UnwindHeader() 103314564Sdim : common_encodings_array_offset(0), common_encodings_array_count(0), 104314564Sdim personality_array_offset(0), personality_array_count(0) {} 105314564Sdim }; 106278332Semaste 107314564Sdim void ScanIndex(const lldb::ProcessSP &process_sp); 108278332Semaste 109314564Sdim bool GetCompactUnwindInfoForFunction(Target &target, Address address, 110314564Sdim FunctionInfo &unwind_info); 111278332Semaste 112314564Sdim lldb::offset_t 113314564Sdim BinarySearchRegularSecondPage(uint32_t entry_page_offset, 114314564Sdim uint32_t entry_count, uint32_t function_offset, 115314564Sdim uint32_t *entry_func_start_offset, 116314564Sdim uint32_t *entry_func_end_offset); 117278332Semaste 118314564Sdim uint32_t BinarySearchCompressedSecondPage(uint32_t entry_page_offset, 119314564Sdim uint32_t entry_count, 120314564Sdim uint32_t function_offset_to_find, 121314564Sdim uint32_t function_offset_base, 122314564Sdim uint32_t *entry_func_start_offset, 123314564Sdim uint32_t *entry_func_end_offset); 124278332Semaste 125314564Sdim uint32_t GetLSDAForFunctionOffset(uint32_t lsda_offset, uint32_t lsda_count, 126314564Sdim uint32_t function_offset); 127278332Semaste 128314564Sdim bool CreateUnwindPlan_x86_64(Target &target, FunctionInfo &function_info, 129314564Sdim UnwindPlan &unwind_plan, 130314564Sdim Address pc_or_function_start); 131278332Semaste 132314564Sdim bool CreateUnwindPlan_i386(Target &target, FunctionInfo &function_info, 133314564Sdim UnwindPlan &unwind_plan, 134314564Sdim Address pc_or_function_start); 135278332Semaste 136314564Sdim bool CreateUnwindPlan_arm64(Target &target, FunctionInfo &function_info, 137314564Sdim UnwindPlan &unwind_plan, 138314564Sdim Address pc_or_function_start); 139278332Semaste 140314564Sdim bool CreateUnwindPlan_armv7(Target &target, FunctionInfo &function_info, 141314564Sdim UnwindPlan &unwind_plan, 142314564Sdim Address pc_or_function_start); 143309124Sdim 144314564Sdim ObjectFile &m_objfile; 145314564Sdim lldb::SectionSP m_section_sp; 146314564Sdim lldb::DataBufferSP m_section_contents_if_encrypted; // if the binary is 147314564Sdim // encrypted, read the 148314564Sdim // sect contents 149314564Sdim // out of live memory and cache them here 150314564Sdim std::mutex m_mutex; 151314564Sdim std::vector<UnwindIndex> m_indexes; 152309124Sdim 153314564Sdim LazyBool m_indexes_computed; // eLazyBoolYes once we've tried to parse the 154314564Sdim // unwind info 155314564Sdim // eLazyBoolNo means we cannot parse the unwind info & should not retry 156314564Sdim // eLazyBoolCalculate means we haven't tried to parse it yet 157278332Semaste 158314564Sdim DataExtractor m_unwindinfo_data; 159314564Sdim bool m_unwindinfo_data_computed; // true once we've mapped in the unwindinfo 160314564Sdim // data 161278332Semaste 162314564Sdim UnwindHeader m_unwind_header; 163278332Semaste}; 164278332Semaste 165278332Semaste} // namespace lldb_private 166278332Semaste 167314564Sdim#endif // liblldb_CompactUnwindInfo_h_ 168