/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Target/UnwindLLDB.h
Line | Count | Source |
1 | | //===-- UnwindLLDB.h --------------------------------------------*- C++ -*-===// |
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 LLDB_TARGET_UNWINDLLDB_H |
10 | | #define LLDB_TARGET_UNWINDLLDB_H |
11 | | |
12 | | #include <vector> |
13 | | |
14 | | #include "lldb/Symbol/FuncUnwinders.h" |
15 | | #include "lldb/Symbol/SymbolContext.h" |
16 | | #include "lldb/Symbol/UnwindPlan.h" |
17 | | #include "lldb/Target/RegisterContext.h" |
18 | | #include "lldb/Target/Unwind.h" |
19 | | #include "lldb/Utility/ConstString.h" |
20 | | #include "lldb/lldb-public.h" |
21 | | |
22 | | namespace lldb_private { |
23 | | |
24 | | class RegisterContextUnwind; |
25 | | |
26 | | class UnwindLLDB : public lldb_private::Unwind { |
27 | | public: |
28 | | UnwindLLDB(lldb_private::Thread &thread); |
29 | | |
30 | 2.75k | ~UnwindLLDB() override = default; |
31 | | |
32 | | enum RegisterSearchResult { |
33 | | eRegisterFound = 0, |
34 | | eRegisterNotFound, |
35 | | eRegisterIsVolatile |
36 | | }; |
37 | | |
38 | | protected: |
39 | | friend class lldb_private::RegisterContextUnwind; |
40 | | |
41 | | struct RegisterLocation { |
42 | | enum RegisterLocationTypes { |
43 | | eRegisterNotSaved = 0, // register was not preserved by callee. If |
44 | | // volatile reg, is unavailable |
45 | | eRegisterSavedAtMemoryLocation, // register is saved at a specific word of |
46 | | // target mem (target_memory_location) |
47 | | eRegisterInRegister, // register is available in a (possible other) |
48 | | // register (register_number) |
49 | | eRegisterSavedAtHostMemoryLocation, // register is saved at a word in |
50 | | // lldb's address space |
51 | | eRegisterValueInferred, // register val was computed (and is in |
52 | | // inferred_value) |
53 | | eRegisterInLiveRegisterContext // register value is in a live (stack frame |
54 | | // #0) register |
55 | | }; |
56 | | int type; |
57 | | union { |
58 | | lldb::addr_t target_memory_location; |
59 | | uint32_t |
60 | | register_number; // in eRegisterKindLLDB register numbering system |
61 | | void *host_memory_location; |
62 | | uint64_t inferred_value; // eRegisterValueInferred - e.g. stack pointer == |
63 | | // cfa + offset |
64 | | } location; |
65 | | }; |
66 | | |
67 | 22.0k | void DoClear() override { |
68 | 22.0k | m_frames.clear(); |
69 | 22.0k | m_candidate_frame.reset(); |
70 | 22.0k | m_unwind_complete = false; |
71 | 22.0k | } |
72 | | |
73 | | uint32_t DoGetFrameCount() override; |
74 | | |
75 | | bool DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, |
76 | | lldb::addr_t &start_pc, |
77 | | bool &behaves_like_zeroth_frame) override; |
78 | | |
79 | | lldb::RegisterContextSP |
80 | | DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; |
81 | | |
82 | | typedef std::shared_ptr<RegisterContextUnwind> RegisterContextLLDBSP; |
83 | | |
84 | | // Needed to retrieve the "next" frame (e.g. frame 2 needs to retrieve frame |
85 | | // 1's RegisterContextUnwind) |
86 | | // The RegisterContext for frame_num must already exist or this returns an |
87 | | // empty shared pointer. |
88 | | RegisterContextLLDBSP GetRegisterContextForFrameNum(uint32_t frame_num); |
89 | | |
90 | | // Iterate over the RegisterContextUnwind's in our m_frames vector, look for |
91 | | // the first one that has a saved location for this reg. |
92 | | bool SearchForSavedLocationForRegister( |
93 | | uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, |
94 | | uint32_t starting_frame_num, bool pc_register); |
95 | | |
96 | | /// Provide the list of user-specified trap handler functions |
97 | | /// |
98 | | /// The Platform is one source of trap handler function names; that |
99 | | /// may be augmented via a setting. The setting needs to be converted |
100 | | /// into an array of ConstStrings before it can be used - we only want |
101 | | /// to do that once per thread so it's here in the UnwindLLDB object. |
102 | | /// |
103 | | /// \return |
104 | | /// Vector of ConstStrings of trap handler function names. May be |
105 | | /// empty. |
106 | 233k | const std::vector<ConstString> &GetUserSpecifiedTrapHandlerFunctionNames() { |
107 | 233k | return m_user_supplied_trap_handler_functions; |
108 | 233k | } |
109 | | |
110 | | private: |
111 | | struct Cursor { |
112 | | lldb::addr_t start_pc = |
113 | | LLDB_INVALID_ADDRESS; // The start address of the function/symbol for |
114 | | // this frame - current pc if unknown |
115 | | lldb::addr_t cfa = LLDB_INVALID_ADDRESS; // The canonical frame address for |
116 | | // this stack frame |
117 | | lldb_private::SymbolContext sctx; // A symbol context we'll contribute to & |
118 | | // provide to the StackFrame creation |
119 | | RegisterContextLLDBSP |
120 | | reg_ctx_lldb_sp; // These are all RegisterContextUnwind's |
121 | | |
122 | 246k | Cursor() = default; |
123 | | |
124 | | private: |
125 | | Cursor(const Cursor &) = delete; |
126 | | const Cursor &operator=(const Cursor &) = delete; |
127 | | }; |
128 | | |
129 | | typedef std::shared_ptr<Cursor> CursorSP; |
130 | | std::vector<CursorSP> m_frames; |
131 | | CursorSP m_candidate_frame; |
132 | | bool m_unwind_complete; // If this is true, we've enumerated all the frames in |
133 | | // the stack, and m_frames.size() is the |
134 | | // number of frames, etc. Otherwise we've only gone as far as directly asked, |
135 | | // and m_frames.size() |
136 | | // is how far we've currently gone. |
137 | | |
138 | | std::vector<ConstString> m_user_supplied_trap_handler_functions; |
139 | | |
140 | | // Check if Full UnwindPlan of First frame is valid or not. |
141 | | // If not then try Fallback UnwindPlan of the frame. If Fallback |
142 | | // UnwindPlan succeeds then update the Full UnwindPlan with the |
143 | | // Fallback UnwindPlan. |
144 | | void UpdateUnwindPlanForFirstFrameIfInvalid(ABI *abi); |
145 | | |
146 | | CursorSP GetOneMoreFrame(ABI *abi); |
147 | | |
148 | | bool AddOneMoreFrame(ABI *abi); |
149 | | |
150 | | bool AddFirstFrame(); |
151 | | |
152 | | // For UnwindLLDB only |
153 | | UnwindLLDB(const UnwindLLDB &) = delete; |
154 | | const UnwindLLDB &operator=(const UnwindLLDB &) = delete; |
155 | | }; |
156 | | |
157 | | } // namespace lldb_private |
158 | | |
159 | | #endif // LLDB_TARGET_UNWINDLLDB_H |