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 isConstant // reg = constant
73 };
74
76
77 bool operator==(const RegisterLocation &rhs) const;
78
79 bool operator!=(const RegisterLocation &rhs) const {
80 return !(*this == rhs);
81 }
82
84
86
87 void SetSame() { m_type = same; }
88
89 bool IsSame() const { return m_type == same; }
90
91 bool IsUnspecified() const { return m_type == unspecified; }
92
93 bool IsUndefined() const { return m_type == undefined; }
94
95 bool IsCFAPlusOffset() const { return m_type == isCFAPlusOffset; }
96
97 bool IsAtCFAPlusOffset() const { return m_type == atCFAPlusOffset; }
98
99 bool IsAFAPlusOffset() const { return m_type == isAFAPlusOffset; }
100
101 bool IsAtAFAPlusOffset() const { return m_type == atAFAPlusOffset; }
102
103 bool IsInOtherRegister() const { return m_type == inOtherRegister; }
104
105 bool IsAtDWARFExpression() const { return m_type == atDWARFExpression; }
106
107 bool IsDWARFExpression() const { return m_type == isDWARFExpression; }
108
109 bool IsConstant() const { return m_type == isConstant; }
110
111 void SetIsConstant(uint64_t value) {
113 m_location.constant_value = value;
114 }
115
116 uint64_t GetConstant() const { return m_location.constant_value; }
117
120 m_location.offset = offset;
121 }
122
125 m_location.offset = offset;
126 }
127
130 m_location.offset = offset;
131 }
132
135 m_location.offset = offset;
136 }
137
138 void SetInRegister(uint32_t reg_num) {
140 m_location.reg_num = reg_num;
141 }
142
143 uint32_t GetRegisterNumber() const {
144 if (m_type == inOtherRegister)
145 return m_location.reg_num;
146 return LLDB_INVALID_REGNUM;
147 }
148
150
151 int32_t GetOffset() const {
152 switch(m_type)
153 {
154 case atCFAPlusOffset:
155 case isCFAPlusOffset:
156 case atAFAPlusOffset:
157 case isAFAPlusOffset:
158 return m_location.offset;
159 default:
160 return 0;
161 }
162 }
163
164 void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const {
166 *opcodes = m_location.expr.opcodes;
167 len = m_location.expr.length;
168 } else {
169 *opcodes = nullptr;
170 len = 0;
171 }
172 }
173
174 void SetAtDWARFExpression(const uint8_t *opcodes, uint32_t len);
175
176 void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len);
177
178 const uint8_t *GetDWARFExpressionBytes() {
180 return m_location.expr.opcodes;
181 return nullptr;
182 }
183
186 return m_location.expr.length;
187 return 0;
188 }
189
190 void Dump(Stream &s, const UnwindPlan *unwind_plan,
191 const UnwindPlan::Row *row, Thread *thread, bool verbose) const;
192
193 private:
194 RestoreType m_type = unspecified; // How do we locate this register?
195 union {
196 // For m_type == atCFAPlusOffset or m_type == isCFAPlusOffset
197 int32_t offset;
198 // For m_type == inOtherRegister
199 uint32_t reg_num; // The register number
200 // For m_type == atDWARFExpression or m_type == isDWARFExpression
201 struct {
202 const uint8_t *opcodes;
203 uint16_t length;
205 // For m_type == isConstant
208 };
209
210 class FAValue {
211 public:
213 unspecified, // not specified
214 isRegisterPlusOffset, // FA = register + offset
216 isDWARFExpression, // FA = eval(dwarf_expr)
217 isRaSearch, // FA = SP + offset + ???
218 };
219
221
222 bool operator==(const FAValue &rhs) const;
223
224 bool operator!=(const FAValue &rhs) const { return !(*this == rhs); }
225
227
228 bool IsUnspecified() const { return m_type == unspecified; }
229
230 void SetRaSearch(int32_t offset) {
232 m_value.ra_search_offset = offset;
233 }
234
235 bool IsRegisterPlusOffset() const {
237 }
238
239 void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset) {
241 m_value.reg.reg_num = reg_num;
242 m_value.reg.offset = offset;
243 }
244
247 }
248
251 m_value.reg.reg_num = reg_num;
252 }
253
254 bool IsDWARFExpression() const { return m_type == isDWARFExpression; }
255
256 void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len) {
258 m_value.expr.opcodes = opcodes;
259 m_value.expr.length = len;
260 }
261
262 uint32_t GetRegisterNumber() const {
264 return m_value.reg.reg_num;
265 return LLDB_INVALID_REGNUM;
266 }
267
268 ValueType GetValueType() const { return m_type; }
269
270 int32_t GetOffset() const {
271 switch (m_type) {
273 return m_value.reg.offset;
274 case isRaSearch:
275 return m_value.ra_search_offset;
276 default:
277 return 0;
278 }
279 }
280
281 void IncOffset(int32_t delta) {
283 m_value.reg.offset += delta;
284 }
285
286 void SetOffset(int32_t offset) {
288 m_value.reg.offset = offset;
289 }
290
291 void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const {
292 if (m_type == isDWARFExpression) {
293 *opcodes = m_value.expr.opcodes;
294 len = m_value.expr.length;
295 } else {
296 *opcodes = nullptr;
297 len = 0;
298 }
299 }
300
301 const uint8_t *GetDWARFExpressionBytes() {
303 return m_value.expr.opcodes;
304 return nullptr;
305 }
306
309 return m_value.expr.length;
310 return 0;
311 }
312
313 void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread) const;
314
315 private:
316 ValueType m_type = unspecified; // How do we compute CFA value?
317 union {
318 struct {
319 // For m_type == isRegisterPlusOffset or m_type ==
320 // isRegisterDereferenced
321 uint32_t reg_num; // The register number
322 // For m_type == isRegisterPlusOffset
323 int32_t offset;
325 // For m_type == isDWARFExpression
326 struct {
327 const uint8_t *opcodes;
328 uint16_t length;
330 // For m_type == isRaSearch
333 }; // class FAValue
334
335 Row();
336
337 bool operator==(const Row &rhs) const;
338
339 bool GetRegisterInfo(uint32_t reg_num,
340 RegisterLocation &register_location) const;
341
342 void SetRegisterInfo(uint32_t reg_num,
343 const RegisterLocation register_location);
344
345 void RemoveRegisterInfo(uint32_t reg_num);
346
347 lldb::addr_t GetOffset() const { return m_offset; }
348
349 void SetOffset(lldb::addr_t offset) { m_offset = offset; }
350
351 void SlideOffset(lldb::addr_t offset) { m_offset += offset; }
352
354
356
357 bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset,
358 bool can_replace);
359
360 bool SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num, int32_t offset,
361 bool can_replace);
362
363 bool SetRegisterLocationToUndefined(uint32_t reg_num, bool can_replace,
364 bool can_replace_only_if_unspecified);
365
366 bool SetRegisterLocationToUnspecified(uint32_t reg_num, bool can_replace);
367
368 bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num,
369 bool can_replace);
370
371 bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace);
372
373 bool SetRegisterLocationToIsConstant(uint32_t reg_num, uint64_t constant,
374 bool can_replace);
375
376 // When this UnspecifiedRegistersAreUndefined mode is
377 // set, any register that is not specified by this Row will
378 // be described as Undefined.
379 // This will prevent the unwinder from iterating down the
380 // stack looking for a spill location, or a live register value
381 // at frame 0.
382 // It would be used for an UnwindPlan row where we can't track
383 // spilled registers -- for instance a jitted stack frame where
384 // we have no unwind information or start address -- and registers
385 // MAY have been spilled and overwritten, so providing the
386 // spilled/live value from a newer frame may show an incorrect value.
387 void SetUnspecifiedRegistersAreUndefined(bool unspec_is_undef) {
389 }
390
393 }
394
395 void Clear();
396
397 void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread,
398 lldb::addr_t base_addr) const;
399
400 protected:
401 typedef std::map<uint32_t, RegisterLocation> collection;
402 lldb::addr_t m_offset = 0; // Offset into the function for this row
403
408 }; // class Row
409
410 typedef std::shared_ptr<Row> RowSP;
411
417
418 // Performs a deep copy of the plan, including all the rows (expensive).
430 m_row_list.reserve(rhs.m_row_list.size());
431 for (const RowSP &row_sp : rhs.m_row_list)
432 m_row_list.emplace_back(new Row(*row_sp));
433 }
434
435 ~UnwindPlan() = default;
436
437 void Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const;
438
439 void AppendRow(const RowSP &row_sp);
440
441 void InsertRow(const RowSP &row_sp, bool replace_existing = false);
442
443 // Returns a pointer to the best row for the given offset into the function's
444 // instructions. If offset is -1 it indicates that the function start is
445 // unknown - the final row in the UnwindPlan is returned. In practice, the
446 // UnwindPlan for a function with no known start address will be the
447 // architectural default UnwindPlan which will only have one row.
449
451
453
454 void SetReturnAddressRegister(uint32_t regnum) {
455 m_return_addr_register = regnum;
456 }
457
459
460 uint32_t GetInitialCFARegister() const {
461 if (m_row_list.empty())
462 return LLDB_INVALID_REGNUM;
463 return m_row_list.front()->GetCFAValue().GetRegisterNumber();
464 }
465
466 // This UnwindPlan may not be valid at every address of the function span.
467 // For instance, a FastUnwindPlan will not be valid at the prologue setup
468 // instructions - only in the body of the function.
469 void SetPlanValidAddressRange(const AddressRange &range);
470
473 }
474
475 bool PlanValidAtAddress(Address addr);
476
477 bool IsValidRowIndex(uint32_t idx) const;
478
479 const UnwindPlan::RowSP GetRowAtIndex(uint32_t idx) const;
480
481 const UnwindPlan::RowSP GetLastRow() const;
482
484
485 void SetSourceName(const char *);
486
487 // Was this UnwindPlan emitted by a compiler?
490 }
491
492 // Was this UnwindPlan emitted by a compiler?
494 m_plan_is_sourced_from_compiler = from_compiler;
495 }
496
497 // Is this UnwindPlan valid at all instructions? If not, then it is assumed
498 // valid at call sites, e.g. for exception handling.
501 }
502
503 // Is this UnwindPlan valid at all instructions? If not, then it is assumed
504 // valid at call sites, e.g. for exception handling.
506 lldb_private::LazyBool valid_at_all_insn) {
508 }
509
510 // Is this UnwindPlan for a signal trap frame? If so, then its saved pc
511 // may have been set manually by the signal dispatch code and therefore
512 // not follow a call to the child frame.
515 }
516
518 m_plan_is_for_signal_trap = is_for_signal_trap;
519 }
520
521 int GetRowCount() const;
522
523 void Clear() {
524 m_row_list.clear();
533 }
534
535 const RegisterInfo *GetRegisterInfo(Thread *thread, uint32_t reg_num) const;
536
538
539 void SetLSDAAddress(Address lsda_addr) { m_lsda_address = lsda_addr; }
540
542
543 void SetPersonalityFunctionPtr(Address presonality_func_ptr) {
544 m_personality_func_addr = presonality_func_ptr;
545 }
546
547private:
548 typedef std::vector<RowSP> collection;
551 lldb::RegisterKind m_register_kind; // The RegisterKind these register numbers
552 // are in terms of - will need to be
553 // translated to lldb native reg nums at unwind time
554 uint32_t m_return_addr_register; // The register that has the return address
555 // for the caller frame
556 // e.g. the lr on arm
558 m_source_name; // for logging, where this UnwindPlan originated from
562
563 Address m_lsda_address; // Where the language specific data area exists in the
564 // module - used
565 // in exception handling.
566 Address m_personality_func_addr; // The address of a pointer to the
567 // personality function - used in
568 // exception handling.
569}; // class UnwindPlan
570
571} // namespace lldb_private
572
573#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:232
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:256
void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread) const
Definition: UnwindPlan.cpp:197
const uint8_t * GetDWARFExpressionBytes()
Definition: UnwindPlan.h:301
union lldb_private::UnwindPlan::Row::FAValue::@26 m_value
bool operator==(const FAValue &rhs) const
Definition: UnwindPlan.cpp:174
struct lldb_private::UnwindPlan::Row::FAValue::@26::@27 reg
void SetIsRegisterDereferenced(uint32_t reg_num)
Definition: UnwindPlan.h:249
struct lldb_private::UnwindPlan::Row::FAValue::@26::@28 expr
bool operator!=(const FAValue &rhs) const
Definition: UnwindPlan.h:224
void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const
Definition: UnwindPlan.h:291
void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset)
Definition: UnwindPlan.h:239
void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const
Definition: UnwindPlan.h:164
bool operator==(const RegisterLocation &rhs) const
Definition: UnwindPlan.cpp:26
union lldb_private::UnwindPlan::Row::RegisterLocation::@24 m_location
struct lldb_private::UnwindPlan::Row::RegisterLocation::@24::@25 expr
bool operator!=(const RegisterLocation &rhs) const
Definition: UnwindPlan.h:79
void SetAtDWARFExpression(const uint8_t *opcodes, uint32_t len)
Definition: UnwindPlan.cpp:58
void Dump(Stream &s, const UnwindPlan *unwind_plan, const UnwindPlan::Row *row, Thread *thread, bool verbose) const
Definition: UnwindPlan.cpp:95
void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len)
Definition: UnwindPlan.cpp:67
bool SetRegisterLocationToIsConstant(uint32_t reg_num, uint64_t constant, bool can_replace)
Definition: UnwindPlan.cpp:359
bool SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num, int32_t offset, bool can_replace)
Definition: UnwindPlan.cpp:296
bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace)
Definition: UnwindPlan.cpp:348
std::map< uint32_t, RegisterLocation > collection
Definition: UnwindPlan.h:401
bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset, bool can_replace)
Definition: UnwindPlan.cpp:284
bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num, bool can_replace)
Definition: UnwindPlan.cpp:336
void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread, lldb::addr_t base_addr) const
Definition: UnwindPlan.cpp:230
bool SetRegisterLocationToUnspecified(uint32_t reg_num, bool can_replace)
Definition: UnwindPlan.cpp:325
void RemoveRegisterInfo(uint32_t reg_num)
Definition: UnwindPlan.cpp:271
lldb::addr_t GetOffset() const
Definition: UnwindPlan.h:347
bool operator==(const Row &rhs) const
Definition: UnwindPlan.cpp:371
bool SetRegisterLocationToUndefined(uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified)
Definition: UnwindPlan.cpp:308
bool GetRegisterInfo(uint32_t reg_num, RegisterLocation &register_location) const
Definition: UnwindPlan.cpp:256
void SlideOffset(lldb::addr_t offset)
Definition: UnwindPlan.h:351
void SetOffset(lldb::addr_t offset)
Definition: UnwindPlan.h:349
void SetUnspecifiedRegistersAreUndefined(bool unspec_is_undef)
Definition: UnwindPlan.h:387
void SetRegisterInfo(uint32_t reg_num, const RegisterLocation register_location)
Definition: UnwindPlan.cpp:278
lldb_private::LazyBool GetUnwindPlanValidAtAllInstructions() const
Definition: UnwindPlan.h:499
void SetUnwindPlanForSignalTrap(lldb_private::LazyBool is_for_signal_trap)
Definition: UnwindPlan.h:517
void InsertRow(const RowSP &row_sp, bool replace_existing=false)
Definition: UnwindPlan.cpp:387
const UnwindPlan::RowSP GetRowAtIndex(uint32_t idx) const
Definition: UnwindPlan.cpp:424
lldb::RegisterKind m_register_kind
Definition: UnwindPlan.h:551
void SetRegisterKind(lldb::RegisterKind kind)
Definition: UnwindPlan.h:452
UnwindPlan(const UnwindPlan &rhs)
Definition: UnwindPlan.h:419
UnwindPlan(lldb::RegisterKind reg_kind)
Definition: UnwindPlan.h:412
uint32_t GetInitialCFARegister() const
Definition: UnwindPlan.h:460
const RegisterInfo * GetRegisterInfo(Thread *thread, uint32_t reg_num) const
Definition: UnwindPlan.cpp:587
Address GetPersonalityFunctionPtr() const
Definition: UnwindPlan.h:541
lldb_private::LazyBool m_plan_is_for_signal_trap
Definition: UnwindPlan.h:561
const UnwindPlan::RowSP GetLastRow() const
Definition: UnwindPlan.cpp:437
void SetPlanValidAddressRange(const AddressRange &range)
Definition: UnwindPlan.cpp:448
void SetReturnAddressRegister(uint32_t regnum)
Definition: UnwindPlan.h:454
uint32_t GetReturnAddressRegister()
Definition: UnwindPlan.h:458
AddressRange m_plan_valid_address_range
Definition: UnwindPlan.h:550
std::vector< RowSP > collection
Definition: UnwindPlan.h:548
bool IsValidRowIndex(uint32_t idx) const
Definition: UnwindPlan.cpp:420
uint32_t m_return_addr_register
Definition: UnwindPlan.h:554
void SetPersonalityFunctionPtr(Address presonality_func_ptr)
Definition: UnwindPlan.h:543
void AppendRow(const RowSP &row_sp)
Definition: UnwindPlan.cpp:379
lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations
Definition: UnwindPlan.h:560
UnwindPlan::RowSP GetRowForFunctionOffset(int offset) const
Definition: UnwindPlan.cpp:402
lldb::RegisterKind GetRegisterKind() const
Definition: UnwindPlan.h:450
std::shared_ptr< Row > RowSP
Definition: UnwindPlan.h:410
void SetLSDAAddress(Address lsda_addr)
Definition: UnwindPlan.h:539
lldb_private::ConstString m_source_name
Definition: UnwindPlan.h:558
void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler)
Definition: UnwindPlan.h:493
const AddressRange & GetAddressRange() const
Definition: UnwindPlan.h:471
bool PlanValidAtAddress(Address addr)
Definition: UnwindPlan.cpp:453
void SetSourceName(const char *)
Definition: UnwindPlan.cpp:581
Address GetLSDAAddress() const
Definition: UnwindPlan.h:537
lldb_private::LazyBool GetUnwindPlanForSignalTrap() const
Definition: UnwindPlan.h:513
void Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const
Definition: UnwindPlan.cpp:510
lldb_private::ConstString GetSourceName() const
Definition: UnwindPlan.cpp:585
lldb_private::LazyBool GetSourcedFromCompiler() const
Definition: UnwindPlan.h:488
void SetUnwindPlanValidAtAllInstructions(lldb_private::LazyBool valid_at_all_insn)
Definition: UnwindPlan.h:505
lldb_private::LazyBool m_plan_is_sourced_from_compiler
Definition: UnwindPlan.h:559
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:87
A class that represents a running process on the host machine.
uint64_t addr_t
Definition: lldb-types.h:80
RegisterKind
Register numbering types.
@ eRegisterKindDWARF
the register numbers seen DWARF
Every register is described in detail including its name, alternate name (optional),...