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