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 16 #include "lldb/Core/AddressRange.h" 17 #include "lldb/Utility/ConstString.h" 18 #include "lldb/Utility/Stream.h" 19 #include "lldb/lldb-private.h" 20 21 namespace 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 53 class UnwindPlan { 54 public: 55 class Row { 56 public: 57 class RegisterLocation { 58 public: 59 enum RestoreType { 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 RegisterLocation()74 RegisterLocation() : m_type(unspecified), m_location() {} 75 76 bool operator==(const RegisterLocation &rhs) const; 77 78 bool operator!=(const RegisterLocation &rhs) const { 79 return !(*this == rhs); 80 } 81 SetUnspecified()82 void SetUnspecified() { m_type = unspecified; } 83 SetUndefined()84 void SetUndefined() { m_type = undefined; } 85 SetSame()86 void SetSame() { m_type = same; } 87 IsSame()88 bool IsSame() const { return m_type == same; } 89 IsUnspecified()90 bool IsUnspecified() const { return m_type == unspecified; } 91 IsUndefined()92 bool IsUndefined() const { return m_type == undefined; } 93 IsCFAPlusOffset()94 bool IsCFAPlusOffset() const { return m_type == isCFAPlusOffset; } 95 IsAtCFAPlusOffset()96 bool IsAtCFAPlusOffset() const { return m_type == atCFAPlusOffset; } 97 IsAFAPlusOffset()98 bool IsAFAPlusOffset() const { return m_type == isAFAPlusOffset; } 99 IsAtAFAPlusOffset()100 bool IsAtAFAPlusOffset() const { return m_type == atAFAPlusOffset; } 101 IsInOtherRegister()102 bool IsInOtherRegister() const { return m_type == inOtherRegister; } 103 IsAtDWARFExpression()104 bool IsAtDWARFExpression() const { return m_type == atDWARFExpression; } 105 IsDWARFExpression()106 bool IsDWARFExpression() const { return m_type == isDWARFExpression; } 107 SetAtCFAPlusOffset(int32_t offset)108 void SetAtCFAPlusOffset(int32_t offset) { 109 m_type = atCFAPlusOffset; 110 m_location.offset = offset; 111 } 112 SetIsCFAPlusOffset(int32_t offset)113 void SetIsCFAPlusOffset(int32_t offset) { 114 m_type = isCFAPlusOffset; 115 m_location.offset = offset; 116 } 117 SetAtAFAPlusOffset(int32_t offset)118 void SetAtAFAPlusOffset(int32_t offset) { 119 m_type = atAFAPlusOffset; 120 m_location.offset = offset; 121 } 122 SetIsAFAPlusOffset(int32_t offset)123 void SetIsAFAPlusOffset(int32_t offset) { 124 m_type = isAFAPlusOffset; 125 m_location.offset = offset; 126 } 127 SetInRegister(uint32_t reg_num)128 void SetInRegister(uint32_t reg_num) { 129 m_type = inOtherRegister; 130 m_location.reg_num = reg_num; 131 } 132 GetRegisterNumber()133 uint32_t GetRegisterNumber() const { 134 if (m_type == inOtherRegister) 135 return m_location.reg_num; 136 return LLDB_INVALID_REGNUM; 137 } 138 GetLocationType()139 RestoreType GetLocationType() const { return m_type; } 140 GetOffset()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 GetDWARFExpr(const uint8_t ** opcodes,uint16_t & len)154 void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const { 155 if (m_type == atDWARFExpression || m_type == isDWARFExpression) { 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 GetDWARFExpressionBytes()168 const uint8_t *GetDWARFExpressionBytes() { 169 if (m_type == atDWARFExpression || m_type == isDWARFExpression) 170 return m_location.expr.opcodes; 171 return nullptr; 172 } 173 GetDWARFExpressionLength()174 int GetDWARFExpressionLength() { 175 if (m_type == atDWARFExpression || m_type == isDWARFExpression) 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; // 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; 194 } expr; 195 } m_location; 196 }; 197 198 class FAValue { 199 public: 200 enum ValueType { 201 unspecified, // not specified 202 isRegisterPlusOffset, // FA = register + offset 203 isRegisterDereferenced, // FA = [reg] 204 isDWARFExpression, // FA = eval(dwarf_expr) 205 isRaSearch, // FA = SP + offset + ??? 206 }; 207 FAValue()208 FAValue() : m_type(unspecified), m_value() {} 209 210 bool operator==(const FAValue &rhs) const; 211 212 bool operator!=(const FAValue &rhs) const { return !(*this == rhs); } 213 SetUnspecified()214 void SetUnspecified() { m_type = unspecified; } 215 IsUnspecified()216 bool IsUnspecified() const { return m_type == unspecified; } 217 SetRaSearch(int32_t offset)218 void SetRaSearch(int32_t offset) { 219 m_type = isRaSearch; 220 m_value.ra_search_offset = offset; 221 } 222 IsRegisterPlusOffset()223 bool IsRegisterPlusOffset() const { 224 return m_type == isRegisterPlusOffset; 225 } 226 SetIsRegisterPlusOffset(uint32_t reg_num,int32_t offset)227 void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset) { 228 m_type = isRegisterPlusOffset; 229 m_value.reg.reg_num = reg_num; 230 m_value.reg.offset = offset; 231 } 232 IsRegisterDereferenced()233 bool IsRegisterDereferenced() const { 234 return m_type == isRegisterDereferenced; 235 } 236 SetIsRegisterDereferenced(uint32_t reg_num)237 void SetIsRegisterDereferenced(uint32_t reg_num) { 238 m_type = isRegisterDereferenced; 239 m_value.reg.reg_num = reg_num; 240 } 241 IsDWARFExpression()242 bool IsDWARFExpression() const { return m_type == isDWARFExpression; } 243 SetIsDWARFExpression(const uint8_t * opcodes,uint32_t len)244 void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len) { 245 m_type = isDWARFExpression; 246 m_value.expr.opcodes = opcodes; 247 m_value.expr.length = len; 248 } 249 GetRegisterNumber()250 uint32_t GetRegisterNumber() const { 251 if (m_type == isRegisterDereferenced || m_type == isRegisterPlusOffset) 252 return m_value.reg.reg_num; 253 return LLDB_INVALID_REGNUM; 254 } 255 GetValueType()256 ValueType GetValueType() const { return m_type; } 257 GetOffset()258 int32_t GetOffset() const { 259 switch (m_type) { 260 case isRegisterPlusOffset: 261 return m_value.reg.offset; 262 case isRaSearch: 263 return m_value.ra_search_offset; 264 default: 265 return 0; 266 } 267 } 268 IncOffset(int32_t delta)269 void IncOffset(int32_t delta) { 270 if (m_type == isRegisterPlusOffset) 271 m_value.reg.offset += delta; 272 } 273 SetOffset(int32_t offset)274 void SetOffset(int32_t offset) { 275 if (m_type == isRegisterPlusOffset) 276 m_value.reg.offset = offset; 277 } 278 GetDWARFExpr(const uint8_t ** opcodes,uint16_t & len)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 GetDWARFExpressionBytes()289 const uint8_t *GetDWARFExpressionBytes() { 290 if (m_type == isDWARFExpression) 291 return m_value.expr.opcodes; 292 return nullptr; 293 } 294 GetDWARFExpressionLength()295 int GetDWARFExpressionLength() { 296 if (m_type == isDWARFExpression) 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; // 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; 312 } reg; 313 // For m_type == isDWARFExpression 314 struct { 315 const uint8_t *opcodes; 316 uint16_t length; 317 } expr; 318 // For m_type == isRaSearch 319 int32_t ra_search_offset; 320 } m_value; 321 }; // class FAValue 322 323 Row(); 324 325 Row(const UnwindPlan::Row &rhs) = default; 326 327 bool operator==(const Row &rhs) const; 328 329 bool GetRegisterInfo(uint32_t reg_num, 330 RegisterLocation ®ister_location) const; 331 332 void SetRegisterInfo(uint32_t reg_num, 333 const RegisterLocation register_location); 334 335 void RemoveRegisterInfo(uint32_t reg_num); 336 GetOffset()337 lldb::addr_t GetOffset() const { return m_offset; } 338 SetOffset(lldb::addr_t offset)339 void SetOffset(lldb::addr_t offset) { m_offset = offset; } 340 SlideOffset(lldb::addr_t offset)341 void SlideOffset(lldb::addr_t offset) { m_offset += offset; } 342 GetCFAValue()343 FAValue &GetCFAValue() { return m_cfa_value; } 344 GetAFAValue()345 FAValue &GetAFAValue() { return m_afa_value; } 346 347 bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset, 348 bool can_replace); 349 350 bool SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num, int32_t offset, 351 bool can_replace); 352 353 bool SetRegisterLocationToUndefined(uint32_t reg_num, bool can_replace, 354 bool can_replace_only_if_unspecified); 355 356 bool SetRegisterLocationToUnspecified(uint32_t reg_num, bool can_replace); 357 358 bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num, 359 bool can_replace); 360 361 bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace); 362 363 void Clear(); 364 365 void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread, 366 lldb::addr_t base_addr) const; 367 368 protected: 369 typedef std::map<uint32_t, RegisterLocation> collection; 370 lldb::addr_t m_offset; // Offset into the function for this row 371 372 FAValue m_cfa_value; 373 FAValue m_afa_value; 374 collection m_register_locations; 375 }; // class Row 376 377 typedef std::shared_ptr<Row> RowSP; 378 UnwindPlan(lldb::RegisterKind reg_kind)379 UnwindPlan(lldb::RegisterKind reg_kind) 380 : m_row_list(), m_plan_valid_address_range(), m_register_kind(reg_kind), 381 m_return_addr_register(LLDB_INVALID_REGNUM), m_source_name(), 382 m_plan_is_sourced_from_compiler(eLazyBoolCalculate), 383 m_plan_is_valid_at_all_instruction_locations(eLazyBoolCalculate), 384 m_plan_is_for_signal_trap(eLazyBoolCalculate), 385 m_lsda_address(), m_personality_func_addr() {} 386 387 // Performs a deep copy of the plan, including all the rows (expensive). UnwindPlan(const UnwindPlan & rhs)388 UnwindPlan(const UnwindPlan &rhs) 389 : m_plan_valid_address_range(rhs.m_plan_valid_address_range), 390 m_register_kind(rhs.m_register_kind), 391 m_return_addr_register(rhs.m_return_addr_register), 392 m_source_name(rhs.m_source_name), 393 m_plan_is_sourced_from_compiler(rhs.m_plan_is_sourced_from_compiler), 394 m_plan_is_valid_at_all_instruction_locations( 395 rhs.m_plan_is_valid_at_all_instruction_locations), 396 m_plan_is_for_signal_trap(rhs.m_plan_is_for_signal_trap), 397 m_lsda_address(rhs.m_lsda_address), 398 m_personality_func_addr(rhs.m_personality_func_addr) { 399 m_row_list.reserve(rhs.m_row_list.size()); 400 for (const RowSP &row_sp : rhs.m_row_list) 401 m_row_list.emplace_back(new Row(*row_sp)); 402 } 403 404 ~UnwindPlan() = default; 405 406 void Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const; 407 408 void AppendRow(const RowSP &row_sp); 409 410 void InsertRow(const RowSP &row_sp, bool replace_existing = false); 411 412 // Returns a pointer to the best row for the given offset into the function's 413 // instructions. If offset is -1 it indicates that the function start is 414 // unknown - the final row in the UnwindPlan is returned. In practice, the 415 // UnwindPlan for a function with no known start address will be the 416 // architectural default UnwindPlan which will only have one row. 417 UnwindPlan::RowSP GetRowForFunctionOffset(int offset) const; 418 GetRegisterKind()419 lldb::RegisterKind GetRegisterKind() const { return m_register_kind; } 420 SetRegisterKind(lldb::RegisterKind kind)421 void SetRegisterKind(lldb::RegisterKind kind) { m_register_kind = kind; } 422 SetReturnAddressRegister(uint32_t regnum)423 void SetReturnAddressRegister(uint32_t regnum) { 424 m_return_addr_register = regnum; 425 } 426 GetReturnAddressRegister(void)427 uint32_t GetReturnAddressRegister(void) { return m_return_addr_register; } 428 GetInitialCFARegister()429 uint32_t GetInitialCFARegister() const { 430 if (m_row_list.empty()) 431 return LLDB_INVALID_REGNUM; 432 return m_row_list.front()->GetCFAValue().GetRegisterNumber(); 433 } 434 435 // This UnwindPlan may not be valid at every address of the function span. 436 // For instance, a FastUnwindPlan will not be valid at the prologue setup 437 // instructions - only in the body of the function. 438 void SetPlanValidAddressRange(const AddressRange &range); 439 GetAddressRange()440 const AddressRange &GetAddressRange() const { 441 return m_plan_valid_address_range; 442 } 443 444 bool PlanValidAtAddress(Address addr); 445 446 bool IsValidRowIndex(uint32_t idx) const; 447 448 const UnwindPlan::RowSP GetRowAtIndex(uint32_t idx) const; 449 450 const UnwindPlan::RowSP GetLastRow() const; 451 452 lldb_private::ConstString GetSourceName() const; 453 454 void SetSourceName(const char *); 455 456 // Was this UnwindPlan emitted by a compiler? GetSourcedFromCompiler()457 lldb_private::LazyBool GetSourcedFromCompiler() const { 458 return m_plan_is_sourced_from_compiler; 459 } 460 461 // Was this UnwindPlan emitted by a compiler? SetSourcedFromCompiler(lldb_private::LazyBool from_compiler)462 void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler) { 463 m_plan_is_sourced_from_compiler = from_compiler; 464 } 465 466 // Is this UnwindPlan valid at all instructions? If not, then it is assumed 467 // valid at call sites, e.g. for exception handling. GetUnwindPlanValidAtAllInstructions()468 lldb_private::LazyBool GetUnwindPlanValidAtAllInstructions() const { 469 return m_plan_is_valid_at_all_instruction_locations; 470 } 471 472 // Is this UnwindPlan valid at all instructions? If not, then it is assumed 473 // valid at call sites, e.g. for exception handling. SetUnwindPlanValidAtAllInstructions(lldb_private::LazyBool valid_at_all_insn)474 void SetUnwindPlanValidAtAllInstructions( 475 lldb_private::LazyBool valid_at_all_insn) { 476 m_plan_is_valid_at_all_instruction_locations = valid_at_all_insn; 477 } 478 479 // Is this UnwindPlan for a signal trap frame? If so, then its saved pc 480 // may have been set manually by the signal dispatch code and therefore 481 // not follow a call to the child frame. GetUnwindPlanForSignalTrap()482 lldb_private::LazyBool GetUnwindPlanForSignalTrap() const { 483 return m_plan_is_for_signal_trap; 484 } 485 SetUnwindPlanForSignalTrap(lldb_private::LazyBool is_for_signal_trap)486 void SetUnwindPlanForSignalTrap(lldb_private::LazyBool is_for_signal_trap) { 487 m_plan_is_for_signal_trap = is_for_signal_trap; 488 } 489 490 int GetRowCount() const; 491 Clear()492 void Clear() { 493 m_row_list.clear(); 494 m_plan_valid_address_range.Clear(); 495 m_register_kind = lldb::eRegisterKindDWARF; 496 m_source_name.Clear(); 497 m_plan_is_sourced_from_compiler = eLazyBoolCalculate; 498 m_plan_is_valid_at_all_instruction_locations = eLazyBoolCalculate; 499 m_plan_is_for_signal_trap = eLazyBoolCalculate; 500 m_lsda_address.Clear(); 501 m_personality_func_addr.Clear(); 502 } 503 504 const RegisterInfo *GetRegisterInfo(Thread *thread, uint32_t reg_num) const; 505 GetLSDAAddress()506 Address GetLSDAAddress() const { return m_lsda_address; } 507 SetLSDAAddress(Address lsda_addr)508 void SetLSDAAddress(Address lsda_addr) { m_lsda_address = lsda_addr; } 509 GetPersonalityFunctionPtr()510 Address GetPersonalityFunctionPtr() const { return m_personality_func_addr; } 511 SetPersonalityFunctionPtr(Address presonality_func_ptr)512 void SetPersonalityFunctionPtr(Address presonality_func_ptr) { 513 m_personality_func_addr = presonality_func_ptr; 514 } 515 516 private: 517 typedef std::vector<RowSP> collection; 518 collection m_row_list; 519 AddressRange m_plan_valid_address_range; 520 lldb::RegisterKind m_register_kind; // The RegisterKind these register numbers 521 // are in terms of - will need to be 522 // translated to lldb native reg nums at unwind time 523 uint32_t m_return_addr_register; // The register that has the return address 524 // for the caller frame 525 // e.g. the lr on arm 526 lldb_private::ConstString 527 m_source_name; // for logging, where this UnwindPlan originated from 528 lldb_private::LazyBool m_plan_is_sourced_from_compiler; 529 lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations; 530 lldb_private::LazyBool m_plan_is_for_signal_trap; 531 532 Address m_lsda_address; // Where the language specific data area exists in the 533 // module - used 534 // in exception handling. 535 Address m_personality_func_addr; // The address of a pointer to the 536 // personality function - used in 537 // exception handling. 538 }; // class UnwindPlan 539 540 } // namespace lldb_private 541 542 #endif // LLDB_SYMBOL_UNWINDPLAN_H 543