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