UnwindAssembly-x86.cpp revision a2c269c017d37b3e35f461af52e11cdd6300d5e4
13a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//===-- UnwindAssemblyProfiler-x86.cpp --------------------------*- C++ -*-===//
23a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//
33a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//                     The LLVM Compiler Infrastructure
43a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//
53a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// This file is distributed under the University of Illinois Open Source
63a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// License. See LICENSE.TXT for details.
73a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//
83a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//===----------------------------------------------------------------------===//
93a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
103a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "UnwindAssemblyProfiler-x86.h"
113a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
123a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "lldb/lldb-private.h"
133a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "lldb/Utility/UnwindAssemblyProfiler.h"
143a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "lldb/Core/Address.h"
153a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "lldb/Core/Error.h"
163a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "lldb/Core/ArchSpec.h"
173a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "lldb/Core/PluginManager.h"
183a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "lldb/Target/ExecutionContext.h"
193a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "lldb/Target/Process.h"
203a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "lldb/Target/RegisterContext.h"
213a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "lldb/Target/Thread.h"
223a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "lldb/Target/Target.h"
233a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "lldb/Symbol/UnwindPlan.h"
243a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
253a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "lldb/lldb-enumerations.h"
263a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "llvm-c/EnhancedDisassembly.h"
273a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
283a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "UnwindAssemblyProfiler-x86.h"
293a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
303a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
313a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendausing namespace lldb;
323a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendausing namespace lldb_private;
333a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
343a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendaenum CPU {
353a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_i386,
363a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_x86_64
373a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda};
383a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
393a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendaenum i386_register_numbers {
403a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_eax = 0,
413a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_ecx = 1,
423a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_edx = 2,
433a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_ebx = 3,
443a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_esp = 4,
453a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_ebp = 5,
463a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_esi = 6,
473a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_edi = 7,
483a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_eip = 8
493a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda};
503a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
513a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendaenum x86_64_register_numbers {
523a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_rax = 0,
533a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_rcx = 1,
543a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_rdx = 2,
553a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_rbx = 3,
563a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_rsp = 4,
573a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_rbp = 5,
583a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_rsi = 6,
593a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_rdi = 7,
603a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_r8 = 8,
613a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_r9 = 9,
623a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_r10 = 10,
633a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_r11 = 11,
643a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_r12 = 12,
653a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_r13 = 13,
663a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_r14 = 14,
673a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_r15 = 15,
683a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    k_machine_rip = 16
693a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda};
703a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
713a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendastruct regmap_ent {
723a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    const char *name;
733a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int machine_regno;
743a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int lldb_regno;
753a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda};
763a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
773a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendastatic struct regmap_ent i386_register_map[] = {
783a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"eax", k_machine_eax, -1},
793a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"ecx", k_machine_ecx, -1},
803a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"edx", k_machine_edx, -1},
813a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"ebx", k_machine_ebx, -1},
823a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"esp", k_machine_esp, -1},
833a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"ebp", k_machine_ebp, -1},
843a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"esi", k_machine_esi, -1},
853a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"edi", k_machine_edi, -1},
863a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"eip", k_machine_eip, -1}
873a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda};
883a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
893a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendaconst int size_of_i386_register_map = sizeof (i386_register_map) / sizeof (struct regmap_ent);
903a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
913a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendastatic int i386_register_map_initialized = 0;
923a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
933a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendastatic struct regmap_ent x86_64_register_map[] = {
943a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"rax", k_machine_rax, -1},
953a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"rcx", k_machine_rcx, -1},
963a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"rdx", k_machine_rdx, -1},
973a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"rbx", k_machine_rbx, -1},
983a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"rsp", k_machine_rsp, -1},
993a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"rbp", k_machine_rbp, -1},
1003a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"rsi", k_machine_rsi, -1},
1013a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"rdi", k_machine_rdi, -1},
1023a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"r8", k_machine_r8, -1},
1033a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"r9", k_machine_r9, -1},
1043a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"r10", k_machine_r10, -1},
1053a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"r11", k_machine_r11, -1},
1063a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"r12", k_machine_r12, -1},
1073a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"r13", k_machine_r13, -1},
1083a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"r14", k_machine_r14, -1},
1093a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"r15", k_machine_r15, -1},
1103a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {"rip", k_machine_rip, -1}
1113a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda};
1123a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1133a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendaconst int size_of_x86_64_register_map = sizeof (x86_64_register_map) / sizeof (struct regmap_ent);
1143a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1153a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendastatic int x86_64_register_map_initialized = 0;
1163a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1173a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//-----------------------------------------------------------------------------------------------
1183a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//  AssemblyParse_x86 local-file class definition & implementation functions
1193a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//-----------------------------------------------------------------------------------------------
1203a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1213a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendaclass AssemblyParse_x86 {
1223a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendapublic:
1233a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1243a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    AssemblyParse_x86 (Target &target, Thread *thread, int cpu, AddressRange func);
1253a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1263a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    bool get_non_call_site_unwind_plan (UnwindPlan &unwind_plan);
1273a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1288280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    bool get_fast_unwind_plan (AddressRange& func, UnwindPlan &unwind_plan);
1293a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1303a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    bool find_first_non_prologue_insn (Address &address);
1313a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1323a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendaprivate:
1333a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    enum { kMaxInstructionByteSize = 32 };
1343a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1353a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    bool nonvolatile_reg_p (int machine_regno);
1363a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    bool push_rbp_pattern_p ();
1373a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    bool push_0_pattern_p ();
1383a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    bool mov_rsp_rbp_pattern_p ();
1393a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    bool sub_rsp_pattern_p (int& amount);
1403a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    bool push_reg_p (int& regno);
1413a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    bool mov_reg_to_local_stack_frame_p (int& regno, int& fp_offset);
1423a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    bool ret_pattern_p ();
1433a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    uint32_t extract_4 (uint8_t *b);
1443a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    bool machine_regno_to_lldb_regno (int machine_regno, uint32_t& lldb_regno);
1453a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    bool instruction_length (Address addr, int &length);
1463a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1473a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    Target &m_target;
1483a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    Thread* m_thread;
1493a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1503a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    AddressRange m_func_bounds;
1513a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1523a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    Address m_cur_insn;
1533a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    uint8_t m_cur_insn_bytes[kMaxInstructionByteSize];
1543a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1553a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int m_machine_ip_regnum;
1563a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int m_machine_sp_regnum;
1573a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int m_machine_fp_regnum;
1583a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1593a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int m_lldb_ip_regnum;
1603a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int m_lldb_sp_regnum;
1613a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int m_lldb_fp_regnum;
1623a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1633a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int m_wordsize;
1643a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int m_cpu;
1653a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda};
1663a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1673a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaAssemblyParse_x86::AssemblyParse_x86 (Target& target, Thread* thread, int cpu, AddressRange func) :
1683a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                         m_target (target), m_thread (thread), m_cpu(cpu), m_func_bounds(func)
1698280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda{
1703a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int *initialized_flag = NULL;
1713a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    m_lldb_ip_regnum = m_lldb_sp_regnum = m_lldb_fp_regnum = -1;
1723a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (cpu == k_i386)
1733a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {
1743a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        m_machine_ip_regnum = k_machine_eip;
1753a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        m_machine_sp_regnum = k_machine_esp;
1763a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        m_machine_fp_regnum = k_machine_ebp;
1773a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        m_wordsize = 4;
1783a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        initialized_flag = &i386_register_map_initialized;
1793a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
1803a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    else
1813a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {
1823a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        m_machine_ip_regnum = k_machine_rip;
1833a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        m_machine_sp_regnum = k_machine_rsp;
1843a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        m_machine_fp_regnum = k_machine_rbp;
1853a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        m_wordsize = 8;
1863a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        initialized_flag = &x86_64_register_map_initialized;
1873a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
1883a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1893a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    // we only look at prologue - it will be complete earlier than 512 bytes into func
1903a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (m_func_bounds.GetByteSize() == 0)
1913a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        m_func_bounds.SetByteSize(512);
1923a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1933a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (m_thread && *initialized_flag == 0)
1943a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {
1953a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        RegisterContext *rctx = m_thread->GetRegisterContext();
1963a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (rctx)
1973a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        {
1983a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            struct regmap_ent *ent;
1993a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            int count, i;
2003a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            if (cpu == k_i386)
2013a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            {
2023a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                ent = i386_register_map;
2033a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                count = size_of_i386_register_map;
2043a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            }
2053a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            else
2063a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            {
2073a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                ent = x86_64_register_map;
2083a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                count = size_of_x86_64_register_map;
2093a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            }
2103a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            for (i = 0; i < count; i++, ent++)
2113a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            {
2123a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                const RegisterInfo *ri = rctx->GetRegisterInfoByName (ent->name);
2133a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                if (ri)
2143a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                    ent->lldb_regno = ri->kinds[eRegisterKindLLDB];
2153a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            }
2163a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            *initialized_flag = 1;
2173a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        }
2183a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
2193a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
2203a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda   // on initial construction we may not have a Thread so these have to remain
2213a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda   // uninitialized until we can get a RegisterContext to set up the register map table
2223a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda   if (*initialized_flag == 1)
2233a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda   {
2243a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda       uint32_t lldb_regno;
2253a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda       if (machine_regno_to_lldb_regno (m_machine_sp_regnum, lldb_regno))
2263a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda           m_lldb_sp_regnum = lldb_regno;
2273a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda       if (machine_regno_to_lldb_regno (m_machine_fp_regnum, lldb_regno))
2283a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda           m_lldb_fp_regnum = lldb_regno;
2293a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda       if (machine_regno_to_lldb_regno (m_machine_ip_regnum, lldb_regno))
2303a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda           m_lldb_ip_regnum = lldb_regno;
2313a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda   }
2323a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
2333a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
2343a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
2353a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// This function expects an x86 native register number (i.e. the bits stripped out of the
2363a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// actual instruction), not an lldb register number.
2373a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
2383a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendabool
2393a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaAssemblyParse_x86::nonvolatile_reg_p (int machine_regno)
2403a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
2413a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (m_cpu == k_i386)
2423a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {
2433a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda          switch (machine_regno) {
2443a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda              case k_machine_ebx:
2453a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda              case k_machine_ebp:  // not actually a nonvolatile but often treated as such by convention
2463a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda              case k_machine_esi:
2473a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda              case k_machine_edi:
2483a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda              case k_machine_esp:
2493a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                  return true;
2503a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda              default:
2513a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                  return false;
2523a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda          }
2533a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
2543a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (m_cpu == k_x86_64)
2553a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {
2563a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda          switch (machine_regno) {
2573a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda              case k_machine_rbx:
2583a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda              case k_machine_rsp:
2593a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda              case k_machine_rbp:  // not actually a nonvolatile but often treated as such by convention
2603a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda              case k_machine_r12:
2613a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda              case k_machine_r13:
2623a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda              case k_machine_r14:
2633a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda              case k_machine_r15:
2643a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                  return true;
2653a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda              default:
2663a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                  return false;
2673a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda          }
2683a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
2693a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return false;
2703a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
2713a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
2723a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
2733a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// Macro to detect if this is a REX mode prefix byte.
2743a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#define REX_W_PREFIX_P(opcode) (((opcode) & (~0x5)) == 0x48)
2753a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
2763a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// The high bit which should be added to the source register number (the "R" bit)
2773a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#define REX_W_SRCREG(opcode) (((opcode) & 0x4) >> 2)
2783a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
2793a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// The high bit which should be added to the destination register number (the "B" bit)
2803a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#define REX_W_DSTREG(opcode) ((opcode) & 0x1)
2813a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
2823a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// pushq %rbp [0x55]
2833a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendabool AssemblyParse_x86::push_rbp_pattern_p () {
2843a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    uint8_t *p = m_cur_insn_bytes;
2853a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (*p == 0x55)
2863a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda      return true;
2873a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return false;
2883a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
2893a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
2903a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// pushq $0 ; the first instruction in start() [0x6a 0x00]
2913a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendabool AssemblyParse_x86::push_0_pattern_p ()
2923a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
2933a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    uint8_t *p = m_cur_insn_bytes;
2943a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (*p == 0x6a && *(p + 1) == 0x0)
2953a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        return true;
2963a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return false;
2973a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
2983a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
2993a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5]
3003a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// movl %esp, %ebp [0x8b 0xec] or [0x89 0xe5]
3013a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendabool AssemblyParse_x86::mov_rsp_rbp_pattern_p () {
3023a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    uint8_t *p = m_cur_insn_bytes;
3033a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (m_wordsize == 8 && *p == 0x48)
3043a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda      p++;
3053a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (*(p) == 0x8b && *(p + 1) == 0xec)
3063a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        return true;
3073a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (*(p) == 0x89 && *(p + 1) == 0xe5)
3083a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        return true;
3093a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return false;
3103a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
3113a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
3123a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// subq $0x20, %rsp
3133a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendabool AssemblyParse_x86::sub_rsp_pattern_p (int& amount) {
3143a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    uint8_t *p = m_cur_insn_bytes;
3153a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (m_wordsize == 8 && *p == 0x48)
3163a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda      p++;
3173a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    // 8-bit immediate operand
3183a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (*p == 0x83 && *(p + 1) == 0xec) {
3193a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        amount = (int8_t) *(p + 2);
3203a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        return true;
3213a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
3223a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    // 32-bit immediate operand
3233a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (*p == 0x81 && *(p + 1) == 0xec) {
3243a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        amount = (int32_t) extract_4 (p + 2);
3253a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        return true;
3263a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
3273a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    // Not handled:  [0x83 0xc4] for imm8 with neg values
3283a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    // [0x81 0xc4] for imm32 with neg values
3293a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return false;
3303a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
3313a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
3323a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// pushq %rbx
3333a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// pushl $ebx
3343a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendabool AssemblyParse_x86::push_reg_p (int& regno) {
3353a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    uint8_t *p = m_cur_insn_bytes;
3363a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int regno_prefix_bit = 0;
3373a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    // If we have a rex prefix byte, check to see if a B bit is set
3383a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (m_wordsize == 8 && *p == 0x41) {
3393a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        regno_prefix_bit = 1 << 3;
3403a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        p++;
3413a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
3423a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (*p >= 0x50 && *p <= 0x57) {
3433a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        regno = (*p - 0x50) | regno_prefix_bit;
3443a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        return true;
3453a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
3463a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return false;
3473a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
3483a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
3493a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// Look for an instruction sequence storing a nonvolatile register
3503a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// on to the stack frame.
3513a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
3523a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//  movq %rax, -0x10(%rbp) [0x48 0x89 0x45 0xf0]
3533a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//  movl %eax, -0xc(%ebp)  [0x89 0x45 0xf4]
3543a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendabool AssemblyParse_x86::mov_reg_to_local_stack_frame_p (int& regno, int& rbp_offset) {
3553a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    uint8_t *p = m_cur_insn_bytes;
3563a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int src_reg_prefix_bit = 0;
3573a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int target_reg_prefix_bit = 0;
3583a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
3593a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (m_wordsize == 8 && REX_W_PREFIX_P (*p)) {
3603a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        src_reg_prefix_bit = REX_W_SRCREG (*p) << 3;
3613a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        target_reg_prefix_bit = REX_W_DSTREG (*p) << 3;
3623a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (target_reg_prefix_bit == 1) {
3633a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            // rbp/ebp don't need a prefix bit - we know this isn't the
3643a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            // reg we care about.
3653a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            return false;
3663a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        }
3673a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        p++;
3683a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
3693a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
3703a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (*p == 0x89) {
3713a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        /* Mask off the 3-5 bits which indicate the destination register
3723a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda           if this is a ModR/M byte.  */
3733a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        int opcode_destreg_masked_out = *(p + 1) & (~0x38);
3743a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
3753a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        /* Is this a ModR/M byte with Mod bits 01 and R/M bits 101
3763a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda           and three bits between them, e.g. 01nnn101
3773a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda           We're looking for a destination of ebp-disp8 or ebp-disp32.   */
3783a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        int immsize;
3793a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (opcode_destreg_masked_out == 0x45)
3803a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda          immsize = 2;
3813a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        else if (opcode_destreg_masked_out == 0x85)
3823a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda          immsize = 4;
3833a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        else
3843a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda          return false;
3853a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
3863a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        int offset = 0;
3873a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (immsize == 2)
3883a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda          offset = (int8_t) *(p + 2);
3893a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (immsize == 4)
3903a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda             offset = (uint32_t) extract_4 (p + 2);
3913a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (offset > 0)
3923a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda          return false;
3933a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
3943a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        regno = ((*(p + 1) >> 3) & 0x7) | src_reg_prefix_bit;
3953a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        rbp_offset = offset > 0 ? offset : -offset;
3963a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        return true;
3973a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
3983a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return false;
3993a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
4003a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
4013a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// ret [0xc9] or [0xc2 imm8] or [0xca imm8]
4023a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendabool
4033a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaAssemblyParse_x86::ret_pattern_p ()
4043a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
4053a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    uint8_t *p = m_cur_insn_bytes;
4063a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (*p == 0xc9 || *p == 0xc2 || *p == 0xca || *p == 0xc3)
4073a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        return true;
4083a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return false;
4093a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
4103a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
4113a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendauint32_t
4123a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaAssemblyParse_x86::extract_4 (uint8_t *b)
4133a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
4143a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    uint32_t v = 0;
4153a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    for (int i = 3; i >= 0; i--)
4163a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        v = (v << 8) | b[i];
4173a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return v;
4183a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
4193a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
4203a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendabool
4213a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaAssemblyParse_x86::machine_regno_to_lldb_regno (int machine_regno, uint32_t &lldb_regno)
4223a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
4233a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    struct regmap_ent *ent;
4243a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int count, i;
4253a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (m_cpu == k_i386)
4263a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {
4273a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        ent = i386_register_map;
4283a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        count = size_of_i386_register_map;
4293a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
4303a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    else
4313a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {
4323a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        ent = x86_64_register_map;
4333a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        count = size_of_x86_64_register_map;
4343a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
4353a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    for (i = 0; i < count; i++, ent++)
4363a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {
4373a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (ent->machine_regno == machine_regno)
4383a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            if (ent->lldb_regno != -1)
4393a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            {
4403a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                lldb_regno = ent->lldb_regno;
4413a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                return true;
4423a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            }
4433a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
4443a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return false;
4453a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
4463a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
4473a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendastruct edis_byte_read_token
4483a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
4493a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    Address *address;
4503a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    Target *target;
4513a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda};
4523a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
4533a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
4543a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendastatic int
4553a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendaread_byte_for_edis (uint8_t *buf, uint64_t offset_address, void *arg)
4563a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
4573a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (arg == 0)
4583a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        return -1;
4593a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    struct edis_byte_read_token *tok = (edis_byte_read_token *) arg;
4603a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    Address *base_address = tok->address;
4613a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    Target *target = tok->target;
4623a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
4633a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    Address read_addr = *base_address;
4643a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    read_addr.SetOffset (offset_address);
4653a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
4663a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    uint8_t onebyte_buf[1];
4673a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    Error error;
4683a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (target->ReadMemory (read_addr, onebyte_buf, 1, error) != -1)
4693a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {
4703a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        *buf = onebyte_buf[0];
4713a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        return 0;
4723a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
4733a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return -1;
4743a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
4753a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
4763a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
4773a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendabool
4783a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaAssemblyParse_x86::instruction_length (Address addr, int &length)
4793a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
4803a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    const char *triple;
4813a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    // FIXME should probably pass down the ArchSpec and work from that to make a portable triple
4823a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (m_cpu == k_i386)
483a2c269c017d37b3e35f461af52e11cdd6300d5e4Jason Molenda        triple = "i386-unknown-unknown";
4843a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    else
485a2c269c017d37b3e35f461af52e11cdd6300d5e4Jason Molenda        triple = "x86_64-unknown-unknown";
4863a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
4873a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    EDDisassemblerRef disasm;
4883a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    EDInstRef         cur_insn;
4893a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
490a2c269c017d37b3e35f461af52e11cdd6300d5e4Jason Molenda    if (EDGetDisassembler (&disasm, triple, kEDAssemblySyntaxX86ATT) != 0)
4913a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {
4928280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda        return false;
4933a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
4943a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
4953a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    uint64_t addr_offset = addr.GetOffset();
4963a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    struct edis_byte_read_token arg;
4973a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    arg.address = &addr;
4983a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    arg.target = &m_target;
4993a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (EDCreateInsts (&cur_insn, 1, disasm, read_byte_for_edis, addr_offset, &arg) != 1)
5003a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {
5018280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda        return false;
5023a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
5033a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    length = EDInstByteSize (cur_insn);
5043a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    EDReleaseInst (cur_insn);
5053a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return true;
5063a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
5073a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
5083a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
5093a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendabool
5103a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaAssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
5113a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
5123a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    UnwindPlan up;
5133a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    UnwindPlan::Row row;
5143a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int non_prologue_insn_count = 0;
5153a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    Address m_cur_insn = m_func_bounds.GetBaseAddress ();
5163a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int current_func_text_offset = 0;
5173a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    int current_sp_bytes_offset_from_cfa = 0;
5183a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    UnwindPlan::Row::RegisterLocation regloc;
5193a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
5203a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    unwind_plan.SetPlanValidAddressRange (m_func_bounds);
5213a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    unwind_plan.SetRegisterKind (eRegisterKindLLDB);
5223a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
5233a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    // At the start of the function, find the CFA by adding wordsize to the SP register
5243a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    row.SetOffset (current_func_text_offset);
5253a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    row.SetCFARegister (m_lldb_sp_regnum);
5263a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    row.SetCFAOffset (m_wordsize);
5273a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
5283a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    // caller's stack pointer value before the call insn is the CFA address
5293a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    regloc.SetIsCFAPlusOffset (0);
5303a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    row.SetRegisterInfo (m_lldb_sp_regnum, regloc);
5313a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
5323a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    // saved instruction pointer can be found at CFA - wordsize.
5333a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    current_sp_bytes_offset_from_cfa = m_wordsize;
5343a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    regloc.SetAtCFAPlusOffset (-current_sp_bytes_offset_from_cfa);
5353a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    row.SetRegisterInfo (m_lldb_ip_regnum, regloc);
5363a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
5373a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    unwind_plan.AppendRow (row);
5383a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
5393a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    while (m_func_bounds.ContainsFileAddress (m_cur_insn) && non_prologue_insn_count < 10)
5403a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {
5413a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        int stack_offset, insn_len;
5423a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        int machine_regno;          // register numbers masked directly out of instructions
5433a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        uint32_t lldb_regno;        // register numbers in lldb's eRegisterKindLLDB numbering scheme
5443a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        Error error;
5453a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
5463a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (!instruction_length (m_cur_insn, insn_len) || insn_len == 0 || insn_len > kMaxInstructionByteSize)
5473a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        {
5483a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            // An unrecognized/junk instruction
5493a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            break;
5503a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        }
5513a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (m_target.ReadMemory (m_cur_insn, m_cur_insn_bytes, insn_len, error) == -1)
5523a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        {
5533a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda           // Error reading the instruction out of the file, stop scanning
5543a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda           break;
5553a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        }
5563a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
5573a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (push_rbp_pattern_p ())
5583a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        {
5593a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            row.SetOffset (current_func_text_offset + insn_len);
5603a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            current_sp_bytes_offset_from_cfa += m_wordsize;
5613a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            row.SetCFAOffset (current_sp_bytes_offset_from_cfa);
5623a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            UnwindPlan::Row::RegisterLocation regloc;
5633a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            regloc.SetAtCFAPlusOffset (-row.GetCFAOffset());
5643a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            row.SetRegisterInfo (m_lldb_fp_regnum, regloc);
5653a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            unwind_plan.AppendRow (row);
5663a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            goto loopnext;
5673a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        }
568a2c269c017d37b3e35f461af52e11cdd6300d5e4Jason Molenda
569a2c269c017d37b3e35f461af52e11cdd6300d5e4Jason Molenda        if (mov_rsp_rbp_pattern_p ())
570a2c269c017d37b3e35f461af52e11cdd6300d5e4Jason Molenda        {
571a2c269c017d37b3e35f461af52e11cdd6300d5e4Jason Molenda            row.SetOffset (current_func_text_offset + insn_len);
572a2c269c017d37b3e35f461af52e11cdd6300d5e4Jason Molenda            row.SetCFARegister (m_lldb_fp_regnum);
573a2c269c017d37b3e35f461af52e11cdd6300d5e4Jason Molenda            unwind_plan.AppendRow (row);
574a2c269c017d37b3e35f461af52e11cdd6300d5e4Jason Molenda            goto loopnext;
575a2c269c017d37b3e35f461af52e11cdd6300d5e4Jason Molenda        }
576a2c269c017d37b3e35f461af52e11cdd6300d5e4Jason Molenda
5778280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda        // This is the start() function (or a pthread equivalent), it starts with a pushl $0x0 which puts the
5788280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda        // saved pc value of 0 on the stack.  In this case we want to pretend we didn't see a stack movement at all --
5798280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda        // normally the saved pc value is already on the stack by the time the function starts executing.
5803a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (push_0_pattern_p ())
5813a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        {
5823a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            goto loopnext;
5833a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        }
5843a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
5853a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (push_reg_p (machine_regno))
5863a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        {
5873a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            current_sp_bytes_offset_from_cfa += m_wordsize;
5883a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            if (nonvolatile_reg_p (machine_regno) && machine_regno_to_lldb_regno (machine_regno, lldb_regno))
5893a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            {
5903a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                row.SetOffset (current_func_text_offset + insn_len);
5913a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                if (row.GetCFARegister() == m_lldb_sp_regnum)
5923a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                {
5933a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                    row.SetCFAOffset (current_sp_bytes_offset_from_cfa);
5943a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                }
5953a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                UnwindPlan::Row::RegisterLocation regloc;
5963a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                regloc.SetAtCFAPlusOffset (-current_sp_bytes_offset_from_cfa);
5973a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                row.SetRegisterInfo (lldb_regno, regloc);
5983a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                unwind_plan.AppendRow (row);
5993a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            }
6003a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            goto loopnext;
6013a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        }
6023a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
6033a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (mov_reg_to_local_stack_frame_p (machine_regno, stack_offset) && nonvolatile_reg_p (machine_regno))
6043a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        {
6053a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            if (machine_regno_to_lldb_regno (machine_regno, lldb_regno))
6063a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            {
6073a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                row.SetOffset (current_func_text_offset + insn_len);
6083a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                UnwindPlan::Row::RegisterLocation regloc;
6093a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                regloc.SetAtCFAPlusOffset (-row.GetCFAOffset());
6103a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                row.SetRegisterInfo (lldb_regno, regloc);
6113a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                unwind_plan.AppendRow (row);
6123a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                goto loopnext;
6133a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            }
6143a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        }
6153a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
6163a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (sub_rsp_pattern_p (stack_offset))
6173a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        {
6183a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            current_sp_bytes_offset_from_cfa += stack_offset;
6193a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            if (row.GetCFARegister() == m_lldb_sp_regnum)
6203a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            {
6213a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                row.SetOffset (current_func_text_offset + insn_len);
6223a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                row.SetCFAOffset (current_sp_bytes_offset_from_cfa);
6233a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                unwind_plan.AppendRow (row);
6243a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            }
6253a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            goto loopnext;
6263a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        }
6273a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
6283a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (ret_pattern_p ())
6293a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        {
6303a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            // we know where the end of the function is; set the limit on the PlanValidAddressRange
6313a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            // in case our initial "high pc" value was overly large
6323a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            // int original_size = m_func_bounds.GetByteSize();
6333a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            // int calculated_size = m_cur_insn.GetOffset() - m_func_bounds.GetBaseAddress().GetOffset() + insn_len + 1;
6343a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            // m_func_bounds.SetByteSize (calculated_size);
6353a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            // unwind_plan.SetPlanValidAddressRange (m_func_bounds);
6363a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            break;
6373a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        }
6383a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
6393a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        // FIXME recognize the i386 picbase setup instruction sequence,
6403a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        // 0x1f16:  call   0x1f1b                   ; main + 11 at /private/tmp/a.c:3
6413a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        // 0x1f1b:  popl   %eax
6423a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        // and record the temporary stack movements if the CFA is not expressed in terms of ebp.
6433a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
6443a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        non_prologue_insn_count++;
6453a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendaloopnext:
6463a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        m_cur_insn.SetOffset (m_cur_insn.GetOffset() + insn_len);
6473a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        current_func_text_offset += insn_len;
6483a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
6493a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
6508280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    unwind_plan.SetSourceName ("assembly insn profiling");
6518280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda
6523a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return true;
6533a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
6543a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
6558280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda/* The "fast unwind plan" is valid for functions that follow the usual convention of
6568280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda   using the frame pointer register (ebp, rbp), i.e. the function prologue looks like
6578280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda     push   %rbp      [0x55]
6588280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda     mov    %rsp,%rbp [0x48 0x89 0xe5]   (this is a 2-byte insn seq on i386)
6598280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda*/
6608280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda
6613a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendabool
6628280cbe80c79bc206335831dd732e0f9fb69c519Jason MolendaAssemblyParse_x86::get_fast_unwind_plan (AddressRange& func, UnwindPlan &unwind_plan)
6633a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
6648280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    UnwindPlan::Row row;
6658280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    UnwindPlan::Row::RegisterLocation pc_reginfo;
6668280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    UnwindPlan::Row::RegisterLocation sp_reginfo;
6678280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    UnwindPlan::Row::RegisterLocation fp_reginfo;
6688280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    unwind_plan.SetRegisterKind (eRegisterKindLLDB);
6698280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda
6708280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    if (!func.GetBaseAddress().IsValid())
6718280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda        return false;
6728280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda
6738280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    uint8_t bytebuf[4];
6748280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    Error error;
6758280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    if (m_target.ReadMemory (func.GetBaseAddress(), bytebuf, sizeof (bytebuf), error) == -1)
6768280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda        return false;
6778280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda
6788280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    uint8_t i386_prologue[] = {0x55, 0x89, 0xe5};
6798280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    uint8_t x86_64_prologue[] = {0x55, 0x48, 0x89, 0xe5};
6808280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    int prologue_size;
6818280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda
6828280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    if (memcmp (bytebuf, i386_prologue, sizeof (i386_prologue)) == 0)
6838280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    {
6848280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda        prologue_size = sizeof (i386_prologue);
6858280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    }
6868280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    else if (memcmp (bytebuf, x86_64_prologue, sizeof (x86_64_prologue)) == 0)
6878280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    {
6888280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda        prologue_size = sizeof (x86_64_prologue);
6898280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    }
6908280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    else
6918280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    {
6928280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda        return false;
6938280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    }
6948280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda
6958280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    pc_reginfo.SetAtCFAPlusOffset (-m_wordsize);
6968280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    row.SetRegisterInfo (m_lldb_ip_regnum, pc_reginfo);
6978280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda
6988280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    sp_reginfo.SetIsCFAPlusOffset (0);
6998280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    row.SetRegisterInfo (m_lldb_sp_regnum, sp_reginfo);
7008280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda
7018280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    // Zero instructions into the function
7028280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    row.SetCFARegister (m_lldb_sp_regnum);
7038280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    row.SetCFAOffset (m_wordsize);
7048280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    row.SetOffset (0);
7058280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    unwind_plan.AppendRow (row);
7068280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda
7078280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    // push %rbp has executed - stack moved, rbp now saved
7088280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    row.SetCFAOffset (2 * m_wordsize);
7098280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    fp_reginfo.SetAtCFAPlusOffset (2 * -m_wordsize);
7108280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    row.SetRegisterInfo (m_lldb_fp_regnum, fp_reginfo);
7118280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    row.SetOffset (1);
7128280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    unwind_plan.AppendRow (row);
7138280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda
7148280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    // mov %rsp, %rbp has executed
7158280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    row.SetCFARegister (m_lldb_fp_regnum);
7168280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    row.SetCFAOffset (2 * m_wordsize);
7178280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    row.SetOffset (prologue_size);     /// 3 or 4 bytes depending on arch
7188280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    unwind_plan.AppendRow (row);
7198280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda
7208280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    unwind_plan.SetPlanValidAddressRange (func);
7218280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    return true;
7223a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
7233a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
7243a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendabool
7253a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaAssemblyParse_x86::find_first_non_prologue_insn (Address &address)
7263a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
7273a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    m_cur_insn = m_func_bounds.GetBaseAddress ();
7283a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    while (m_func_bounds.ContainsFileAddress (m_cur_insn))
7293a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {
7303a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        Error error;
7313a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        int insn_len, offset, regno;
7323a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (!instruction_length (m_cur_insn, insn_len) || insn_len > kMaxInstructionByteSize || insn_len == 0)
7333a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        {
7343a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            // An error parsing the instruction, i.e. probably data/garbage - stop scanning
7353a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            break;
7363a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        }
7373a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (m_target.ReadMemory (m_cur_insn, m_cur_insn_bytes, insn_len, error) == -1)
7383a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        {
7393a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda           // Error reading the instruction out of the file, stop scanning
7403a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda           break;
7413a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        }
7423a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
7433a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (push_rbp_pattern_p () || mov_rsp_rbp_pattern_p () || sub_rsp_pattern_p (offset)
7443a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            || push_reg_p (regno) || mov_reg_to_local_stack_frame_p (regno, offset))
7453a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        {
7463a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            m_cur_insn.SetOffset (m_cur_insn.GetOffset() + insn_len);
7473a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            continue;
7483a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        }
7493a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
7503a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        // Unknown non-prologue instruction - stop scanning
7513a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        break;
7523a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
7533a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
7543a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    address = m_cur_insn;
7553a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return true;
7563a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
7573a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
7583a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
7593a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
7603a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
7613a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
7623a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
7633a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//-----------------------------------------------------------------------------------------------
7643a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//  UnwindAssemblyParser_x86 method definitions
7653a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//-----------------------------------------------------------------------------------------------
7663a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
7673a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendabool
7683a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaUnwindAssemblyProfiler_x86::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& func, Thread& thread, UnwindPlan& unwind_plan)
7693a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
7703a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    AssemblyParse_x86 asm_parse(thread.GetProcess().GetTarget(), &thread, m_cpu, func);
7713a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return asm_parse.get_non_call_site_unwind_plan (unwind_plan);
7723a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
7733a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
7743a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendabool
7753a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaUnwindAssemblyProfiler_x86::GetFastUnwindPlan (AddressRange& func, Thread& thread, UnwindPlan &unwind_plan)
7763a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
7773a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    AssemblyParse_x86 asm_parse(thread.GetProcess().GetTarget(), &thread, m_cpu, func);
7788280cbe80c79bc206335831dd732e0f9fb69c519Jason Molenda    return asm_parse.get_fast_unwind_plan (func, unwind_plan);
7793a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
7803a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
7813a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendabool
7823a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaUnwindAssemblyProfiler_x86::FirstNonPrologueInsn (AddressRange& func, Target& target, Thread* thread, Address& first_non_prologue_insn)
7833a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
7843a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    AssemblyParse_x86 asm_parse(target, thread, m_cpu, func);
7853a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return asm_parse.find_first_non_prologue_insn (first_non_prologue_insn);
7863a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
7873a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
7883a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendalldb_private::UnwindAssemblyProfiler *
7893a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaUnwindAssemblyProfiler_x86::CreateInstance (const lldb_private::ArchSpec &arch)
7903a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
7913a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda   uint32_t cpu = arch.GetCPUType ();
7923a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda   if (cpu != CPU_TYPE_X86_64 && cpu != CPU_TYPE_I386)
7933a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda       return NULL;
7943a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
7953a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda   return new UnwindAssemblyProfiler_x86 (cpu == CPU_TYPE_X86_64 ? k_x86_64 : k_i386);
7963a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
7973a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
7983a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
7993a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//------------------------------------------------------------------
8003a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// PluginInterface protocol in UnwindAssemblyParser_x86
8013a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//------------------------------------------------------------------
8023a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
8033a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendaconst char *
8043a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaUnwindAssemblyProfiler_x86::GetPluginName()
8053a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
8063a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return "UnwindAssemblyProfiler_x86";
8073a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
8083a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
8093a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendaconst char *
8103a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaUnwindAssemblyProfiler_x86::GetShortPluginName()
8113a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
8123a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return "unwindassemblyprofiler.x86";
8133a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
8143a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
8153a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
8163a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendauint32_t
8173a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaUnwindAssemblyProfiler_x86::GetPluginVersion()
8183a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
8193a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return 1;
8203a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
8213a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
8223a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendavoid
8233a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaUnwindAssemblyProfiler_x86::GetPluginCommandHelp (const char *command, Stream *strm)
8243a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
8253a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
8263a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
8273a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaError
8283a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaUnwindAssemblyProfiler_x86::ExecutePluginCommand (Args &command, Stream *strm)
8293a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
8303a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    Error error;
8313a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    error.SetErrorString("No plug-in command are currently supported.");
8323a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return error;
8333a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
8343a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
8353a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaLog *
8363a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaUnwindAssemblyProfiler_x86::EnablePluginLogging (Stream *strm, Args &command)
8373a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
8383a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return NULL;
8393a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
8403a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
8413a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendavoid
8423a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaUnwindAssemblyProfiler_x86::Initialize()
8433a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
8443a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    PluginManager::RegisterPlugin (GetPluginNameStatic(),
8453a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                                   GetPluginDescriptionStatic(),
8463a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda                                   CreateInstance);
8473a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
8483a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
8493a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendavoid
8503a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaUnwindAssemblyProfiler_x86::Terminate()
8513a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
8523a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    PluginManager::UnregisterPlugin (CreateInstance);
8533a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
8543a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
8553a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
8563a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendaconst char *
8573a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaUnwindAssemblyProfiler_x86::GetPluginNameStatic()
8583a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
8593a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return "UnwindAssemblyProfiler_x86";
8603a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
8613a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
8623a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendaconst char *
8633a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaUnwindAssemblyProfiler_x86::GetPluginDescriptionStatic()
8643a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
8653a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return "i386 and x86_64 assembly language profiler plugin.";
8663a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
867