1254721Semaste//===-- UnwindPlan.cpp ----------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/Symbol/UnwindPlan.h" 11254721Semaste 12254721Semaste#include "lldb/Core/ConstString.h" 13263367Semaste#include "lldb/Core/Log.h" 14254721Semaste#include "lldb/Target/Process.h" 15254721Semaste#include "lldb/Target/RegisterContext.h" 16254721Semaste#include "lldb/Target/Thread.h" 17254721Semaste 18254721Semasteusing namespace lldb; 19254721Semasteusing namespace lldb_private; 20254721Semaste 21254721Semastebool 22254721SemasteUnwindPlan::Row::RegisterLocation::operator == (const UnwindPlan::Row::RegisterLocation& rhs) const 23254721Semaste{ 24254721Semaste if (m_type == rhs.m_type) 25254721Semaste { 26254721Semaste switch (m_type) 27254721Semaste { 28254721Semaste case unspecified: 29254721Semaste case undefined: 30254721Semaste case same: 31254721Semaste return true; 32254721Semaste 33254721Semaste case atCFAPlusOffset: 34254721Semaste case isCFAPlusOffset: 35254721Semaste return m_location.offset == rhs.m_location.offset; 36254721Semaste 37254721Semaste case inOtherRegister: 38254721Semaste return m_location.reg_num == rhs.m_location.reg_num; 39254721Semaste 40254721Semaste case atDWARFExpression: 41254721Semaste case isDWARFExpression: 42254721Semaste if (m_location.expr.length == rhs.m_location.expr.length) 43254721Semaste return !memcmp (m_location.expr.opcodes, rhs.m_location.expr.opcodes, m_location.expr.length); 44254721Semaste break; 45254721Semaste } 46254721Semaste } 47254721Semaste return false; 48254721Semaste} 49254721Semaste 50254721Semaste// This function doesn't copy the dwarf expression bytes; they must remain in allocated 51254721Semaste// memory for the lifespan of this UnwindPlan object. 52254721Semastevoid 53254721SemasteUnwindPlan::Row::RegisterLocation::SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len) 54254721Semaste{ 55254721Semaste m_type = atDWARFExpression; 56254721Semaste m_location.expr.opcodes = opcodes; 57254721Semaste m_location.expr.length = len; 58254721Semaste} 59254721Semaste 60254721Semaste// This function doesn't copy the dwarf expression bytes; they must remain in allocated 61254721Semaste// memory for the lifespan of this UnwindPlan object. 62254721Semastevoid 63254721SemasteUnwindPlan::Row::RegisterLocation::SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len) 64254721Semaste{ 65254721Semaste m_type = isDWARFExpression; 66254721Semaste m_location.expr.opcodes = opcodes; 67254721Semaste m_location.expr.length = len; 68254721Semaste} 69254721Semaste 70254721Semastevoid 71254721SemasteUnwindPlan::Row::RegisterLocation::Dump (Stream &s, const UnwindPlan* unwind_plan, const UnwindPlan::Row* row, Thread* thread, bool verbose) const 72254721Semaste{ 73254721Semaste switch (m_type) 74254721Semaste { 75254721Semaste case unspecified: 76254721Semaste if (verbose) 77254721Semaste s.PutCString ("=<unspec>"); 78254721Semaste else 79254721Semaste s.PutCString ("=!"); 80254721Semaste break; 81254721Semaste case undefined: 82254721Semaste if (verbose) 83254721Semaste s.PutCString ("=<undef>"); 84254721Semaste else 85254721Semaste s.PutCString ("=?"); 86254721Semaste break; 87254721Semaste case same: 88254721Semaste s.PutCString ("= <same>"); 89254721Semaste break; 90254721Semaste 91254721Semaste case atCFAPlusOffset: 92254721Semaste case isCFAPlusOffset: 93254721Semaste { 94254721Semaste s.PutChar('='); 95254721Semaste if (m_type == atCFAPlusOffset) 96254721Semaste s.PutChar('['); 97254721Semaste if (verbose) 98254721Semaste s.Printf ("CFA%+d", m_location.offset); 99254721Semaste 100254721Semaste if (unwind_plan && row) 101254721Semaste { 102254721Semaste const uint32_t cfa_reg = row->GetCFARegister(); 103254721Semaste const RegisterInfo *cfa_reg_info = unwind_plan->GetRegisterInfo (thread, cfa_reg); 104254721Semaste const int32_t offset = row->GetCFAOffset() + m_location.offset; 105254721Semaste if (verbose) 106254721Semaste { 107254721Semaste if (cfa_reg_info) 108254721Semaste s.Printf (" (%s%+d)", cfa_reg_info->name, offset); 109254721Semaste else 110254721Semaste s.Printf (" (reg(%u)%+d)", cfa_reg, offset); 111254721Semaste } 112254721Semaste else 113254721Semaste { 114254721Semaste if (cfa_reg_info) 115254721Semaste s.Printf ("%s", cfa_reg_info->name); 116254721Semaste else 117254721Semaste s.Printf ("reg(%u)", cfa_reg); 118254721Semaste if (offset != 0) 119254721Semaste s.Printf ("%+d", offset); 120254721Semaste } 121254721Semaste } 122254721Semaste if (m_type == atCFAPlusOffset) 123254721Semaste s.PutChar(']'); 124254721Semaste } 125254721Semaste break; 126254721Semaste 127254721Semaste case inOtherRegister: 128254721Semaste { 129254721Semaste const RegisterInfo *other_reg_info = NULL; 130254721Semaste if (unwind_plan) 131254721Semaste other_reg_info = unwind_plan->GetRegisterInfo (thread, m_location.reg_num); 132254721Semaste if (other_reg_info) 133254721Semaste s.Printf ("=%s", other_reg_info->name); 134254721Semaste else 135254721Semaste s.Printf ("=reg(%u)", m_location.reg_num); 136254721Semaste } 137254721Semaste break; 138254721Semaste 139254721Semaste case atDWARFExpression: 140254721Semaste case isDWARFExpression: 141254721Semaste { 142254721Semaste s.PutChar('='); 143254721Semaste if (m_type == atDWARFExpression) 144254721Semaste s.PutCString("[dwarf-expr]"); 145254721Semaste else 146254721Semaste s.PutCString("dwarf-expr"); 147254721Semaste } 148254721Semaste break; 149254721Semaste 150254721Semaste } 151254721Semaste} 152254721Semaste 153254721Semastevoid 154254721SemasteUnwindPlan::Row::Clear () 155254721Semaste{ 156254721Semaste m_offset = 0; 157254721Semaste m_cfa_reg_num = LLDB_INVALID_REGNUM; 158254721Semaste m_cfa_offset = 0; 159254721Semaste m_register_locations.clear(); 160254721Semaste} 161254721Semaste 162254721Semastevoid 163254721SemasteUnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, addr_t base_addr) const 164254721Semaste{ 165254721Semaste const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo (thread, GetCFARegister()); 166254721Semaste 167254721Semaste if (base_addr != LLDB_INVALID_ADDRESS) 168254721Semaste s.Printf ("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset()); 169254721Semaste else 170254721Semaste s.Printf ("0x%8.8" PRIx64 ": CFA=", GetOffset()); 171254721Semaste 172254721Semaste if (reg_info) 173254721Semaste s.Printf ("%s", reg_info->name); 174254721Semaste else 175254721Semaste s.Printf ("reg(%u)", GetCFARegister()); 176254721Semaste s.Printf ("%+3d => ", GetCFAOffset ()); 177254721Semaste for (collection::const_iterator idx = m_register_locations.begin (); idx != m_register_locations.end (); ++idx) 178254721Semaste { 179254721Semaste reg_info = unwind_plan->GetRegisterInfo (thread, idx->first); 180254721Semaste if (reg_info) 181254721Semaste s.Printf ("%s", reg_info->name); 182254721Semaste else 183254721Semaste s.Printf ("reg(%u)", idx->first); 184254721Semaste const bool verbose = false; 185254721Semaste idx->second.Dump(s, unwind_plan, this, thread, verbose); 186254721Semaste s.PutChar (' '); 187254721Semaste } 188254721Semaste s.EOL(); 189254721Semaste} 190254721Semaste 191254721SemasteUnwindPlan::Row::Row() : 192254721Semaste m_offset(0), 193254721Semaste m_cfa_reg_num(LLDB_INVALID_REGNUM), 194254721Semaste m_cfa_offset(0), 195254721Semaste m_register_locations() 196254721Semaste{ 197254721Semaste} 198254721Semaste 199254721Semastebool 200254721SemasteUnwindPlan::Row::GetRegisterInfo (uint32_t reg_num, UnwindPlan::Row::RegisterLocation& register_location) const 201254721Semaste{ 202254721Semaste collection::const_iterator pos = m_register_locations.find(reg_num); 203254721Semaste if (pos != m_register_locations.end()) 204254721Semaste { 205254721Semaste register_location = pos->second; 206254721Semaste return true; 207254721Semaste } 208254721Semaste return false; 209254721Semaste} 210254721Semaste 211254721Semastevoid 212254721SemasteUnwindPlan::Row::SetRegisterInfo (uint32_t reg_num, const UnwindPlan::Row::RegisterLocation register_location) 213254721Semaste{ 214254721Semaste m_register_locations[reg_num] = register_location; 215254721Semaste} 216254721Semaste 217254721Semastebool 218254721SemasteUnwindPlan::Row::SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num, int32_t offset, bool can_replace) 219254721Semaste{ 220254721Semaste if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end()) 221254721Semaste return false; 222254721Semaste RegisterLocation reg_loc; 223254721Semaste reg_loc.SetAtCFAPlusOffset(offset); 224254721Semaste m_register_locations[reg_num] = reg_loc; 225254721Semaste return true; 226254721Semaste} 227254721Semaste 228254721Semastebool 229254721SemasteUnwindPlan::Row::SetRegisterLocationToIsCFAPlusOffset (uint32_t reg_num, int32_t offset, bool can_replace) 230254721Semaste{ 231254721Semaste if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end()) 232254721Semaste return false; 233254721Semaste RegisterLocation reg_loc; 234254721Semaste reg_loc.SetIsCFAPlusOffset(offset); 235254721Semaste m_register_locations[reg_num] = reg_loc; 236254721Semaste return true; 237254721Semaste} 238254721Semaste 239254721Semastebool 240254721SemasteUnwindPlan::Row::SetRegisterLocationToUndefined (uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified) 241254721Semaste{ 242254721Semaste collection::iterator pos = m_register_locations.find(reg_num); 243254721Semaste collection::iterator end = m_register_locations.end(); 244254721Semaste 245254721Semaste if (pos != end) 246254721Semaste { 247254721Semaste if (!can_replace) 248254721Semaste return false; 249254721Semaste if (can_replace_only_if_unspecified && !pos->second.IsUnspecified()) 250254721Semaste return false; 251254721Semaste } 252254721Semaste RegisterLocation reg_loc; 253254721Semaste reg_loc.SetUndefined(); 254254721Semaste m_register_locations[reg_num] = reg_loc; 255254721Semaste return true; 256254721Semaste} 257254721Semaste 258254721Semastebool 259254721SemasteUnwindPlan::Row::SetRegisterLocationToUnspecified (uint32_t reg_num, bool can_replace) 260254721Semaste{ 261254721Semaste if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end()) 262254721Semaste return false; 263254721Semaste RegisterLocation reg_loc; 264254721Semaste reg_loc.SetUnspecified(); 265254721Semaste m_register_locations[reg_num] = reg_loc; 266254721Semaste return true; 267254721Semaste} 268254721Semaste 269254721Semastebool 270254721SemasteUnwindPlan::Row::SetRegisterLocationToRegister (uint32_t reg_num, 271254721Semaste uint32_t other_reg_num, 272254721Semaste bool can_replace) 273254721Semaste{ 274254721Semaste if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end()) 275254721Semaste return false; 276254721Semaste RegisterLocation reg_loc; 277254721Semaste reg_loc.SetInRegister(other_reg_num); 278254721Semaste m_register_locations[reg_num] = reg_loc; 279254721Semaste return true; 280254721Semaste} 281254721Semaste 282254721Semastebool 283254721SemasteUnwindPlan::Row::SetRegisterLocationToSame (uint32_t reg_num, bool must_replace) 284254721Semaste{ 285254721Semaste if (must_replace && m_register_locations.find(reg_num) == m_register_locations.end()) 286254721Semaste return false; 287254721Semaste RegisterLocation reg_loc; 288254721Semaste reg_loc.SetSame(); 289254721Semaste m_register_locations[reg_num] = reg_loc; 290254721Semaste return true; 291254721Semaste} 292254721Semaste 293254721Semastevoid 294254721SemasteUnwindPlan::Row::SetCFARegister (uint32_t reg_num) 295254721Semaste{ 296254721Semaste m_cfa_reg_num = reg_num; 297254721Semaste} 298254721Semaste 299254721Semastebool 300254721SemasteUnwindPlan::Row::operator == (const UnwindPlan::Row& rhs) const 301254721Semaste{ 302254721Semaste if (m_offset != rhs.m_offset || m_cfa_reg_num != rhs.m_cfa_reg_num || m_cfa_offset != rhs.m_cfa_offset) 303254721Semaste return false; 304254721Semaste return m_register_locations == rhs.m_register_locations; 305254721Semaste} 306254721Semaste 307254721Semastevoid 308254721SemasteUnwindPlan::AppendRow (const UnwindPlan::RowSP &row_sp) 309254721Semaste{ 310254721Semaste if (m_row_list.empty() || m_row_list.back()->GetOffset() != row_sp->GetOffset()) 311254721Semaste m_row_list.push_back(row_sp); 312254721Semaste else 313254721Semaste m_row_list.back() = row_sp; 314254721Semaste} 315254721Semaste 316254721SemasteUnwindPlan::RowSP 317254721SemasteUnwindPlan::GetRowForFunctionOffset (int offset) const 318254721Semaste{ 319254721Semaste RowSP row; 320254721Semaste if (!m_row_list.empty()) 321254721Semaste { 322254721Semaste if (offset == -1) 323254721Semaste row = m_row_list.back(); 324254721Semaste else 325254721Semaste { 326254721Semaste collection::const_iterator pos, end = m_row_list.end(); 327254721Semaste for (pos = m_row_list.begin(); pos != end; ++pos) 328254721Semaste { 329254721Semaste if ((*pos)->GetOffset() <= offset) 330254721Semaste row = *pos; 331254721Semaste else 332254721Semaste break; 333254721Semaste } 334254721Semaste } 335254721Semaste } 336254721Semaste return row; 337254721Semaste} 338254721Semaste 339254721Semastebool 340254721SemasteUnwindPlan::IsValidRowIndex (uint32_t idx) const 341254721Semaste{ 342254721Semaste return idx < m_row_list.size(); 343254721Semaste} 344254721Semaste 345254721Semasteconst UnwindPlan::RowSP 346254721SemasteUnwindPlan::GetRowAtIndex (uint32_t idx) const 347254721Semaste{ 348254721Semaste // You must call IsValidRowIndex(idx) first before calling this!!! 349254721Semaste assert (idx < m_row_list.size()); 350254721Semaste return m_row_list[idx]; 351254721Semaste} 352254721Semaste 353254721Semasteconst UnwindPlan::RowSP 354254721SemasteUnwindPlan::GetLastRow () const 355254721Semaste{ 356254721Semaste // You must call GetRowCount() first to make sure there is at least one row 357254721Semaste assert (!m_row_list.empty()); 358254721Semaste return m_row_list.back(); 359254721Semaste} 360254721Semaste 361254721Semasteint 362254721SemasteUnwindPlan::GetRowCount () const 363254721Semaste{ 364254721Semaste return m_row_list.size (); 365254721Semaste} 366254721Semaste 367254721Semastevoid 368254721SemasteUnwindPlan::SetPlanValidAddressRange (const AddressRange& range) 369254721Semaste{ 370254721Semaste if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0) 371254721Semaste m_plan_valid_address_range = range; 372254721Semaste} 373254721Semaste 374254721Semastebool 375254721SemasteUnwindPlan::PlanValidAtAddress (Address addr) 376254721Semaste{ 377263367Semaste // If this UnwindPlan has no rows, it is an invalid UnwindPlan. 378263367Semaste if (GetRowCount() == 0) 379263367Semaste { 380263367Semaste Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); 381263367Semaste if (log) 382263369Semaste { 383263369Semaste StreamString s; 384263369Semaste if (addr.Dump (&s, NULL, Address::DumpStyleSectionNameOffset)) 385263369Semaste { 386263369Semaste log->Printf ("UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s' at address %s", 387263369Semaste m_source_name.GetCString(), s.GetData()); 388263369Semaste } 389263369Semaste else 390263369Semaste { 391263369Semaste log->Printf ("UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'", 392263369Semaste m_source_name.GetCString()); 393263369Semaste } 394263369Semaste } 395263367Semaste return false; 396263367Semaste } 397263367Semaste 398263367Semaste // If the 0th Row of unwind instructions is missing, or if it doesn't provide 399263367Semaste // a register to use to find the Canonical Frame Address, this is not a valid UnwindPlan. 400263367Semaste if (GetRowAtIndex(0).get() == NULL || GetRowAtIndex(0)->GetCFARegister() == LLDB_INVALID_REGNUM) 401263367Semaste { 402263367Semaste Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); 403263367Semaste if (log) 404263369Semaste { 405263369Semaste StreamString s; 406263369Semaste if (addr.Dump (&s, NULL, Address::DumpStyleSectionNameOffset)) 407263369Semaste { 408263369Semaste log->Printf ("UnwindPlan is invalid -- no CFA register defined in row 0 for UnwindPlan '%s' at address %s", 409263369Semaste m_source_name.GetCString(), s.GetData()); 410263369Semaste } 411263369Semaste else 412263369Semaste { 413263369Semaste log->Printf ("UnwindPlan is invalid -- no CFA register defined in row 0 for UnwindPlan '%s'", 414263369Semaste m_source_name.GetCString()); 415263369Semaste } 416263369Semaste } 417263367Semaste return false; 418263367Semaste } 419263367Semaste 420254721Semaste if (!m_plan_valid_address_range.GetBaseAddress().IsValid() || m_plan_valid_address_range.GetByteSize() == 0) 421254721Semaste return true; 422254721Semaste 423254721Semaste if (!addr.IsValid()) 424254721Semaste return true; 425254721Semaste 426254721Semaste if (m_plan_valid_address_range.ContainsFileAddress (addr)) 427254721Semaste return true; 428254721Semaste 429254721Semaste return false; 430254721Semaste} 431254721Semaste 432254721Semastevoid 433254721SemasteUnwindPlan::Dump (Stream& s, Thread *thread, lldb::addr_t base_addr) const 434254721Semaste{ 435254721Semaste if (!m_source_name.IsEmpty()) 436254721Semaste { 437254721Semaste s.Printf ("This UnwindPlan originally sourced from %s\n", m_source_name.GetCString()); 438254721Semaste } 439254721Semaste if (m_plan_valid_address_range.GetBaseAddress().IsValid() && m_plan_valid_address_range.GetByteSize() > 0) 440254721Semaste { 441254721Semaste s.PutCString ("Address range of this UnwindPlan: "); 442254721Semaste TargetSP target_sp(thread->CalculateTarget()); 443254721Semaste m_plan_valid_address_range.Dump (&s, target_sp.get(), Address::DumpStyleSectionNameOffset); 444254721Semaste s.EOL(); 445254721Semaste } 446254721Semaste collection::const_iterator pos, begin = m_row_list.begin(), end = m_row_list.end(); 447254721Semaste for (pos = begin; pos != end; ++pos) 448254721Semaste { 449254721Semaste s.Printf ("row[%u]: ", (uint32_t)std::distance (begin, pos)); 450254721Semaste (*pos)->Dump(s, this, thread, base_addr); 451254721Semaste } 452254721Semaste} 453254721Semaste 454254721Semastevoid 455254721SemasteUnwindPlan::SetSourceName (const char *source) 456254721Semaste{ 457254721Semaste m_source_name = ConstString (source); 458254721Semaste} 459254721Semaste 460254721SemasteConstString 461254721SemasteUnwindPlan::GetSourceName () const 462254721Semaste{ 463254721Semaste return m_source_name; 464254721Semaste} 465254721Semaste 466254721Semasteconst RegisterInfo * 467254721SemasteUnwindPlan::GetRegisterInfo (Thread* thread, uint32_t unwind_reg) const 468254721Semaste{ 469254721Semaste if (thread) 470254721Semaste { 471254721Semaste RegisterContext *reg_ctx = thread->GetRegisterContext().get(); 472254721Semaste if (reg_ctx) 473254721Semaste { 474254721Semaste uint32_t reg; 475254721Semaste if (m_register_kind == eRegisterKindLLDB) 476254721Semaste reg = unwind_reg; 477254721Semaste else 478254721Semaste reg = reg_ctx->ConvertRegisterKindToRegisterNumber (m_register_kind, unwind_reg); 479254721Semaste if (reg != LLDB_INVALID_REGNUM) 480254721Semaste return reg_ctx->GetRegisterInfoAtIndex (reg); 481254721Semaste } 482254721Semaste } 483254721Semaste return NULL; 484254721Semaste} 485254721Semaste 486