1*30fdc8d8SChris Lattner //===-- DWARFCallFrameInfo.cpp ----------------------------------*- C++ -*-===// 2*30fdc8d8SChris Lattner // 3*30fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 4*30fdc8d8SChris Lattner // 5*30fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 6*30fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 7*30fdc8d8SChris Lattner // 8*30fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 9*30fdc8d8SChris Lattner 10*30fdc8d8SChris Lattner 11*30fdc8d8SChris Lattner // C Includes 12*30fdc8d8SChris Lattner // C++ Includes 13*30fdc8d8SChris Lattner #include <list> 14*30fdc8d8SChris Lattner 15*30fdc8d8SChris Lattner // Other libraries and framework includes 16*30fdc8d8SChris Lattner // Project includes 17*30fdc8d8SChris Lattner #include "lldb/Symbol/DWARFCallFrameInfo.h" 18*30fdc8d8SChris Lattner #include "lldb/Core/ArchSpec.h" 19*30fdc8d8SChris Lattner #include "lldb/Core/Module.h" 20*30fdc8d8SChris Lattner #include "lldb/Symbol/ObjectFile.h" 21*30fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h" 22*30fdc8d8SChris Lattner #include "lldb/Core/Section.h" 23*30fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 24*30fdc8d8SChris Lattner 25*30fdc8d8SChris Lattner using namespace lldb; 26*30fdc8d8SChris Lattner using namespace lldb_private; 27*30fdc8d8SChris Lattner 28*30fdc8d8SChris Lattner static void 29*30fdc8d8SChris Lattner DumpRegisterName (Stream *s, Thread *thread, const ArchSpec *arch, uint32_t reg_kind, uint32_t reg_num) 30*30fdc8d8SChris Lattner { 31*30fdc8d8SChris Lattner const char *reg_name = NULL; 32*30fdc8d8SChris Lattner RegisterContext *reg_ctx = NULL; 33*30fdc8d8SChris Lattner if (thread) 34*30fdc8d8SChris Lattner { 35*30fdc8d8SChris Lattner reg_ctx = thread->GetRegisterContext(); 36*30fdc8d8SChris Lattner if (reg_ctx) 37*30fdc8d8SChris Lattner reg_name = reg_ctx->GetRegisterName (reg_ctx->ConvertRegisterKindToRegisterNumber (reg_kind, reg_num)); 38*30fdc8d8SChris Lattner } 39*30fdc8d8SChris Lattner 40*30fdc8d8SChris Lattner if (reg_name == NULL && arch != NULL) 41*30fdc8d8SChris Lattner { 42*30fdc8d8SChris Lattner switch (reg_kind) 43*30fdc8d8SChris Lattner { 44*30fdc8d8SChris Lattner case eRegisterKindDWARF: reg_name = arch->GetRegisterName(reg_num, eRegisterKindDWARF); break; 45*30fdc8d8SChris Lattner case eRegisterKindGCC: reg_name = arch->GetRegisterName(reg_num, eRegisterKindGCC); break; 46*30fdc8d8SChris Lattner default: 47*30fdc8d8SChris Lattner break; 48*30fdc8d8SChris Lattner } 49*30fdc8d8SChris Lattner } 50*30fdc8d8SChris Lattner 51*30fdc8d8SChris Lattner if (reg_name) 52*30fdc8d8SChris Lattner s->PutCString(reg_name); 53*30fdc8d8SChris Lattner else 54*30fdc8d8SChris Lattner { 55*30fdc8d8SChris Lattner const char *reg_kind_name = NULL; 56*30fdc8d8SChris Lattner switch (reg_kind) 57*30fdc8d8SChris Lattner { 58*30fdc8d8SChris Lattner case eRegisterKindDWARF: reg_kind_name = "dwarf-reg"; break; 59*30fdc8d8SChris Lattner case eRegisterKindGCC: reg_kind_name = "compiler-reg"; break; 60*30fdc8d8SChris Lattner case eRegisterKindGeneric: reg_kind_name = "generic-reg"; break; 61*30fdc8d8SChris Lattner default: 62*30fdc8d8SChris Lattner break; 63*30fdc8d8SChris Lattner } 64*30fdc8d8SChris Lattner if (reg_kind_name) 65*30fdc8d8SChris Lattner s->Printf("%s(%u)", reg_kind_name, reg_num); 66*30fdc8d8SChris Lattner else 67*30fdc8d8SChris Lattner s->Printf("reg(%d.%u)", reg_kind, reg_num); 68*30fdc8d8SChris Lattner } 69*30fdc8d8SChris Lattner } 70*30fdc8d8SChris Lattner 71*30fdc8d8SChris Lattner 72*30fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::RegisterLocation 73*30fdc8d8SChris Lattner 74*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::RegisterLocation() : 75*30fdc8d8SChris Lattner m_type(isSame) 76*30fdc8d8SChris Lattner { 77*30fdc8d8SChris Lattner } 78*30fdc8d8SChris Lattner 79*30fdc8d8SChris Lattner 80*30fdc8d8SChris Lattner bool 81*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::operator == (const DWARFCallFrameInfo::RegisterLocation& rhs) const 82*30fdc8d8SChris Lattner { 83*30fdc8d8SChris Lattner if (m_type != rhs.m_type) 84*30fdc8d8SChris Lattner return false; 85*30fdc8d8SChris Lattner switch (m_type) 86*30fdc8d8SChris Lattner { 87*30fdc8d8SChris Lattner case unspecified: 88*30fdc8d8SChris Lattner case isUndefined: 89*30fdc8d8SChris Lattner case isSame: 90*30fdc8d8SChris Lattner return true; 91*30fdc8d8SChris Lattner 92*30fdc8d8SChris Lattner case atCFAPlusOffset: 93*30fdc8d8SChris Lattner return m_location.offset == rhs.m_location.offset; 94*30fdc8d8SChris Lattner 95*30fdc8d8SChris Lattner case isCFAPlusOffset: 96*30fdc8d8SChris Lattner return m_location.offset == rhs.m_location.offset; 97*30fdc8d8SChris Lattner 98*30fdc8d8SChris Lattner case inOtherRegister: 99*30fdc8d8SChris Lattner return m_location.reg_num == rhs.m_location.reg_num; 100*30fdc8d8SChris Lattner 101*30fdc8d8SChris Lattner default: 102*30fdc8d8SChris Lattner break; 103*30fdc8d8SChris Lattner } 104*30fdc8d8SChris Lattner return false; 105*30fdc8d8SChris Lattner } 106*30fdc8d8SChris Lattner 107*30fdc8d8SChris Lattner void 108*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetUnspecified() 109*30fdc8d8SChris Lattner { 110*30fdc8d8SChris Lattner m_type = unspecified; 111*30fdc8d8SChris Lattner } 112*30fdc8d8SChris Lattner 113*30fdc8d8SChris Lattner void 114*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetUndefined() 115*30fdc8d8SChris Lattner { 116*30fdc8d8SChris Lattner m_type = isUndefined; 117*30fdc8d8SChris Lattner } 118*30fdc8d8SChris Lattner 119*30fdc8d8SChris Lattner void 120*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetSame() 121*30fdc8d8SChris Lattner { 122*30fdc8d8SChris Lattner m_type = isSame; 123*30fdc8d8SChris Lattner } 124*30fdc8d8SChris Lattner 125*30fdc8d8SChris Lattner void 126*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetAtCFAPlusOffset(int64_t offset) 127*30fdc8d8SChris Lattner { 128*30fdc8d8SChris Lattner m_type = atCFAPlusOffset; 129*30fdc8d8SChris Lattner m_location.offset = offset; 130*30fdc8d8SChris Lattner } 131*30fdc8d8SChris Lattner 132*30fdc8d8SChris Lattner void 133*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetIsCFAPlusOffset(int64_t offset) 134*30fdc8d8SChris Lattner { 135*30fdc8d8SChris Lattner m_type = isCFAPlusOffset; 136*30fdc8d8SChris Lattner m_location.offset = offset; 137*30fdc8d8SChris Lattner } 138*30fdc8d8SChris Lattner 139*30fdc8d8SChris Lattner void 140*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetInRegister (uint32_t reg_num) 141*30fdc8d8SChris Lattner { 142*30fdc8d8SChris Lattner m_type = inOtherRegister; 143*30fdc8d8SChris Lattner m_location.reg_num = reg_num; 144*30fdc8d8SChris Lattner } 145*30fdc8d8SChris Lattner 146*30fdc8d8SChris Lattner void 147*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetAtDWARFExpression(const uint8_t *opcodes, uint32_t len) 148*30fdc8d8SChris Lattner { 149*30fdc8d8SChris Lattner m_type = atDWARFExpression; 150*30fdc8d8SChris Lattner m_location.expr.opcodes = opcodes; 151*30fdc8d8SChris Lattner m_location.expr.length = len; 152*30fdc8d8SChris Lattner } 153*30fdc8d8SChris Lattner 154*30fdc8d8SChris Lattner void 155*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len) 156*30fdc8d8SChris Lattner { 157*30fdc8d8SChris Lattner m_type = isDWARFExpression; 158*30fdc8d8SChris Lattner m_location.expr.opcodes = opcodes; 159*30fdc8d8SChris Lattner m_location.expr.length = len; 160*30fdc8d8SChris Lattner } 161*30fdc8d8SChris Lattner 162*30fdc8d8SChris Lattner void 163*30fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::Dump(Stream *s, const DWARFCallFrameInfo &cfi, Thread *thread, const Row *row, uint32_t reg_num) const 164*30fdc8d8SChris Lattner { 165*30fdc8d8SChris Lattner const ArchSpec *arch = cfi.GetArchitecture(); 166*30fdc8d8SChris Lattner const uint32_t reg_kind = cfi.GetRegisterKind(); 167*30fdc8d8SChris Lattner 168*30fdc8d8SChris Lattner DumpRegisterName (s, thread, arch, reg_kind, reg_num); 169*30fdc8d8SChris Lattner s->PutChar('='); 170*30fdc8d8SChris Lattner 171*30fdc8d8SChris Lattner switch (m_type) 172*30fdc8d8SChris Lattner { 173*30fdc8d8SChris Lattner case unspecified: 174*30fdc8d8SChris Lattner s->PutChar('?'); 175*30fdc8d8SChris Lattner break; 176*30fdc8d8SChris Lattner 177*30fdc8d8SChris Lattner case isUndefined: 178*30fdc8d8SChris Lattner s->PutCString("undefined"); 179*30fdc8d8SChris Lattner break; 180*30fdc8d8SChris Lattner 181*30fdc8d8SChris Lattner case isSame: 182*30fdc8d8SChris Lattner s->PutCString("same"); 183*30fdc8d8SChris Lattner break; 184*30fdc8d8SChris Lattner 185*30fdc8d8SChris Lattner case atCFAPlusOffset: 186*30fdc8d8SChris Lattner s->PutChar('['); 187*30fdc8d8SChris Lattner // Fall through to isCFAPlusOffset... 188*30fdc8d8SChris Lattner case isCFAPlusOffset: 189*30fdc8d8SChris Lattner { 190*30fdc8d8SChris Lattner DumpRegisterName (s, thread, arch, reg_kind, row->GetCFARegister()); 191*30fdc8d8SChris Lattner int32_t offset = row->GetCFAOffset() + m_location.offset; 192*30fdc8d8SChris Lattner if (offset != 0) 193*30fdc8d8SChris Lattner s->Printf("%-+d", offset); 194*30fdc8d8SChris Lattner if (m_type == atCFAPlusOffset) 195*30fdc8d8SChris Lattner s->PutChar(']'); 196*30fdc8d8SChris Lattner } 197*30fdc8d8SChris Lattner break; 198*30fdc8d8SChris Lattner 199*30fdc8d8SChris Lattner case inOtherRegister: 200*30fdc8d8SChris Lattner DumpRegisterName (s, thread, arch, reg_kind, m_location.reg_num); 201*30fdc8d8SChris Lattner break; 202*30fdc8d8SChris Lattner 203*30fdc8d8SChris Lattner case atDWARFExpression: 204*30fdc8d8SChris Lattner s->PutCString("[EXPR] "); 205*30fdc8d8SChris Lattner break; 206*30fdc8d8SChris Lattner 207*30fdc8d8SChris Lattner case isDWARFExpression: 208*30fdc8d8SChris Lattner s->PutCString("EXPR "); 209*30fdc8d8SChris Lattner break; 210*30fdc8d8SChris Lattner } 211*30fdc8d8SChris Lattner } 212*30fdc8d8SChris Lattner 213*30fdc8d8SChris Lattner 214*30fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::Row 215*30fdc8d8SChris Lattner 216*30fdc8d8SChris Lattner DWARFCallFrameInfo::Row::Row() : 217*30fdc8d8SChris Lattner m_offset(0), 218*30fdc8d8SChris Lattner m_cfa_reg_num(0), 219*30fdc8d8SChris Lattner m_cfa_offset(0), 220*30fdc8d8SChris Lattner m_register_locations() 221*30fdc8d8SChris Lattner { 222*30fdc8d8SChris Lattner } 223*30fdc8d8SChris Lattner 224*30fdc8d8SChris Lattner DWARFCallFrameInfo::Row::~Row() 225*30fdc8d8SChris Lattner { 226*30fdc8d8SChris Lattner } 227*30fdc8d8SChris Lattner 228*30fdc8d8SChris Lattner void 229*30fdc8d8SChris Lattner DWARFCallFrameInfo::Row::Clear() 230*30fdc8d8SChris Lattner { 231*30fdc8d8SChris Lattner m_register_locations.clear(); 232*30fdc8d8SChris Lattner } 233*30fdc8d8SChris Lattner bool 234*30fdc8d8SChris Lattner DWARFCallFrameInfo::Row::GetRegisterInfo (uint32_t reg_num, DWARFCallFrameInfo::RegisterLocation& register_location) const 235*30fdc8d8SChris Lattner { 236*30fdc8d8SChris Lattner collection::const_iterator pos = m_register_locations.find(reg_num); 237*30fdc8d8SChris Lattner if (pos != m_register_locations.end()) 238*30fdc8d8SChris Lattner { 239*30fdc8d8SChris Lattner register_location = pos->second; 240*30fdc8d8SChris Lattner return true; 241*30fdc8d8SChris Lattner } 242*30fdc8d8SChris Lattner return false; 243*30fdc8d8SChris Lattner } 244*30fdc8d8SChris Lattner 245*30fdc8d8SChris Lattner void 246*30fdc8d8SChris Lattner DWARFCallFrameInfo::Row::SetRegisterInfo (uint32_t reg_num, const RegisterLocation& register_location) 247*30fdc8d8SChris Lattner { 248*30fdc8d8SChris Lattner m_register_locations[reg_num] = register_location; 249*30fdc8d8SChris Lattner } 250*30fdc8d8SChris Lattner 251*30fdc8d8SChris Lattner 252*30fdc8d8SChris Lattner void 253*30fdc8d8SChris Lattner DWARFCallFrameInfo::Row::Dump(Stream* s, const DWARFCallFrameInfo &cfi, Thread *thread, lldb::addr_t base_addr) const 254*30fdc8d8SChris Lattner { 255*30fdc8d8SChris Lattner const ArchSpec *arch = cfi.GetArchitecture(); 256*30fdc8d8SChris Lattner const uint32_t reg_kind = cfi.GetRegisterKind(); 257*30fdc8d8SChris Lattner collection::const_iterator pos, end = m_register_locations.end(); 258*30fdc8d8SChris Lattner s->Indent(); 259*30fdc8d8SChris Lattner s->Printf("0x%16.16llx: CFA=", m_offset + base_addr); 260*30fdc8d8SChris Lattner DumpRegisterName(s, thread, arch, reg_kind, m_cfa_reg_num); 261*30fdc8d8SChris Lattner if (m_cfa_offset != 0) 262*30fdc8d8SChris Lattner s->Printf("%-+lld", m_cfa_offset); 263*30fdc8d8SChris Lattner 264*30fdc8d8SChris Lattner for (pos = m_register_locations.begin(); pos != end; ++pos) 265*30fdc8d8SChris Lattner { 266*30fdc8d8SChris Lattner s->PutChar(' '); 267*30fdc8d8SChris Lattner pos->second.Dump(s, cfi, thread, this, pos->first); 268*30fdc8d8SChris Lattner } 269*30fdc8d8SChris Lattner s->EOL(); 270*30fdc8d8SChris Lattner } 271*30fdc8d8SChris Lattner 272*30fdc8d8SChris Lattner 273*30fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::FDE 274*30fdc8d8SChris Lattner 275*30fdc8d8SChris Lattner 276*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::FDE (dw_offset_t offset, const AddressRange &range) : 277*30fdc8d8SChris Lattner m_fde_offset (offset), 278*30fdc8d8SChris Lattner m_range (range), 279*30fdc8d8SChris Lattner m_row_list () 280*30fdc8d8SChris Lattner { 281*30fdc8d8SChris Lattner } 282*30fdc8d8SChris Lattner 283*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::~FDE() 284*30fdc8d8SChris Lattner { 285*30fdc8d8SChris Lattner } 286*30fdc8d8SChris Lattner 287*30fdc8d8SChris Lattner void 288*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::AppendRow (const Row &row) 289*30fdc8d8SChris Lattner { 290*30fdc8d8SChris Lattner if (m_row_list.empty() || m_row_list.back().GetOffset() != row.GetOffset()) 291*30fdc8d8SChris Lattner m_row_list.push_back(row); 292*30fdc8d8SChris Lattner else 293*30fdc8d8SChris Lattner m_row_list.back() = row; 294*30fdc8d8SChris Lattner } 295*30fdc8d8SChris Lattner 296*30fdc8d8SChris Lattner void 297*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::Dump (Stream *s, const DWARFCallFrameInfo &cfi, Thread* thread) const 298*30fdc8d8SChris Lattner { 299*30fdc8d8SChris Lattner s->Indent(); 300*30fdc8d8SChris Lattner s->Printf("FDE{0x%8.8x} ", m_fde_offset); 301*30fdc8d8SChris Lattner m_range.Dump(s, NULL, Address::DumpStyleFileAddress); 302*30fdc8d8SChris Lattner lldb::addr_t fde_base_addr = m_range.GetBaseAddress().GetFileAddress(); 303*30fdc8d8SChris Lattner s->EOL(); 304*30fdc8d8SChris Lattner s->IndentMore(); 305*30fdc8d8SChris Lattner collection::const_iterator pos, end = m_row_list.end(); 306*30fdc8d8SChris Lattner for (pos = m_row_list.begin(); pos != end; ++pos) 307*30fdc8d8SChris Lattner { 308*30fdc8d8SChris Lattner pos->Dump(s, cfi, thread, fde_base_addr); 309*30fdc8d8SChris Lattner } 310*30fdc8d8SChris Lattner s->IndentLess(); 311*30fdc8d8SChris Lattner } 312*30fdc8d8SChris Lattner 313*30fdc8d8SChris Lattner const AddressRange & 314*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::GetAddressRange() const 315*30fdc8d8SChris Lattner { 316*30fdc8d8SChris Lattner return m_range; 317*30fdc8d8SChris Lattner } 318*30fdc8d8SChris Lattner 319*30fdc8d8SChris Lattner bool 320*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::IsValidRowIndex (uint32_t idx) const 321*30fdc8d8SChris Lattner { 322*30fdc8d8SChris Lattner return idx < m_row_list.size(); 323*30fdc8d8SChris Lattner } 324*30fdc8d8SChris Lattner 325*30fdc8d8SChris Lattner const DWARFCallFrameInfo::Row& 326*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::GetRowAtIndex (uint32_t idx) 327*30fdc8d8SChris Lattner { 328*30fdc8d8SChris Lattner // You must call IsValidRowIndex(idx) first before calling this!!! 329*30fdc8d8SChris Lattner return m_row_list[idx]; 330*30fdc8d8SChris Lattner } 331*30fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::FDEInfo 332*30fdc8d8SChris Lattner 333*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDEInfo::FDEInfo () : 334*30fdc8d8SChris Lattner fde_offset (0), 335*30fdc8d8SChris Lattner fde_sp() 336*30fdc8d8SChris Lattner { 337*30fdc8d8SChris Lattner } 338*30fdc8d8SChris Lattner 339*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDEInfo::FDEInfo (off_t offset) : 340*30fdc8d8SChris Lattner fde_offset(offset), 341*30fdc8d8SChris Lattner fde_sp() 342*30fdc8d8SChris Lattner { 343*30fdc8d8SChris Lattner } 344*30fdc8d8SChris Lattner 345*30fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::CIE 346*30fdc8d8SChris Lattner 347*30fdc8d8SChris Lattner DWARFCallFrameInfo::CIE::CIE(dw_offset_t offset) : 348*30fdc8d8SChris Lattner cie_offset (offset), 349*30fdc8d8SChris Lattner version (0), 350*30fdc8d8SChris Lattner augmentation(), 351*30fdc8d8SChris Lattner code_align (0), 352*30fdc8d8SChris Lattner data_align (0), 353*30fdc8d8SChris Lattner return_addr_reg_num (0), 354*30fdc8d8SChris Lattner inst_offset (0), 355*30fdc8d8SChris Lattner inst_length (0), 356*30fdc8d8SChris Lattner ptr_encoding (DW_GNU_EH_PE_absptr) 357*30fdc8d8SChris Lattner { 358*30fdc8d8SChris Lattner } 359*30fdc8d8SChris Lattner 360*30fdc8d8SChris Lattner 361*30fdc8d8SChris Lattner DWARFCallFrameInfo::CIE::~CIE() 362*30fdc8d8SChris Lattner { 363*30fdc8d8SChris Lattner } 364*30fdc8d8SChris Lattner 365*30fdc8d8SChris Lattner void 366*30fdc8d8SChris Lattner DWARFCallFrameInfo::CIE::Dump(Stream *s, Thread* thread, const ArchSpec *arch, uint32_t reg_kind) const 367*30fdc8d8SChris Lattner { 368*30fdc8d8SChris Lattner s->Indent(); 369*30fdc8d8SChris Lattner s->Printf("CIE{0x%8.8x} version=%u, code_align=%u, data_align=%d, return_addr_reg=", cie_offset, version, code_align, data_align); 370*30fdc8d8SChris Lattner DumpRegisterName(s, thread, arch, reg_kind, return_addr_reg_num); 371*30fdc8d8SChris Lattner s->Printf(", instr_offset=0x%8.8x, instr_length=%u, ptr_encoding=0x%02x\n", 372*30fdc8d8SChris Lattner inst_offset, 373*30fdc8d8SChris Lattner inst_length, 374*30fdc8d8SChris Lattner ptr_encoding); 375*30fdc8d8SChris Lattner } 376*30fdc8d8SChris Lattner 377*30fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::CIE 378*30fdc8d8SChris Lattner 379*30fdc8d8SChris Lattner DWARFCallFrameInfo::DWARFCallFrameInfo(ObjectFile *objfile, Section *section, uint32_t reg_kind) : 380*30fdc8d8SChris Lattner m_objfile (objfile), 381*30fdc8d8SChris Lattner m_section (section), 382*30fdc8d8SChris Lattner m_reg_kind (reg_kind), // The flavor of registers that the CFI data uses (One of the defines that starts with "LLDB_REGKIND_") 383*30fdc8d8SChris Lattner m_cfi_data (), 384*30fdc8d8SChris Lattner m_cie_map (), 385*30fdc8d8SChris Lattner m_fde_map () 386*30fdc8d8SChris Lattner { 387*30fdc8d8SChris Lattner if (objfile && section) 388*30fdc8d8SChris Lattner { 389*30fdc8d8SChris Lattner section->ReadSectionDataFromObjectFile (objfile, m_cfi_data); 390*30fdc8d8SChris Lattner } 391*30fdc8d8SChris Lattner } 392*30fdc8d8SChris Lattner 393*30fdc8d8SChris Lattner DWARFCallFrameInfo::~DWARFCallFrameInfo() 394*30fdc8d8SChris Lattner { 395*30fdc8d8SChris Lattner } 396*30fdc8d8SChris Lattner 397*30fdc8d8SChris Lattner bool 398*30fdc8d8SChris Lattner DWARFCallFrameInfo::IsEHFrame() const 399*30fdc8d8SChris Lattner { 400*30fdc8d8SChris Lattner return (m_reg_kind == eRegisterKindGCC); 401*30fdc8d8SChris Lattner } 402*30fdc8d8SChris Lattner 403*30fdc8d8SChris Lattner const ArchSpec * 404*30fdc8d8SChris Lattner DWARFCallFrameInfo::GetArchitecture() const 405*30fdc8d8SChris Lattner { 406*30fdc8d8SChris Lattner if (m_objfile && m_objfile->GetModule()) 407*30fdc8d8SChris Lattner return &m_objfile->GetModule()->GetArchitecture(); 408*30fdc8d8SChris Lattner return NULL; 409*30fdc8d8SChris Lattner } 410*30fdc8d8SChris Lattner 411*30fdc8d8SChris Lattner uint32_t 412*30fdc8d8SChris Lattner DWARFCallFrameInfo::GetRegisterKind () const 413*30fdc8d8SChris Lattner { 414*30fdc8d8SChris Lattner return m_reg_kind; 415*30fdc8d8SChris Lattner } 416*30fdc8d8SChris Lattner 417*30fdc8d8SChris Lattner void 418*30fdc8d8SChris Lattner DWARFCallFrameInfo::SetRegisterKind (uint32_t reg_kind) 419*30fdc8d8SChris Lattner { 420*30fdc8d8SChris Lattner m_reg_kind = reg_kind; 421*30fdc8d8SChris Lattner } 422*30fdc8d8SChris Lattner 423*30fdc8d8SChris Lattner 424*30fdc8d8SChris Lattner 425*30fdc8d8SChris Lattner 426*30fdc8d8SChris Lattner const DWARFCallFrameInfo::CIE* 427*30fdc8d8SChris Lattner DWARFCallFrameInfo::GetCIE(dw_offset_t cie_offset) 428*30fdc8d8SChris Lattner { 429*30fdc8d8SChris Lattner Index (); 430*30fdc8d8SChris Lattner 431*30fdc8d8SChris Lattner cie_map_t::iterator pos = m_cie_map.find(cie_offset); 432*30fdc8d8SChris Lattner 433*30fdc8d8SChris Lattner if (pos != m_cie_map.end()) 434*30fdc8d8SChris Lattner { 435*30fdc8d8SChris Lattner // Parse and cache the CIE 436*30fdc8d8SChris Lattner if (pos->second.get() == NULL) 437*30fdc8d8SChris Lattner pos->second = ParseCIE (cie_offset); 438*30fdc8d8SChris Lattner 439*30fdc8d8SChris Lattner return pos->second.get(); 440*30fdc8d8SChris Lattner } 441*30fdc8d8SChris Lattner return NULL; 442*30fdc8d8SChris Lattner } 443*30fdc8d8SChris Lattner 444*30fdc8d8SChris Lattner DWARFCallFrameInfo::CIE::shared_ptr 445*30fdc8d8SChris Lattner DWARFCallFrameInfo::ParseCIE (const dw_offset_t cie_offset) 446*30fdc8d8SChris Lattner { 447*30fdc8d8SChris Lattner CIE::shared_ptr cie_sp(new CIE(cie_offset)); 448*30fdc8d8SChris Lattner const bool for_eh_frame = IsEHFrame(); 449*30fdc8d8SChris Lattner dw_offset_t offset = cie_offset; 450*30fdc8d8SChris Lattner const uint32_t length = m_cfi_data.GetU32(&offset); 451*30fdc8d8SChris Lattner const dw_offset_t cie_id = m_cfi_data.GetU32(&offset); 452*30fdc8d8SChris Lattner const dw_offset_t end_offset = cie_offset + length + 4; 453*30fdc8d8SChris Lattner if (length > 0 && (!for_eh_frame && cie_id == 0xfffffffful) || (for_eh_frame && cie_id == 0ul)) 454*30fdc8d8SChris Lattner { 455*30fdc8d8SChris Lattner size_t i; 456*30fdc8d8SChris Lattner // cie.offset = cie_offset; 457*30fdc8d8SChris Lattner // cie.length = length; 458*30fdc8d8SChris Lattner // cie.cieID = cieID; 459*30fdc8d8SChris Lattner cie_sp->ptr_encoding = DW_GNU_EH_PE_absptr; 460*30fdc8d8SChris Lattner cie_sp->version = m_cfi_data.GetU8(&offset); 461*30fdc8d8SChris Lattner 462*30fdc8d8SChris Lattner for (i=0; i<CFI_AUG_MAX_SIZE; ++i) 463*30fdc8d8SChris Lattner { 464*30fdc8d8SChris Lattner cie_sp->augmentation[i] = m_cfi_data.GetU8(&offset); 465*30fdc8d8SChris Lattner if (cie_sp->augmentation[i] == '\0') 466*30fdc8d8SChris Lattner { 467*30fdc8d8SChris Lattner // Zero out remaining bytes in augmentation string 468*30fdc8d8SChris Lattner for (size_t j = i+1; j<CFI_AUG_MAX_SIZE; ++j) 469*30fdc8d8SChris Lattner cie_sp->augmentation[j] = '\0'; 470*30fdc8d8SChris Lattner 471*30fdc8d8SChris Lattner break; 472*30fdc8d8SChris Lattner } 473*30fdc8d8SChris Lattner } 474*30fdc8d8SChris Lattner 475*30fdc8d8SChris Lattner if (i == CFI_AUG_MAX_SIZE && cie_sp->augmentation[CFI_AUG_MAX_SIZE-1] != '\0') 476*30fdc8d8SChris Lattner { 477*30fdc8d8SChris Lattner fprintf(stderr, "CIE parse error: CIE augmentation string was too large for the fixed sized buffer of %d bytes.\n", CFI_AUG_MAX_SIZE); 478*30fdc8d8SChris Lattner return cie_sp; 479*30fdc8d8SChris Lattner } 480*30fdc8d8SChris Lattner cie_sp->code_align = (uint32_t)m_cfi_data.GetULEB128(&offset); 481*30fdc8d8SChris Lattner cie_sp->data_align = (int32_t)m_cfi_data.GetSLEB128(&offset); 482*30fdc8d8SChris Lattner cie_sp->return_addr_reg_num = m_cfi_data.GetU8(&offset); 483*30fdc8d8SChris Lattner 484*30fdc8d8SChris Lattner if (cie_sp->augmentation[0]) 485*30fdc8d8SChris Lattner { 486*30fdc8d8SChris Lattner // Get the length of the eh_frame augmentation data 487*30fdc8d8SChris Lattner // which starts with a ULEB128 length in bytes 488*30fdc8d8SChris Lattner const size_t aug_data_len = (size_t)m_cfi_data.GetULEB128(&offset); 489*30fdc8d8SChris Lattner const size_t aug_data_end = offset + aug_data_len; 490*30fdc8d8SChris Lattner const size_t aug_str_len = strlen(cie_sp->augmentation); 491*30fdc8d8SChris Lattner // A 'z' may be present as the first character of the string. 492*30fdc8d8SChris Lattner // If present, the Augmentation Data field shall be present. 493*30fdc8d8SChris Lattner // The contents of the Augmentation Data shall be intepreted 494*30fdc8d8SChris Lattner // according to other characters in the Augmentation String. 495*30fdc8d8SChris Lattner if (cie_sp->augmentation[0] == 'z') 496*30fdc8d8SChris Lattner { 497*30fdc8d8SChris Lattner // Extract the Augmentation Data 498*30fdc8d8SChris Lattner size_t aug_str_idx = 0; 499*30fdc8d8SChris Lattner for (aug_str_idx = 1; aug_str_idx < aug_str_len; aug_str_idx++) 500*30fdc8d8SChris Lattner { 501*30fdc8d8SChris Lattner char aug = cie_sp->augmentation[aug_str_idx]; 502*30fdc8d8SChris Lattner switch (aug) 503*30fdc8d8SChris Lattner { 504*30fdc8d8SChris Lattner case 'L': 505*30fdc8d8SChris Lattner // Indicates the presence of one argument in the 506*30fdc8d8SChris Lattner // Augmentation Data of the CIE, and a corresponding 507*30fdc8d8SChris Lattner // argument in the Augmentation Data of the FDE. The 508*30fdc8d8SChris Lattner // argument in the Augmentation Data of the CIE is 509*30fdc8d8SChris Lattner // 1-byte and represents the pointer encoding used 510*30fdc8d8SChris Lattner // for the argument in the Augmentation Data of the 511*30fdc8d8SChris Lattner // FDE, which is the address of a language-specific 512*30fdc8d8SChris Lattner // data area (LSDA). The size of the LSDA pointer is 513*30fdc8d8SChris Lattner // specified by the pointer encoding used. 514*30fdc8d8SChris Lattner m_cfi_data.GetU8(&offset); 515*30fdc8d8SChris Lattner break; 516*30fdc8d8SChris Lattner 517*30fdc8d8SChris Lattner case 'P': 518*30fdc8d8SChris Lattner // Indicates the presence of two arguments in the 519*30fdc8d8SChris Lattner // Augmentation Data of the cie_sp-> The first argument 520*30fdc8d8SChris Lattner // is 1-byte and represents the pointer encoding 521*30fdc8d8SChris Lattner // used for the second argument, which is the 522*30fdc8d8SChris Lattner // address of a personality routine handler. The 523*30fdc8d8SChris Lattner // size of the personality routine pointer is 524*30fdc8d8SChris Lattner // specified by the pointer encoding used. 525*30fdc8d8SChris Lattner { 526*30fdc8d8SChris Lattner uint8_t arg_ptr_encoding = m_cfi_data.GetU8(&offset); 527*30fdc8d8SChris Lattner m_cfi_data.GetGNUEHPointer(&offset, arg_ptr_encoding, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS); 528*30fdc8d8SChris Lattner } 529*30fdc8d8SChris Lattner break; 530*30fdc8d8SChris Lattner 531*30fdc8d8SChris Lattner case 'R': 532*30fdc8d8SChris Lattner // A 'R' may be present at any position after the 533*30fdc8d8SChris Lattner // first character of the string. The Augmentation 534*30fdc8d8SChris Lattner // Data shall include a 1 byte argument that 535*30fdc8d8SChris Lattner // represents the pointer encoding for the address 536*30fdc8d8SChris Lattner // pointers used in the FDE. 537*30fdc8d8SChris Lattner cie_sp->ptr_encoding = m_cfi_data.GetU8(&offset); 538*30fdc8d8SChris Lattner break; 539*30fdc8d8SChris Lattner } 540*30fdc8d8SChris Lattner } 541*30fdc8d8SChris Lattner } 542*30fdc8d8SChris Lattner else if (strcmp(cie_sp->augmentation, "eh") == 0) 543*30fdc8d8SChris Lattner { 544*30fdc8d8SChris Lattner // If the Augmentation string has the value "eh", then 545*30fdc8d8SChris Lattner // the EH Data field shall be present 546*30fdc8d8SChris Lattner } 547*30fdc8d8SChris Lattner 548*30fdc8d8SChris Lattner // Set the offset to be the end of the augmentation data just in case 549*30fdc8d8SChris Lattner // we didn't understand any of the data. 550*30fdc8d8SChris Lattner offset = (uint32_t)aug_data_end; 551*30fdc8d8SChris Lattner } 552*30fdc8d8SChris Lattner 553*30fdc8d8SChris Lattner if (end_offset > offset) 554*30fdc8d8SChris Lattner { 555*30fdc8d8SChris Lattner cie_sp->inst_offset = offset; 556*30fdc8d8SChris Lattner cie_sp->inst_length = end_offset - offset; 557*30fdc8d8SChris Lattner } 558*30fdc8d8SChris Lattner } 559*30fdc8d8SChris Lattner 560*30fdc8d8SChris Lattner return cie_sp; 561*30fdc8d8SChris Lattner } 562*30fdc8d8SChris Lattner 563*30fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::shared_ptr 564*30fdc8d8SChris Lattner DWARFCallFrameInfo::ParseFDE(const dw_offset_t fde_offset) 565*30fdc8d8SChris Lattner { 566*30fdc8d8SChris Lattner const bool for_eh_frame = IsEHFrame(); 567*30fdc8d8SChris Lattner FDE::shared_ptr fde_sp; 568*30fdc8d8SChris Lattner 569*30fdc8d8SChris Lattner dw_offset_t offset = fde_offset; 570*30fdc8d8SChris Lattner const uint32_t length = m_cfi_data.GetU32(&offset); 571*30fdc8d8SChris Lattner dw_offset_t cie_offset = m_cfi_data.GetU32(&offset); 572*30fdc8d8SChris Lattner const dw_offset_t end_offset = fde_offset + length + 4; 573*30fdc8d8SChris Lattner 574*30fdc8d8SChris Lattner // Translate the CIE_id from the eh_frame format, which 575*30fdc8d8SChris Lattner // is relative to the FDE offset, into a __eh_frame section 576*30fdc8d8SChris Lattner // offset 577*30fdc8d8SChris Lattner if (for_eh_frame) 578*30fdc8d8SChris Lattner cie_offset = offset - (cie_offset + 4); 579*30fdc8d8SChris Lattner 580*30fdc8d8SChris Lattner const CIE* cie = GetCIE(cie_offset); 581*30fdc8d8SChris Lattner if (cie) 582*30fdc8d8SChris Lattner { 583*30fdc8d8SChris Lattner const lldb::addr_t pc_rel_addr = m_section->GetFileAddress(); 584*30fdc8d8SChris Lattner const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS; 585*30fdc8d8SChris Lattner const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS; 586*30fdc8d8SChris Lattner lldb::addr_t range_base = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr); 587*30fdc8d8SChris Lattner lldb::addr_t range_len = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding & DW_GNU_EH_PE_MASK_ENCODING, pc_rel_addr, text_addr, data_addr); 588*30fdc8d8SChris Lattner 589*30fdc8d8SChris Lattner if (cie->augmentation[0] == 'z') 590*30fdc8d8SChris Lattner { 591*30fdc8d8SChris Lattner uint32_t aug_data_len = (uint32_t)m_cfi_data.GetULEB128(&offset); 592*30fdc8d8SChris Lattner offset += aug_data_len; 593*30fdc8d8SChris Lattner } 594*30fdc8d8SChris Lattner 595*30fdc8d8SChris Lattner AddressRange fde_range (range_base, range_len, m_objfile->GetSectionList ()); 596*30fdc8d8SChris Lattner fde_sp.reset(new FDE(fde_offset, fde_range)); 597*30fdc8d8SChris Lattner if (offset < end_offset) 598*30fdc8d8SChris Lattner { 599*30fdc8d8SChris Lattner dw_offset_t fde_instr_offset = offset; 600*30fdc8d8SChris Lattner uint32_t fde_instr_length = end_offset - offset; 601*30fdc8d8SChris Lattner if (cie->inst_length > 0) 602*30fdc8d8SChris Lattner ParseInstructions(cie, fde_sp.get(), cie->inst_offset, cie->inst_length); 603*30fdc8d8SChris Lattner ParseInstructions(cie, fde_sp.get(), fde_instr_offset, fde_instr_length); 604*30fdc8d8SChris Lattner } 605*30fdc8d8SChris Lattner } 606*30fdc8d8SChris Lattner return fde_sp; 607*30fdc8d8SChris Lattner } 608*30fdc8d8SChris Lattner 609*30fdc8d8SChris Lattner const DWARFCallFrameInfo::FDE * 610*30fdc8d8SChris Lattner DWARFCallFrameInfo::FindFDE(const Address &addr) 611*30fdc8d8SChris Lattner { 612*30fdc8d8SChris Lattner Index (); 613*30fdc8d8SChris Lattner 614*30fdc8d8SChris Lattner VMRange find_range(addr.GetFileAddress(), 0); 615*30fdc8d8SChris Lattner fde_map_t::iterator pos = m_fde_map.lower_bound (find_range); 616*30fdc8d8SChris Lattner fde_map_t::iterator end = m_fde_map.end(); 617*30fdc8d8SChris Lattner 618*30fdc8d8SChris Lattner if (pos != end) 619*30fdc8d8SChris Lattner { 620*30fdc8d8SChris Lattner if (pos->first.Contains(find_range.GetBaseAddress())) 621*30fdc8d8SChris Lattner { 622*30fdc8d8SChris Lattner // Parse and cache the FDE if we already haven't 623*30fdc8d8SChris Lattner if (pos->second.fde_sp.get() == NULL) 624*30fdc8d8SChris Lattner pos->second.fde_sp = ParseFDE(pos->second.fde_offset); 625*30fdc8d8SChris Lattner 626*30fdc8d8SChris Lattner return pos->second.fde_sp.get(); 627*30fdc8d8SChris Lattner } 628*30fdc8d8SChris Lattner } 629*30fdc8d8SChris Lattner return NULL; 630*30fdc8d8SChris Lattner } 631*30fdc8d8SChris Lattner 632*30fdc8d8SChris Lattner 633*30fdc8d8SChris Lattner void 634*30fdc8d8SChris Lattner DWARFCallFrameInfo::Index () 635*30fdc8d8SChris Lattner { 636*30fdc8d8SChris Lattner if (m_flags.IsClear(eFlagParsedIndex)) 637*30fdc8d8SChris Lattner { 638*30fdc8d8SChris Lattner m_flags.Set (eFlagParsedIndex); 639*30fdc8d8SChris Lattner const bool for_eh_frame = IsEHFrame(); 640*30fdc8d8SChris Lattner CIE::shared_ptr empty_cie_sp; 641*30fdc8d8SChris Lattner dw_offset_t offset = 0; 642*30fdc8d8SChris Lattner // Parse all of the CIEs first since we will need them to be able to 643*30fdc8d8SChris Lattner // properly parse the FDE addresses due to them possibly having 644*30fdc8d8SChris Lattner // GNU pointer encodings in their augmentations... 645*30fdc8d8SChris Lattner while (m_cfi_data.ValidOffsetForDataOfSize(offset, 8)) 646*30fdc8d8SChris Lattner { 647*30fdc8d8SChris Lattner const dw_offset_t curr_offset = offset; 648*30fdc8d8SChris Lattner const uint32_t length = m_cfi_data.GetU32(&offset); 649*30fdc8d8SChris Lattner const dw_offset_t next_offset = offset + length; 650*30fdc8d8SChris Lattner const dw_offset_t cie_id = m_cfi_data.GetU32(&offset); 651*30fdc8d8SChris Lattner 652*30fdc8d8SChris Lattner bool is_cie = for_eh_frame ? cie_id == 0 : cie_id == UINT32_MAX; 653*30fdc8d8SChris Lattner if (is_cie) 654*30fdc8d8SChris Lattner m_cie_map[curr_offset]= ParseCIE(curr_offset); 655*30fdc8d8SChris Lattner 656*30fdc8d8SChris Lattner offset = next_offset; 657*30fdc8d8SChris Lattner } 658*30fdc8d8SChris Lattner 659*30fdc8d8SChris Lattner // Now go back through and index all FDEs 660*30fdc8d8SChris Lattner offset = 0; 661*30fdc8d8SChris Lattner const lldb::addr_t pc_rel_addr = m_section->GetFileAddress(); 662*30fdc8d8SChris Lattner const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS; 663*30fdc8d8SChris Lattner const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS; 664*30fdc8d8SChris Lattner while (m_cfi_data.ValidOffsetForDataOfSize(offset, 8)) 665*30fdc8d8SChris Lattner { 666*30fdc8d8SChris Lattner const dw_offset_t curr_offset = offset; 667*30fdc8d8SChris Lattner const uint32_t length = m_cfi_data.GetU32(&offset); 668*30fdc8d8SChris Lattner const dw_offset_t next_offset = offset + length; 669*30fdc8d8SChris Lattner const dw_offset_t cie_id = m_cfi_data.GetU32(&offset); 670*30fdc8d8SChris Lattner 671*30fdc8d8SChris Lattner bool is_fde = for_eh_frame ? cie_id != 0 : cie_id != UINT32_MAX; 672*30fdc8d8SChris Lattner if (is_fde) 673*30fdc8d8SChris Lattner { 674*30fdc8d8SChris Lattner dw_offset_t cie_offset; 675*30fdc8d8SChris Lattner if (for_eh_frame) 676*30fdc8d8SChris Lattner cie_offset = offset - (cie_id + 4); 677*30fdc8d8SChris Lattner else 678*30fdc8d8SChris Lattner cie_offset = cie_id; 679*30fdc8d8SChris Lattner 680*30fdc8d8SChris Lattner const CIE* cie = GetCIE(cie_offset); 681*30fdc8d8SChris Lattner assert(cie); 682*30fdc8d8SChris Lattner lldb::addr_t addr = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr); 683*30fdc8d8SChris Lattner lldb::addr_t length = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding & DW_GNU_EH_PE_MASK_ENCODING, pc_rel_addr, text_addr, data_addr); 684*30fdc8d8SChris Lattner m_fde_map[VMRange(addr, addr + length)] = FDEInfo(curr_offset); 685*30fdc8d8SChris Lattner } 686*30fdc8d8SChris Lattner 687*30fdc8d8SChris Lattner offset = next_offset; 688*30fdc8d8SChris Lattner } 689*30fdc8d8SChris Lattner } 690*30fdc8d8SChris Lattner } 691*30fdc8d8SChris Lattner 692*30fdc8d8SChris Lattner //---------------------------------------------------------------------- 693*30fdc8d8SChris Lattner // Parse instructions for a FDE. The initial instruction for the CIE 694*30fdc8d8SChris Lattner // are parsed first, then the instructions for the FDE are parsed 695*30fdc8d8SChris Lattner //---------------------------------------------------------------------- 696*30fdc8d8SChris Lattner void 697*30fdc8d8SChris Lattner DWARFCallFrameInfo::ParseInstructions(const CIE *cie, FDE *fde, dw_offset_t instr_offset, uint32_t instr_length) 698*30fdc8d8SChris Lattner { 699*30fdc8d8SChris Lattner if (cie != NULL && fde == NULL) 700*30fdc8d8SChris Lattner return; 701*30fdc8d8SChris Lattner 702*30fdc8d8SChris Lattner uint32_t reg_num = 0; 703*30fdc8d8SChris Lattner int32_t op_offset = 0; 704*30fdc8d8SChris Lattner uint32_t tmp_uval32; 705*30fdc8d8SChris Lattner uint32_t code_align = cie->code_align; 706*30fdc8d8SChris Lattner int32_t data_align = cie->data_align; 707*30fdc8d8SChris Lattner typedef std::list<Row> RowStack; 708*30fdc8d8SChris Lattner 709*30fdc8d8SChris Lattner RowStack row_stack; 710*30fdc8d8SChris Lattner Row row; 711*30fdc8d8SChris Lattner if (fde->IsValidRowIndex(0)) 712*30fdc8d8SChris Lattner row = fde->GetRowAtIndex(0); 713*30fdc8d8SChris Lattner 714*30fdc8d8SChris Lattner dw_offset_t offset = instr_offset; 715*30fdc8d8SChris Lattner const dw_offset_t end_offset = instr_offset + instr_length; 716*30fdc8d8SChris Lattner RegisterLocation reg_location; 717*30fdc8d8SChris Lattner while (m_cfi_data.ValidOffset(offset) && offset < end_offset) 718*30fdc8d8SChris Lattner { 719*30fdc8d8SChris Lattner uint8_t inst = m_cfi_data.GetU8(&offset); 720*30fdc8d8SChris Lattner uint8_t primary_opcode = inst & 0xC0; 721*30fdc8d8SChris Lattner uint8_t extended_opcode = inst & 0x3F; 722*30fdc8d8SChris Lattner 723*30fdc8d8SChris Lattner if (primary_opcode) 724*30fdc8d8SChris Lattner { 725*30fdc8d8SChris Lattner switch (primary_opcode) 726*30fdc8d8SChris Lattner { 727*30fdc8d8SChris Lattner case DW_CFA_advance_loc : // (Row Creation Instruction) 728*30fdc8d8SChris Lattner { // 0x40 - high 2 bits are 0x1, lower 6 bits are delta 729*30fdc8d8SChris Lattner // takes a single argument that represents a constant delta. The 730*30fdc8d8SChris Lattner // required action is to create a new table row with a location 731*30fdc8d8SChris Lattner // value that is computed by taking the current entry's location 732*30fdc8d8SChris Lattner // value and adding (delta * code_align). All other 733*30fdc8d8SChris Lattner // values in the new row are initially identical to the current row. 734*30fdc8d8SChris Lattner fde->AppendRow(row); 735*30fdc8d8SChris Lattner row.SlideOffset(extended_opcode * code_align); 736*30fdc8d8SChris Lattner } 737*30fdc8d8SChris Lattner break; 738*30fdc8d8SChris Lattner 739*30fdc8d8SChris Lattner case DW_CFA_offset : 740*30fdc8d8SChris Lattner { // 0x80 - high 2 bits are 0x2, lower 6 bits are register 741*30fdc8d8SChris Lattner // takes two arguments: an unsigned LEB128 constant representing a 742*30fdc8d8SChris Lattner // factored offset and a register number. The required action is to 743*30fdc8d8SChris Lattner // change the rule for the register indicated by the register number 744*30fdc8d8SChris Lattner // to be an offset(N) rule with a value of 745*30fdc8d8SChris Lattner // (N = factored offset * data_align). 746*30fdc8d8SChris Lattner reg_num = extended_opcode; 747*30fdc8d8SChris Lattner op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align; 748*30fdc8d8SChris Lattner reg_location.SetAtCFAPlusOffset(op_offset); 749*30fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 750*30fdc8d8SChris Lattner } 751*30fdc8d8SChris Lattner break; 752*30fdc8d8SChris Lattner 753*30fdc8d8SChris Lattner case DW_CFA_restore : 754*30fdc8d8SChris Lattner { // 0xC0 - high 2 bits are 0x3, lower 6 bits are register 755*30fdc8d8SChris Lattner // takes a single argument that represents a register number. The 756*30fdc8d8SChris Lattner // required action is to change the rule for the indicated register 757*30fdc8d8SChris Lattner // to the rule assigned it by the initial_instructions in the CIE. 758*30fdc8d8SChris Lattner reg_num = extended_opcode; 759*30fdc8d8SChris Lattner // We only keep enough register locations around to 760*30fdc8d8SChris Lattner // unwind what is in our thread, and these are organized 761*30fdc8d8SChris Lattner // by the register index in that state, so we need to convert our 762*30fdc8d8SChris Lattner // GCC register number from the EH frame info, to a registe index 763*30fdc8d8SChris Lattner 764*30fdc8d8SChris Lattner if (fde->IsValidRowIndex(0) && fde->GetRowAtIndex(0).GetRegisterInfo(reg_num, reg_location)) 765*30fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 766*30fdc8d8SChris Lattner } 767*30fdc8d8SChris Lattner break; 768*30fdc8d8SChris Lattner } 769*30fdc8d8SChris Lattner } 770*30fdc8d8SChris Lattner else 771*30fdc8d8SChris Lattner { 772*30fdc8d8SChris Lattner switch (extended_opcode) 773*30fdc8d8SChris Lattner { 774*30fdc8d8SChris Lattner case DW_CFA_nop : // 0x0 775*30fdc8d8SChris Lattner break; 776*30fdc8d8SChris Lattner 777*30fdc8d8SChris Lattner case DW_CFA_set_loc : // 0x1 (Row Creation Instruction) 778*30fdc8d8SChris Lattner { 779*30fdc8d8SChris Lattner // DW_CFA_set_loc takes a single argument that represents an address. 780*30fdc8d8SChris Lattner // The required action is to create a new table row using the 781*30fdc8d8SChris Lattner // specified address as the location. All other values in the new row 782*30fdc8d8SChris Lattner // are initially identical to the current row. The new location value 783*30fdc8d8SChris Lattner // should always be greater than the current one. 784*30fdc8d8SChris Lattner fde->AppendRow(row); 785*30fdc8d8SChris Lattner row.SetOffset(m_cfi_data.GetPointer(&offset) - fde->GetAddressRange().GetBaseAddress().GetFileAddress()); 786*30fdc8d8SChris Lattner } 787*30fdc8d8SChris Lattner break; 788*30fdc8d8SChris Lattner 789*30fdc8d8SChris Lattner case DW_CFA_advance_loc1 : // 0x2 (Row Creation Instruction) 790*30fdc8d8SChris Lattner { 791*30fdc8d8SChris Lattner // takes a single uword argument that represents a constant delta. 792*30fdc8d8SChris Lattner // This instruction is identical to DW_CFA_advance_loc except for the 793*30fdc8d8SChris Lattner // encoding and size of the delta argument. 794*30fdc8d8SChris Lattner fde->AppendRow(row); 795*30fdc8d8SChris Lattner row.SlideOffset (m_cfi_data.GetU8(&offset) * code_align); 796*30fdc8d8SChris Lattner } 797*30fdc8d8SChris Lattner break; 798*30fdc8d8SChris Lattner 799*30fdc8d8SChris Lattner case DW_CFA_advance_loc2 : // 0x3 (Row Creation Instruction) 800*30fdc8d8SChris Lattner { 801*30fdc8d8SChris Lattner // takes a single uword argument that represents a constant delta. 802*30fdc8d8SChris Lattner // This instruction is identical to DW_CFA_advance_loc except for the 803*30fdc8d8SChris Lattner // encoding and size of the delta argument. 804*30fdc8d8SChris Lattner fde->AppendRow(row); 805*30fdc8d8SChris Lattner row.SlideOffset (m_cfi_data.GetU16(&offset) * code_align); 806*30fdc8d8SChris Lattner } 807*30fdc8d8SChris Lattner break; 808*30fdc8d8SChris Lattner 809*30fdc8d8SChris Lattner case DW_CFA_advance_loc4 : // 0x4 (Row Creation Instruction) 810*30fdc8d8SChris Lattner { 811*30fdc8d8SChris Lattner // takes a single uword argument that represents a constant delta. 812*30fdc8d8SChris Lattner // This instruction is identical to DW_CFA_advance_loc except for the 813*30fdc8d8SChris Lattner // encoding and size of the delta argument. 814*30fdc8d8SChris Lattner fde->AppendRow(row); 815*30fdc8d8SChris Lattner row.SlideOffset (m_cfi_data.GetU32(&offset) * code_align); 816*30fdc8d8SChris Lattner } 817*30fdc8d8SChris Lattner break; 818*30fdc8d8SChris Lattner 819*30fdc8d8SChris Lattner case DW_CFA_offset_extended : // 0x5 820*30fdc8d8SChris Lattner { 821*30fdc8d8SChris Lattner // takes two unsigned LEB128 arguments representing a register number 822*30fdc8d8SChris Lattner // and a factored offset. This instruction is identical to DW_CFA_offset 823*30fdc8d8SChris Lattner // except for the encoding and size of the register argument. 824*30fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 825*30fdc8d8SChris Lattner op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align; 826*30fdc8d8SChris Lattner reg_location.SetAtCFAPlusOffset(op_offset); 827*30fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 828*30fdc8d8SChris Lattner } 829*30fdc8d8SChris Lattner break; 830*30fdc8d8SChris Lattner 831*30fdc8d8SChris Lattner case DW_CFA_restore_extended : // 0x6 832*30fdc8d8SChris Lattner { 833*30fdc8d8SChris Lattner // takes a single unsigned LEB128 argument that represents a register 834*30fdc8d8SChris Lattner // number. This instruction is identical to DW_CFA_restore except for 835*30fdc8d8SChris Lattner // the encoding and size of the register argument. 836*30fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 837*30fdc8d8SChris Lattner if (fde->IsValidRowIndex(0) && fde->GetRowAtIndex(0).GetRegisterInfo(reg_num, reg_location)) 838*30fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 839*30fdc8d8SChris Lattner } 840*30fdc8d8SChris Lattner break; 841*30fdc8d8SChris Lattner 842*30fdc8d8SChris Lattner case DW_CFA_undefined : // 0x7 843*30fdc8d8SChris Lattner { 844*30fdc8d8SChris Lattner // takes a single unsigned LEB128 argument that represents a register 845*30fdc8d8SChris Lattner // number. The required action is to set the rule for the specified 846*30fdc8d8SChris Lattner // register to undefined. 847*30fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 848*30fdc8d8SChris Lattner reg_location.SetUndefined(); 849*30fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 850*30fdc8d8SChris Lattner } 851*30fdc8d8SChris Lattner break; 852*30fdc8d8SChris Lattner 853*30fdc8d8SChris Lattner case DW_CFA_same_value : // 0x8 854*30fdc8d8SChris Lattner { 855*30fdc8d8SChris Lattner // takes a single unsigned LEB128 argument that represents a register 856*30fdc8d8SChris Lattner // number. The required action is to set the rule for the specified 857*30fdc8d8SChris Lattner // register to same value. 858*30fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 859*30fdc8d8SChris Lattner reg_location.SetSame(); 860*30fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 861*30fdc8d8SChris Lattner } 862*30fdc8d8SChris Lattner break; 863*30fdc8d8SChris Lattner 864*30fdc8d8SChris Lattner case DW_CFA_register : // 0x9 865*30fdc8d8SChris Lattner { 866*30fdc8d8SChris Lattner // takes two unsigned LEB128 arguments representing register numbers. 867*30fdc8d8SChris Lattner // The required action is to set the rule for the first register to be 868*30fdc8d8SChris Lattner // the second register. 869*30fdc8d8SChris Lattner 870*30fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 871*30fdc8d8SChris Lattner uint32_t other_reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 872*30fdc8d8SChris Lattner reg_location.SetInRegister(other_reg_num); 873*30fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 874*30fdc8d8SChris Lattner } 875*30fdc8d8SChris Lattner break; 876*30fdc8d8SChris Lattner 877*30fdc8d8SChris Lattner case DW_CFA_remember_state : // 0xA 878*30fdc8d8SChris Lattner // These instructions define a stack of information. Encountering the 879*30fdc8d8SChris Lattner // DW_CFA_remember_state instruction means to save the rules for every 880*30fdc8d8SChris Lattner // register on the current row on the stack. Encountering the 881*30fdc8d8SChris Lattner // DW_CFA_restore_state instruction means to pop the set of rules off 882*30fdc8d8SChris Lattner // the stack and place them in the current row. (This operation is 883*30fdc8d8SChris Lattner // useful for compilers that move epilogue code into the body of a 884*30fdc8d8SChris Lattner // function.) 885*30fdc8d8SChris Lattner row_stack.push_back(row); 886*30fdc8d8SChris Lattner break; 887*30fdc8d8SChris Lattner 888*30fdc8d8SChris Lattner case DW_CFA_restore_state : // 0xB 889*30fdc8d8SChris Lattner // These instructions define a stack of information. Encountering the 890*30fdc8d8SChris Lattner // DW_CFA_remember_state instruction means to save the rules for every 891*30fdc8d8SChris Lattner // register on the current row on the stack. Encountering the 892*30fdc8d8SChris Lattner // DW_CFA_restore_state instruction means to pop the set of rules off 893*30fdc8d8SChris Lattner // the stack and place them in the current row. (This operation is 894*30fdc8d8SChris Lattner // useful for compilers that move epilogue code into the body of a 895*30fdc8d8SChris Lattner // function.) 896*30fdc8d8SChris Lattner { 897*30fdc8d8SChris Lattner row = row_stack.back(); 898*30fdc8d8SChris Lattner row_stack.pop_back(); 899*30fdc8d8SChris Lattner } 900*30fdc8d8SChris Lattner break; 901*30fdc8d8SChris Lattner 902*30fdc8d8SChris Lattner case DW_CFA_def_cfa : // 0xC (CFA Definition Instruction) 903*30fdc8d8SChris Lattner { 904*30fdc8d8SChris Lattner // Takes two unsigned LEB128 operands representing a register 905*30fdc8d8SChris Lattner // number and a (non-factored) offset. The required action 906*30fdc8d8SChris Lattner // is to define the current CFA rule to use the provided 907*30fdc8d8SChris Lattner // register and offset. 908*30fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 909*30fdc8d8SChris Lattner op_offset = (int32_t)m_cfi_data.GetULEB128(&offset); 910*30fdc8d8SChris Lattner row.SetCFARegister (reg_num); 911*30fdc8d8SChris Lattner row.SetCFAOffset (op_offset); 912*30fdc8d8SChris Lattner } 913*30fdc8d8SChris Lattner break; 914*30fdc8d8SChris Lattner 915*30fdc8d8SChris Lattner case DW_CFA_def_cfa_register : // 0xD (CFA Definition Instruction) 916*30fdc8d8SChris Lattner { 917*30fdc8d8SChris Lattner // takes a single unsigned LEB128 argument representing a register 918*30fdc8d8SChris Lattner // number. The required action is to define the current CFA rule to 919*30fdc8d8SChris Lattner // use the provided register (but to keep the old offset). 920*30fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 921*30fdc8d8SChris Lattner row.SetCFARegister (reg_num); 922*30fdc8d8SChris Lattner } 923*30fdc8d8SChris Lattner break; 924*30fdc8d8SChris Lattner 925*30fdc8d8SChris Lattner case DW_CFA_def_cfa_offset : // 0xE (CFA Definition Instruction) 926*30fdc8d8SChris Lattner { 927*30fdc8d8SChris Lattner // Takes a single unsigned LEB128 operand representing a 928*30fdc8d8SChris Lattner // (non-factored) offset. The required action is to define 929*30fdc8d8SChris Lattner // the current CFA rule to use the provided offset (but 930*30fdc8d8SChris Lattner // to keep the old register). 931*30fdc8d8SChris Lattner op_offset = (int32_t)m_cfi_data.GetULEB128(&offset); 932*30fdc8d8SChris Lattner row.SetCFAOffset (op_offset); 933*30fdc8d8SChris Lattner } 934*30fdc8d8SChris Lattner break; 935*30fdc8d8SChris Lattner 936*30fdc8d8SChris Lattner case DW_CFA_def_cfa_expression : // 0xF (CFA Definition Instruction) 937*30fdc8d8SChris Lattner { 938*30fdc8d8SChris Lattner size_t block_len = (size_t)m_cfi_data.GetULEB128(&offset); 939*30fdc8d8SChris Lattner offset += (uint32_t)block_len; 940*30fdc8d8SChris Lattner } 941*30fdc8d8SChris Lattner break; 942*30fdc8d8SChris Lattner 943*30fdc8d8SChris Lattner case DW_CFA_expression : // 0x10 944*30fdc8d8SChris Lattner { 945*30fdc8d8SChris Lattner // Takes two operands: an unsigned LEB128 value representing 946*30fdc8d8SChris Lattner // a register number, and a DW_FORM_block value representing a DWARF 947*30fdc8d8SChris Lattner // expression. The required action is to change the rule for the 948*30fdc8d8SChris Lattner // register indicated by the register number to be an expression(E) 949*30fdc8d8SChris Lattner // rule where E is the DWARF expression. That is, the DWARF 950*30fdc8d8SChris Lattner // expression computes the address. The value of the CFA is 951*30fdc8d8SChris Lattner // pushed on the DWARF evaluation stack prior to execution of 952*30fdc8d8SChris Lattner // the DWARF expression. 953*30fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 954*30fdc8d8SChris Lattner uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset); 955*30fdc8d8SChris Lattner const uint8_t *block_data = (uint8_t *)m_cfi_data.GetData(&offset, block_len); 956*30fdc8d8SChris Lattner 957*30fdc8d8SChris Lattner reg_location.SetAtDWARFExpression(block_data, block_len); 958*30fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 959*30fdc8d8SChris Lattner } 960*30fdc8d8SChris Lattner break; 961*30fdc8d8SChris Lattner 962*30fdc8d8SChris Lattner case DW_CFA_offset_extended_sf : // 0x11 963*30fdc8d8SChris Lattner { 964*30fdc8d8SChris Lattner // takes two operands: an unsigned LEB128 value representing a 965*30fdc8d8SChris Lattner // register number and a signed LEB128 factored offset. This 966*30fdc8d8SChris Lattner // instruction is identical to DW_CFA_offset_extended except 967*30fdc8d8SChris Lattner //that the second operand is signed and factored. 968*30fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 969*30fdc8d8SChris Lattner op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align; 970*30fdc8d8SChris Lattner reg_location.SetAtCFAPlusOffset(op_offset); 971*30fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 972*30fdc8d8SChris Lattner } 973*30fdc8d8SChris Lattner break; 974*30fdc8d8SChris Lattner 975*30fdc8d8SChris Lattner case DW_CFA_def_cfa_sf : // 0x12 (CFA Definition Instruction) 976*30fdc8d8SChris Lattner { 977*30fdc8d8SChris Lattner // Takes two operands: an unsigned LEB128 value representing 978*30fdc8d8SChris Lattner // a register number and a signed LEB128 factored offset. 979*30fdc8d8SChris Lattner // This instruction is identical to DW_CFA_def_cfa except 980*30fdc8d8SChris Lattner // that the second operand is signed and factored. 981*30fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 982*30fdc8d8SChris Lattner op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align; 983*30fdc8d8SChris Lattner row.SetCFARegister (reg_num); 984*30fdc8d8SChris Lattner row.SetCFAOffset (op_offset); 985*30fdc8d8SChris Lattner } 986*30fdc8d8SChris Lattner break; 987*30fdc8d8SChris Lattner 988*30fdc8d8SChris Lattner case DW_CFA_def_cfa_offset_sf : // 0x13 (CFA Definition Instruction) 989*30fdc8d8SChris Lattner { 990*30fdc8d8SChris Lattner // takes a signed LEB128 operand representing a factored 991*30fdc8d8SChris Lattner // offset. This instruction is identical to DW_CFA_def_cfa_offset 992*30fdc8d8SChris Lattner // except that the operand is signed and factored. 993*30fdc8d8SChris Lattner op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align; 994*30fdc8d8SChris Lattner row.SetCFAOffset (op_offset); 995*30fdc8d8SChris Lattner } 996*30fdc8d8SChris Lattner break; 997*30fdc8d8SChris Lattner 998*30fdc8d8SChris Lattner case DW_CFA_val_expression : // 0x16 999*30fdc8d8SChris Lattner { 1000*30fdc8d8SChris Lattner // takes two operands: an unsigned LEB128 value representing a register 1001*30fdc8d8SChris Lattner // number, and a DW_FORM_block value representing a DWARF expression. 1002*30fdc8d8SChris Lattner // The required action is to change the rule for the register indicated 1003*30fdc8d8SChris Lattner // by the register number to be a val_expression(E) rule where E is the 1004*30fdc8d8SChris Lattner // DWARF expression. That is, the DWARF expression computes the value of 1005*30fdc8d8SChris Lattner // the given register. The value of the CFA is pushed on the DWARF 1006*30fdc8d8SChris Lattner // evaluation stack prior to execution of the DWARF expression. 1007*30fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 1008*30fdc8d8SChris Lattner uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset); 1009*30fdc8d8SChris Lattner const uint8_t* block_data = (uint8_t*)m_cfi_data.GetData(&offset, block_len); 1010*30fdc8d8SChris Lattner //#if defined(__i386__) || defined(__x86_64__) 1011*30fdc8d8SChris Lattner // // The EH frame info for EIP and RIP contains code that looks for traps to 1012*30fdc8d8SChris Lattner // // be a specific type and increments the PC. 1013*30fdc8d8SChris Lattner // // For i386: 1014*30fdc8d8SChris Lattner // // DW_CFA_val_expression where: 1015*30fdc8d8SChris Lattner // // eip = DW_OP_breg6(+28), DW_OP_deref, DW_OP_dup, DW_OP_plus_uconst(0x34), 1016*30fdc8d8SChris Lattner // // DW_OP_deref, DW_OP_swap, DW_OP_plus_uconst(0), DW_OP_deref, 1017*30fdc8d8SChris Lattner // // DW_OP_dup, DW_OP_lit3, DW_OP_ne, DW_OP_swap, DW_OP_lit4, DW_OP_ne, 1018*30fdc8d8SChris Lattner // // DW_OP_and, DW_OP_plus 1019*30fdc8d8SChris Lattner // // This basically does a: 1020*30fdc8d8SChris Lattner // // eip = ucontenxt.mcontext32->gpr.eip; 1021*30fdc8d8SChris Lattner // // if (ucontenxt.mcontext32->exc.trapno != 3 && ucontenxt.mcontext32->exc.trapno != 4) 1022*30fdc8d8SChris Lattner // // eip++; 1023*30fdc8d8SChris Lattner // // 1024*30fdc8d8SChris Lattner // // For x86_64: 1025*30fdc8d8SChris Lattner // // DW_CFA_val_expression where: 1026*30fdc8d8SChris Lattner // // rip = DW_OP_breg3(+48), DW_OP_deref, DW_OP_dup, DW_OP_plus_uconst(0x90), DW_OP_deref, 1027*30fdc8d8SChris Lattner // // DW_OP_swap, DW_OP_plus_uconst(0), DW_OP_deref_size(4), DW_OP_dup, DW_OP_lit3, 1028*30fdc8d8SChris Lattner // // DW_OP_ne, DW_OP_swap, DW_OP_lit4, DW_OP_ne, DW_OP_and, DW_OP_plus 1029*30fdc8d8SChris Lattner // // This basically does a: 1030*30fdc8d8SChris Lattner // // rip = ucontenxt.mcontext64->gpr.rip; 1031*30fdc8d8SChris Lattner // // if (ucontenxt.mcontext64->exc.trapno != 3 && ucontenxt.mcontext64->exc.trapno != 4) 1032*30fdc8d8SChris Lattner // // rip++; 1033*30fdc8d8SChris Lattner // // The trap comparisons and increments are not needed as it hoses up the unwound PC which 1034*30fdc8d8SChris Lattner // // is expected to point at least past the instruction that causes the fault/trap. So we 1035*30fdc8d8SChris Lattner // // take it out by trimming the expression right at the first "DW_OP_swap" opcodes 1036*30fdc8d8SChris Lattner // if (block_data != NULL && thread->GetPCRegNum(Thread::GCC) == reg_num) 1037*30fdc8d8SChris Lattner // { 1038*30fdc8d8SChris Lattner // if (thread->Is64Bit()) 1039*30fdc8d8SChris Lattner // { 1040*30fdc8d8SChris Lattner // if (block_len > 9 && block_data[8] == DW_OP_swap && block_data[9] == DW_OP_plus_uconst) 1041*30fdc8d8SChris Lattner // block_len = 8; 1042*30fdc8d8SChris Lattner // } 1043*30fdc8d8SChris Lattner // else 1044*30fdc8d8SChris Lattner // { 1045*30fdc8d8SChris Lattner // if (block_len > 8 && block_data[7] == DW_OP_swap && block_data[8] == DW_OP_plus_uconst) 1046*30fdc8d8SChris Lattner // block_len = 7; 1047*30fdc8d8SChris Lattner // } 1048*30fdc8d8SChris Lattner // } 1049*30fdc8d8SChris Lattner //#endif 1050*30fdc8d8SChris Lattner reg_location.SetIsDWARFExpression(block_data, block_len); 1051*30fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 1052*30fdc8d8SChris Lattner } 1053*30fdc8d8SChris Lattner break; 1054*30fdc8d8SChris Lattner 1055*30fdc8d8SChris Lattner case DW_CFA_val_offset : // 0x14 1056*30fdc8d8SChris Lattner case DW_CFA_val_offset_sf : // 0x15 1057*30fdc8d8SChris Lattner default: 1058*30fdc8d8SChris Lattner tmp_uval32 = extended_opcode; 1059*30fdc8d8SChris Lattner break; 1060*30fdc8d8SChris Lattner } 1061*30fdc8d8SChris Lattner } 1062*30fdc8d8SChris Lattner } 1063*30fdc8d8SChris Lattner fde->AppendRow(row); 1064*30fdc8d8SChris Lattner } 1065*30fdc8d8SChris Lattner 1066*30fdc8d8SChris Lattner void 1067*30fdc8d8SChris Lattner DWARFCallFrameInfo::ParseAll() 1068*30fdc8d8SChris Lattner { 1069*30fdc8d8SChris Lattner Index(); 1070*30fdc8d8SChris Lattner fde_map_t::iterator pos, end = m_fde_map.end(); 1071*30fdc8d8SChris Lattner for (pos = m_fde_map.begin(); pos != end; ++ pos) 1072*30fdc8d8SChris Lattner { 1073*30fdc8d8SChris Lattner if (pos->second.fde_sp.get() == NULL) 1074*30fdc8d8SChris Lattner pos->second.fde_sp = ParseFDE(pos->second.fde_offset); 1075*30fdc8d8SChris Lattner } 1076*30fdc8d8SChris Lattner } 1077*30fdc8d8SChris Lattner 1078*30fdc8d8SChris Lattner 1079*30fdc8d8SChris Lattner //bool 1080*30fdc8d8SChris Lattner //DWARFCallFrameInfo::UnwindRegisterAtIndex 1081*30fdc8d8SChris Lattner //( 1082*30fdc8d8SChris Lattner // const uint32_t reg_idx, 1083*30fdc8d8SChris Lattner // const Thread* currState, 1084*30fdc8d8SChris Lattner // const DWARFCallFrameInfo::Row* row, 1085*30fdc8d8SChris Lattner // mapped_memory_t * memCache, 1086*30fdc8d8SChris Lattner // Thread* unwindState 1087*30fdc8d8SChris Lattner //) 1088*30fdc8d8SChris Lattner //{ 1089*30fdc8d8SChris Lattner // bool get_reg_success = false; 1090*30fdc8d8SChris Lattner // 1091*30fdc8d8SChris Lattner // const RegLocation* regLocation = row->regs.GetRegisterInfo(reg_idx); 1092*30fdc8d8SChris Lattner // 1093*30fdc8d8SChris Lattner // // On some systems, we may not get unwind info for the program counter, 1094*30fdc8d8SChris Lattner // // but the return address register can be used to get that information. 1095*30fdc8d8SChris Lattner // if (reg_idx == currState->GetPCRegNum(Thread::Index)) 1096*30fdc8d8SChris Lattner // { 1097*30fdc8d8SChris Lattner // const RegLocation* returnAddrRegLocation = row->regs.GetRegisterInfo(currState->GetRARegNum(Thread::Index)); 1098*30fdc8d8SChris Lattner // if (regLocation == NULL) 1099*30fdc8d8SChris Lattner // { 1100*30fdc8d8SChris Lattner // // We have nothing to the program counter, so lets see if this 1101*30fdc8d8SChris Lattner // // thread state has a return address (link register) that can 1102*30fdc8d8SChris Lattner // // help us track down the previous PC 1103*30fdc8d8SChris Lattner // regLocation = returnAddrRegLocation; 1104*30fdc8d8SChris Lattner // } 1105*30fdc8d8SChris Lattner // else if (regLocation->type == RegLocation::unspecified) 1106*30fdc8d8SChris Lattner // { 1107*30fdc8d8SChris Lattner // // We did have a location that didn't specify a value for unwinding 1108*30fdc8d8SChris Lattner // // the PC, so if there is a info for the return return address 1109*30fdc8d8SChris Lattner // // register (link register) lets use that 1110*30fdc8d8SChris Lattner // if (returnAddrRegLocation) 1111*30fdc8d8SChris Lattner // regLocation = returnAddrRegLocation; 1112*30fdc8d8SChris Lattner // } 1113*30fdc8d8SChris Lattner // } 1114*30fdc8d8SChris Lattner // 1115*30fdc8d8SChris Lattner // if (regLocation) 1116*30fdc8d8SChris Lattner // { 1117*30fdc8d8SChris Lattner // mach_vm_address_t unwoundRegValue = INVALID_VMADDR; 1118*30fdc8d8SChris Lattner // switch (regLocation->type) 1119*30fdc8d8SChris Lattner // { 1120*30fdc8d8SChris Lattner // case RegLocation::undefined: 1121*30fdc8d8SChris Lattner // // Register is not available, mark it as invalid 1122*30fdc8d8SChris Lattner // unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false); 1123*30fdc8d8SChris Lattner // return true; 1124*30fdc8d8SChris Lattner // 1125*30fdc8d8SChris Lattner // case RegLocation::unspecified: 1126*30fdc8d8SChris Lattner // // Nothing to do if it is the same 1127*30fdc8d8SChris Lattner // return true; 1128*30fdc8d8SChris Lattner // 1129*30fdc8d8SChris Lattner // case RegLocation::same: 1130*30fdc8d8SChris Lattner // // Nothing to do if it is the same 1131*30fdc8d8SChris Lattner // return true; 1132*30fdc8d8SChris Lattner // 1133*30fdc8d8SChris Lattner // case RegLocation::atFPPlusOffset: 1134*30fdc8d8SChris Lattner // case RegLocation::isFPPlusOffset: 1135*30fdc8d8SChris Lattner // { 1136*30fdc8d8SChris Lattner // uint64_t unwindAddress = currState->GetRegisterValue(row->cfa_register, Thread::GCC, INVALID_VMADDR, &get_reg_success); 1137*30fdc8d8SChris Lattner // 1138*30fdc8d8SChris Lattner // if (get_reg_success) 1139*30fdc8d8SChris Lattner // { 1140*30fdc8d8SChris Lattner // unwindAddress += row->cfa_offset + regLocation->location.offset; 1141*30fdc8d8SChris Lattner // 1142*30fdc8d8SChris Lattner // if (regLocation->type == RegLocation::isFPPlusOffset) 1143*30fdc8d8SChris Lattner // { 1144*30fdc8d8SChris Lattner // unwindState->SetRegisterValue(reg_idx, Thread::Index, unwindAddress); 1145*30fdc8d8SChris Lattner // return true; 1146*30fdc8d8SChris Lattner // } 1147*30fdc8d8SChris Lattner // else 1148*30fdc8d8SChris Lattner // { 1149*30fdc8d8SChris Lattner // kern_return_t err = mapped_memory_read_pointer(memCache, unwindAddress, &unwoundRegValue); 1150*30fdc8d8SChris Lattner // if (err != KERN_SUCCESS) 1151*30fdc8d8SChris Lattner // { 1152*30fdc8d8SChris Lattner // unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false); 1153*30fdc8d8SChris Lattner // return false; 1154*30fdc8d8SChris Lattner // } 1155*30fdc8d8SChris Lattner // unwindState->SetRegisterValue(reg_idx, Thread::Index, unwoundRegValue); 1156*30fdc8d8SChris Lattner // return true; 1157*30fdc8d8SChris Lattner // } 1158*30fdc8d8SChris Lattner // } 1159*30fdc8d8SChris Lattner // else 1160*30fdc8d8SChris Lattner // { 1161*30fdc8d8SChris Lattner // unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false); 1162*30fdc8d8SChris Lattner // } 1163*30fdc8d8SChris Lattner // return false; 1164*30fdc8d8SChris Lattner // } 1165*30fdc8d8SChris Lattner // break; 1166*30fdc8d8SChris Lattner // 1167*30fdc8d8SChris Lattner // case RegLocation::atDWARFExpression: 1168*30fdc8d8SChris Lattner // case RegLocation::isDWARFExpression: 1169*30fdc8d8SChris Lattner // { 1170*30fdc8d8SChris Lattner // bool swap = false; 1171*30fdc8d8SChris Lattner // DWARFExpressionBaton baton = { currState, memCache, swap }; 1172*30fdc8d8SChris Lattner // uint64_t expr_result = 0; 1173*30fdc8d8SChris Lattner // CSBinaryDataRef opcodes(regLocation->location.expr.opcodes, regLocation->location.expr.length, swap); 1174*30fdc8d8SChris Lattner // opcodes.SetPointerSize(currState->Is64Bit() ? 8 : 4); 1175*30fdc8d8SChris Lattner // const char * expr_err = CSDWARFExpression::Evaluate(DWARFExpressionReadMemoryDCScriptInterpreter::Type, 1176*30fdc8d8SChris Lattner // DWARFExpressionReadRegisterDCScriptInterpreter::Type, 1177*30fdc8d8SChris Lattner // &baton, 1178*30fdc8d8SChris Lattner // opcodes, 1179*30fdc8d8SChris Lattner // 0, 1180*30fdc8d8SChris Lattner // regLocation->location.expr.length, 1181*30fdc8d8SChris Lattner // NULL, 1182*30fdc8d8SChris Lattner // expr_result); 1183*30fdc8d8SChris Lattner // if (expr_err == NULL) 1184*30fdc8d8SChris Lattner // { 1185*30fdc8d8SChris Lattner // // SUCCESS! 1186*30fdc8d8SChris Lattner // if (regLocation->type == RegLocation::isDWARFExpression) 1187*30fdc8d8SChris Lattner // { 1188*30fdc8d8SChris Lattner // unwindState->SetRegisterValue(reg_idx, Thread::Index, expr_result); 1189*30fdc8d8SChris Lattner // return true; 1190*30fdc8d8SChris Lattner // } 1191*30fdc8d8SChris Lattner // else 1192*30fdc8d8SChris Lattner // { 1193*30fdc8d8SChris Lattner // kern_return_t err = mapped_memory_read_pointer(memCache, expr_result, &unwoundRegValue); 1194*30fdc8d8SChris Lattner // if (err != KERN_SUCCESS) 1195*30fdc8d8SChris Lattner // { 1196*30fdc8d8SChris Lattner // unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false); 1197*30fdc8d8SChris Lattner // return false; 1198*30fdc8d8SChris Lattner // } 1199*30fdc8d8SChris Lattner // unwindState->SetRegisterValue(reg_idx, Thread::Index, unwoundRegValue); 1200*30fdc8d8SChris Lattner // return true; 1201*30fdc8d8SChris Lattner // } 1202*30fdc8d8SChris Lattner // } 1203*30fdc8d8SChris Lattner // else 1204*30fdc8d8SChris Lattner // { 1205*30fdc8d8SChris Lattner // // FAIL 1206*30fdc8d8SChris Lattner // unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false); 1207*30fdc8d8SChris Lattner // } 1208*30fdc8d8SChris Lattner // return false; 1209*30fdc8d8SChris Lattner // } 1210*30fdc8d8SChris Lattner // break; 1211*30fdc8d8SChris Lattner // 1212*30fdc8d8SChris Lattner // 1213*30fdc8d8SChris Lattner // case RegLocation::inRegister: 1214*30fdc8d8SChris Lattner // // The value is in another register. 1215*30fdc8d8SChris Lattner // unwoundRegValue = currState->GetRegisterValue(regLocation->location.reg, Thread::GCC, 0, &get_reg_success); 1216*30fdc8d8SChris Lattner // if (get_reg_success) 1217*30fdc8d8SChris Lattner // { 1218*30fdc8d8SChris Lattner // unwindState->SetRegisterValue(reg_idx, Thread::Index, unwoundRegValue); 1219*30fdc8d8SChris Lattner // return true; 1220*30fdc8d8SChris Lattner // } 1221*30fdc8d8SChris Lattner // return false; 1222*30fdc8d8SChris Lattner // 1223*30fdc8d8SChris Lattner // default: 1224*30fdc8d8SChris Lattner // break; 1225*30fdc8d8SChris Lattner // } 1226*30fdc8d8SChris Lattner // } 1227*30fdc8d8SChris Lattner // 1228*30fdc8d8SChris Lattner // if (reg_idx == currState->GetSPRegNum(Thread::Index)) 1229*30fdc8d8SChris Lattner // { 1230*30fdc8d8SChris Lattner // uint64_t cfa = currState->GetRegisterValue(row->cfa_register, Thread::GCC, 0, &get_reg_success); 1231*30fdc8d8SChris Lattner // if (get_reg_success) 1232*30fdc8d8SChris Lattner // { 1233*30fdc8d8SChris Lattner // return unwindState->SetSP(cfa + row->cfa_offset); 1234*30fdc8d8SChris Lattner // } 1235*30fdc8d8SChris Lattner // else 1236*30fdc8d8SChris Lattner // { 1237*30fdc8d8SChris Lattner // unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false); 1238*30fdc8d8SChris Lattner // return false; 1239*30fdc8d8SChris Lattner // } 1240*30fdc8d8SChris Lattner // } 1241*30fdc8d8SChris Lattner // 1242*30fdc8d8SChris Lattner // return false; 1243*30fdc8d8SChris Lattner //} 1244*30fdc8d8SChris Lattner 1245*30fdc8d8SChris Lattner void 1246*30fdc8d8SChris Lattner DWARFCallFrameInfo::Dump(Stream *s, Thread *thread) const 1247*30fdc8d8SChris Lattner { 1248*30fdc8d8SChris Lattner s->Indent(); 1249*30fdc8d8SChris Lattner s->Printf("DWARFCallFrameInfo for "); 1250*30fdc8d8SChris Lattner *s << m_objfile->GetFileSpec(); 1251*30fdc8d8SChris Lattner if (m_flags.IsSet(eFlagParsedIndex)) 1252*30fdc8d8SChris Lattner { 1253*30fdc8d8SChris Lattner s->Printf(" (CIE[%zu], FDE[%zu])\n", m_cie_map.size(), m_fde_map.size()); 1254*30fdc8d8SChris Lattner s->IndentMore(); 1255*30fdc8d8SChris Lattner cie_map_t::const_iterator cie_pos, cie_end = m_cie_map.end(); 1256*30fdc8d8SChris Lattner const ArchSpec *arch = &m_objfile->GetModule()->GetArchitecture(); 1257*30fdc8d8SChris Lattner 1258*30fdc8d8SChris Lattner for (cie_pos = m_cie_map.begin(); cie_pos != cie_end; ++ cie_pos) 1259*30fdc8d8SChris Lattner { 1260*30fdc8d8SChris Lattner if (cie_pos->second.get() == NULL) 1261*30fdc8d8SChris Lattner { 1262*30fdc8d8SChris Lattner s->Indent(); 1263*30fdc8d8SChris Lattner s->Printf("CIE{0x%8.8x} - unparsed\n", cie_pos->first); 1264*30fdc8d8SChris Lattner } 1265*30fdc8d8SChris Lattner else 1266*30fdc8d8SChris Lattner { 1267*30fdc8d8SChris Lattner cie_pos->second->Dump(s, thread, arch, m_reg_kind); 1268*30fdc8d8SChris Lattner } 1269*30fdc8d8SChris Lattner } 1270*30fdc8d8SChris Lattner 1271*30fdc8d8SChris Lattner fde_map_t::const_iterator fde_pos, fde_end = m_fde_map.end(); 1272*30fdc8d8SChris Lattner for (fde_pos = m_fde_map.begin(); fde_pos != fde_end; ++ fde_pos) 1273*30fdc8d8SChris Lattner { 1274*30fdc8d8SChris Lattner if (fde_pos->second.fde_sp.get() == NULL) 1275*30fdc8d8SChris Lattner { 1276*30fdc8d8SChris Lattner s->Indent(); 1277*30fdc8d8SChris Lattner s->Printf("FDE{0x%8.8x} - unparsed\n", fde_pos->second.fde_offset); 1278*30fdc8d8SChris Lattner } 1279*30fdc8d8SChris Lattner else 1280*30fdc8d8SChris Lattner { 1281*30fdc8d8SChris Lattner fde_pos->second.fde_sp->Dump(s, *this, thread); 1282*30fdc8d8SChris Lattner } 1283*30fdc8d8SChris Lattner } 1284*30fdc8d8SChris Lattner s->IndentLess(); 1285*30fdc8d8SChris Lattner } 1286*30fdc8d8SChris Lattner else 1287*30fdc8d8SChris Lattner { 1288*30fdc8d8SChris Lattner s->PutCString(" (not indexed yet)\n"); 1289*30fdc8d8SChris Lattner } 1290*30fdc8d8SChris Lattner } 1291*30fdc8d8SChris Lattner 1292*30fdc8d8SChris Lattner 1293*30fdc8d8SChris Lattner //uint32_t 1294*30fdc8d8SChris Lattner //DWARFCallFrameInfo::UnwindThreadState(const Thread* currState, mapped_memory_t *memCache, bool is_first_frame, Thread* unwindState) 1295*30fdc8d8SChris Lattner //{ 1296*30fdc8d8SChris Lattner // if (currState == NULL || unwindState == NULL) 1297*30fdc8d8SChris Lattner // return 0; 1298*30fdc8d8SChris Lattner // 1299*30fdc8d8SChris Lattner // *unwindState = *currState; 1300*30fdc8d8SChris Lattner // uint32_t numRegisterUnwound = 0; 1301*30fdc8d8SChris Lattner // uint64_t currPC = currState->GetPC(INVALID_VMADDR); 1302*30fdc8d8SChris Lattner // 1303*30fdc8d8SChris Lattner // if (currPC != INVALID_VMADDR) 1304*30fdc8d8SChris Lattner // { 1305*30fdc8d8SChris Lattner // // If this is not the first frame, we care about the previous instruction 1306*30fdc8d8SChris Lattner // // since it will be at the instruction following the instruction that 1307*30fdc8d8SChris Lattner // // made the function call. 1308*30fdc8d8SChris Lattner // uint64_t unwindPC = currPC; 1309*30fdc8d8SChris Lattner // if (unwindPC > 0 && !is_first_frame) 1310*30fdc8d8SChris Lattner // --unwindPC; 1311*30fdc8d8SChris Lattner // 1312*30fdc8d8SChris Lattner //#if defined(__i386__) || defined(__x86_64__) 1313*30fdc8d8SChris Lattner // // Only on i386 do we have __IMPORT segments that contain trampolines 1314*30fdc8d8SChris Lattner // if (!currState->Is64Bit() && ImportRangesContainsAddress(unwindPC)) 1315*30fdc8d8SChris Lattner // { 1316*30fdc8d8SChris Lattner // uint64_t curr_sp = currState->GetSP(INVALID_VMADDR); 1317*30fdc8d8SChris Lattner // mach_vm_address_t pc = INVALID_VMADDR; 1318*30fdc8d8SChris Lattner // unwindState->SetSP(curr_sp + 4); 1319*30fdc8d8SChris Lattner // kern_return_t err = mapped_memory_read_pointer(memCache, curr_sp, &pc); 1320*30fdc8d8SChris Lattner // if (err == KERN_SUCCESS) 1321*30fdc8d8SChris Lattner // { 1322*30fdc8d8SChris Lattner // unwindState->SetPC(pc); 1323*30fdc8d8SChris Lattner // return 2; 1324*30fdc8d8SChris Lattner // } 1325*30fdc8d8SChris Lattner // } 1326*30fdc8d8SChris Lattner //#endif 1327*30fdc8d8SChris Lattner // FDE *fde = FindFDE(unwindPC); 1328*30fdc8d8SChris Lattner // if (fde) 1329*30fdc8d8SChris Lattner // { 1330*30fdc8d8SChris Lattner // FindRowUserData rowUserData (currState, unwindPC); 1331*30fdc8d8SChris Lattner // ParseInstructions (currState, fde, FindRowForAddress, &rowUserData); 1332*30fdc8d8SChris Lattner // 1333*30fdc8d8SChris Lattner // const uint32_t numRegs = currState->NumRegisters(); 1334*30fdc8d8SChris Lattner // for (uint32_t regNum = 0; regNum < numRegs; regNum++) 1335*30fdc8d8SChris Lattner // { 1336*30fdc8d8SChris Lattner // if (UnwindRegisterAtIndex(regNum, currState, &rowUserData.state, memCache, unwindState)) 1337*30fdc8d8SChris Lattner // numRegisterUnwound++; 1338*30fdc8d8SChris Lattner // } 1339*30fdc8d8SChris Lattner // } 1340*30fdc8d8SChris Lattner // } 1341*30fdc8d8SChris Lattner // return numRegisterUnwound; 1342*30fdc8d8SChris Lattner //} 1343*30fdc8d8SChris Lattner 1344*30fdc8d8SChris Lattner 1345