summaryrefslogtreecommitdiffstats
path: root/lldb/include/lldb/Symbol/CompactUnwindInfo.h
blob: 239eb3ac77ad8e17941b003a72072f343cd9175b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//===-- CompactUnwindInfo.h -------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_CompactUnwindInfo_h_
#define liblldb_CompactUnwindInfo_h_

#include <vector>

#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/RangeMap.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/lldb-private.h"

namespace lldb_private {

// Compact Unwind info is an unwind format used on Darwin.  The unwind instructions
// for typical compiler-generated functions can be expressed in a 32-bit encoding.
// The format includes a two-level index so the unwind information for a function
// can be found by two binary searches in the section.  It can represent both
// stack frames that use a frame-pointer register and frameless functions, on
// i386/x86_64 for instance.  When a function is too complex to be represented in
// the compact unwind format, it calls out to eh_frame unwind instructions.

// On Mac OS X / iOS, a function will have either a compact unwind representation 
// or an eh_frame representation.  If lldb is going to benefit  from the compiler's 
// description about saved register locations, it must be able to read both 
// sources of information.

class CompactUnwindInfo
{
public:

    CompactUnwindInfo (ObjectFile& objfile,
                       lldb::SectionSP& section);

    ~CompactUnwindInfo();

    bool
    GetUnwindPlan (Target &target, Address addr, UnwindPlan& unwind_plan);

    bool
    IsValid (const lldb::ProcessSP &process_sp);

private:

    
    // The top level index entries of the compact unwind info
    //   (internal representation of struct unwind_info_section_header_index_entry)
    // There are relatively few of these (one per 500/1000 functions, depending on format) so
    // creating them on first scan will not be too costly.
    struct UnwindIndex
    {
        uint32_t        function_offset; // The offset of the first function covered by this index
        uint32_t        second_level;    // The offset (inside unwind_info sect) to the second level page for this index
        // (either UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED)
        uint32_t        lsda_array_start;// The offset (inside unwind_info sect) LSDA array for this index
        uint32_t        lsda_array_end;  // The offset to the LSDA array for the NEXT index
        bool            sentinal_entry;  // There is an empty index at the end which provides the upper bound of
        // function addresses that are described
        
        UnwindIndex() :
        function_offset (0),
        second_level (0),
        lsda_array_start(0),
        lsda_array_end(0),
        sentinal_entry (false)
        { }

        bool
        operator< (const CompactUnwindInfo::UnwindIndex& rhs) const
        {
            return function_offset < rhs.function_offset;
        }

        bool
        operator== (const CompactUnwindInfo::UnwindIndex& rhs) const
        {
            return function_offset == rhs.function_offset;
        }

    };

    // An internal object used to store the information we retrieve about a function --
    // the encoding bits and possibly the LSDA/personality function.  
    struct FunctionInfo
    {
        uint32_t  encoding;                   // compact encoding 32-bit value for this function
        Address   lsda_address;               // the address of the LSDA data for this function
        Address   personality_ptr_address;    // the address where the personality routine addr can be found

        uint32_t  valid_range_offset_start;   // first offset that this encoding is valid for (start of the function)
        uint32_t  valid_range_offset_end;     // the offset of the start of the next function
        FunctionInfo () : encoding(0), lsda_address(), personality_ptr_address(), valid_range_offset_start(0), valid_range_offset_end(0) { }
    };

    struct UnwindHeader
    {
        uint32_t    version;
        uint32_t    common_encodings_array_offset;
        uint32_t    common_encodings_array_count;
        uint32_t    personality_array_offset;
        uint32_t    personality_array_count;

        UnwindHeader () : common_encodings_array_offset (0), common_encodings_array_count (0), personality_array_offset (0), personality_array_count (0) { }
    };

    void
    ScanIndex(const lldb::ProcessSP &process_sp);

    bool
    GetCompactUnwindInfoForFunction (Target &target, Address address, FunctionInfo &unwind_info);

    lldb::offset_t
    BinarySearchRegularSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset, uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset);

    uint32_t
    BinarySearchCompressedSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset_to_find, uint32_t function_offset_base, uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset);

    uint32_t
    GetLSDAForFunctionOffset (uint32_t lsda_offset, uint32_t lsda_count, uint32_t function_offset);

    bool
    CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start);

    bool
    CreateUnwindPlan_i386 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start);

    ObjectFile                  &m_objfile;
    lldb::SectionSP             m_section_sp;
    lldb::DataBufferSP          m_section_contents_if_encrypted; // if the binary is encrypted, read the sect contents
                                                                 // out of live memory and cache them here
    Mutex                       m_mutex;
    std::vector<UnwindIndex>    m_indexes;

    LazyBool                    m_indexes_computed;         // eLazyBoolYes once we've tried to parse the unwind info
                                                            // eLazyBoolNo means we cannot parse the unwind info & should not retry
                                                            // eLazyBoolCalculate means we haven't tried to parse it yet

    DataExtractor               m_unwindinfo_data;
    bool                        m_unwindinfo_data_computed; // true once we've mapped in the unwindinfo data

    UnwindHeader                m_unwind_header;
};

} // namespace lldb_private

#endif  // liblldb_CompactUnwindInfo_h_
OpenPOWER on IntegriCloud