LLDB mainline
UnwindPlan.h
Go to the documentation of this file.
1//===-- UnwindPlan.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_SYMBOL_UNWINDPLAN_H
10#define LLDB_SYMBOL_UNWINDPLAN_H
11
12#include <map>
13#include <memory>
14#include <vector>
15
18#include "lldb/Utility/Stream.h"
19#include "lldb/lldb-private.h"
20
21namespace lldb_private {
22
23// The UnwindPlan object specifies how to unwind out of a function - where this
24// function saves the caller's register values before modifying them (for non-
25// volatile aka saved registers) and how to find this frame's Canonical Frame
26// Address (CFA) or Aligned Frame Address (AFA).
27
28// CFA is a DWARF's Canonical Frame Address.
29// Most commonly, registers are saved on the stack, offset some bytes from the
30// Canonical Frame Address, or CFA, which is the starting address of this
31// function's stack frame (the CFA is same as the eh_frame's CFA, whatever that
32// may be on a given architecture). The CFA address for the stack frame does
33// not change during the lifetime of the function.
34
35// AFA is an artificially introduced Aligned Frame Address.
36// It is used only for stack frames with realignment (e.g. when some of the
37// locals has an alignment requirement higher than the stack alignment right
38// after the function call). It is used to access register values saved on the
39// stack after the realignment (and so they are inaccessible through the CFA).
40// AFA usually equals the stack pointer value right after the realignment.
41
42// Internally, the UnwindPlan is structured as a vector of register locations
43// organized by code address in the function, showing which registers have been
44// saved at that point and where they are saved. It can be thought of as the
45// expanded table form of the DWARF CFI encoded information.
46
47// Other unwind information sources will be converted into UnwindPlans before
48// being added to a FuncUnwinders object. The unwind source may be an eh_frame
49// FDE, a DWARF debug_frame FDE, or assembly language based prologue analysis.
50// The UnwindPlan is the canonical form of this information that the unwinder
51// code will use when walking the stack.
52
54public:
55 class Row {
56 public:
58 public:
60 unspecified, // not specified, we may be able to assume this
61 // is the same register. gcc doesn't specify all
62 // initial values so we really don't know...
63 undefined, // reg is not available, e.g. volatile reg
64 same, // reg is unchanged
65 atCFAPlusOffset, // reg = deref(CFA + offset)
66 isCFAPlusOffset, // reg = CFA + offset
67 atAFAPlusOffset, // reg = deref(AFA + offset)
68 isAFAPlusOffset, // reg = AFA + offset
69 inOtherRegister, // reg = other reg
70 atDWARFExpression, // reg = deref(eval(dwarf_expr))
71 isDWARFExpression // reg = eval(dwarf_expr)
72 };
73
75
76 bool operator==(const RegisterLocation &rhs) const;
77
78 bool operator!=(const RegisterLocation &rhs) const {
79 return !(*this == rhs);
80 }
81
83
85
86 void SetSame() { m_type = same; }
87
88 bool IsSame() const { return m_type == same; }
89
90 bool IsUnspecified() const { return m_type == unspecified; }
91
92 bool IsUndefined() const { return m_type == undefined; }
93
94 bool IsCFAPlusOffset() const { return m_type == isCFAPlusOffset; }
95
96 bool IsAtCFAPlusOffset() const { return m_type == atCFAPlusOffset; }
97
98 bool IsAFAPlusOffset() const { return m_type == isAFAPlusOffset; }
99
100 bool IsAtAFAPlusOffset() const { return m_type == atAFAPlusOffset; }
101
102 bool IsInOtherRegister() const { return m_type == inOtherRegister; }
103
104 bool IsAtDWARFExpression() const { return m_type == atDWARFExpression; }
105
106 bool IsDWARFExpression() const { return m_type == isDWARFExpression; }
107
110 m_location.offset = offset;
111 }
112
115 m_location.offset = offset;
116 }
117
120 m_location.offset = offset;
121 }
122
125 m_location.offset = offset;
126 }
127
128 void SetInRegister(uint32_t reg_num) {
130 m_location.reg_num = reg_num;
131 }
132
133 uint32_t GetRegisterNumber() const {
134 if (m_type == inOtherRegister)
135 return m_location.reg_num;
136 return LLDB_INVALID_REGNUM;
137 }
138
140
141 int32_t GetOffset() const {
142 switch(m_type)
143 {
144 case atCFAPlusOffset:
145 case isCFAPlusOffset:
146 case atAFAPlusOffset:
147 case isAFAPlusOffset:
148 return m_location.offset;
149 default:
150 return 0;
151 }
152 }
153
154 void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const {
156 *opcodes = m_location.expr.opcodes;
157 len = m_location.expr.length;
158 } else {
159 *opcodes = nullptr;
160 len = 0;
161 }
162 }
163
164 void SetAtDWARFExpression(const uint8_t *opcodes, uint32_t len);
165
166 void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len);
167
168 const uint8_t *GetDWARFExpressionBytes() {
170 return m_location.expr.opcodes;
171 return nullptr;
172 }
173
176 return m_location.expr.length;
177 return 0;
178 }
179
180 void Dump(Stream &s, const UnwindPlan *unwind_plan,
181 const UnwindPlan::Row *row, Thread *thread, bool verbose) const;
182
183 private:
184 RestoreType m_type = unspecified; // How do we locate this register?
185 union {
186 // For m_type == atCFAPlusOffset or m_type == isCFAPlusOffset
187 int32_t offset;
188 // For m_type == inOtherRegister
189 uint32_t reg_num; // The register number
190 // For m_type == atDWARFExpression or m_type == isDWARFExpression
191 struct {
192 const uint8_t *opcodes;
193 uint16_t length;
196 };
197
198 class FAValue {
199 public:
201 unspecified, // not specified
202 isRegisterPlusOffset, // FA = register + offset
204 isDWARFExpression, // FA = eval(dwarf_expr)
205 isRaSearch, // FA = SP + offset + ???
206 };
207
209
210 bool operator==(const FAValue &rhs) const;
211
212 bool operator!=(const FAValue &rhs) const { return !(*this == rhs); }
213
215
216 bool IsUnspecified() const { return m_type == unspecified; }
217
218 void SetRaSearch(int32_t offset) {
220 m_value.ra_search_offset = offset;
221 }
222
223 bool IsRegisterPlusOffset() const {
225 }
226
227 void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset) {
229 m_value.reg.reg_num = reg_num;
230 m_value.reg.offset = offset;
231 }
232
235 }
236
239 m_value.reg.reg_num = reg_num;
240 }
241
242 bool IsDWARFExpression() const { return m_type == isDWARFExpression; }
243
244 void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len) {
246 m_value.expr.opcodes = opcodes;
247 m_value.expr.length = len;
248 }
249
250 uint32_t GetRegisterNumber() const {
252 return m_value.reg.reg_num;
253 return LLDB_INVALID_REGNUM;
254 }
255
256 ValueType GetValueType() const { return m_type; }
257
258 int32_t GetOffset() const {
259 switch (m_type) {
261 return m_value.reg.offset;
262 case isRaSearch:
263 return m_value.ra_search_offset;
264 default:
265 return 0;
266 }
267 }
268
269 void IncOffset(int32_t delta) {
271 m_value.reg.offset += delta;
272 }
273
274 void SetOffset(int32_t offset) {
276 m_value.reg.offset = offset;
277 }
278
279 void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const {
280 if (m_type == isDWARFExpression) {
281 *opcodes = m_value.expr.opcodes;
282 len = m_value.expr.length;
283 } else {
284 *opcodes = nullptr;
285 len = 0;
286 }
287 }
288
289 const uint8_t *GetDWARFExpressionBytes() {
291 return m_value.expr.opcodes;
292 return nullptr;
293 }
294
297 return m_value.expr.length;
298 return 0;
299 }
300
301 void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread) const;
302
303 private:
304 ValueType m_type = unspecified; // How do we compute CFA value?
305 union {
306 struct {
307 // For m_type == isRegisterPlusOffset or m_type ==
308 // isRegisterDereferenced
309 uint32_t reg_num; // The register number
310 // For m_type == isRegisterPlusOffset
311 int32_t offset;
313 // For m_type == isDWARFExpression
314 struct {
315 const uint8_t *opcodes;
316 uint16_t length;
318 // For m_type == isRaSearch
321 }; // class FAValue
322
323 Row();
324
325 bool operator==(const Row &rhs) const;
326
327 bool GetRegisterInfo(uint32_t reg_num,
328 RegisterLocation &register_location) const;
329
330 void SetRegisterInfo(uint32_t reg_num,
331 const RegisterLocation register_location);
332
333 void RemoveRegisterInfo(uint32_t reg_num);
334
335 lldb::addr_t GetOffset() const { return m_offset; }
336
337 void SetOffset(lldb::addr_t offset) { m_offset = offset; }
338
339 void SlideOffset(lldb::addr_t offset) { m_offset += offset; }
340
342
344
345 bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset,
346 bool can_replace);
347
348 bool SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num, int32_t offset,
349 bool can_replace);
350
351 bool SetRegisterLocationToUndefined(uint32_t reg_num, bool can_replace,
352 bool can_replace_only_if_unspecified);
353
354 bool SetRegisterLocationToUnspecified(uint32_t reg_num, bool can_replace);
355
356 bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num,
357 bool can_replace);
358
359 bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace);
360
361 // When this UnspecifiedRegistersAreUndefined mode is
362 // set, any register that is not specified by this Row will
363 // be described as Undefined.
364 // This will prevent the unwinder from iterating down the
365 // stack looking for a spill location, or a live register value
366 // at frame 0.
367 // It would be used for an UnwindPlan row where we can't track
368 // spilled registers -- for instance a jitted stack frame where
369 // we have no unwind information or start address -- and registers
370 // MAY have been spilled and overwritten, so providing the
371 // spilled/live value from a newer frame may show an incorrect value.
372 void SetUnspecifiedRegistersAreUndefined(bool unspec_is_undef) {
374 }
375
378 }
379
380 void Clear();
381
382 void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread,
383 lldb::addr_t base_addr) const;
384
385 protected:
386 typedef std::map<uint32_t, RegisterLocation> collection;
387 lldb::addr_t m_offset = 0; // Offset into the function for this row
388
393 }; // class Row
394
395 typedef std::shared_ptr<Row> RowSP;
396
402
403 // Performs a deep copy of the plan, including all the rows (expensive).
415 m_row_list.reserve(rhs.m_row_list.size());
416 for (const RowSP &row_sp : rhs.m_row_list)
417 m_row_list.emplace_back(new Row(*row_sp));
418 }
419
420 ~UnwindPlan() = default;
421
422 void Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const;
423
424 void AppendRow(const RowSP &row_sp);
425
426 void InsertRow(const RowSP &row_sp, bool replace_existing = false);
427
428 // Returns a pointer to the best row for the given offset into the function's
429 // instructions. If offset is -1 it indicates that the function start is
430 // unknown - the final row in the UnwindPlan is returned. In practice, the
431 // UnwindPlan for a function with no known start address will be the
432 // architectural default UnwindPlan which will only have one row.
434
436
438
439 void SetReturnAddressRegister(uint32_t regnum) {
440 m_return_addr_register = regnum;
441 }
442
444
445 uint32_t GetInitialCFARegister() const {
446 if (m_row_list.empty())
447 return LLDB_INVALID_REGNUM;
448 return m_row_list.front()->GetCFAValue().GetRegisterNumber();
449 }
450
451 // This UnwindPlan may not be valid at every address of the function span.
452 // For instance, a FastUnwindPlan will not be valid at the prologue setup
453 // instructions - only in the body of the function.
454 void SetPlanValidAddressRange(const AddressRange &range);
455
458 }
459
460 bool PlanValidAtAddress(Address addr);
461
462 bool IsValidRowIndex(uint32_t idx) const;
463
464 const UnwindPlan::RowSP GetRowAtIndex(uint32_t idx) const;
465
466 const UnwindPlan::RowSP GetLastRow() const;
467
469
470 void SetSourceName(const char *);
471
472 // Was this UnwindPlan emitted by a compiler?
475 }
476
477 // Was this UnwindPlan emitted by a compiler?
479 m_plan_is_sourced_from_compiler = from_compiler;
480 }
481
482 // Is this UnwindPlan valid at all instructions? If not, then it is assumed
483 // valid at call sites, e.g. for exception handling.
486 }
487
488 // Is this UnwindPlan valid at all instructions? If not, then it is assumed
489 // valid at call sites, e.g. for exception handling.
491 lldb_private::LazyBool valid_at_all_insn) {
493 }
494
495 // Is this UnwindPlan for a signal trap frame? If so, then its saved pc
496 // may have been set manually by the signal dispatch code and therefore
497 // not follow a call to the child frame.
500 }
501
503 m_plan_is_for_signal_trap = is_for_signal_trap;
504 }
505
506 int GetRowCount() const;
507
508 void Clear() {
509 m_row_list.clear();
518 }
519
520 const RegisterInfo *GetRegisterInfo(Thread *thread, uint32_t reg_num) const;
521
523
524 void SetLSDAAddress(Address lsda_addr) { m_lsda_address = lsda_addr; }
525
527
528 void SetPersonalityFunctionPtr(Address presonality_func_ptr) {
529 m_personality_func_addr = presonality_func_ptr;
530 }
531
532private:
533 typedef std::vector<RowSP> collection;
536 lldb::RegisterKind m_register_kind; // The RegisterKind these register numbers
537 // are in terms of - will need to be
538 // translated to lldb native reg nums at unwind time
539 uint32_t m_return_addr_register; // The register that has the return address
540 // for the caller frame
541 // e.g. the lr on arm
543 m_source_name; // for logging, where this UnwindPlan originated from
547
548 Address m_lsda_address; // Where the language specific data area exists in the
549 // module - used
550 // in exception handling.
551 Address m_personality_func_addr; // The address of a pointer to the
552 // personality function - used in
553 // exception handling.
554}; // class UnwindPlan
555
556} // namespace lldb_private
557
558#endif // LLDB_SYMBOL_UNWINDPLAN_H
A section + offset based address range class.
Definition: AddressRange.h:25
void Clear()
Clear the object's state.
A section + offset based address class.
Definition: Address.h:62
void Clear()
Clear the object's state.
Definition: Address.h:181
A uniqued constant string class.
Definition: ConstString.h:40
void Clear()
Clear this object's state.
Definition: ConstString.h:230
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len)
Definition: UnwindPlan.h:244
void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread) const
Definition: UnwindPlan.cpp:192
struct lldb_private::UnwindPlan::Row::FAValue::@27::@28 reg
const uint8_t * GetDWARFExpressionBytes()
Definition: UnwindPlan.h:289
struct lldb_private::UnwindPlan::Row::FAValue::@27::@29 expr
bool operator==(const FAValue &rhs) const
Definition: UnwindPlan.cpp:169
void SetIsRegisterDereferenced(uint32_t reg_num)
Definition: UnwindPlan.h:237
bool operator!=(const FAValue &rhs) const
Definition: UnwindPlan.h:212
union lldb_private::UnwindPlan::Row::FAValue::@27 m_value
void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const
Definition: UnwindPlan.h:279
void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset)
Definition: UnwindPlan.h:227
void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const
Definition: UnwindPlan.h:154
bool operator==(const RegisterLocation &rhs) const
Definition: UnwindPlan.cpp:26
bool operator!=(const RegisterLocation &rhs) const
Definition: UnwindPlan.h:78
void SetAtDWARFExpression(const uint8_t *opcodes, uint32_t len)
Definition: UnwindPlan.cpp:56
void Dump(Stream &s, const UnwindPlan *unwind_plan, const UnwindPlan::Row *row, Thread *thread, bool verbose) const
Definition: UnwindPlan.cpp:93
void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len)
Definition: UnwindPlan.cpp:65
union lldb_private::UnwindPlan::Row::RegisterLocation::@25 m_location
struct lldb_private::UnwindPlan::Row::RegisterLocation::@25::@26 expr
bool SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num, int32_t offset, bool can_replace)
Definition: UnwindPlan.cpp:291
bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace)
Definition: UnwindPlan.cpp:343
std::map< uint32_t, RegisterLocation > collection
Definition: UnwindPlan.h:386
bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset, bool can_replace)
Definition: UnwindPlan.cpp:279
bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num, bool can_replace)
Definition: UnwindPlan.cpp:331
void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread, lldb::addr_t base_addr) const
Definition: UnwindPlan.cpp:225
bool SetRegisterLocationToUnspecified(uint32_t reg_num, bool can_replace)
Definition: UnwindPlan.cpp:320
void RemoveRegisterInfo(uint32_t reg_num)
Definition: UnwindPlan.cpp:266
lldb::addr_t GetOffset() const
Definition: UnwindPlan.h:335
bool operator==(const Row &rhs) const
Definition: UnwindPlan.cpp:354
bool SetRegisterLocationToUndefined(uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified)
Definition: UnwindPlan.cpp:303
bool GetRegisterInfo(uint32_t reg_num, RegisterLocation &register_location) const
Definition: UnwindPlan.cpp:251
void SlideOffset(lldb::addr_t offset)
Definition: UnwindPlan.h:339
void SetOffset(lldb::addr_t offset)
Definition: UnwindPlan.h:337
void SetUnspecifiedRegistersAreUndefined(bool unspec_is_undef)
Definition: UnwindPlan.h:372
void SetRegisterInfo(uint32_t reg_num, const RegisterLocation register_location)
Definition: UnwindPlan.cpp:273
lldb_private::LazyBool GetUnwindPlanValidAtAllInstructions() const
Definition: UnwindPlan.h:484
void SetUnwindPlanForSignalTrap(lldb_private::LazyBool is_for_signal_trap)
Definition: UnwindPlan.h:502
void InsertRow(const RowSP &row_sp, bool replace_existing=false)
Definition: UnwindPlan.cpp:370
const UnwindPlan::RowSP GetRowAtIndex(uint32_t idx) const
Definition: UnwindPlan.cpp:407
lldb::RegisterKind m_register_kind
Definition: UnwindPlan.h:536
void SetRegisterKind(lldb::RegisterKind kind)
Definition: UnwindPlan.h:437
UnwindPlan(const UnwindPlan &rhs)
Definition: UnwindPlan.h:404
UnwindPlan(lldb::RegisterKind reg_kind)
Definition: UnwindPlan.h:397
uint32_t GetInitialCFARegister() const
Definition: UnwindPlan.h:445
const RegisterInfo * GetRegisterInfo(Thread *thread, uint32_t reg_num) const
Definition: UnwindPlan.cpp:570
Address GetPersonalityFunctionPtr() const
Definition: UnwindPlan.h:526
lldb_private::LazyBool m_plan_is_for_signal_trap
Definition: UnwindPlan.h:546
const UnwindPlan::RowSP GetLastRow() const
Definition: UnwindPlan.cpp:420
void SetPlanValidAddressRange(const AddressRange &range)
Definition: UnwindPlan.cpp:431
void SetReturnAddressRegister(uint32_t regnum)
Definition: UnwindPlan.h:439
uint32_t GetReturnAddressRegister()
Definition: UnwindPlan.h:443
AddressRange m_plan_valid_address_range
Definition: UnwindPlan.h:535
std::vector< RowSP > collection
Definition: UnwindPlan.h:533
bool IsValidRowIndex(uint32_t idx) const
Definition: UnwindPlan.cpp:403
uint32_t m_return_addr_register
Definition: UnwindPlan.h:539
void SetPersonalityFunctionPtr(Address presonality_func_ptr)
Definition: UnwindPlan.h:528
void AppendRow(const RowSP &row_sp)
Definition: UnwindPlan.cpp:362
lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations
Definition: UnwindPlan.h:545
UnwindPlan::RowSP GetRowForFunctionOffset(int offset) const
Definition: UnwindPlan.cpp:385
lldb::RegisterKind GetRegisterKind() const
Definition: UnwindPlan.h:435
std::shared_ptr< Row > RowSP
Definition: UnwindPlan.h:395
void SetLSDAAddress(Address lsda_addr)
Definition: UnwindPlan.h:524
lldb_private::ConstString m_source_name
Definition: UnwindPlan.h:543
void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler)
Definition: UnwindPlan.h:478
const AddressRange & GetAddressRange() const
Definition: UnwindPlan.h:456
bool PlanValidAtAddress(Address addr)
Definition: UnwindPlan.cpp:436
void SetSourceName(const char *)
Definition: UnwindPlan.cpp:564
Address GetLSDAAddress() const
Definition: UnwindPlan.h:522
lldb_private::LazyBool GetUnwindPlanForSignalTrap() const
Definition: UnwindPlan.h:498
void Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const
Definition: UnwindPlan.cpp:493
lldb_private::ConstString GetSourceName() const
Definition: UnwindPlan.cpp:568
lldb_private::LazyBool GetSourcedFromCompiler() const
Definition: UnwindPlan.h:473
void SetUnwindPlanValidAtAllInstructions(lldb_private::LazyBool valid_at_all_insn)
Definition: UnwindPlan.h:490
lldb_private::LazyBool m_plan_is_sourced_from_compiler
Definition: UnwindPlan.h:544
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:87
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
uint64_t addr_t
Definition: lldb-types.h:79
RegisterKind
Register numbering types.
@ eRegisterKindDWARF
the register numbers seen DWARF
Every register is described in detail including its name, alternate name (optional),...