1 //===-- UnwindPlan.h --------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef liblldb_UnwindPlan_h 11 #define liblldb_UnwindPlan_h 12 13 #include <map> 14 #include <memory> 15 #include <vector> 16 17 #include "lldb/Core/AddressRange.h" 18 #include "lldb/Utility/ConstString.h" 19 #include "lldb/Utility/Stream.h" 20 #include "lldb/lldb-private.h" 21 22 namespace lldb_private { 23 24 // The UnwindPlan object specifies how to unwind out of a function - where this 25 // function saves the caller's register values before modifying them (for non- 26 // volatile aka saved registers) and how to find this frame's Canonical Frame 27 // Address (CFA) or Aligned Frame Address (AFA). 28 29 // CFA is a DWARF's Canonical Frame Address. 30 // Most commonly, registers are saved on the stack, offset some bytes from the 31 // Canonical Frame Address, or CFA, which is the starting address of this 32 // function's stack frame (the CFA is same as the eh_frame's CFA, whatever that 33 // may be on a given architecture). The CFA address for the stack frame does 34 // not change during the lifetime of the function. 35 36 // AFA is an artificially introduced Aligned Frame Address. 37 // It is used only for stack frames with realignment (e.g. when some of the 38 // locals has an alignment requirement higher than the stack alignment right 39 // after the function call). It is used to access register values saved on the 40 // stack after the realignment (and so they are inaccessible through the CFA). 41 // AFA usually equals the stack pointer value right after the realignment. 42 43 // Internally, the UnwindPlan is structured as a vector of register locations 44 // organized by code address in the function, showing which registers have been 45 // saved at that point and where they are saved. It can be thought of as the 46 // expanded table form of the DWARF CFI encoded information. 47 48 // Other unwind information sources will be converted into UnwindPlans before 49 // being added to a FuncUnwinders object. The unwind source may be an eh_frame 50 // FDE, a DWARF debug_frame FDE, or assembly language based prologue analysis. 51 // The UnwindPlan is the canonical form of this information that the unwinder 52 // code will use when walking the stack. 53 54 class UnwindPlan { 55 public: 56 class Row { 57 public: 58 class RegisterLocation { 59 public: 60 enum RestoreType { 61 unspecified, // not specified, we may be able to assume this 62 // is the same register. gcc doesn't specify all 63 // initial values so we really don't know... 64 undefined, // reg is not available, e.g. volatile reg 65 same, // reg is unchanged 66 atCFAPlusOffset, // reg = deref(CFA + offset) 67 isCFAPlusOffset, // reg = CFA + offset 68 atAFAPlusOffset, // reg = deref(AFA + offset) 69 isAFAPlusOffset, // reg = AFA + offset 70 inOtherRegister, // reg = other reg 71 atDWARFExpression, // reg = deref(eval(dwarf_expr)) 72 isDWARFExpression // reg = eval(dwarf_expr) 73 }; 74 RegisterLocation()75 RegisterLocation() : m_type(unspecified), m_location() {} 76 77 bool operator==(const RegisterLocation &rhs) const; 78 79 bool operator!=(const RegisterLocation &rhs) const { 80 return !(*this == rhs); 81 } 82 SetUnspecified()83 void SetUnspecified() { m_type = unspecified; } 84 SetUndefined()85 void SetUndefined() { m_type = undefined; } 86 SetSame()87 void SetSame() { m_type = same; } 88 IsSame()89 bool IsSame() const { return m_type == same; } 90 IsUnspecified()91 bool IsUnspecified() const { return m_type == unspecified; } 92 IsUndefined()93 bool IsUndefined() const { return m_type == undefined; } 94 IsCFAPlusOffset()95 bool IsCFAPlusOffset() const { return m_type == isCFAPlusOffset; } 96 IsAtCFAPlusOffset()97 bool IsAtCFAPlusOffset() const { return m_type == atCFAPlusOffset; } 98 IsAFAPlusOffset()99 bool IsAFAPlusOffset() const { return m_type == isAFAPlusOffset; } 100 IsAtAFAPlusOffset()101 bool IsAtAFAPlusOffset() const { return m_type == atAFAPlusOffset; } 102 IsInOtherRegister()103 bool IsInOtherRegister() const { return m_type == inOtherRegister; } 104 IsAtDWARFExpression()105 bool IsAtDWARFExpression() const { return m_type == atDWARFExpression; } 106 IsDWARFExpression()107 bool IsDWARFExpression() const { return m_type == isDWARFExpression; } 108 SetAtCFAPlusOffset(int32_t offset)109 void SetAtCFAPlusOffset(int32_t offset) { 110 m_type = atCFAPlusOffset; 111 m_location.offset = offset; 112 } 113 SetIsCFAPlusOffset(int32_t offset)114 void SetIsCFAPlusOffset(int32_t offset) { 115 m_type = isCFAPlusOffset; 116 m_location.offset = offset; 117 } 118 SetAtAFAPlusOffset(int32_t offset)119 void SetAtAFAPlusOffset(int32_t offset) { 120 m_type = atAFAPlusOffset; 121 m_location.offset = offset; 122 } 123 SetIsAFAPlusOffset(int32_t offset)124 void SetIsAFAPlusOffset(int32_t offset) { 125 m_type = isAFAPlusOffset; 126 m_location.offset = offset; 127 } 128 SetInRegister(uint32_t reg_num)129 void SetInRegister(uint32_t reg_num) { 130 m_type = inOtherRegister; 131 m_location.reg_num = reg_num; 132 } 133 GetRegisterNumber()134 uint32_t GetRegisterNumber() const { 135 if (m_type == inOtherRegister) 136 return m_location.reg_num; 137 return LLDB_INVALID_REGNUM; 138 } 139 GetLocationType()140 RestoreType GetLocationType() const { return m_type; } 141 GetOffset()142 int32_t GetOffset() const { 143 switch(m_type) 144 { 145 case atCFAPlusOffset: 146 case isCFAPlusOffset: 147 case atAFAPlusOffset: 148 case isAFAPlusOffset: 149 return m_location.offset; 150 default: 151 return 0; 152 } 153 } 154 GetDWARFExpr(const uint8_t ** opcodes,uint16_t & len)155 void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const { 156 if (m_type == atDWARFExpression || m_type == isDWARFExpression) { 157 *opcodes = m_location.expr.opcodes; 158 len = m_location.expr.length; 159 } else { 160 *opcodes = nullptr; 161 len = 0; 162 } 163 } 164 165 void SetAtDWARFExpression(const uint8_t *opcodes, uint32_t len); 166 167 void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len); 168 GetDWARFExpressionBytes()169 const uint8_t *GetDWARFExpressionBytes() { 170 if (m_type == atDWARFExpression || m_type == isDWARFExpression) 171 return m_location.expr.opcodes; 172 return nullptr; 173 } 174 GetDWARFExpressionLength()175 int GetDWARFExpressionLength() { 176 if (m_type == atDWARFExpression || m_type == isDWARFExpression) 177 return m_location.expr.length; 178 return 0; 179 } 180 181 void Dump(Stream &s, const UnwindPlan *unwind_plan, 182 const UnwindPlan::Row *row, Thread *thread, bool verbose) const; 183 184 private: 185 RestoreType m_type; // How do we locate this register? 186 union { 187 // For m_type == atCFAPlusOffset or m_type == isCFAPlusOffset 188 int32_t offset; 189 // For m_type == inOtherRegister 190 uint32_t reg_num; // The register number 191 // For m_type == atDWARFExpression or m_type == isDWARFExpression 192 struct { 193 const uint8_t *opcodes; 194 uint16_t length; 195 } expr; 196 } m_location; 197 }; 198 199 class FAValue { 200 public: 201 enum ValueType { 202 unspecified, // not specified 203 isRegisterPlusOffset, // FA = register + offset 204 isRegisterDereferenced, // FA = [reg] 205 isDWARFExpression // FA = eval(dwarf_expr) 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 IsRegisterPlusOffset()218 bool IsRegisterPlusOffset() const { 219 return m_type == isRegisterPlusOffset; 220 } 221 SetIsRegisterPlusOffset(uint32_t reg_num,int32_t offset)222 void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset) { 223 m_type = isRegisterPlusOffset; 224 m_value.reg.reg_num = reg_num; 225 m_value.reg.offset = offset; 226 } 227 IsRegisterDereferenced()228 bool IsRegisterDereferenced() const { 229 return m_type == isRegisterDereferenced; 230 } 231 SetIsRegisterDereferenced(uint32_t reg_num)232 void SetIsRegisterDereferenced(uint32_t reg_num) { 233 m_type = isRegisterDereferenced; 234 m_value.reg.reg_num = reg_num; 235 } 236 IsDWARFExpression()237 bool IsDWARFExpression() const { return m_type == isDWARFExpression; } 238 SetIsDWARFExpression(const uint8_t * opcodes,uint32_t len)239 void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len) { 240 m_type = isDWARFExpression; 241 m_value.expr.opcodes = opcodes; 242 m_value.expr.length = len; 243 } 244 GetRegisterNumber()245 uint32_t GetRegisterNumber() const { 246 if (m_type == isRegisterDereferenced || m_type == isRegisterPlusOffset) 247 return m_value.reg.reg_num; 248 return LLDB_INVALID_REGNUM; 249 } 250 GetValueType()251 ValueType GetValueType() const { return m_type; } 252 GetOffset()253 int32_t GetOffset() const { 254 if (m_type == isRegisterPlusOffset) 255 return m_value.reg.offset; 256 return 0; 257 } 258 IncOffset(int32_t delta)259 void IncOffset(int32_t delta) { 260 if (m_type == isRegisterPlusOffset) 261 m_value.reg.offset += delta; 262 } 263 SetOffset(int32_t offset)264 void SetOffset(int32_t offset) { 265 if (m_type == isRegisterPlusOffset) 266 m_value.reg.offset = offset; 267 } 268 GetDWARFExpr(const uint8_t ** opcodes,uint16_t & len)269 void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const { 270 if (m_type == isDWARFExpression) { 271 *opcodes = m_value.expr.opcodes; 272 len = m_value.expr.length; 273 } else { 274 *opcodes = nullptr; 275 len = 0; 276 } 277 } 278 GetDWARFExpressionBytes()279 const uint8_t *GetDWARFExpressionBytes() { 280 if (m_type == isDWARFExpression) 281 return m_value.expr.opcodes; 282 return nullptr; 283 } 284 GetDWARFExpressionLength()285 int GetDWARFExpressionLength() { 286 if (m_type == isDWARFExpression) 287 return m_value.expr.length; 288 return 0; 289 } 290 291 void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread) const; 292 293 private: 294 ValueType m_type; // How do we compute CFA value? 295 union { 296 struct { 297 // For m_type == isRegisterPlusOffset or m_type == 298 // isRegisterDereferenced 299 uint32_t reg_num; // The register number 300 // For m_type == isRegisterPlusOffset 301 int32_t offset; 302 } reg; 303 // For m_type == isDWARFExpression 304 struct { 305 const uint8_t *opcodes; 306 uint16_t length; 307 } expr; 308 } m_value; 309 }; // class FAValue 310 311 public: 312 Row(); 313 314 Row(const UnwindPlan::Row &rhs) = default; 315 316 bool operator==(const Row &rhs) const; 317 318 bool GetRegisterInfo(uint32_t reg_num, 319 RegisterLocation ®ister_location) const; 320 321 void SetRegisterInfo(uint32_t reg_num, 322 const RegisterLocation register_location); 323 324 void RemoveRegisterInfo(uint32_t reg_num); 325 GetOffset()326 lldb::addr_t GetOffset() const { return m_offset; } 327 SetOffset(lldb::addr_t offset)328 void SetOffset(lldb::addr_t offset) { m_offset = offset; } 329 SlideOffset(lldb::addr_t offset)330 void SlideOffset(lldb::addr_t offset) { m_offset += offset; } 331 GetCFAValue()332 FAValue &GetCFAValue() { return m_cfa_value; } 333 GetAFAValue()334 FAValue &GetAFAValue() { return m_afa_value; } 335 336 bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset, 337 bool can_replace); 338 339 bool SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num, int32_t offset, 340 bool can_replace); 341 342 bool SetRegisterLocationToUndefined(uint32_t reg_num, bool can_replace, 343 bool can_replace_only_if_unspecified); 344 345 bool SetRegisterLocationToUnspecified(uint32_t reg_num, bool can_replace); 346 347 bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num, 348 bool can_replace); 349 350 bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace); 351 352 void Clear(); 353 354 void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread, 355 lldb::addr_t base_addr) const; 356 357 protected: 358 typedef std::map<uint32_t, RegisterLocation> collection; 359 lldb::addr_t m_offset; // Offset into the function for this row 360 361 FAValue m_cfa_value; 362 FAValue m_afa_value; 363 collection m_register_locations; 364 }; // class Row 365 366 public: 367 typedef std::shared_ptr<Row> RowSP; 368 UnwindPlan(lldb::RegisterKind reg_kind)369 UnwindPlan(lldb::RegisterKind reg_kind) 370 : m_row_list(), m_plan_valid_address_range(), m_register_kind(reg_kind), 371 m_return_addr_register(LLDB_INVALID_REGNUM), m_source_name(), 372 m_plan_is_sourced_from_compiler(eLazyBoolCalculate), 373 m_plan_is_valid_at_all_instruction_locations(eLazyBoolCalculate), 374 m_lsda_address(), m_personality_func_addr() {} 375 376 // Performs a deep copy of the plan, including all the rows (expensive). UnwindPlan(const UnwindPlan & rhs)377 UnwindPlan(const UnwindPlan &rhs) 378 : m_plan_valid_address_range(rhs.m_plan_valid_address_range), 379 m_register_kind(rhs.m_register_kind), 380 m_return_addr_register(rhs.m_return_addr_register), 381 m_source_name(rhs.m_source_name), 382 m_plan_is_sourced_from_compiler(rhs.m_plan_is_sourced_from_compiler), 383 m_plan_is_valid_at_all_instruction_locations( 384 rhs.m_plan_is_valid_at_all_instruction_locations), 385 m_lsda_address(rhs.m_lsda_address), 386 m_personality_func_addr(rhs.m_personality_func_addr) { 387 m_row_list.reserve(rhs.m_row_list.size()); 388 for (const RowSP &row_sp : rhs.m_row_list) 389 m_row_list.emplace_back(new Row(*row_sp)); 390 } 391 392 ~UnwindPlan() = default; 393 394 void Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const; 395 396 void AppendRow(const RowSP &row_sp); 397 398 void InsertRow(const RowSP &row_sp, bool replace_existing = false); 399 400 // Returns a pointer to the best row for the given offset into the function's 401 // instructions. If offset is -1 it indicates that the function start is 402 // unknown - the final row in the UnwindPlan is returned. In practice, the 403 // UnwindPlan for a function with no known start address will be the 404 // architectural default UnwindPlan which will only have one row. 405 UnwindPlan::RowSP GetRowForFunctionOffset(int offset) const; 406 GetRegisterKind()407 lldb::RegisterKind GetRegisterKind() const { return m_register_kind; } 408 SetRegisterKind(lldb::RegisterKind kind)409 void SetRegisterKind(lldb::RegisterKind kind) { m_register_kind = kind; } 410 SetReturnAddressRegister(uint32_t regnum)411 void SetReturnAddressRegister(uint32_t regnum) { 412 m_return_addr_register = regnum; 413 } 414 GetReturnAddressRegister(void)415 uint32_t GetReturnAddressRegister(void) { return m_return_addr_register; } 416 GetInitialCFARegister()417 uint32_t GetInitialCFARegister() const { 418 if (m_row_list.empty()) 419 return LLDB_INVALID_REGNUM; 420 return m_row_list.front()->GetCFAValue().GetRegisterNumber(); 421 } 422 423 // This UnwindPlan may not be valid at every address of the function span. 424 // For instance, a FastUnwindPlan will not be valid at the prologue setup 425 // instructions - only in the body of the function. 426 void SetPlanValidAddressRange(const AddressRange &range); 427 GetAddressRange()428 const AddressRange &GetAddressRange() const { 429 return m_plan_valid_address_range; 430 } 431 432 bool PlanValidAtAddress(Address addr); 433 434 bool IsValidRowIndex(uint32_t idx) const; 435 436 const UnwindPlan::RowSP GetRowAtIndex(uint32_t idx) const; 437 438 const UnwindPlan::RowSP GetLastRow() const; 439 440 lldb_private::ConstString GetSourceName() const; 441 442 void SetSourceName(const char *); 443 444 // Was this UnwindPlan emitted by a compiler? GetSourcedFromCompiler()445 lldb_private::LazyBool GetSourcedFromCompiler() const { 446 return m_plan_is_sourced_from_compiler; 447 } 448 449 // Was this UnwindPlan emitted by a compiler? SetSourcedFromCompiler(lldb_private::LazyBool from_compiler)450 void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler) { 451 m_plan_is_sourced_from_compiler = from_compiler; 452 } 453 454 // Is this UnwindPlan valid at all instructions? If not, then it is assumed 455 // valid at call sites, e.g. for exception handling. GetUnwindPlanValidAtAllInstructions()456 lldb_private::LazyBool GetUnwindPlanValidAtAllInstructions() const { 457 return m_plan_is_valid_at_all_instruction_locations; 458 } 459 460 // Is this UnwindPlan valid at all instructions? If not, then it is assumed 461 // valid at call sites, e.g. for exception handling. SetUnwindPlanValidAtAllInstructions(lldb_private::LazyBool valid_at_all_insn)462 void SetUnwindPlanValidAtAllInstructions( 463 lldb_private::LazyBool valid_at_all_insn) { 464 m_plan_is_valid_at_all_instruction_locations = valid_at_all_insn; 465 } 466 467 int GetRowCount() const; 468 Clear()469 void Clear() { 470 m_row_list.clear(); 471 m_plan_valid_address_range.Clear(); 472 m_register_kind = lldb::eRegisterKindDWARF; 473 m_source_name.Clear(); 474 m_plan_is_sourced_from_compiler = eLazyBoolCalculate; 475 m_plan_is_valid_at_all_instruction_locations = eLazyBoolCalculate; 476 m_lsda_address.Clear(); 477 m_personality_func_addr.Clear(); 478 } 479 480 const RegisterInfo *GetRegisterInfo(Thread *thread, uint32_t reg_num) const; 481 GetLSDAAddress()482 Address GetLSDAAddress() const { return m_lsda_address; } 483 SetLSDAAddress(Address lsda_addr)484 void SetLSDAAddress(Address lsda_addr) { m_lsda_address = lsda_addr; } 485 GetPersonalityFunctionPtr()486 Address GetPersonalityFunctionPtr() const { return m_personality_func_addr; } 487 SetPersonalityFunctionPtr(Address presonality_func_ptr)488 void SetPersonalityFunctionPtr(Address presonality_func_ptr) { 489 m_personality_func_addr = presonality_func_ptr; 490 } 491 492 private: 493 typedef std::vector<RowSP> collection; 494 collection m_row_list; 495 AddressRange m_plan_valid_address_range; 496 lldb::RegisterKind m_register_kind; // The RegisterKind these register numbers 497 // are in terms of - will need to be 498 // translated to lldb native reg nums at unwind time 499 uint32_t m_return_addr_register; // The register that has the return address 500 // for the caller frame 501 // e.g. the lr on arm 502 lldb_private::ConstString 503 m_source_name; // for logging, where this UnwindPlan originated from 504 lldb_private::LazyBool m_plan_is_sourced_from_compiler; 505 lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations; 506 507 Address m_lsda_address; // Where the language specific data area exists in the 508 // module - used 509 // in exception handling. 510 Address m_personality_func_addr; // The address of a pointer to the 511 // personality function - used in 512 // exception handling. 513 }; // class UnwindPlan 514 515 } // namespace lldb_private 516 517 #endif // liblldb_UnwindPlan_h 518