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