130fdc8d8SChris Lattner //===-- DWARFCallFrameInfo.cpp ----------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner 1130fdc8d8SChris Lattner // C Includes 1230fdc8d8SChris Lattner // C++ Includes 1330fdc8d8SChris Lattner #include <list> 1430fdc8d8SChris Lattner 1530fdc8d8SChris Lattner // Other libraries and framework includes 1630fdc8d8SChris Lattner // Project includes 1730fdc8d8SChris Lattner #include "lldb/Symbol/DWARFCallFrameInfo.h" 1830fdc8d8SChris Lattner #include "lldb/Core/ArchSpec.h" 1930fdc8d8SChris Lattner #include "lldb/Core/Module.h" 2030fdc8d8SChris Lattner #include "lldb/Symbol/ObjectFile.h" 2130fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h" 2230fdc8d8SChris Lattner #include "lldb/Core/Section.h" 2330fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 2430fdc8d8SChris Lattner 2530fdc8d8SChris Lattner using namespace lldb; 2630fdc8d8SChris Lattner using namespace lldb_private; 2730fdc8d8SChris Lattner 2830fdc8d8SChris Lattner static void 2930fdc8d8SChris Lattner DumpRegisterName (Stream *s, Thread *thread, const ArchSpec *arch, uint32_t reg_kind, uint32_t reg_num) 3030fdc8d8SChris Lattner { 3130fdc8d8SChris Lattner const char *reg_name = NULL; 3230fdc8d8SChris Lattner RegisterContext *reg_ctx = NULL; 3330fdc8d8SChris Lattner if (thread) 3430fdc8d8SChris Lattner { 3530fdc8d8SChris Lattner reg_ctx = thread->GetRegisterContext(); 3630fdc8d8SChris Lattner if (reg_ctx) 3730fdc8d8SChris Lattner reg_name = reg_ctx->GetRegisterName (reg_ctx->ConvertRegisterKindToRegisterNumber (reg_kind, reg_num)); 3830fdc8d8SChris Lattner } 3930fdc8d8SChris Lattner 4030fdc8d8SChris Lattner if (reg_name == NULL && arch != NULL) 4130fdc8d8SChris Lattner { 4230fdc8d8SChris Lattner switch (reg_kind) 4330fdc8d8SChris Lattner { 4430fdc8d8SChris Lattner case eRegisterKindDWARF: reg_name = arch->GetRegisterName(reg_num, eRegisterKindDWARF); break; 4530fdc8d8SChris Lattner case eRegisterKindGCC: reg_name = arch->GetRegisterName(reg_num, eRegisterKindGCC); break; 4630fdc8d8SChris Lattner default: 4730fdc8d8SChris Lattner break; 4830fdc8d8SChris Lattner } 4930fdc8d8SChris Lattner } 5030fdc8d8SChris Lattner 5130fdc8d8SChris Lattner if (reg_name) 5230fdc8d8SChris Lattner s->PutCString(reg_name); 5330fdc8d8SChris Lattner else 5430fdc8d8SChris Lattner { 5530fdc8d8SChris Lattner const char *reg_kind_name = NULL; 5630fdc8d8SChris Lattner switch (reg_kind) 5730fdc8d8SChris Lattner { 5830fdc8d8SChris Lattner case eRegisterKindDWARF: reg_kind_name = "dwarf-reg"; break; 5930fdc8d8SChris Lattner case eRegisterKindGCC: reg_kind_name = "compiler-reg"; break; 6030fdc8d8SChris Lattner case eRegisterKindGeneric: reg_kind_name = "generic-reg"; break; 6130fdc8d8SChris Lattner default: 6230fdc8d8SChris Lattner break; 6330fdc8d8SChris Lattner } 6430fdc8d8SChris Lattner if (reg_kind_name) 6530fdc8d8SChris Lattner s->Printf("%s(%u)", reg_kind_name, reg_num); 6630fdc8d8SChris Lattner else 6730fdc8d8SChris Lattner s->Printf("reg(%d.%u)", reg_kind, reg_num); 6830fdc8d8SChris Lattner } 6930fdc8d8SChris Lattner } 7030fdc8d8SChris Lattner 7130fdc8d8SChris Lattner 7230fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::RegisterLocation 7330fdc8d8SChris Lattner 7430fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::RegisterLocation() : 7530fdc8d8SChris Lattner m_type(isSame) 7630fdc8d8SChris Lattner { 7730fdc8d8SChris Lattner } 7830fdc8d8SChris Lattner 7930fdc8d8SChris Lattner 8030fdc8d8SChris Lattner bool 8130fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::operator == (const DWARFCallFrameInfo::RegisterLocation& rhs) const 8230fdc8d8SChris Lattner { 8330fdc8d8SChris Lattner if (m_type != rhs.m_type) 8430fdc8d8SChris Lattner return false; 8530fdc8d8SChris Lattner switch (m_type) 8630fdc8d8SChris Lattner { 8730fdc8d8SChris Lattner case unspecified: 8830fdc8d8SChris Lattner case isUndefined: 8930fdc8d8SChris Lattner case isSame: 9030fdc8d8SChris Lattner return true; 9130fdc8d8SChris Lattner 9230fdc8d8SChris Lattner case atCFAPlusOffset: 9330fdc8d8SChris Lattner return m_location.offset == rhs.m_location.offset; 9430fdc8d8SChris Lattner 9530fdc8d8SChris Lattner case isCFAPlusOffset: 9630fdc8d8SChris Lattner return m_location.offset == rhs.m_location.offset; 9730fdc8d8SChris Lattner 9830fdc8d8SChris Lattner case inOtherRegister: 9930fdc8d8SChris Lattner return m_location.reg_num == rhs.m_location.reg_num; 10030fdc8d8SChris Lattner 10130fdc8d8SChris Lattner default: 10230fdc8d8SChris Lattner break; 10330fdc8d8SChris Lattner } 10430fdc8d8SChris Lattner return false; 10530fdc8d8SChris Lattner } 10630fdc8d8SChris Lattner 10730fdc8d8SChris Lattner void 10830fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetUnspecified() 10930fdc8d8SChris Lattner { 11030fdc8d8SChris Lattner m_type = unspecified; 11130fdc8d8SChris Lattner } 11230fdc8d8SChris Lattner 11330fdc8d8SChris Lattner void 11430fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetUndefined() 11530fdc8d8SChris Lattner { 11630fdc8d8SChris Lattner m_type = isUndefined; 11730fdc8d8SChris Lattner } 11830fdc8d8SChris Lattner 11930fdc8d8SChris Lattner void 12030fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetSame() 12130fdc8d8SChris Lattner { 12230fdc8d8SChris Lattner m_type = isSame; 12330fdc8d8SChris Lattner } 12430fdc8d8SChris Lattner 12530fdc8d8SChris Lattner void 12630fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetAtCFAPlusOffset(int64_t offset) 12730fdc8d8SChris Lattner { 12830fdc8d8SChris Lattner m_type = atCFAPlusOffset; 12930fdc8d8SChris Lattner m_location.offset = offset; 13030fdc8d8SChris Lattner } 13130fdc8d8SChris Lattner 13230fdc8d8SChris Lattner void 13330fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetIsCFAPlusOffset(int64_t offset) 13430fdc8d8SChris Lattner { 13530fdc8d8SChris Lattner m_type = isCFAPlusOffset; 13630fdc8d8SChris Lattner m_location.offset = offset; 13730fdc8d8SChris Lattner } 13830fdc8d8SChris Lattner 13930fdc8d8SChris Lattner void 14030fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetInRegister (uint32_t reg_num) 14130fdc8d8SChris Lattner { 14230fdc8d8SChris Lattner m_type = inOtherRegister; 14330fdc8d8SChris Lattner m_location.reg_num = reg_num; 14430fdc8d8SChris Lattner } 14530fdc8d8SChris Lattner 14630fdc8d8SChris Lattner void 14730fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetAtDWARFExpression(const uint8_t *opcodes, uint32_t len) 14830fdc8d8SChris Lattner { 14930fdc8d8SChris Lattner m_type = atDWARFExpression; 15030fdc8d8SChris Lattner m_location.expr.opcodes = opcodes; 15130fdc8d8SChris Lattner m_location.expr.length = len; 15230fdc8d8SChris Lattner } 15330fdc8d8SChris Lattner 15430fdc8d8SChris Lattner void 15530fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len) 15630fdc8d8SChris Lattner { 15730fdc8d8SChris Lattner m_type = isDWARFExpression; 15830fdc8d8SChris Lattner m_location.expr.opcodes = opcodes; 15930fdc8d8SChris Lattner m_location.expr.length = len; 16030fdc8d8SChris Lattner } 16130fdc8d8SChris Lattner 16230fdc8d8SChris Lattner void 16330fdc8d8SChris Lattner DWARFCallFrameInfo::RegisterLocation::Dump(Stream *s, const DWARFCallFrameInfo &cfi, Thread *thread, const Row *row, uint32_t reg_num) const 16430fdc8d8SChris Lattner { 16530fdc8d8SChris Lattner const ArchSpec *arch = cfi.GetArchitecture(); 16630fdc8d8SChris Lattner const uint32_t reg_kind = cfi.GetRegisterKind(); 16730fdc8d8SChris Lattner 16830fdc8d8SChris Lattner DumpRegisterName (s, thread, arch, reg_kind, reg_num); 16930fdc8d8SChris Lattner s->PutChar('='); 17030fdc8d8SChris Lattner 17130fdc8d8SChris Lattner switch (m_type) 17230fdc8d8SChris Lattner { 17330fdc8d8SChris Lattner case unspecified: 17430fdc8d8SChris Lattner s->PutChar('?'); 17530fdc8d8SChris Lattner break; 17630fdc8d8SChris Lattner 17730fdc8d8SChris Lattner case isUndefined: 17830fdc8d8SChris Lattner s->PutCString("undefined"); 17930fdc8d8SChris Lattner break; 18030fdc8d8SChris Lattner 18130fdc8d8SChris Lattner case isSame: 18230fdc8d8SChris Lattner s->PutCString("same"); 18330fdc8d8SChris Lattner break; 18430fdc8d8SChris Lattner 18530fdc8d8SChris Lattner case atCFAPlusOffset: 18630fdc8d8SChris Lattner s->PutChar('['); 18730fdc8d8SChris Lattner // Fall through to isCFAPlusOffset... 18830fdc8d8SChris Lattner case isCFAPlusOffset: 18930fdc8d8SChris Lattner { 19030fdc8d8SChris Lattner DumpRegisterName (s, thread, arch, reg_kind, row->GetCFARegister()); 19130fdc8d8SChris Lattner int32_t offset = row->GetCFAOffset() + m_location.offset; 19230fdc8d8SChris Lattner if (offset != 0) 19330fdc8d8SChris Lattner s->Printf("%-+d", offset); 19430fdc8d8SChris Lattner if (m_type == atCFAPlusOffset) 19530fdc8d8SChris Lattner s->PutChar(']'); 19630fdc8d8SChris Lattner } 19730fdc8d8SChris Lattner break; 19830fdc8d8SChris Lattner 19930fdc8d8SChris Lattner case inOtherRegister: 20030fdc8d8SChris Lattner DumpRegisterName (s, thread, arch, reg_kind, m_location.reg_num); 20130fdc8d8SChris Lattner break; 20230fdc8d8SChris Lattner 20330fdc8d8SChris Lattner case atDWARFExpression: 20430fdc8d8SChris Lattner s->PutCString("[EXPR] "); 20530fdc8d8SChris Lattner break; 20630fdc8d8SChris Lattner 20730fdc8d8SChris Lattner case isDWARFExpression: 20830fdc8d8SChris Lattner s->PutCString("EXPR "); 20930fdc8d8SChris Lattner break; 21030fdc8d8SChris Lattner } 21130fdc8d8SChris Lattner } 21230fdc8d8SChris Lattner 21330fdc8d8SChris Lattner 21430fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::Row 21530fdc8d8SChris Lattner 21630fdc8d8SChris Lattner DWARFCallFrameInfo::Row::Row() : 21730fdc8d8SChris Lattner m_offset(0), 21830fdc8d8SChris Lattner m_cfa_reg_num(0), 21930fdc8d8SChris Lattner m_cfa_offset(0), 22030fdc8d8SChris Lattner m_register_locations() 22130fdc8d8SChris Lattner { 22230fdc8d8SChris Lattner } 22330fdc8d8SChris Lattner 22430fdc8d8SChris Lattner DWARFCallFrameInfo::Row::~Row() 22530fdc8d8SChris Lattner { 22630fdc8d8SChris Lattner } 22730fdc8d8SChris Lattner 22830fdc8d8SChris Lattner void 22930fdc8d8SChris Lattner DWARFCallFrameInfo::Row::Clear() 23030fdc8d8SChris Lattner { 23130fdc8d8SChris Lattner m_register_locations.clear(); 23230fdc8d8SChris Lattner } 23330fdc8d8SChris Lattner bool 23430fdc8d8SChris Lattner DWARFCallFrameInfo::Row::GetRegisterInfo (uint32_t reg_num, DWARFCallFrameInfo::RegisterLocation& register_location) const 23530fdc8d8SChris Lattner { 23630fdc8d8SChris Lattner collection::const_iterator pos = m_register_locations.find(reg_num); 23730fdc8d8SChris Lattner if (pos != m_register_locations.end()) 23830fdc8d8SChris Lattner { 23930fdc8d8SChris Lattner register_location = pos->second; 24030fdc8d8SChris Lattner return true; 24130fdc8d8SChris Lattner } 24230fdc8d8SChris Lattner return false; 24330fdc8d8SChris Lattner } 24430fdc8d8SChris Lattner 24530fdc8d8SChris Lattner void 24630fdc8d8SChris Lattner DWARFCallFrameInfo::Row::SetRegisterInfo (uint32_t reg_num, const RegisterLocation& register_location) 24730fdc8d8SChris Lattner { 24830fdc8d8SChris Lattner m_register_locations[reg_num] = register_location; 24930fdc8d8SChris Lattner } 25030fdc8d8SChris Lattner 25130fdc8d8SChris Lattner 25230fdc8d8SChris Lattner void 25330fdc8d8SChris Lattner DWARFCallFrameInfo::Row::Dump(Stream* s, const DWARFCallFrameInfo &cfi, Thread *thread, lldb::addr_t base_addr) const 25430fdc8d8SChris Lattner { 25530fdc8d8SChris Lattner const ArchSpec *arch = cfi.GetArchitecture(); 25630fdc8d8SChris Lattner const uint32_t reg_kind = cfi.GetRegisterKind(); 25730fdc8d8SChris Lattner collection::const_iterator pos, end = m_register_locations.end(); 25830fdc8d8SChris Lattner s->Indent(); 25930fdc8d8SChris Lattner s->Printf("0x%16.16llx: CFA=", m_offset + base_addr); 26030fdc8d8SChris Lattner DumpRegisterName(s, thread, arch, reg_kind, m_cfa_reg_num); 26130fdc8d8SChris Lattner if (m_cfa_offset != 0) 26230fdc8d8SChris Lattner s->Printf("%-+lld", m_cfa_offset); 26330fdc8d8SChris Lattner 26430fdc8d8SChris Lattner for (pos = m_register_locations.begin(); pos != end; ++pos) 26530fdc8d8SChris Lattner { 26630fdc8d8SChris Lattner s->PutChar(' '); 26730fdc8d8SChris Lattner pos->second.Dump(s, cfi, thread, this, pos->first); 26830fdc8d8SChris Lattner } 26930fdc8d8SChris Lattner s->EOL(); 27030fdc8d8SChris Lattner } 27130fdc8d8SChris Lattner 27230fdc8d8SChris Lattner 27330fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::FDE 27430fdc8d8SChris Lattner 27530fdc8d8SChris Lattner 27630fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::FDE (dw_offset_t offset, const AddressRange &range) : 27730fdc8d8SChris Lattner m_fde_offset (offset), 27830fdc8d8SChris Lattner m_range (range), 27930fdc8d8SChris Lattner m_row_list () 28030fdc8d8SChris Lattner { 28130fdc8d8SChris Lattner } 28230fdc8d8SChris Lattner 28330fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::~FDE() 28430fdc8d8SChris Lattner { 28530fdc8d8SChris Lattner } 28630fdc8d8SChris Lattner 28730fdc8d8SChris Lattner void 28830fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::AppendRow (const Row &row) 28930fdc8d8SChris Lattner { 29030fdc8d8SChris Lattner if (m_row_list.empty() || m_row_list.back().GetOffset() != row.GetOffset()) 29130fdc8d8SChris Lattner m_row_list.push_back(row); 29230fdc8d8SChris Lattner else 29330fdc8d8SChris Lattner m_row_list.back() = row; 29430fdc8d8SChris Lattner } 29530fdc8d8SChris Lattner 29630fdc8d8SChris Lattner void 29730fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::Dump (Stream *s, const DWARFCallFrameInfo &cfi, Thread* thread) const 29830fdc8d8SChris Lattner { 29930fdc8d8SChris Lattner s->Indent(); 30030fdc8d8SChris Lattner s->Printf("FDE{0x%8.8x} ", m_fde_offset); 30130fdc8d8SChris Lattner m_range.Dump(s, NULL, Address::DumpStyleFileAddress); 30230fdc8d8SChris Lattner lldb::addr_t fde_base_addr = m_range.GetBaseAddress().GetFileAddress(); 30330fdc8d8SChris Lattner s->EOL(); 30430fdc8d8SChris Lattner s->IndentMore(); 30530fdc8d8SChris Lattner collection::const_iterator pos, end = m_row_list.end(); 30630fdc8d8SChris Lattner for (pos = m_row_list.begin(); pos != end; ++pos) 30730fdc8d8SChris Lattner { 30830fdc8d8SChris Lattner pos->Dump(s, cfi, thread, fde_base_addr); 30930fdc8d8SChris Lattner } 31030fdc8d8SChris Lattner s->IndentLess(); 31130fdc8d8SChris Lattner } 31230fdc8d8SChris Lattner 31330fdc8d8SChris Lattner const AddressRange & 31430fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::GetAddressRange() const 31530fdc8d8SChris Lattner { 31630fdc8d8SChris Lattner return m_range; 31730fdc8d8SChris Lattner } 31830fdc8d8SChris Lattner 31930fdc8d8SChris Lattner bool 32030fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::IsValidRowIndex (uint32_t idx) const 32130fdc8d8SChris Lattner { 32230fdc8d8SChris Lattner return idx < m_row_list.size(); 32330fdc8d8SChris Lattner } 32430fdc8d8SChris Lattner 32530fdc8d8SChris Lattner const DWARFCallFrameInfo::Row& 32630fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::GetRowAtIndex (uint32_t idx) 32730fdc8d8SChris Lattner { 32830fdc8d8SChris Lattner // You must call IsValidRowIndex(idx) first before calling this!!! 32930fdc8d8SChris Lattner return m_row_list[idx]; 33030fdc8d8SChris Lattner } 33130fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::FDEInfo 33230fdc8d8SChris Lattner 33330fdc8d8SChris Lattner DWARFCallFrameInfo::FDEInfo::FDEInfo () : 33430fdc8d8SChris Lattner fde_offset (0), 33530fdc8d8SChris Lattner fde_sp() 33630fdc8d8SChris Lattner { 33730fdc8d8SChris Lattner } 33830fdc8d8SChris Lattner 33930fdc8d8SChris Lattner DWARFCallFrameInfo::FDEInfo::FDEInfo (off_t offset) : 34030fdc8d8SChris Lattner fde_offset(offset), 34130fdc8d8SChris Lattner fde_sp() 34230fdc8d8SChris Lattner { 34330fdc8d8SChris Lattner } 34430fdc8d8SChris Lattner 34530fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::CIE 34630fdc8d8SChris Lattner 34730fdc8d8SChris Lattner DWARFCallFrameInfo::CIE::CIE(dw_offset_t offset) : 34830fdc8d8SChris Lattner cie_offset (offset), 34930fdc8d8SChris Lattner version (0), 35030fdc8d8SChris Lattner augmentation(), 35130fdc8d8SChris Lattner code_align (0), 35230fdc8d8SChris Lattner data_align (0), 35330fdc8d8SChris Lattner return_addr_reg_num (0), 35430fdc8d8SChris Lattner inst_offset (0), 35530fdc8d8SChris Lattner inst_length (0), 356*ea84e764SJason Molenda ptr_encoding (DW_EH_PE_absptr) 35730fdc8d8SChris Lattner { 35830fdc8d8SChris Lattner } 35930fdc8d8SChris Lattner 36030fdc8d8SChris Lattner 36130fdc8d8SChris Lattner DWARFCallFrameInfo::CIE::~CIE() 36230fdc8d8SChris Lattner { 36330fdc8d8SChris Lattner } 36430fdc8d8SChris Lattner 36530fdc8d8SChris Lattner void 36630fdc8d8SChris Lattner DWARFCallFrameInfo::CIE::Dump(Stream *s, Thread* thread, const ArchSpec *arch, uint32_t reg_kind) const 36730fdc8d8SChris Lattner { 36830fdc8d8SChris Lattner s->Indent(); 36930fdc8d8SChris 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); 37030fdc8d8SChris Lattner DumpRegisterName(s, thread, arch, reg_kind, return_addr_reg_num); 37130fdc8d8SChris Lattner s->Printf(", instr_offset=0x%8.8x, instr_length=%u, ptr_encoding=0x%02x\n", 37230fdc8d8SChris Lattner inst_offset, 37330fdc8d8SChris Lattner inst_length, 37430fdc8d8SChris Lattner ptr_encoding); 37530fdc8d8SChris Lattner } 37630fdc8d8SChris Lattner 37730fdc8d8SChris Lattner #pragma mark DWARFCallFrameInfo::CIE 37830fdc8d8SChris Lattner 37930fdc8d8SChris Lattner DWARFCallFrameInfo::DWARFCallFrameInfo(ObjectFile *objfile, Section *section, uint32_t reg_kind) : 38030fdc8d8SChris Lattner m_objfile (objfile), 38130fdc8d8SChris Lattner m_section (section), 38230fdc8d8SChris Lattner m_reg_kind (reg_kind), // The flavor of registers that the CFI data uses (One of the defines that starts with "LLDB_REGKIND_") 38330fdc8d8SChris Lattner m_cfi_data (), 38430fdc8d8SChris Lattner m_cie_map (), 38530fdc8d8SChris Lattner m_fde_map () 38630fdc8d8SChris Lattner { 38730fdc8d8SChris Lattner if (objfile && section) 38830fdc8d8SChris Lattner { 38930fdc8d8SChris Lattner section->ReadSectionDataFromObjectFile (objfile, m_cfi_data); 39030fdc8d8SChris Lattner } 39130fdc8d8SChris Lattner } 39230fdc8d8SChris Lattner 39330fdc8d8SChris Lattner DWARFCallFrameInfo::~DWARFCallFrameInfo() 39430fdc8d8SChris Lattner { 39530fdc8d8SChris Lattner } 39630fdc8d8SChris Lattner 39730fdc8d8SChris Lattner bool 39830fdc8d8SChris Lattner DWARFCallFrameInfo::IsEHFrame() const 39930fdc8d8SChris Lattner { 40030fdc8d8SChris Lattner return (m_reg_kind == eRegisterKindGCC); 40130fdc8d8SChris Lattner } 40230fdc8d8SChris Lattner 40330fdc8d8SChris Lattner const ArchSpec * 40430fdc8d8SChris Lattner DWARFCallFrameInfo::GetArchitecture() const 40530fdc8d8SChris Lattner { 40630fdc8d8SChris Lattner if (m_objfile && m_objfile->GetModule()) 40730fdc8d8SChris Lattner return &m_objfile->GetModule()->GetArchitecture(); 40830fdc8d8SChris Lattner return NULL; 40930fdc8d8SChris Lattner } 41030fdc8d8SChris Lattner 41130fdc8d8SChris Lattner uint32_t 41230fdc8d8SChris Lattner DWARFCallFrameInfo::GetRegisterKind () const 41330fdc8d8SChris Lattner { 41430fdc8d8SChris Lattner return m_reg_kind; 41530fdc8d8SChris Lattner } 41630fdc8d8SChris Lattner 41730fdc8d8SChris Lattner void 41830fdc8d8SChris Lattner DWARFCallFrameInfo::SetRegisterKind (uint32_t reg_kind) 41930fdc8d8SChris Lattner { 42030fdc8d8SChris Lattner m_reg_kind = reg_kind; 42130fdc8d8SChris Lattner } 42230fdc8d8SChris Lattner 42330fdc8d8SChris Lattner 42430fdc8d8SChris Lattner 42530fdc8d8SChris Lattner 42630fdc8d8SChris Lattner const DWARFCallFrameInfo::CIE* 42730fdc8d8SChris Lattner DWARFCallFrameInfo::GetCIE(dw_offset_t cie_offset) 42830fdc8d8SChris Lattner { 42930fdc8d8SChris Lattner Index (); 43030fdc8d8SChris Lattner 43130fdc8d8SChris Lattner cie_map_t::iterator pos = m_cie_map.find(cie_offset); 43230fdc8d8SChris Lattner 43330fdc8d8SChris Lattner if (pos != m_cie_map.end()) 43430fdc8d8SChris Lattner { 43530fdc8d8SChris Lattner // Parse and cache the CIE 43630fdc8d8SChris Lattner if (pos->second.get() == NULL) 43730fdc8d8SChris Lattner pos->second = ParseCIE (cie_offset); 43830fdc8d8SChris Lattner 43930fdc8d8SChris Lattner return pos->second.get(); 44030fdc8d8SChris Lattner } 44130fdc8d8SChris Lattner return NULL; 44230fdc8d8SChris Lattner } 44330fdc8d8SChris Lattner 44430fdc8d8SChris Lattner DWARFCallFrameInfo::CIE::shared_ptr 44530fdc8d8SChris Lattner DWARFCallFrameInfo::ParseCIE (const dw_offset_t cie_offset) 44630fdc8d8SChris Lattner { 44730fdc8d8SChris Lattner CIE::shared_ptr cie_sp(new CIE(cie_offset)); 44830fdc8d8SChris Lattner const bool for_eh_frame = IsEHFrame(); 44930fdc8d8SChris Lattner dw_offset_t offset = cie_offset; 45030fdc8d8SChris Lattner const uint32_t length = m_cfi_data.GetU32(&offset); 45130fdc8d8SChris Lattner const dw_offset_t cie_id = m_cfi_data.GetU32(&offset); 45230fdc8d8SChris Lattner const dw_offset_t end_offset = cie_offset + length + 4; 45330fdc8d8SChris Lattner if (length > 0 && (!for_eh_frame && cie_id == 0xfffffffful) || (for_eh_frame && cie_id == 0ul)) 45430fdc8d8SChris Lattner { 45530fdc8d8SChris Lattner size_t i; 45630fdc8d8SChris Lattner // cie.offset = cie_offset; 45730fdc8d8SChris Lattner // cie.length = length; 45830fdc8d8SChris Lattner // cie.cieID = cieID; 459*ea84e764SJason Molenda cie_sp->ptr_encoding = DW_EH_PE_absptr; 46030fdc8d8SChris Lattner cie_sp->version = m_cfi_data.GetU8(&offset); 46130fdc8d8SChris Lattner 46230fdc8d8SChris Lattner for (i=0; i<CFI_AUG_MAX_SIZE; ++i) 46330fdc8d8SChris Lattner { 46430fdc8d8SChris Lattner cie_sp->augmentation[i] = m_cfi_data.GetU8(&offset); 46530fdc8d8SChris Lattner if (cie_sp->augmentation[i] == '\0') 46630fdc8d8SChris Lattner { 46730fdc8d8SChris Lattner // Zero out remaining bytes in augmentation string 46830fdc8d8SChris Lattner for (size_t j = i+1; j<CFI_AUG_MAX_SIZE; ++j) 46930fdc8d8SChris Lattner cie_sp->augmentation[j] = '\0'; 47030fdc8d8SChris Lattner 47130fdc8d8SChris Lattner break; 47230fdc8d8SChris Lattner } 47330fdc8d8SChris Lattner } 47430fdc8d8SChris Lattner 47530fdc8d8SChris Lattner if (i == CFI_AUG_MAX_SIZE && cie_sp->augmentation[CFI_AUG_MAX_SIZE-1] != '\0') 47630fdc8d8SChris Lattner { 47730fdc8d8SChris 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); 47830fdc8d8SChris Lattner return cie_sp; 47930fdc8d8SChris Lattner } 48030fdc8d8SChris Lattner cie_sp->code_align = (uint32_t)m_cfi_data.GetULEB128(&offset); 48130fdc8d8SChris Lattner cie_sp->data_align = (int32_t)m_cfi_data.GetSLEB128(&offset); 48230fdc8d8SChris Lattner cie_sp->return_addr_reg_num = m_cfi_data.GetU8(&offset); 48330fdc8d8SChris Lattner 48430fdc8d8SChris Lattner if (cie_sp->augmentation[0]) 48530fdc8d8SChris Lattner { 48630fdc8d8SChris Lattner // Get the length of the eh_frame augmentation data 48730fdc8d8SChris Lattner // which starts with a ULEB128 length in bytes 48830fdc8d8SChris Lattner const size_t aug_data_len = (size_t)m_cfi_data.GetULEB128(&offset); 48930fdc8d8SChris Lattner const size_t aug_data_end = offset + aug_data_len; 49030fdc8d8SChris Lattner const size_t aug_str_len = strlen(cie_sp->augmentation); 49130fdc8d8SChris Lattner // A 'z' may be present as the first character of the string. 49230fdc8d8SChris Lattner // If present, the Augmentation Data field shall be present. 49330fdc8d8SChris Lattner // The contents of the Augmentation Data shall be intepreted 49430fdc8d8SChris Lattner // according to other characters in the Augmentation String. 49530fdc8d8SChris Lattner if (cie_sp->augmentation[0] == 'z') 49630fdc8d8SChris Lattner { 49730fdc8d8SChris Lattner // Extract the Augmentation Data 49830fdc8d8SChris Lattner size_t aug_str_idx = 0; 49930fdc8d8SChris Lattner for (aug_str_idx = 1; aug_str_idx < aug_str_len; aug_str_idx++) 50030fdc8d8SChris Lattner { 50130fdc8d8SChris Lattner char aug = cie_sp->augmentation[aug_str_idx]; 50230fdc8d8SChris Lattner switch (aug) 50330fdc8d8SChris Lattner { 50430fdc8d8SChris Lattner case 'L': 50530fdc8d8SChris Lattner // Indicates the presence of one argument in the 50630fdc8d8SChris Lattner // Augmentation Data of the CIE, and a corresponding 50730fdc8d8SChris Lattner // argument in the Augmentation Data of the FDE. The 50830fdc8d8SChris Lattner // argument in the Augmentation Data of the CIE is 50930fdc8d8SChris Lattner // 1-byte and represents the pointer encoding used 51030fdc8d8SChris Lattner // for the argument in the Augmentation Data of the 51130fdc8d8SChris Lattner // FDE, which is the address of a language-specific 51230fdc8d8SChris Lattner // data area (LSDA). The size of the LSDA pointer is 51330fdc8d8SChris Lattner // specified by the pointer encoding used. 51430fdc8d8SChris Lattner m_cfi_data.GetU8(&offset); 51530fdc8d8SChris Lattner break; 51630fdc8d8SChris Lattner 51730fdc8d8SChris Lattner case 'P': 51830fdc8d8SChris Lattner // Indicates the presence of two arguments in the 51930fdc8d8SChris Lattner // Augmentation Data of the cie_sp-> The first argument 52030fdc8d8SChris Lattner // is 1-byte and represents the pointer encoding 52130fdc8d8SChris Lattner // used for the second argument, which is the 52230fdc8d8SChris Lattner // address of a personality routine handler. The 52330fdc8d8SChris Lattner // size of the personality routine pointer is 52430fdc8d8SChris Lattner // specified by the pointer encoding used. 52530fdc8d8SChris Lattner { 52630fdc8d8SChris Lattner uint8_t arg_ptr_encoding = m_cfi_data.GetU8(&offset); 52730fdc8d8SChris Lattner m_cfi_data.GetGNUEHPointer(&offset, arg_ptr_encoding, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS); 52830fdc8d8SChris Lattner } 52930fdc8d8SChris Lattner break; 53030fdc8d8SChris Lattner 53130fdc8d8SChris Lattner case 'R': 53230fdc8d8SChris Lattner // A 'R' may be present at any position after the 53330fdc8d8SChris Lattner // first character of the string. The Augmentation 53430fdc8d8SChris Lattner // Data shall include a 1 byte argument that 53530fdc8d8SChris Lattner // represents the pointer encoding for the address 53630fdc8d8SChris Lattner // pointers used in the FDE. 53730fdc8d8SChris Lattner cie_sp->ptr_encoding = m_cfi_data.GetU8(&offset); 53830fdc8d8SChris Lattner break; 53930fdc8d8SChris Lattner } 54030fdc8d8SChris Lattner } 54130fdc8d8SChris Lattner } 54230fdc8d8SChris Lattner else if (strcmp(cie_sp->augmentation, "eh") == 0) 54330fdc8d8SChris Lattner { 54430fdc8d8SChris Lattner // If the Augmentation string has the value "eh", then 54530fdc8d8SChris Lattner // the EH Data field shall be present 54630fdc8d8SChris Lattner } 54730fdc8d8SChris Lattner 54830fdc8d8SChris Lattner // Set the offset to be the end of the augmentation data just in case 54930fdc8d8SChris Lattner // we didn't understand any of the data. 55030fdc8d8SChris Lattner offset = (uint32_t)aug_data_end; 55130fdc8d8SChris Lattner } 55230fdc8d8SChris Lattner 55330fdc8d8SChris Lattner if (end_offset > offset) 55430fdc8d8SChris Lattner { 55530fdc8d8SChris Lattner cie_sp->inst_offset = offset; 55630fdc8d8SChris Lattner cie_sp->inst_length = end_offset - offset; 55730fdc8d8SChris Lattner } 55830fdc8d8SChris Lattner } 55930fdc8d8SChris Lattner 56030fdc8d8SChris Lattner return cie_sp; 56130fdc8d8SChris Lattner } 56230fdc8d8SChris Lattner 56330fdc8d8SChris Lattner DWARFCallFrameInfo::FDE::shared_ptr 56430fdc8d8SChris Lattner DWARFCallFrameInfo::ParseFDE(const dw_offset_t fde_offset) 56530fdc8d8SChris Lattner { 56630fdc8d8SChris Lattner const bool for_eh_frame = IsEHFrame(); 56730fdc8d8SChris Lattner FDE::shared_ptr fde_sp; 56830fdc8d8SChris Lattner 56930fdc8d8SChris Lattner dw_offset_t offset = fde_offset; 57030fdc8d8SChris Lattner const uint32_t length = m_cfi_data.GetU32(&offset); 57130fdc8d8SChris Lattner dw_offset_t cie_offset = m_cfi_data.GetU32(&offset); 57230fdc8d8SChris Lattner const dw_offset_t end_offset = fde_offset + length + 4; 57330fdc8d8SChris Lattner 57430fdc8d8SChris Lattner // Translate the CIE_id from the eh_frame format, which 57530fdc8d8SChris Lattner // is relative to the FDE offset, into a __eh_frame section 57630fdc8d8SChris Lattner // offset 57730fdc8d8SChris Lattner if (for_eh_frame) 57830fdc8d8SChris Lattner cie_offset = offset - (cie_offset + 4); 57930fdc8d8SChris Lattner 58030fdc8d8SChris Lattner const CIE* cie = GetCIE(cie_offset); 58130fdc8d8SChris Lattner if (cie) 58230fdc8d8SChris Lattner { 58330fdc8d8SChris Lattner const lldb::addr_t pc_rel_addr = m_section->GetFileAddress(); 58430fdc8d8SChris Lattner const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS; 58530fdc8d8SChris Lattner const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS; 58630fdc8d8SChris Lattner lldb::addr_t range_base = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr); 587*ea84e764SJason Molenda lldb::addr_t range_len = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING, pc_rel_addr, text_addr, data_addr); 58830fdc8d8SChris Lattner 58930fdc8d8SChris Lattner if (cie->augmentation[0] == 'z') 59030fdc8d8SChris Lattner { 59130fdc8d8SChris Lattner uint32_t aug_data_len = (uint32_t)m_cfi_data.GetULEB128(&offset); 59230fdc8d8SChris Lattner offset += aug_data_len; 59330fdc8d8SChris Lattner } 59430fdc8d8SChris Lattner 59530fdc8d8SChris Lattner AddressRange fde_range (range_base, range_len, m_objfile->GetSectionList ()); 59630fdc8d8SChris Lattner fde_sp.reset(new FDE(fde_offset, fde_range)); 59730fdc8d8SChris Lattner if (offset < end_offset) 59830fdc8d8SChris Lattner { 59930fdc8d8SChris Lattner dw_offset_t fde_instr_offset = offset; 60030fdc8d8SChris Lattner uint32_t fde_instr_length = end_offset - offset; 60130fdc8d8SChris Lattner if (cie->inst_length > 0) 60230fdc8d8SChris Lattner ParseInstructions(cie, fde_sp.get(), cie->inst_offset, cie->inst_length); 60330fdc8d8SChris Lattner ParseInstructions(cie, fde_sp.get(), fde_instr_offset, fde_instr_length); 60430fdc8d8SChris Lattner } 60530fdc8d8SChris Lattner } 60630fdc8d8SChris Lattner return fde_sp; 60730fdc8d8SChris Lattner } 60830fdc8d8SChris Lattner 60930fdc8d8SChris Lattner const DWARFCallFrameInfo::FDE * 61030fdc8d8SChris Lattner DWARFCallFrameInfo::FindFDE(const Address &addr) 61130fdc8d8SChris Lattner { 61230fdc8d8SChris Lattner Index (); 61330fdc8d8SChris Lattner 61430fdc8d8SChris Lattner VMRange find_range(addr.GetFileAddress(), 0); 61530fdc8d8SChris Lattner fde_map_t::iterator pos = m_fde_map.lower_bound (find_range); 61630fdc8d8SChris Lattner fde_map_t::iterator end = m_fde_map.end(); 61730fdc8d8SChris Lattner 61830fdc8d8SChris Lattner if (pos != end) 61930fdc8d8SChris Lattner { 62030fdc8d8SChris Lattner if (pos->first.Contains(find_range.GetBaseAddress())) 62130fdc8d8SChris Lattner { 62230fdc8d8SChris Lattner // Parse and cache the FDE if we already haven't 62330fdc8d8SChris Lattner if (pos->second.fde_sp.get() == NULL) 62430fdc8d8SChris Lattner pos->second.fde_sp = ParseFDE(pos->second.fde_offset); 62530fdc8d8SChris Lattner 62630fdc8d8SChris Lattner return pos->second.fde_sp.get(); 62730fdc8d8SChris Lattner } 62830fdc8d8SChris Lattner } 62930fdc8d8SChris Lattner return NULL; 63030fdc8d8SChris Lattner } 63130fdc8d8SChris Lattner 63230fdc8d8SChris Lattner 63330fdc8d8SChris Lattner void 63430fdc8d8SChris Lattner DWARFCallFrameInfo::Index () 63530fdc8d8SChris Lattner { 63630fdc8d8SChris Lattner if (m_flags.IsClear(eFlagParsedIndex)) 63730fdc8d8SChris Lattner { 63830fdc8d8SChris Lattner m_flags.Set (eFlagParsedIndex); 63930fdc8d8SChris Lattner const bool for_eh_frame = IsEHFrame(); 64030fdc8d8SChris Lattner CIE::shared_ptr empty_cie_sp; 64130fdc8d8SChris Lattner dw_offset_t offset = 0; 64230fdc8d8SChris Lattner // Parse all of the CIEs first since we will need them to be able to 64330fdc8d8SChris Lattner // properly parse the FDE addresses due to them possibly having 64430fdc8d8SChris Lattner // GNU pointer encodings in their augmentations... 64530fdc8d8SChris Lattner while (m_cfi_data.ValidOffsetForDataOfSize(offset, 8)) 64630fdc8d8SChris Lattner { 64730fdc8d8SChris Lattner const dw_offset_t curr_offset = offset; 64830fdc8d8SChris Lattner const uint32_t length = m_cfi_data.GetU32(&offset); 64930fdc8d8SChris Lattner const dw_offset_t next_offset = offset + length; 65030fdc8d8SChris Lattner const dw_offset_t cie_id = m_cfi_data.GetU32(&offset); 65130fdc8d8SChris Lattner 65230fdc8d8SChris Lattner bool is_cie = for_eh_frame ? cie_id == 0 : cie_id == UINT32_MAX; 65330fdc8d8SChris Lattner if (is_cie) 65430fdc8d8SChris Lattner m_cie_map[curr_offset]= ParseCIE(curr_offset); 65530fdc8d8SChris Lattner 65630fdc8d8SChris Lattner offset = next_offset; 65730fdc8d8SChris Lattner } 65830fdc8d8SChris Lattner 65930fdc8d8SChris Lattner // Now go back through and index all FDEs 66030fdc8d8SChris Lattner offset = 0; 66130fdc8d8SChris Lattner const lldb::addr_t pc_rel_addr = m_section->GetFileAddress(); 66230fdc8d8SChris Lattner const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS; 66330fdc8d8SChris Lattner const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS; 66430fdc8d8SChris Lattner while (m_cfi_data.ValidOffsetForDataOfSize(offset, 8)) 66530fdc8d8SChris Lattner { 66630fdc8d8SChris Lattner const dw_offset_t curr_offset = offset; 66730fdc8d8SChris Lattner const uint32_t length = m_cfi_data.GetU32(&offset); 66830fdc8d8SChris Lattner const dw_offset_t next_offset = offset + length; 66930fdc8d8SChris Lattner const dw_offset_t cie_id = m_cfi_data.GetU32(&offset); 67030fdc8d8SChris Lattner 67130fdc8d8SChris Lattner bool is_fde = for_eh_frame ? cie_id != 0 : cie_id != UINT32_MAX; 67230fdc8d8SChris Lattner if (is_fde) 67330fdc8d8SChris Lattner { 67430fdc8d8SChris Lattner dw_offset_t cie_offset; 67530fdc8d8SChris Lattner if (for_eh_frame) 67630fdc8d8SChris Lattner cie_offset = offset - (cie_id + 4); 67730fdc8d8SChris Lattner else 67830fdc8d8SChris Lattner cie_offset = cie_id; 67930fdc8d8SChris Lattner 68030fdc8d8SChris Lattner const CIE* cie = GetCIE(cie_offset); 68130fdc8d8SChris Lattner assert(cie); 68230fdc8d8SChris Lattner lldb::addr_t addr = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr); 683*ea84e764SJason Molenda lldb::addr_t length = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING, pc_rel_addr, text_addr, data_addr); 68430fdc8d8SChris Lattner m_fde_map[VMRange(addr, addr + length)] = FDEInfo(curr_offset); 68530fdc8d8SChris Lattner } 68630fdc8d8SChris Lattner 68730fdc8d8SChris Lattner offset = next_offset; 68830fdc8d8SChris Lattner } 68930fdc8d8SChris Lattner } 69030fdc8d8SChris Lattner } 69130fdc8d8SChris Lattner 69230fdc8d8SChris Lattner //---------------------------------------------------------------------- 69330fdc8d8SChris Lattner // Parse instructions for a FDE. The initial instruction for the CIE 69430fdc8d8SChris Lattner // are parsed first, then the instructions for the FDE are parsed 69530fdc8d8SChris Lattner //---------------------------------------------------------------------- 69630fdc8d8SChris Lattner void 69730fdc8d8SChris Lattner DWARFCallFrameInfo::ParseInstructions(const CIE *cie, FDE *fde, dw_offset_t instr_offset, uint32_t instr_length) 69830fdc8d8SChris Lattner { 69930fdc8d8SChris Lattner if (cie != NULL && fde == NULL) 70030fdc8d8SChris Lattner return; 70130fdc8d8SChris Lattner 70230fdc8d8SChris Lattner uint32_t reg_num = 0; 70330fdc8d8SChris Lattner int32_t op_offset = 0; 70430fdc8d8SChris Lattner uint32_t tmp_uval32; 70530fdc8d8SChris Lattner uint32_t code_align = cie->code_align; 70630fdc8d8SChris Lattner int32_t data_align = cie->data_align; 70730fdc8d8SChris Lattner typedef std::list<Row> RowStack; 70830fdc8d8SChris Lattner 70930fdc8d8SChris Lattner RowStack row_stack; 71030fdc8d8SChris Lattner Row row; 71130fdc8d8SChris Lattner if (fde->IsValidRowIndex(0)) 71230fdc8d8SChris Lattner row = fde->GetRowAtIndex(0); 71330fdc8d8SChris Lattner 71430fdc8d8SChris Lattner dw_offset_t offset = instr_offset; 71530fdc8d8SChris Lattner const dw_offset_t end_offset = instr_offset + instr_length; 71630fdc8d8SChris Lattner RegisterLocation reg_location; 71730fdc8d8SChris Lattner while (m_cfi_data.ValidOffset(offset) && offset < end_offset) 71830fdc8d8SChris Lattner { 71930fdc8d8SChris Lattner uint8_t inst = m_cfi_data.GetU8(&offset); 72030fdc8d8SChris Lattner uint8_t primary_opcode = inst & 0xC0; 72130fdc8d8SChris Lattner uint8_t extended_opcode = inst & 0x3F; 72230fdc8d8SChris Lattner 72330fdc8d8SChris Lattner if (primary_opcode) 72430fdc8d8SChris Lattner { 72530fdc8d8SChris Lattner switch (primary_opcode) 72630fdc8d8SChris Lattner { 72730fdc8d8SChris Lattner case DW_CFA_advance_loc : // (Row Creation Instruction) 72830fdc8d8SChris Lattner { // 0x40 - high 2 bits are 0x1, lower 6 bits are delta 72930fdc8d8SChris Lattner // takes a single argument that represents a constant delta. The 73030fdc8d8SChris Lattner // required action is to create a new table row with a location 73130fdc8d8SChris Lattner // value that is computed by taking the current entry's location 73230fdc8d8SChris Lattner // value and adding (delta * code_align). All other 73330fdc8d8SChris Lattner // values in the new row are initially identical to the current row. 73430fdc8d8SChris Lattner fde->AppendRow(row); 73530fdc8d8SChris Lattner row.SlideOffset(extended_opcode * code_align); 73630fdc8d8SChris Lattner } 73730fdc8d8SChris Lattner break; 73830fdc8d8SChris Lattner 73930fdc8d8SChris Lattner case DW_CFA_offset : 74030fdc8d8SChris Lattner { // 0x80 - high 2 bits are 0x2, lower 6 bits are register 74130fdc8d8SChris Lattner // takes two arguments: an unsigned LEB128 constant representing a 74230fdc8d8SChris Lattner // factored offset and a register number. The required action is to 74330fdc8d8SChris Lattner // change the rule for the register indicated by the register number 74430fdc8d8SChris Lattner // to be an offset(N) rule with a value of 74530fdc8d8SChris Lattner // (N = factored offset * data_align). 74630fdc8d8SChris Lattner reg_num = extended_opcode; 74730fdc8d8SChris Lattner op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align; 74830fdc8d8SChris Lattner reg_location.SetAtCFAPlusOffset(op_offset); 74930fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 75030fdc8d8SChris Lattner } 75130fdc8d8SChris Lattner break; 75230fdc8d8SChris Lattner 75330fdc8d8SChris Lattner case DW_CFA_restore : 75430fdc8d8SChris Lattner { // 0xC0 - high 2 bits are 0x3, lower 6 bits are register 75530fdc8d8SChris Lattner // takes a single argument that represents a register number. The 75630fdc8d8SChris Lattner // required action is to change the rule for the indicated register 75730fdc8d8SChris Lattner // to the rule assigned it by the initial_instructions in the CIE. 75830fdc8d8SChris Lattner reg_num = extended_opcode; 75930fdc8d8SChris Lattner // We only keep enough register locations around to 76030fdc8d8SChris Lattner // unwind what is in our thread, and these are organized 76130fdc8d8SChris Lattner // by the register index in that state, so we need to convert our 76230fdc8d8SChris Lattner // GCC register number from the EH frame info, to a registe index 76330fdc8d8SChris Lattner 76430fdc8d8SChris Lattner if (fde->IsValidRowIndex(0) && fde->GetRowAtIndex(0).GetRegisterInfo(reg_num, reg_location)) 76530fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 76630fdc8d8SChris Lattner } 76730fdc8d8SChris Lattner break; 76830fdc8d8SChris Lattner } 76930fdc8d8SChris Lattner } 77030fdc8d8SChris Lattner else 77130fdc8d8SChris Lattner { 77230fdc8d8SChris Lattner switch (extended_opcode) 77330fdc8d8SChris Lattner { 77430fdc8d8SChris Lattner case DW_CFA_nop : // 0x0 77530fdc8d8SChris Lattner break; 77630fdc8d8SChris Lattner 77730fdc8d8SChris Lattner case DW_CFA_set_loc : // 0x1 (Row Creation Instruction) 77830fdc8d8SChris Lattner { 77930fdc8d8SChris Lattner // DW_CFA_set_loc takes a single argument that represents an address. 78030fdc8d8SChris Lattner // The required action is to create a new table row using the 78130fdc8d8SChris Lattner // specified address as the location. All other values in the new row 78230fdc8d8SChris Lattner // are initially identical to the current row. The new location value 78330fdc8d8SChris Lattner // should always be greater than the current one. 78430fdc8d8SChris Lattner fde->AppendRow(row); 78530fdc8d8SChris Lattner row.SetOffset(m_cfi_data.GetPointer(&offset) - fde->GetAddressRange().GetBaseAddress().GetFileAddress()); 78630fdc8d8SChris Lattner } 78730fdc8d8SChris Lattner break; 78830fdc8d8SChris Lattner 78930fdc8d8SChris Lattner case DW_CFA_advance_loc1 : // 0x2 (Row Creation Instruction) 79030fdc8d8SChris Lattner { 79130fdc8d8SChris Lattner // takes a single uword argument that represents a constant delta. 79230fdc8d8SChris Lattner // This instruction is identical to DW_CFA_advance_loc except for the 79330fdc8d8SChris Lattner // encoding and size of the delta argument. 79430fdc8d8SChris Lattner fde->AppendRow(row); 79530fdc8d8SChris Lattner row.SlideOffset (m_cfi_data.GetU8(&offset) * code_align); 79630fdc8d8SChris Lattner } 79730fdc8d8SChris Lattner break; 79830fdc8d8SChris Lattner 79930fdc8d8SChris Lattner case DW_CFA_advance_loc2 : // 0x3 (Row Creation Instruction) 80030fdc8d8SChris Lattner { 80130fdc8d8SChris Lattner // takes a single uword argument that represents a constant delta. 80230fdc8d8SChris Lattner // This instruction is identical to DW_CFA_advance_loc except for the 80330fdc8d8SChris Lattner // encoding and size of the delta argument. 80430fdc8d8SChris Lattner fde->AppendRow(row); 80530fdc8d8SChris Lattner row.SlideOffset (m_cfi_data.GetU16(&offset) * code_align); 80630fdc8d8SChris Lattner } 80730fdc8d8SChris Lattner break; 80830fdc8d8SChris Lattner 80930fdc8d8SChris Lattner case DW_CFA_advance_loc4 : // 0x4 (Row Creation Instruction) 81030fdc8d8SChris Lattner { 81130fdc8d8SChris Lattner // takes a single uword argument that represents a constant delta. 81230fdc8d8SChris Lattner // This instruction is identical to DW_CFA_advance_loc except for the 81330fdc8d8SChris Lattner // encoding and size of the delta argument. 81430fdc8d8SChris Lattner fde->AppendRow(row); 81530fdc8d8SChris Lattner row.SlideOffset (m_cfi_data.GetU32(&offset) * code_align); 81630fdc8d8SChris Lattner } 81730fdc8d8SChris Lattner break; 81830fdc8d8SChris Lattner 81930fdc8d8SChris Lattner case DW_CFA_offset_extended : // 0x5 82030fdc8d8SChris Lattner { 82130fdc8d8SChris Lattner // takes two unsigned LEB128 arguments representing a register number 82230fdc8d8SChris Lattner // and a factored offset. This instruction is identical to DW_CFA_offset 82330fdc8d8SChris Lattner // except for the encoding and size of the register argument. 82430fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 82530fdc8d8SChris Lattner op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align; 82630fdc8d8SChris Lattner reg_location.SetAtCFAPlusOffset(op_offset); 82730fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 82830fdc8d8SChris Lattner } 82930fdc8d8SChris Lattner break; 83030fdc8d8SChris Lattner 83130fdc8d8SChris Lattner case DW_CFA_restore_extended : // 0x6 83230fdc8d8SChris Lattner { 83330fdc8d8SChris Lattner // takes a single unsigned LEB128 argument that represents a register 83430fdc8d8SChris Lattner // number. This instruction is identical to DW_CFA_restore except for 83530fdc8d8SChris Lattner // the encoding and size of the register argument. 83630fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 83730fdc8d8SChris Lattner if (fde->IsValidRowIndex(0) && fde->GetRowAtIndex(0).GetRegisterInfo(reg_num, reg_location)) 83830fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 83930fdc8d8SChris Lattner } 84030fdc8d8SChris Lattner break; 84130fdc8d8SChris Lattner 84230fdc8d8SChris Lattner case DW_CFA_undefined : // 0x7 84330fdc8d8SChris Lattner { 84430fdc8d8SChris Lattner // takes a single unsigned LEB128 argument that represents a register 84530fdc8d8SChris Lattner // number. The required action is to set the rule for the specified 84630fdc8d8SChris Lattner // register to undefined. 84730fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 84830fdc8d8SChris Lattner reg_location.SetUndefined(); 84930fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 85030fdc8d8SChris Lattner } 85130fdc8d8SChris Lattner break; 85230fdc8d8SChris Lattner 85330fdc8d8SChris Lattner case DW_CFA_same_value : // 0x8 85430fdc8d8SChris Lattner { 85530fdc8d8SChris Lattner // takes a single unsigned LEB128 argument that represents a register 85630fdc8d8SChris Lattner // number. The required action is to set the rule for the specified 85730fdc8d8SChris Lattner // register to same value. 85830fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 85930fdc8d8SChris Lattner reg_location.SetSame(); 86030fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 86130fdc8d8SChris Lattner } 86230fdc8d8SChris Lattner break; 86330fdc8d8SChris Lattner 86430fdc8d8SChris Lattner case DW_CFA_register : // 0x9 86530fdc8d8SChris Lattner { 86630fdc8d8SChris Lattner // takes two unsigned LEB128 arguments representing register numbers. 86730fdc8d8SChris Lattner // The required action is to set the rule for the first register to be 86830fdc8d8SChris Lattner // the second register. 86930fdc8d8SChris Lattner 87030fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 87130fdc8d8SChris Lattner uint32_t other_reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 87230fdc8d8SChris Lattner reg_location.SetInRegister(other_reg_num); 87330fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 87430fdc8d8SChris Lattner } 87530fdc8d8SChris Lattner break; 87630fdc8d8SChris Lattner 87730fdc8d8SChris Lattner case DW_CFA_remember_state : // 0xA 87830fdc8d8SChris Lattner // These instructions define a stack of information. Encountering the 87930fdc8d8SChris Lattner // DW_CFA_remember_state instruction means to save the rules for every 88030fdc8d8SChris Lattner // register on the current row on the stack. Encountering the 88130fdc8d8SChris Lattner // DW_CFA_restore_state instruction means to pop the set of rules off 88230fdc8d8SChris Lattner // the stack and place them in the current row. (This operation is 88330fdc8d8SChris Lattner // useful for compilers that move epilogue code into the body of a 88430fdc8d8SChris Lattner // function.) 88530fdc8d8SChris Lattner row_stack.push_back(row); 88630fdc8d8SChris Lattner break; 88730fdc8d8SChris Lattner 88830fdc8d8SChris Lattner case DW_CFA_restore_state : // 0xB 88930fdc8d8SChris Lattner // These instructions define a stack of information. Encountering the 89030fdc8d8SChris Lattner // DW_CFA_remember_state instruction means to save the rules for every 89130fdc8d8SChris Lattner // register on the current row on the stack. Encountering the 89230fdc8d8SChris Lattner // DW_CFA_restore_state instruction means to pop the set of rules off 89330fdc8d8SChris Lattner // the stack and place them in the current row. (This operation is 89430fdc8d8SChris Lattner // useful for compilers that move epilogue code into the body of a 89530fdc8d8SChris Lattner // function.) 89630fdc8d8SChris Lattner { 89730fdc8d8SChris Lattner row = row_stack.back(); 89830fdc8d8SChris Lattner row_stack.pop_back(); 89930fdc8d8SChris Lattner } 90030fdc8d8SChris Lattner break; 90130fdc8d8SChris Lattner 90230fdc8d8SChris Lattner case DW_CFA_def_cfa : // 0xC (CFA Definition Instruction) 90330fdc8d8SChris Lattner { 90430fdc8d8SChris Lattner // Takes two unsigned LEB128 operands representing a register 90530fdc8d8SChris Lattner // number and a (non-factored) offset. The required action 90630fdc8d8SChris Lattner // is to define the current CFA rule to use the provided 90730fdc8d8SChris Lattner // register and offset. 90830fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 90930fdc8d8SChris Lattner op_offset = (int32_t)m_cfi_data.GetULEB128(&offset); 91030fdc8d8SChris Lattner row.SetCFARegister (reg_num); 91130fdc8d8SChris Lattner row.SetCFAOffset (op_offset); 91230fdc8d8SChris Lattner } 91330fdc8d8SChris Lattner break; 91430fdc8d8SChris Lattner 91530fdc8d8SChris Lattner case DW_CFA_def_cfa_register : // 0xD (CFA Definition Instruction) 91630fdc8d8SChris Lattner { 91730fdc8d8SChris Lattner // takes a single unsigned LEB128 argument representing a register 91830fdc8d8SChris Lattner // number. The required action is to define the current CFA rule to 91930fdc8d8SChris Lattner // use the provided register (but to keep the old offset). 92030fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 92130fdc8d8SChris Lattner row.SetCFARegister (reg_num); 92230fdc8d8SChris Lattner } 92330fdc8d8SChris Lattner break; 92430fdc8d8SChris Lattner 92530fdc8d8SChris Lattner case DW_CFA_def_cfa_offset : // 0xE (CFA Definition Instruction) 92630fdc8d8SChris Lattner { 92730fdc8d8SChris Lattner // Takes a single unsigned LEB128 operand representing a 92830fdc8d8SChris Lattner // (non-factored) offset. The required action is to define 92930fdc8d8SChris Lattner // the current CFA rule to use the provided offset (but 93030fdc8d8SChris Lattner // to keep the old register). 93130fdc8d8SChris Lattner op_offset = (int32_t)m_cfi_data.GetULEB128(&offset); 93230fdc8d8SChris Lattner row.SetCFAOffset (op_offset); 93330fdc8d8SChris Lattner } 93430fdc8d8SChris Lattner break; 93530fdc8d8SChris Lattner 93630fdc8d8SChris Lattner case DW_CFA_def_cfa_expression : // 0xF (CFA Definition Instruction) 93730fdc8d8SChris Lattner { 93830fdc8d8SChris Lattner size_t block_len = (size_t)m_cfi_data.GetULEB128(&offset); 93930fdc8d8SChris Lattner offset += (uint32_t)block_len; 94030fdc8d8SChris Lattner } 94130fdc8d8SChris Lattner break; 94230fdc8d8SChris Lattner 94330fdc8d8SChris Lattner case DW_CFA_expression : // 0x10 94430fdc8d8SChris Lattner { 94530fdc8d8SChris Lattner // Takes two operands: an unsigned LEB128 value representing 94630fdc8d8SChris Lattner // a register number, and a DW_FORM_block value representing a DWARF 94730fdc8d8SChris Lattner // expression. The required action is to change the rule for the 94830fdc8d8SChris Lattner // register indicated by the register number to be an expression(E) 94930fdc8d8SChris Lattner // rule where E is the DWARF expression. That is, the DWARF 95030fdc8d8SChris Lattner // expression computes the address. The value of the CFA is 95130fdc8d8SChris Lattner // pushed on the DWARF evaluation stack prior to execution of 95230fdc8d8SChris Lattner // the DWARF expression. 95330fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 95430fdc8d8SChris Lattner uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset); 95530fdc8d8SChris Lattner const uint8_t *block_data = (uint8_t *)m_cfi_data.GetData(&offset, block_len); 95630fdc8d8SChris Lattner 95730fdc8d8SChris Lattner reg_location.SetAtDWARFExpression(block_data, block_len); 95830fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 95930fdc8d8SChris Lattner } 96030fdc8d8SChris Lattner break; 96130fdc8d8SChris Lattner 96230fdc8d8SChris Lattner case DW_CFA_offset_extended_sf : // 0x11 96330fdc8d8SChris Lattner { 96430fdc8d8SChris Lattner // takes two operands: an unsigned LEB128 value representing a 96530fdc8d8SChris Lattner // register number and a signed LEB128 factored offset. This 96630fdc8d8SChris Lattner // instruction is identical to DW_CFA_offset_extended except 96730fdc8d8SChris Lattner //that the second operand is signed and factored. 96830fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 96930fdc8d8SChris Lattner op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align; 97030fdc8d8SChris Lattner reg_location.SetAtCFAPlusOffset(op_offset); 97130fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 97230fdc8d8SChris Lattner } 97330fdc8d8SChris Lattner break; 97430fdc8d8SChris Lattner 97530fdc8d8SChris Lattner case DW_CFA_def_cfa_sf : // 0x12 (CFA Definition Instruction) 97630fdc8d8SChris Lattner { 97730fdc8d8SChris Lattner // Takes two operands: an unsigned LEB128 value representing 97830fdc8d8SChris Lattner // a register number and a signed LEB128 factored offset. 97930fdc8d8SChris Lattner // This instruction is identical to DW_CFA_def_cfa except 98030fdc8d8SChris Lattner // that the second operand is signed and factored. 98130fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 98230fdc8d8SChris Lattner op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align; 98330fdc8d8SChris Lattner row.SetCFARegister (reg_num); 98430fdc8d8SChris Lattner row.SetCFAOffset (op_offset); 98530fdc8d8SChris Lattner } 98630fdc8d8SChris Lattner break; 98730fdc8d8SChris Lattner 98830fdc8d8SChris Lattner case DW_CFA_def_cfa_offset_sf : // 0x13 (CFA Definition Instruction) 98930fdc8d8SChris Lattner { 99030fdc8d8SChris Lattner // takes a signed LEB128 operand representing a factored 99130fdc8d8SChris Lattner // offset. This instruction is identical to DW_CFA_def_cfa_offset 99230fdc8d8SChris Lattner // except that the operand is signed and factored. 99330fdc8d8SChris Lattner op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align; 99430fdc8d8SChris Lattner row.SetCFAOffset (op_offset); 99530fdc8d8SChris Lattner } 99630fdc8d8SChris Lattner break; 99730fdc8d8SChris Lattner 99830fdc8d8SChris Lattner case DW_CFA_val_expression : // 0x16 99930fdc8d8SChris Lattner { 100030fdc8d8SChris Lattner // takes two operands: an unsigned LEB128 value representing a register 100130fdc8d8SChris Lattner // number, and a DW_FORM_block value representing a DWARF expression. 100230fdc8d8SChris Lattner // The required action is to change the rule for the register indicated 100330fdc8d8SChris Lattner // by the register number to be a val_expression(E) rule where E is the 100430fdc8d8SChris Lattner // DWARF expression. That is, the DWARF expression computes the value of 100530fdc8d8SChris Lattner // the given register. The value of the CFA is pushed on the DWARF 100630fdc8d8SChris Lattner // evaluation stack prior to execution of the DWARF expression. 100730fdc8d8SChris Lattner reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); 100830fdc8d8SChris Lattner uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset); 100930fdc8d8SChris Lattner const uint8_t* block_data = (uint8_t*)m_cfi_data.GetData(&offset, block_len); 101030fdc8d8SChris Lattner //#if defined(__i386__) || defined(__x86_64__) 101130fdc8d8SChris Lattner // // The EH frame info for EIP and RIP contains code that looks for traps to 101230fdc8d8SChris Lattner // // be a specific type and increments the PC. 101330fdc8d8SChris Lattner // // For i386: 101430fdc8d8SChris Lattner // // DW_CFA_val_expression where: 101530fdc8d8SChris Lattner // // eip = DW_OP_breg6(+28), DW_OP_deref, DW_OP_dup, DW_OP_plus_uconst(0x34), 101630fdc8d8SChris Lattner // // DW_OP_deref, DW_OP_swap, DW_OP_plus_uconst(0), DW_OP_deref, 101730fdc8d8SChris Lattner // // DW_OP_dup, DW_OP_lit3, DW_OP_ne, DW_OP_swap, DW_OP_lit4, DW_OP_ne, 101830fdc8d8SChris Lattner // // DW_OP_and, DW_OP_plus 101930fdc8d8SChris Lattner // // This basically does a: 102030fdc8d8SChris Lattner // // eip = ucontenxt.mcontext32->gpr.eip; 102130fdc8d8SChris Lattner // // if (ucontenxt.mcontext32->exc.trapno != 3 && ucontenxt.mcontext32->exc.trapno != 4) 102230fdc8d8SChris Lattner // // eip++; 102330fdc8d8SChris Lattner // // 102430fdc8d8SChris Lattner // // For x86_64: 102530fdc8d8SChris Lattner // // DW_CFA_val_expression where: 102630fdc8d8SChris Lattner // // rip = DW_OP_breg3(+48), DW_OP_deref, DW_OP_dup, DW_OP_plus_uconst(0x90), DW_OP_deref, 102730fdc8d8SChris Lattner // // DW_OP_swap, DW_OP_plus_uconst(0), DW_OP_deref_size(4), DW_OP_dup, DW_OP_lit3, 102830fdc8d8SChris Lattner // // DW_OP_ne, DW_OP_swap, DW_OP_lit4, DW_OP_ne, DW_OP_and, DW_OP_plus 102930fdc8d8SChris Lattner // // This basically does a: 103030fdc8d8SChris Lattner // // rip = ucontenxt.mcontext64->gpr.rip; 103130fdc8d8SChris Lattner // // if (ucontenxt.mcontext64->exc.trapno != 3 && ucontenxt.mcontext64->exc.trapno != 4) 103230fdc8d8SChris Lattner // // rip++; 103330fdc8d8SChris Lattner // // The trap comparisons and increments are not needed as it hoses up the unwound PC which 103430fdc8d8SChris Lattner // // is expected to point at least past the instruction that causes the fault/trap. So we 103530fdc8d8SChris Lattner // // take it out by trimming the expression right at the first "DW_OP_swap" opcodes 103630fdc8d8SChris Lattner // if (block_data != NULL && thread->GetPCRegNum(Thread::GCC) == reg_num) 103730fdc8d8SChris Lattner // { 103830fdc8d8SChris Lattner // if (thread->Is64Bit()) 103930fdc8d8SChris Lattner // { 104030fdc8d8SChris Lattner // if (block_len > 9 && block_data[8] == DW_OP_swap && block_data[9] == DW_OP_plus_uconst) 104130fdc8d8SChris Lattner // block_len = 8; 104230fdc8d8SChris Lattner // } 104330fdc8d8SChris Lattner // else 104430fdc8d8SChris Lattner // { 104530fdc8d8SChris Lattner // if (block_len > 8 && block_data[7] == DW_OP_swap && block_data[8] == DW_OP_plus_uconst) 104630fdc8d8SChris Lattner // block_len = 7; 104730fdc8d8SChris Lattner // } 104830fdc8d8SChris Lattner // } 104930fdc8d8SChris Lattner //#endif 105030fdc8d8SChris Lattner reg_location.SetIsDWARFExpression(block_data, block_len); 105130fdc8d8SChris Lattner row.SetRegisterInfo (reg_num, reg_location); 105230fdc8d8SChris Lattner } 105330fdc8d8SChris Lattner break; 105430fdc8d8SChris Lattner 105530fdc8d8SChris Lattner case DW_CFA_val_offset : // 0x14 105630fdc8d8SChris Lattner case DW_CFA_val_offset_sf : // 0x15 105730fdc8d8SChris Lattner default: 105830fdc8d8SChris Lattner tmp_uval32 = extended_opcode; 105930fdc8d8SChris Lattner break; 106030fdc8d8SChris Lattner } 106130fdc8d8SChris Lattner } 106230fdc8d8SChris Lattner } 106330fdc8d8SChris Lattner fde->AppendRow(row); 106430fdc8d8SChris Lattner } 106530fdc8d8SChris Lattner 106630fdc8d8SChris Lattner void 106730fdc8d8SChris Lattner DWARFCallFrameInfo::ParseAll() 106830fdc8d8SChris Lattner { 106930fdc8d8SChris Lattner Index(); 107030fdc8d8SChris Lattner fde_map_t::iterator pos, end = m_fde_map.end(); 107130fdc8d8SChris Lattner for (pos = m_fde_map.begin(); pos != end; ++ pos) 107230fdc8d8SChris Lattner { 107330fdc8d8SChris Lattner if (pos->second.fde_sp.get() == NULL) 107430fdc8d8SChris Lattner pos->second.fde_sp = ParseFDE(pos->second.fde_offset); 107530fdc8d8SChris Lattner } 107630fdc8d8SChris Lattner } 107730fdc8d8SChris Lattner 107830fdc8d8SChris Lattner 107930fdc8d8SChris Lattner //bool 108030fdc8d8SChris Lattner //DWARFCallFrameInfo::UnwindRegisterAtIndex 108130fdc8d8SChris Lattner //( 108230fdc8d8SChris Lattner // const uint32_t reg_idx, 108330fdc8d8SChris Lattner // const Thread* currState, 108430fdc8d8SChris Lattner // const DWARFCallFrameInfo::Row* row, 108530fdc8d8SChris Lattner // mapped_memory_t * memCache, 108630fdc8d8SChris Lattner // Thread* unwindState 108730fdc8d8SChris Lattner //) 108830fdc8d8SChris Lattner //{ 108930fdc8d8SChris Lattner // bool get_reg_success = false; 109030fdc8d8SChris Lattner // 109130fdc8d8SChris Lattner // const RegLocation* regLocation = row->regs.GetRegisterInfo(reg_idx); 109230fdc8d8SChris Lattner // 109330fdc8d8SChris Lattner // // On some systems, we may not get unwind info for the program counter, 109430fdc8d8SChris Lattner // // but the return address register can be used to get that information. 109530fdc8d8SChris Lattner // if (reg_idx == currState->GetPCRegNum(Thread::Index)) 109630fdc8d8SChris Lattner // { 109730fdc8d8SChris Lattner // const RegLocation* returnAddrRegLocation = row->regs.GetRegisterInfo(currState->GetRARegNum(Thread::Index)); 109830fdc8d8SChris Lattner // if (regLocation == NULL) 109930fdc8d8SChris Lattner // { 110030fdc8d8SChris Lattner // // We have nothing to the program counter, so lets see if this 110130fdc8d8SChris Lattner // // thread state has a return address (link register) that can 110230fdc8d8SChris Lattner // // help us track down the previous PC 110330fdc8d8SChris Lattner // regLocation = returnAddrRegLocation; 110430fdc8d8SChris Lattner // } 110530fdc8d8SChris Lattner // else if (regLocation->type == RegLocation::unspecified) 110630fdc8d8SChris Lattner // { 110730fdc8d8SChris Lattner // // We did have a location that didn't specify a value for unwinding 110830fdc8d8SChris Lattner // // the PC, so if there is a info for the return return address 110930fdc8d8SChris Lattner // // register (link register) lets use that 111030fdc8d8SChris Lattner // if (returnAddrRegLocation) 111130fdc8d8SChris Lattner // regLocation = returnAddrRegLocation; 111230fdc8d8SChris Lattner // } 111330fdc8d8SChris Lattner // } 111430fdc8d8SChris Lattner // 111530fdc8d8SChris Lattner // if (regLocation) 111630fdc8d8SChris Lattner // { 111730fdc8d8SChris Lattner // mach_vm_address_t unwoundRegValue = INVALID_VMADDR; 111830fdc8d8SChris Lattner // switch (regLocation->type) 111930fdc8d8SChris Lattner // { 112030fdc8d8SChris Lattner // case RegLocation::undefined: 112130fdc8d8SChris Lattner // // Register is not available, mark it as invalid 112230fdc8d8SChris Lattner // unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false); 112330fdc8d8SChris Lattner // return true; 112430fdc8d8SChris Lattner // 112530fdc8d8SChris Lattner // case RegLocation::unspecified: 112630fdc8d8SChris Lattner // // Nothing to do if it is the same 112730fdc8d8SChris Lattner // return true; 112830fdc8d8SChris Lattner // 112930fdc8d8SChris Lattner // case RegLocation::same: 113030fdc8d8SChris Lattner // // Nothing to do if it is the same 113130fdc8d8SChris Lattner // return true; 113230fdc8d8SChris Lattner // 113330fdc8d8SChris Lattner // case RegLocation::atFPPlusOffset: 113430fdc8d8SChris Lattner // case RegLocation::isFPPlusOffset: 113530fdc8d8SChris Lattner // { 113630fdc8d8SChris Lattner // uint64_t unwindAddress = currState->GetRegisterValue(row->cfa_register, Thread::GCC, INVALID_VMADDR, &get_reg_success); 113730fdc8d8SChris Lattner // 113830fdc8d8SChris Lattner // if (get_reg_success) 113930fdc8d8SChris Lattner // { 114030fdc8d8SChris Lattner // unwindAddress += row->cfa_offset + regLocation->location.offset; 114130fdc8d8SChris Lattner // 114230fdc8d8SChris Lattner // if (regLocation->type == RegLocation::isFPPlusOffset) 114330fdc8d8SChris Lattner // { 114430fdc8d8SChris Lattner // unwindState->SetRegisterValue(reg_idx, Thread::Index, unwindAddress); 114530fdc8d8SChris Lattner // return true; 114630fdc8d8SChris Lattner // } 114730fdc8d8SChris Lattner // else 114830fdc8d8SChris Lattner // { 114930fdc8d8SChris Lattner // kern_return_t err = mapped_memory_read_pointer(memCache, unwindAddress, &unwoundRegValue); 115030fdc8d8SChris Lattner // if (err != KERN_SUCCESS) 115130fdc8d8SChris Lattner // { 115230fdc8d8SChris Lattner // unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false); 115330fdc8d8SChris Lattner // return false; 115430fdc8d8SChris Lattner // } 115530fdc8d8SChris Lattner // unwindState->SetRegisterValue(reg_idx, Thread::Index, unwoundRegValue); 115630fdc8d8SChris Lattner // return true; 115730fdc8d8SChris Lattner // } 115830fdc8d8SChris Lattner // } 115930fdc8d8SChris Lattner // else 116030fdc8d8SChris Lattner // { 116130fdc8d8SChris Lattner // unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false); 116230fdc8d8SChris Lattner // } 116330fdc8d8SChris Lattner // return false; 116430fdc8d8SChris Lattner // } 116530fdc8d8SChris Lattner // break; 116630fdc8d8SChris Lattner // 116730fdc8d8SChris Lattner // case RegLocation::atDWARFExpression: 116830fdc8d8SChris Lattner // case RegLocation::isDWARFExpression: 116930fdc8d8SChris Lattner // { 117030fdc8d8SChris Lattner // bool swap = false; 117130fdc8d8SChris Lattner // DWARFExpressionBaton baton = { currState, memCache, swap }; 117230fdc8d8SChris Lattner // uint64_t expr_result = 0; 117330fdc8d8SChris Lattner // CSBinaryDataRef opcodes(regLocation->location.expr.opcodes, regLocation->location.expr.length, swap); 117430fdc8d8SChris Lattner // opcodes.SetPointerSize(currState->Is64Bit() ? 8 : 4); 117530fdc8d8SChris Lattner // const char * expr_err = CSDWARFExpression::Evaluate(DWARFExpressionReadMemoryDCScriptInterpreter::Type, 117630fdc8d8SChris Lattner // DWARFExpressionReadRegisterDCScriptInterpreter::Type, 117730fdc8d8SChris Lattner // &baton, 117830fdc8d8SChris Lattner // opcodes, 117930fdc8d8SChris Lattner // 0, 118030fdc8d8SChris Lattner // regLocation->location.expr.length, 118130fdc8d8SChris Lattner // NULL, 118230fdc8d8SChris Lattner // expr_result); 118330fdc8d8SChris Lattner // if (expr_err == NULL) 118430fdc8d8SChris Lattner // { 118530fdc8d8SChris Lattner // // SUCCESS! 118630fdc8d8SChris Lattner // if (regLocation->type == RegLocation::isDWARFExpression) 118730fdc8d8SChris Lattner // { 118830fdc8d8SChris Lattner // unwindState->SetRegisterValue(reg_idx, Thread::Index, expr_result); 118930fdc8d8SChris Lattner // return true; 119030fdc8d8SChris Lattner // } 119130fdc8d8SChris Lattner // else 119230fdc8d8SChris Lattner // { 119330fdc8d8SChris Lattner // kern_return_t err = mapped_memory_read_pointer(memCache, expr_result, &unwoundRegValue); 119430fdc8d8SChris Lattner // if (err != KERN_SUCCESS) 119530fdc8d8SChris Lattner // { 119630fdc8d8SChris Lattner // unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false); 119730fdc8d8SChris Lattner // return false; 119830fdc8d8SChris Lattner // } 119930fdc8d8SChris Lattner // unwindState->SetRegisterValue(reg_idx, Thread::Index, unwoundRegValue); 120030fdc8d8SChris Lattner // return true; 120130fdc8d8SChris Lattner // } 120230fdc8d8SChris Lattner // } 120330fdc8d8SChris Lattner // else 120430fdc8d8SChris Lattner // { 120530fdc8d8SChris Lattner // // FAIL 120630fdc8d8SChris Lattner // unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false); 120730fdc8d8SChris Lattner // } 120830fdc8d8SChris Lattner // return false; 120930fdc8d8SChris Lattner // } 121030fdc8d8SChris Lattner // break; 121130fdc8d8SChris Lattner // 121230fdc8d8SChris Lattner // 121330fdc8d8SChris Lattner // case RegLocation::inRegister: 121430fdc8d8SChris Lattner // // The value is in another register. 121530fdc8d8SChris Lattner // unwoundRegValue = currState->GetRegisterValue(regLocation->location.reg, Thread::GCC, 0, &get_reg_success); 121630fdc8d8SChris Lattner // if (get_reg_success) 121730fdc8d8SChris Lattner // { 121830fdc8d8SChris Lattner // unwindState->SetRegisterValue(reg_idx, Thread::Index, unwoundRegValue); 121930fdc8d8SChris Lattner // return true; 122030fdc8d8SChris Lattner // } 122130fdc8d8SChris Lattner // return false; 122230fdc8d8SChris Lattner // 122330fdc8d8SChris Lattner // default: 122430fdc8d8SChris Lattner // break; 122530fdc8d8SChris Lattner // } 122630fdc8d8SChris Lattner // } 122730fdc8d8SChris Lattner // 122830fdc8d8SChris Lattner // if (reg_idx == currState->GetSPRegNum(Thread::Index)) 122930fdc8d8SChris Lattner // { 123030fdc8d8SChris Lattner // uint64_t cfa = currState->GetRegisterValue(row->cfa_register, Thread::GCC, 0, &get_reg_success); 123130fdc8d8SChris Lattner // if (get_reg_success) 123230fdc8d8SChris Lattner // { 123330fdc8d8SChris Lattner // return unwindState->SetSP(cfa + row->cfa_offset); 123430fdc8d8SChris Lattner // } 123530fdc8d8SChris Lattner // else 123630fdc8d8SChris Lattner // { 123730fdc8d8SChris Lattner // unwindState->SetRegisterIsValid(reg_idx, Thread::Index, false); 123830fdc8d8SChris Lattner // return false; 123930fdc8d8SChris Lattner // } 124030fdc8d8SChris Lattner // } 124130fdc8d8SChris Lattner // 124230fdc8d8SChris Lattner // return false; 124330fdc8d8SChris Lattner //} 124430fdc8d8SChris Lattner 124530fdc8d8SChris Lattner void 124630fdc8d8SChris Lattner DWARFCallFrameInfo::Dump(Stream *s, Thread *thread) const 124730fdc8d8SChris Lattner { 124830fdc8d8SChris Lattner s->Indent(); 124930fdc8d8SChris Lattner s->Printf("DWARFCallFrameInfo for "); 125030fdc8d8SChris Lattner *s << m_objfile->GetFileSpec(); 125130fdc8d8SChris Lattner if (m_flags.IsSet(eFlagParsedIndex)) 125230fdc8d8SChris Lattner { 125330fdc8d8SChris Lattner s->Printf(" (CIE[%zu], FDE[%zu])\n", m_cie_map.size(), m_fde_map.size()); 125430fdc8d8SChris Lattner s->IndentMore(); 125530fdc8d8SChris Lattner cie_map_t::const_iterator cie_pos, cie_end = m_cie_map.end(); 125630fdc8d8SChris Lattner const ArchSpec *arch = &m_objfile->GetModule()->GetArchitecture(); 125730fdc8d8SChris Lattner 125830fdc8d8SChris Lattner for (cie_pos = m_cie_map.begin(); cie_pos != cie_end; ++ cie_pos) 125930fdc8d8SChris Lattner { 126030fdc8d8SChris Lattner if (cie_pos->second.get() == NULL) 126130fdc8d8SChris Lattner { 126230fdc8d8SChris Lattner s->Indent(); 126330fdc8d8SChris Lattner s->Printf("CIE{0x%8.8x} - unparsed\n", cie_pos->first); 126430fdc8d8SChris Lattner } 126530fdc8d8SChris Lattner else 126630fdc8d8SChris Lattner { 126730fdc8d8SChris Lattner cie_pos->second->Dump(s, thread, arch, m_reg_kind); 126830fdc8d8SChris Lattner } 126930fdc8d8SChris Lattner } 127030fdc8d8SChris Lattner 127130fdc8d8SChris Lattner fde_map_t::const_iterator fde_pos, fde_end = m_fde_map.end(); 127230fdc8d8SChris Lattner for (fde_pos = m_fde_map.begin(); fde_pos != fde_end; ++ fde_pos) 127330fdc8d8SChris Lattner { 127430fdc8d8SChris Lattner if (fde_pos->second.fde_sp.get() == NULL) 127530fdc8d8SChris Lattner { 127630fdc8d8SChris Lattner s->Indent(); 127730fdc8d8SChris Lattner s->Printf("FDE{0x%8.8x} - unparsed\n", fde_pos->second.fde_offset); 127830fdc8d8SChris Lattner } 127930fdc8d8SChris Lattner else 128030fdc8d8SChris Lattner { 128130fdc8d8SChris Lattner fde_pos->second.fde_sp->Dump(s, *this, thread); 128230fdc8d8SChris Lattner } 128330fdc8d8SChris Lattner } 128430fdc8d8SChris Lattner s->IndentLess(); 128530fdc8d8SChris Lattner } 128630fdc8d8SChris Lattner else 128730fdc8d8SChris Lattner { 128830fdc8d8SChris Lattner s->PutCString(" (not indexed yet)\n"); 128930fdc8d8SChris Lattner } 129030fdc8d8SChris Lattner } 129130fdc8d8SChris Lattner 129230fdc8d8SChris Lattner 129330fdc8d8SChris Lattner //uint32_t 129430fdc8d8SChris Lattner //DWARFCallFrameInfo::UnwindThreadState(const Thread* currState, mapped_memory_t *memCache, bool is_first_frame, Thread* unwindState) 129530fdc8d8SChris Lattner //{ 129630fdc8d8SChris Lattner // if (currState == NULL || unwindState == NULL) 129730fdc8d8SChris Lattner // return 0; 129830fdc8d8SChris Lattner // 129930fdc8d8SChris Lattner // *unwindState = *currState; 130030fdc8d8SChris Lattner // uint32_t numRegisterUnwound = 0; 130130fdc8d8SChris Lattner // uint64_t currPC = currState->GetPC(INVALID_VMADDR); 130230fdc8d8SChris Lattner // 130330fdc8d8SChris Lattner // if (currPC != INVALID_VMADDR) 130430fdc8d8SChris Lattner // { 130530fdc8d8SChris Lattner // // If this is not the first frame, we care about the previous instruction 130630fdc8d8SChris Lattner // // since it will be at the instruction following the instruction that 130730fdc8d8SChris Lattner // // made the function call. 130830fdc8d8SChris Lattner // uint64_t unwindPC = currPC; 130930fdc8d8SChris Lattner // if (unwindPC > 0 && !is_first_frame) 131030fdc8d8SChris Lattner // --unwindPC; 131130fdc8d8SChris Lattner // 131230fdc8d8SChris Lattner //#if defined(__i386__) || defined(__x86_64__) 131330fdc8d8SChris Lattner // // Only on i386 do we have __IMPORT segments that contain trampolines 131430fdc8d8SChris Lattner // if (!currState->Is64Bit() && ImportRangesContainsAddress(unwindPC)) 131530fdc8d8SChris Lattner // { 131630fdc8d8SChris Lattner // uint64_t curr_sp = currState->GetSP(INVALID_VMADDR); 131730fdc8d8SChris Lattner // mach_vm_address_t pc = INVALID_VMADDR; 131830fdc8d8SChris Lattner // unwindState->SetSP(curr_sp + 4); 131930fdc8d8SChris Lattner // kern_return_t err = mapped_memory_read_pointer(memCache, curr_sp, &pc); 132030fdc8d8SChris Lattner // if (err == KERN_SUCCESS) 132130fdc8d8SChris Lattner // { 132230fdc8d8SChris Lattner // unwindState->SetPC(pc); 132330fdc8d8SChris Lattner // return 2; 132430fdc8d8SChris Lattner // } 132530fdc8d8SChris Lattner // } 132630fdc8d8SChris Lattner //#endif 132730fdc8d8SChris Lattner // FDE *fde = FindFDE(unwindPC); 132830fdc8d8SChris Lattner // if (fde) 132930fdc8d8SChris Lattner // { 133030fdc8d8SChris Lattner // FindRowUserData rowUserData (currState, unwindPC); 133130fdc8d8SChris Lattner // ParseInstructions (currState, fde, FindRowForAddress, &rowUserData); 133230fdc8d8SChris Lattner // 133330fdc8d8SChris Lattner // const uint32_t numRegs = currState->NumRegisters(); 133430fdc8d8SChris Lattner // for (uint32_t regNum = 0; regNum < numRegs; regNum++) 133530fdc8d8SChris Lattner // { 133630fdc8d8SChris Lattner // if (UnwindRegisterAtIndex(regNum, currState, &rowUserData.state, memCache, unwindState)) 133730fdc8d8SChris Lattner // numRegisterUnwound++; 133830fdc8d8SChris Lattner // } 133930fdc8d8SChris Lattner // } 134030fdc8d8SChris Lattner // } 134130fdc8d8SChris Lattner // return numRegisterUnwound; 134230fdc8d8SChris Lattner //} 134330fdc8d8SChris Lattner 134430fdc8d8SChris Lattner 1345