1 //===-- UnwindAssembly-x86.cpp ----------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "UnwindAssembly-x86.h" 11 12 #include "llvm-c/Disassembler.h" 13 #include "llvm/Support/TargetSelect.h" 14 15 #include "lldb/Core/Address.h" 16 #include "lldb/Core/Error.h" 17 #include "lldb/Core/ArchSpec.h" 18 #include "lldb/Core/PluginManager.h" 19 #include "lldb/Symbol/UnwindPlan.h" 20 #include "lldb/Target/ExecutionContext.h" 21 #include "lldb/Target/Process.h" 22 #include "lldb/Target/RegisterContext.h" 23 #include "lldb/Target/Thread.h" 24 #include "lldb/Target/Target.h" 25 #include "lldb/Target/UnwindAssembly.h" 26 27 using namespace lldb; 28 using namespace lldb_private; 29 30 enum CPU 31 { 32 k_i386, 33 k_x86_64 34 }; 35 36 enum i386_register_numbers 37 { 38 k_machine_eax = 0, 39 k_machine_ecx = 1, 40 k_machine_edx = 2, 41 k_machine_ebx = 3, 42 k_machine_esp = 4, 43 k_machine_ebp = 5, 44 k_machine_esi = 6, 45 k_machine_edi = 7, 46 k_machine_eip = 8 47 }; 48 49 enum x86_64_register_numbers 50 { 51 k_machine_rax = 0, 52 k_machine_rcx = 1, 53 k_machine_rdx = 2, 54 k_machine_rbx = 3, 55 k_machine_rsp = 4, 56 k_machine_rbp = 5, 57 k_machine_rsi = 6, 58 k_machine_rdi = 7, 59 k_machine_r8 = 8, 60 k_machine_r9 = 9, 61 k_machine_r10 = 10, 62 k_machine_r11 = 11, 63 k_machine_r12 = 12, 64 k_machine_r13 = 13, 65 k_machine_r14 = 14, 66 k_machine_r15 = 15, 67 k_machine_rip = 16 68 }; 69 70 struct regmap_ent 71 { 72 const char *name; 73 int machine_regno; 74 int lldb_regno; 75 }; 76 77 static struct regmap_ent i386_register_map[] = 78 { 79 {"eax", k_machine_eax, -1}, 80 {"ecx", k_machine_ecx, -1}, 81 {"edx", k_machine_edx, -1}, 82 {"ebx", k_machine_ebx, -1}, 83 {"esp", k_machine_esp, -1}, 84 {"ebp", k_machine_ebp, -1}, 85 {"esi", k_machine_esi, -1}, 86 {"edi", k_machine_edi, -1}, 87 {"eip", k_machine_eip, -1} 88 }; 89 90 const int size_of_i386_register_map = llvm::array_lengthof (i386_register_map); 91 92 static int i386_register_map_initialized = 0; 93 94 static struct regmap_ent x86_64_register_map[] = 95 { 96 {"rax", k_machine_rax, -1}, 97 {"rcx", k_machine_rcx, -1}, 98 {"rdx", k_machine_rdx, -1}, 99 {"rbx", k_machine_rbx, -1}, 100 {"rsp", k_machine_rsp, -1}, 101 {"rbp", k_machine_rbp, -1}, 102 {"rsi", k_machine_rsi, -1}, 103 {"rdi", k_machine_rdi, -1}, 104 {"r8", k_machine_r8, -1}, 105 {"r9", k_machine_r9, -1}, 106 {"r10", k_machine_r10, -1}, 107 {"r11", k_machine_r11, -1}, 108 {"r12", k_machine_r12, -1}, 109 {"r13", k_machine_r13, -1}, 110 {"r14", k_machine_r14, -1}, 111 {"r15", k_machine_r15, -1}, 112 {"rip", k_machine_rip, -1} 113 }; 114 115 const int size_of_x86_64_register_map = llvm::array_lengthof (x86_64_register_map); 116 117 static int x86_64_register_map_initialized = 0; 118 119 //----------------------------------------------------------------------------------------------- 120 // AssemblyParse_x86 local-file class definition & implementation functions 121 //----------------------------------------------------------------------------------------------- 122 123 class AssemblyParse_x86 124 { 125 public: 126 127 AssemblyParse_x86 (const ExecutionContext &exe_ctx, int cpu, ArchSpec &arch, AddressRange func); 128 129 ~AssemblyParse_x86 (); 130 131 bool get_non_call_site_unwind_plan (UnwindPlan &unwind_plan); 132 133 bool augment_unwind_plan_from_call_site (AddressRange& func, UnwindPlan &unwind_plan); 134 135 bool get_fast_unwind_plan (AddressRange& func, UnwindPlan &unwind_plan); 136 137 bool find_first_non_prologue_insn (Address &address); 138 139 private: 140 enum { kMaxInstructionByteSize = 32 }; 141 142 bool nonvolatile_reg_p (int machine_regno); 143 bool push_rbp_pattern_p (); 144 bool push_0_pattern_p (); 145 bool mov_rsp_rbp_pattern_p (); 146 bool sub_rsp_pattern_p (int& amount); 147 bool add_rsp_pattern_p (int& amount); 148 bool push_reg_p (int& regno); 149 bool pop_reg_p (int& regno); 150 bool push_imm_pattern_p (); 151 bool mov_reg_to_local_stack_frame_p (int& regno, int& fp_offset); 152 bool ret_pattern_p (); 153 bool pop_rbp_pattern_p (); 154 bool call_next_insn_pattern_p(); 155 uint32_t extract_4 (uint8_t *b); 156 bool machine_regno_to_lldb_regno (int machine_regno, uint32_t& lldb_regno); 157 bool instruction_length (Address addr, int &length); 158 159 const ExecutionContext m_exe_ctx; 160 161 AddressRange m_func_bounds; 162 163 Address m_cur_insn; 164 uint8_t m_cur_insn_bytes[kMaxInstructionByteSize]; 165 166 uint32_t m_machine_ip_regnum; 167 uint32_t m_machine_sp_regnum; 168 uint32_t m_machine_fp_regnum; 169 170 uint32_t m_lldb_ip_regnum; 171 uint32_t m_lldb_sp_regnum; 172 uint32_t m_lldb_fp_regnum; 173 174 int m_wordsize; 175 int m_cpu; 176 ArchSpec m_arch; 177 ::LLVMDisasmContextRef m_disasm_context; 178 179 DISALLOW_COPY_AND_ASSIGN (AssemblyParse_x86); 180 }; 181 182 AssemblyParse_x86::AssemblyParse_x86 (const ExecutionContext &exe_ctx, int cpu, ArchSpec &arch, AddressRange func) : 183 m_exe_ctx (exe_ctx), 184 m_func_bounds(func), 185 m_cur_insn (), 186 m_machine_ip_regnum (LLDB_INVALID_REGNUM), 187 m_machine_sp_regnum (LLDB_INVALID_REGNUM), 188 m_machine_fp_regnum (LLDB_INVALID_REGNUM), 189 m_lldb_ip_regnum (LLDB_INVALID_REGNUM), 190 m_lldb_sp_regnum (LLDB_INVALID_REGNUM), 191 m_lldb_fp_regnum (LLDB_INVALID_REGNUM), 192 m_wordsize (-1), 193 m_cpu(cpu), 194 m_arch(arch) 195 { 196 int *initialized_flag = NULL; 197 if (cpu == k_i386) 198 { 199 m_machine_ip_regnum = k_machine_eip; 200 m_machine_sp_regnum = k_machine_esp; 201 m_machine_fp_regnum = k_machine_ebp; 202 m_wordsize = 4; 203 initialized_flag = &i386_register_map_initialized; 204 } 205 else 206 { 207 m_machine_ip_regnum = k_machine_rip; 208 m_machine_sp_regnum = k_machine_rsp; 209 m_machine_fp_regnum = k_machine_rbp; 210 m_wordsize = 8; 211 initialized_flag = &x86_64_register_map_initialized; 212 } 213 214 // we only look at prologue - it will be complete earlier than 512 bytes into func 215 if (m_func_bounds.GetByteSize() == 0) 216 m_func_bounds.SetByteSize(512); 217 218 Thread *thread = m_exe_ctx.GetThreadPtr(); 219 if (thread && *initialized_flag == 0) 220 { 221 RegisterContext *reg_ctx = thread->GetRegisterContext().get(); 222 if (reg_ctx) 223 { 224 struct regmap_ent *ent; 225 int count, i; 226 if (cpu == k_i386) 227 { 228 ent = i386_register_map; 229 count = size_of_i386_register_map; 230 } 231 else 232 { 233 ent = x86_64_register_map; 234 count = size_of_x86_64_register_map; 235 } 236 for (i = 0; i < count; i++, ent++) 237 { 238 const RegisterInfo *ri = reg_ctx->GetRegisterInfoByName (ent->name); 239 if (ri) 240 ent->lldb_regno = ri->kinds[eRegisterKindLLDB]; 241 } 242 *initialized_flag = 1; 243 } 244 } 245 246 // on initial construction we may not have a Thread so these have to remain 247 // uninitialized until we can get a RegisterContext to set up the register map table 248 if (*initialized_flag == 1) 249 { 250 uint32_t lldb_regno; 251 if (machine_regno_to_lldb_regno (m_machine_sp_regnum, lldb_regno)) 252 m_lldb_sp_regnum = lldb_regno; 253 if (machine_regno_to_lldb_regno (m_machine_fp_regnum, lldb_regno)) 254 m_lldb_fp_regnum = lldb_regno; 255 if (machine_regno_to_lldb_regno (m_machine_ip_regnum, lldb_regno)) 256 m_lldb_ip_regnum = lldb_regno; 257 } 258 259 m_disasm_context = ::LLVMCreateDisasm(m_arch.GetTriple().getTriple().c_str(), 260 (void*)this, 261 /*TagType=*/1, 262 NULL, 263 NULL); 264 } 265 266 AssemblyParse_x86::~AssemblyParse_x86 () 267 { 268 ::LLVMDisasmDispose(m_disasm_context); 269 } 270 271 // This function expects an x86 native register number (i.e. the bits stripped out of the 272 // actual instruction), not an lldb register number. 273 274 bool 275 AssemblyParse_x86::nonvolatile_reg_p (int machine_regno) 276 { 277 if (m_cpu == k_i386) 278 { 279 switch (machine_regno) 280 { 281 case k_machine_ebx: 282 case k_machine_ebp: // not actually a nonvolatile but often treated as such by convention 283 case k_machine_esi: 284 case k_machine_edi: 285 case k_machine_esp: 286 return true; 287 default: 288 return false; 289 } 290 } 291 if (m_cpu == k_x86_64) 292 { 293 switch (machine_regno) 294 { 295 case k_machine_rbx: 296 case k_machine_rsp: 297 case k_machine_rbp: // not actually a nonvolatile but often treated as such by convention 298 case k_machine_r12: 299 case k_machine_r13: 300 case k_machine_r14: 301 case k_machine_r15: 302 return true; 303 default: 304 return false; 305 } 306 } 307 return false; 308 } 309 310 311 // Macro to detect if this is a REX mode prefix byte. 312 #define REX_W_PREFIX_P(opcode) (((opcode) & (~0x5)) == 0x48) 313 314 // The high bit which should be added to the source register number (the "R" bit) 315 #define REX_W_SRCREG(opcode) (((opcode) & 0x4) >> 2) 316 317 // The high bit which should be added to the destination register number (the "B" bit) 318 #define REX_W_DSTREG(opcode) ((opcode) & 0x1) 319 320 // pushq %rbp [0x55] 321 bool AssemblyParse_x86::push_rbp_pattern_p () 322 { 323 uint8_t *p = m_cur_insn_bytes; 324 if (*p == 0x55) 325 return true; 326 return false; 327 } 328 329 // pushq $0 ; the first instruction in start() [0x6a 0x00] 330 bool AssemblyParse_x86::push_0_pattern_p () 331 { 332 uint8_t *p = m_cur_insn_bytes; 333 if (*p == 0x6a && *(p + 1) == 0x0) 334 return true; 335 return false; 336 } 337 338 // pushq $0 339 // pushl $0 340 bool AssemblyParse_x86::push_imm_pattern_p () 341 { 342 uint8_t *p = m_cur_insn_bytes; 343 if (*p == 0x68 || *p == 0x6a) 344 return true; 345 return false; 346 } 347 348 // movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5] 349 // movl %esp, %ebp [0x8b 0xec] or [0x89 0xe5] 350 bool AssemblyParse_x86::mov_rsp_rbp_pattern_p () 351 { 352 uint8_t *p = m_cur_insn_bytes; 353 if (m_wordsize == 8 && *p == 0x48) 354 p++; 355 if (*(p) == 0x8b && *(p + 1) == 0xec) 356 return true; 357 if (*(p) == 0x89 && *(p + 1) == 0xe5) 358 return true; 359 return false; 360 } 361 362 // subq $0x20, %rsp 363 bool AssemblyParse_x86::sub_rsp_pattern_p (int& amount) 364 { 365 uint8_t *p = m_cur_insn_bytes; 366 if (m_wordsize == 8 && *p == 0x48) 367 p++; 368 // 8-bit immediate operand 369 if (*p == 0x83 && *(p + 1) == 0xec) 370 { 371 amount = (int8_t) *(p + 2); 372 return true; 373 } 374 // 32-bit immediate operand 375 if (*p == 0x81 && *(p + 1) == 0xec) 376 { 377 amount = (int32_t) extract_4 (p + 2); 378 return true; 379 } 380 return false; 381 } 382 383 // addq $0x20, %rsp 384 bool AssemblyParse_x86::add_rsp_pattern_p (int& amount) 385 { 386 uint8_t *p = m_cur_insn_bytes; 387 if (m_wordsize == 8 && *p == 0x48) 388 p++; 389 // 8-bit immediate operand 390 if (*p == 0x83 && *(p + 1) == 0xc4) 391 { 392 amount = (int8_t) *(p + 2); 393 return true; 394 } 395 // 32-bit immediate operand 396 if (*p == 0x81 && *(p + 1) == 0xc4) 397 { 398 amount = (int32_t) extract_4 (p + 2); 399 return true; 400 } 401 return false; 402 } 403 404 // pushq %rbx 405 // pushl %ebx 406 bool AssemblyParse_x86::push_reg_p (int& regno) 407 { 408 uint8_t *p = m_cur_insn_bytes; 409 int regno_prefix_bit = 0; 410 // If we have a rex prefix byte, check to see if a B bit is set 411 if (m_wordsize == 8 && *p == 0x41) 412 { 413 regno_prefix_bit = 1 << 3; 414 p++; 415 } 416 if (*p >= 0x50 && *p <= 0x57) 417 { 418 regno = (*p - 0x50) | regno_prefix_bit; 419 return true; 420 } 421 return false; 422 } 423 424 // popq %rbx 425 // popl %ebx 426 bool AssemblyParse_x86::pop_reg_p (int& regno) 427 { 428 uint8_t *p = m_cur_insn_bytes; 429 int regno_prefix_bit = 0; 430 // If we have a rex prefix byte, check to see if a B bit is set 431 if (m_wordsize == 8 && *p == 0x41) 432 { 433 regno_prefix_bit = 1 << 3; 434 p++; 435 } 436 if (*p >= 0x58 && *p <= 0x5f) 437 { 438 regno = (*p - 0x58) | regno_prefix_bit; 439 return true; 440 } 441 return false; 442 } 443 444 // popq %rbp [0x5d] 445 // popl %ebp [0x5d] 446 bool AssemblyParse_x86::pop_rbp_pattern_p () 447 { 448 uint8_t *p = m_cur_insn_bytes; 449 return (*p == 0x5d); 450 } 451 452 // call $0 [0xe8 0x0 0x0 0x0 0x0] 453 bool AssemblyParse_x86::call_next_insn_pattern_p () 454 { 455 uint8_t *p = m_cur_insn_bytes; 456 return (*p == 0xe8) && (*(p+1) == 0x0) && (*(p+2) == 0x0) 457 && (*(p+3) == 0x0) && (*(p+4) == 0x0); 458 } 459 460 // Look for an instruction sequence storing a nonvolatile register 461 // on to the stack frame. 462 463 // movq %rax, -0x10(%rbp) [0x48 0x89 0x45 0xf0] 464 // movl %eax, -0xc(%ebp) [0x89 0x45 0xf4] 465 466 // The offset value returned in rbp_offset will be positive -- 467 // but it must be subtraced from the frame base register to get 468 // the actual location. The positive value returned for the offset 469 // is a convention used elsewhere for CFA offsets et al. 470 471 bool AssemblyParse_x86::mov_reg_to_local_stack_frame_p (int& regno, int& rbp_offset) 472 { 473 uint8_t *p = m_cur_insn_bytes; 474 int src_reg_prefix_bit = 0; 475 int target_reg_prefix_bit = 0; 476 477 if (m_wordsize == 8 && REX_W_PREFIX_P (*p)) 478 { 479 src_reg_prefix_bit = REX_W_SRCREG (*p) << 3; 480 target_reg_prefix_bit = REX_W_DSTREG (*p) << 3; 481 if (target_reg_prefix_bit == 1) 482 { 483 // rbp/ebp don't need a prefix bit - we know this isn't the 484 // reg we care about. 485 return false; 486 } 487 p++; 488 } 489 490 if (*p == 0x89) 491 { 492 /* Mask off the 3-5 bits which indicate the destination register 493 if this is a ModR/M byte. */ 494 int opcode_destreg_masked_out = *(p + 1) & (~0x38); 495 496 /* Is this a ModR/M byte with Mod bits 01 and R/M bits 101 497 and three bits between them, e.g. 01nnn101 498 We're looking for a destination of ebp-disp8 or ebp-disp32. */ 499 int immsize; 500 if (opcode_destreg_masked_out == 0x45) 501 immsize = 2; 502 else if (opcode_destreg_masked_out == 0x85) 503 immsize = 4; 504 else 505 return false; 506 507 int offset = 0; 508 if (immsize == 2) 509 offset = (int8_t) *(p + 2); 510 if (immsize == 4) 511 offset = (uint32_t) extract_4 (p + 2); 512 if (offset > 0) 513 return false; 514 515 regno = ((*(p + 1) >> 3) & 0x7) | src_reg_prefix_bit; 516 rbp_offset = offset > 0 ? offset : -offset; 517 return true; 518 } 519 return false; 520 } 521 522 // ret [0xc9] or [0xc2 imm8] or [0xca imm8] 523 bool 524 AssemblyParse_x86::ret_pattern_p () 525 { 526 uint8_t *p = m_cur_insn_bytes; 527 if (*p == 0xc9 || *p == 0xc2 || *p == 0xca || *p == 0xc3) 528 return true; 529 return false; 530 } 531 532 uint32_t 533 AssemblyParse_x86::extract_4 (uint8_t *b) 534 { 535 uint32_t v = 0; 536 for (int i = 3; i >= 0; i--) 537 v = (v << 8) | b[i]; 538 return v; 539 } 540 541 bool 542 AssemblyParse_x86::machine_regno_to_lldb_regno (int machine_regno, uint32_t &lldb_regno) 543 { 544 struct regmap_ent *ent; 545 int count, i; 546 if (m_cpu == k_i386) 547 { 548 ent = i386_register_map; 549 count = size_of_i386_register_map; 550 } 551 else 552 { 553 ent = x86_64_register_map; 554 count = size_of_x86_64_register_map; 555 } 556 for (i = 0; i < count; i++, ent++) 557 { 558 if (ent->machine_regno == machine_regno) 559 if (ent->lldb_regno != -1) 560 { 561 lldb_regno = ent->lldb_regno; 562 return true; 563 } 564 } 565 return false; 566 } 567 568 bool 569 AssemblyParse_x86::instruction_length (Address addr, int &length) 570 { 571 const uint32_t max_op_byte_size = m_arch.GetMaximumOpcodeByteSize(); 572 llvm::SmallVector <uint8_t, 32> opcode_data; 573 opcode_data.resize (max_op_byte_size); 574 575 if (!addr.IsValid()) 576 return false; 577 578 const bool prefer_file_cache = true; 579 Error error; 580 Target *target = m_exe_ctx.GetTargetPtr(); 581 if (target->ReadMemory (addr, prefer_file_cache, opcode_data.data(), 582 max_op_byte_size, error) == static_cast<size_t>(-1)) 583 { 584 return false; 585 } 586 587 char out_string[512]; 588 const addr_t pc = addr.GetFileAddress(); 589 const size_t inst_size = ::LLVMDisasmInstruction (m_disasm_context, 590 opcode_data.data(), 591 max_op_byte_size, 592 pc, // PC value 593 out_string, 594 sizeof(out_string)); 595 596 length = inst_size; 597 return true; 598 } 599 600 601 bool 602 AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan) 603 { 604 UnwindPlan::RowSP row(new UnwindPlan::Row); 605 int non_prologue_insn_count = 0; 606 m_cur_insn = m_func_bounds.GetBaseAddress (); 607 int current_func_text_offset = 0; 608 int current_sp_bytes_offset_from_cfa = 0; 609 UnwindPlan::Row::RegisterLocation initial_regloc; 610 Error error; 611 612 if (!m_cur_insn.IsValid()) 613 { 614 return false; 615 } 616 617 unwind_plan.SetPlanValidAddressRange (m_func_bounds); 618 unwind_plan.SetRegisterKind (eRegisterKindLLDB); 619 620 // At the start of the function, find the CFA by adding wordsize to the SP register 621 row->SetOffset (current_func_text_offset); 622 row->SetCFARegister (m_lldb_sp_regnum); 623 row->SetCFAOffset (m_wordsize); 624 625 // caller's stack pointer value before the call insn is the CFA address 626 initial_regloc.SetIsCFAPlusOffset (0); 627 row->SetRegisterInfo (m_lldb_sp_regnum, initial_regloc); 628 629 // saved instruction pointer can be found at CFA - wordsize. 630 current_sp_bytes_offset_from_cfa = m_wordsize; 631 initial_regloc.SetAtCFAPlusOffset (-current_sp_bytes_offset_from_cfa); 632 row->SetRegisterInfo (m_lldb_ip_regnum, initial_regloc); 633 634 unwind_plan.AppendRow (row); 635 636 // Allocate a new Row, populate it with the existing Row contents. 637 UnwindPlan::Row *newrow = new UnwindPlan::Row; 638 *newrow = *row.get(); 639 row.reset(newrow); 640 641 const bool prefer_file_cache = true; 642 643 Target *target = m_exe_ctx.GetTargetPtr(); 644 while (m_func_bounds.ContainsFileAddress (m_cur_insn) && non_prologue_insn_count < 10) 645 { 646 int stack_offset, insn_len; 647 int machine_regno; // register numbers masked directly out of instructions 648 uint32_t lldb_regno; // register numbers in lldb's eRegisterKindLLDB numbering scheme 649 650 if (!instruction_length (m_cur_insn, insn_len) || insn_len == 0 || insn_len > kMaxInstructionByteSize) 651 { 652 // An unrecognized/junk instruction 653 break; 654 } 655 if (target->ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes, 656 insn_len, error) == static_cast<size_t>(-1)) 657 { 658 // Error reading the instruction out of the file, stop scanning 659 break; 660 } 661 662 if (push_rbp_pattern_p ()) 663 { 664 row->SetOffset (current_func_text_offset + insn_len); 665 current_sp_bytes_offset_from_cfa += m_wordsize; 666 row->SetCFAOffset (current_sp_bytes_offset_from_cfa); 667 UnwindPlan::Row::RegisterLocation regloc; 668 regloc.SetAtCFAPlusOffset (-row->GetCFAOffset()); 669 row->SetRegisterInfo (m_lldb_fp_regnum, regloc); 670 unwind_plan.AppendRow (row); 671 // Allocate a new Row, populate it with the existing Row contents. 672 newrow = new UnwindPlan::Row; 673 *newrow = *row.get(); 674 row.reset(newrow); 675 goto loopnext; 676 } 677 678 if (mov_rsp_rbp_pattern_p ()) 679 { 680 row->SetOffset (current_func_text_offset + insn_len); 681 row->SetCFARegister (m_lldb_fp_regnum); 682 unwind_plan.AppendRow (row); 683 // Allocate a new Row, populate it with the existing Row contents. 684 newrow = new UnwindPlan::Row; 685 *newrow = *row.get(); 686 row.reset(newrow); 687 goto loopnext; 688 } 689 690 // This is the start() function (or a pthread equivalent), it starts with a pushl $0x0 which puts the 691 // saved pc value of 0 on the stack. In this case we want to pretend we didn't see a stack movement at all -- 692 // normally the saved pc value is already on the stack by the time the function starts executing. 693 if (push_0_pattern_p ()) 694 { 695 goto loopnext; 696 } 697 698 if (push_reg_p (machine_regno)) 699 { 700 current_sp_bytes_offset_from_cfa += m_wordsize; 701 bool need_to_push_row = false; 702 // the PUSH instruction has moved the stack pointer - if the CFA is set in terms of the stack pointer, 703 // we need to add a new row of instructions. 704 if (row->GetCFARegister() == m_lldb_sp_regnum) 705 { 706 need_to_push_row = true; 707 row->SetCFAOffset (current_sp_bytes_offset_from_cfa); 708 } 709 // record where non-volatile (callee-saved, spilled) registers are saved on the stack 710 if (nonvolatile_reg_p (machine_regno) && machine_regno_to_lldb_regno (machine_regno, lldb_regno)) 711 { 712 need_to_push_row = true; 713 UnwindPlan::Row::RegisterLocation regloc; 714 regloc.SetAtCFAPlusOffset (-current_sp_bytes_offset_from_cfa); 715 row->SetRegisterInfo (lldb_regno, regloc); 716 } 717 if (need_to_push_row) 718 { 719 row->SetOffset (current_func_text_offset + insn_len); 720 unwind_plan.AppendRow (row); 721 // Allocate a new Row, populate it with the existing Row contents. 722 newrow = new UnwindPlan::Row; 723 *newrow = *row.get(); 724 row.reset(newrow); 725 } 726 goto loopnext; 727 } 728 729 if (mov_reg_to_local_stack_frame_p (machine_regno, stack_offset) && nonvolatile_reg_p (machine_regno)) 730 { 731 if (machine_regno_to_lldb_regno (machine_regno, lldb_regno)) 732 { 733 row->SetOffset (current_func_text_offset + insn_len); 734 UnwindPlan::Row::RegisterLocation regloc; 735 736 // stack_offset for 'movq %r15, -80(%rbp)' will be 80. 737 // In the Row, we want to express this as the offset from the CFA. If the frame base 738 // is rbp (like the above instruction), the CFA offset for rbp is probably 16. So we 739 // want to say that the value is stored at the CFA address - 96. 740 regloc.SetAtCFAPlusOffset (-(stack_offset + row->GetCFAOffset())); 741 742 row->SetRegisterInfo (lldb_regno, regloc); 743 unwind_plan.AppendRow (row); 744 // Allocate a new Row, populate it with the existing Row contents. 745 newrow = new UnwindPlan::Row; 746 *newrow = *row.get(); 747 row.reset(newrow); 748 goto loopnext; 749 } 750 } 751 752 if (sub_rsp_pattern_p (stack_offset)) 753 { 754 current_sp_bytes_offset_from_cfa += stack_offset; 755 if (row->GetCFARegister() == m_lldb_sp_regnum) 756 { 757 row->SetOffset (current_func_text_offset + insn_len); 758 row->SetCFAOffset (current_sp_bytes_offset_from_cfa); 759 unwind_plan.AppendRow (row); 760 // Allocate a new Row, populate it with the existing Row contents. 761 newrow = new UnwindPlan::Row; 762 *newrow = *row.get(); 763 row.reset(newrow); 764 } 765 goto loopnext; 766 } 767 768 if (ret_pattern_p ()) 769 { 770 // we know where the end of the function is; set the limit on the PlanValidAddressRange 771 // in case our initial "high pc" value was overly large 772 // int original_size = m_func_bounds.GetByteSize(); 773 // int calculated_size = m_cur_insn.GetOffset() - m_func_bounds.GetBaseAddress().GetOffset() + insn_len + 1; 774 // m_func_bounds.SetByteSize (calculated_size); 775 // unwind_plan.SetPlanValidAddressRange (m_func_bounds); 776 break; 777 } 778 779 // FIXME recognize the i386 picbase setup instruction sequence, 780 // 0x1f16: call 0x1f1b ; main + 11 at /private/tmp/a.c:3 781 // 0x1f1b: popl %eax 782 // and record the temporary stack movements if the CFA is not expressed in terms of ebp. 783 784 non_prologue_insn_count++; 785 loopnext: 786 m_cur_insn.SetOffset (m_cur_insn.GetOffset() + insn_len); 787 current_func_text_offset += insn_len; 788 } 789 790 // Now look at the byte at the end of the AddressRange for a limited attempt at describing the 791 // epilogue. We're looking for the sequence 792 793 // [ 0x5d ] mov %rbp, %rsp (aka pop %rbp) 794 // [ 0xc3 ] ret 795 796 // or 797 798 // [ 0x5d ] mov %rbp, %rsp (aka pop %rbp) 799 // [ 0xe9 xx xx xx xx ] jmp objc_retainAutoreleaseReturnValue (this is sometimes the final insn in the function) 800 801 // or 802 803 // [ 0x5d ] mov %rbp, %rsp (aka pop %rbp) 804 // [ 0xc3 ] ret 805 // [ 0xe8 xx xx xx xx ] call __stack_chk_fail (this is sometimes the final insn in the function) 806 807 // We want to add a Row describing how to unwind when we're stopped on the 'ret' instruction where the 808 // CFA is no longer defined in terms of rbp, but is now defined in terms of rsp like on function entry. 809 // (or the 'jmp' instruction in the second case) 810 811 uint64_t ret_insn_offset = LLDB_INVALID_ADDRESS; 812 Address end_of_fun(m_func_bounds.GetBaseAddress()); 813 end_of_fun.SetOffset (end_of_fun.GetOffset() + m_func_bounds.GetByteSize()); 814 815 if (m_func_bounds.GetByteSize() > 7) 816 { 817 uint8_t bytebuf[7]; 818 Address last_seven_bytes(end_of_fun); 819 last_seven_bytes.SetOffset (last_seven_bytes.GetOffset() - 7); 820 if (target->ReadMemory (last_seven_bytes, prefer_file_cache, bytebuf, 7, 821 error) != static_cast<size_t>(-1)) 822 { 823 if (bytebuf[5] == 0x5d && bytebuf[6] == 0xc3) // mov & ret 824 { 825 ret_insn_offset = m_func_bounds.GetByteSize() - 1; 826 } 827 else if (bytebuf[1] == 0x5d && bytebuf[2] == 0xe9) // mov & jmp 828 { 829 // When the pc is sitting on the 'jmp' instruction, we have the same 830 // unwind state as if it was sitting on a 'ret' instruction. 831 ret_insn_offset = m_func_bounds.GetByteSize() - 5; 832 } 833 else if (bytebuf[0] == 0x5d && bytebuf[1] == 0xc3 && bytebuf[2] == 0xe8) // mov & ret & call 834 { 835 ret_insn_offset = m_func_bounds.GetByteSize() - 6; 836 } 837 } 838 } 839 else if (m_func_bounds.GetByteSize() > 2) 840 { 841 uint8_t bytebuf[2]; 842 Address last_two_bytes(end_of_fun); 843 last_two_bytes.SetOffset (last_two_bytes.GetOffset() - 2); 844 if (target->ReadMemory (last_two_bytes, prefer_file_cache, bytebuf, 2, 845 error) != static_cast<size_t>(-1)) 846 { 847 if (bytebuf[0] == 0x5d && bytebuf[1] == 0xc3) // mov & ret 848 { 849 ret_insn_offset = m_func_bounds.GetByteSize() - 1; 850 } 851 } 852 } 853 854 if (ret_insn_offset != LLDB_INVALID_ADDRESS) 855 { 856 // Create a fresh, empty Row and RegisterLocation - don't mention any other registers 857 UnwindPlan::RowSP epi_row(new UnwindPlan::Row); 858 UnwindPlan::Row::RegisterLocation epi_regloc; 859 860 // When the ret instruction is about to be executed, here's our state 861 epi_row->SetOffset (ret_insn_offset); 862 epi_row->SetCFARegister (m_lldb_sp_regnum); 863 epi_row->SetCFAOffset (m_wordsize); 864 865 // caller's stack pointer value before the call insn is the CFA address 866 epi_regloc.SetIsCFAPlusOffset (0); 867 epi_row->SetRegisterInfo (m_lldb_sp_regnum, epi_regloc); 868 869 // saved instruction pointer can be found at CFA - wordsize 870 epi_regloc.SetAtCFAPlusOffset (-m_wordsize); 871 epi_row->SetRegisterInfo (m_lldb_ip_regnum, epi_regloc); 872 873 unwind_plan.AppendRow (epi_row); 874 } 875 876 unwind_plan.SetSourceName ("assembly insn profiling"); 877 unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); 878 unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes); 879 880 return true; 881 } 882 883 bool 884 AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, UnwindPlan &unwind_plan) 885 { 886 // Is func address valid? 887 Address addr_start = func.GetBaseAddress(); 888 if (!addr_start.IsValid()) 889 return false; 890 891 // Is original unwind_plan valid? 892 // unwind_plan should have at least one row which is ABI-default (CFA register is sp), 893 // and another row in mid-function. 894 if (unwind_plan.GetRowCount() < 2) 895 return false; 896 UnwindPlan::RowSP first_row = unwind_plan.GetRowAtIndex (0); 897 if (first_row->GetOffset() != 0) 898 return false; 899 uint32_t cfa_reg = m_exe_ctx.GetThreadPtr()->GetRegisterContext() 900 ->ConvertRegisterKindToRegisterNumber (unwind_plan.GetRegisterKind(), 901 first_row->GetCFARegister()); 902 if (cfa_reg != m_lldb_sp_regnum || first_row->GetCFAOffset() != m_wordsize) 903 return false; 904 905 Target *target = m_exe_ctx.GetTargetPtr(); 906 m_cur_insn = func.GetBaseAddress(); 907 uint64_t offset = 0; 908 int row_id = 1; 909 bool unwind_plan_updated = false; 910 UnwindPlan::RowSP row(new UnwindPlan::Row(*first_row)); 911 while (func.ContainsFileAddress (m_cur_insn)) 912 { 913 int insn_len; 914 if (!instruction_length (m_cur_insn, insn_len) 915 || insn_len == 0 || insn_len > kMaxInstructionByteSize) 916 { 917 // An unrecognized/junk instruction. 918 break; 919 } 920 const bool prefer_file_cache = true; 921 Error error; 922 if (target->ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes, 923 insn_len, error) == static_cast<size_t>(-1)) 924 { 925 // Error reading the instruction out of the file, stop scanning. 926 break; 927 } 928 929 // Advance offsets. 930 offset += insn_len; 931 m_cur_insn.SetOffset(m_cur_insn.GetOffset() + insn_len); 932 933 // If we already have one row for this instruction, we can continue. 934 while (row_id < unwind_plan.GetRowCount() 935 && unwind_plan.GetRowAtIndex (row_id)->GetOffset() <= offset) 936 row_id++; 937 UnwindPlan::RowSP original_row = unwind_plan.GetRowAtIndex (row_id - 1); 938 if (original_row->GetOffset() == offset) 939 { 940 *row = *original_row; 941 continue; 942 } 943 944 if (row_id == 0) 945 { 946 // If we are here, compiler didn't generate CFI for prologue. 947 // This won't happen to GCC or clang. 948 // In this case, bail out directly. 949 return false; 950 } 951 952 // Inspect the instruction to check if we need a new row for it. 953 cfa_reg = m_exe_ctx.GetThreadPtr()->GetRegisterContext() 954 ->ConvertRegisterKindToRegisterNumber (unwind_plan.GetRegisterKind(), 955 row->GetCFARegister()); 956 if (cfa_reg == m_lldb_sp_regnum) 957 { 958 // CFA register is sp. 959 960 // call next instruction 961 // call 0 962 // => pop %ebx 963 if (call_next_insn_pattern_p ()) 964 { 965 row->SetOffset (offset); 966 row->SetCFAOffset (m_wordsize + row->GetCFAOffset()); 967 968 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); 969 unwind_plan.InsertRow (new_row); 970 unwind_plan_updated = true; 971 continue; 972 } 973 974 // push/pop register 975 int regno; 976 if (push_reg_p (regno)) 977 { 978 row->SetOffset (offset); 979 row->SetCFAOffset (m_wordsize + row->GetCFAOffset()); 980 981 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); 982 unwind_plan.InsertRow (new_row); 983 unwind_plan_updated = true; 984 continue; 985 } 986 if (pop_reg_p (regno)) 987 { 988 // Technically, this might be a nonvolatile register recover in epilogue. 989 // We should reset RegisterInfo for the register. 990 // But in practice, previous rule for the register is still valid... 991 // So we ignore this case. 992 993 row->SetOffset (offset); 994 row->SetCFAOffset (-m_wordsize + row->GetCFAOffset()); 995 996 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); 997 unwind_plan.InsertRow (new_row); 998 unwind_plan_updated = true; 999 continue; 1000 } 1001 1002 // push imm 1003 if (push_imm_pattern_p ()) 1004 { 1005 row->SetOffset (offset); 1006 row->SetCFAOffset (m_wordsize + row->GetCFAOffset()); 1007 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); 1008 unwind_plan.InsertRow (new_row); 1009 unwind_plan_updated = true; 1010 continue; 1011 } 1012 1013 // add/sub %rsp/%esp 1014 int amount; 1015 if (add_rsp_pattern_p (amount)) 1016 { 1017 row->SetOffset (offset); 1018 row->SetCFAOffset (-amount + row->GetCFAOffset()); 1019 1020 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); 1021 unwind_plan.InsertRow (new_row); 1022 unwind_plan_updated = true; 1023 continue; 1024 } 1025 if (sub_rsp_pattern_p (amount)) 1026 { 1027 row->SetOffset (offset); 1028 row->SetCFAOffset (amount + row->GetCFAOffset()); 1029 1030 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); 1031 unwind_plan.InsertRow (new_row); 1032 unwind_plan_updated = true; 1033 continue; 1034 } 1035 } 1036 else if (cfa_reg == m_lldb_fp_regnum) 1037 { 1038 // CFA register is fp. 1039 1040 // The only case we care about is epilogue: 1041 // [0x5d] pop %rbp/%ebp 1042 // => [0xc3] ret 1043 if (pop_rbp_pattern_p ()) 1044 { 1045 if (target->ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes, 1046 1, error) != static_cast<size_t>(-1) 1047 && ret_pattern_p ()) 1048 { 1049 row->SetOffset (offset); 1050 row->SetCFARegister (first_row->GetCFARegister()); 1051 row->SetCFAOffset (m_wordsize); 1052 1053 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); 1054 unwind_plan.InsertRow (new_row); 1055 unwind_plan_updated = true; 1056 continue; 1057 } 1058 } 1059 } 1060 else 1061 { 1062 // CFA register is not sp or fp. 1063 1064 // This must be hand-written assembly. 1065 // Just trust eh_frame and assume we have finished. 1066 break; 1067 } 1068 } 1069 1070 unwind_plan.SetPlanValidAddressRange (func); 1071 if (unwind_plan_updated) 1072 { 1073 std::string unwind_plan_source (unwind_plan.GetSourceName().AsCString()); 1074 unwind_plan_source += " plus augmentation from assembly parsing"; 1075 unwind_plan.SetSourceName (unwind_plan_source.c_str()); 1076 unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); 1077 } 1078 return true; 1079 } 1080 1081 /* The "fast unwind plan" is valid for functions that follow the usual convention of 1082 using the frame pointer register (ebp, rbp), i.e. the function prologue looks like 1083 push %rbp [0x55] 1084 mov %rsp,%rbp [0x48 0x89 0xe5] (this is a 2-byte insn seq on i386) 1085 */ 1086 1087 bool 1088 AssemblyParse_x86::get_fast_unwind_plan (AddressRange& func, UnwindPlan &unwind_plan) 1089 { 1090 UnwindPlan::RowSP row(new UnwindPlan::Row); 1091 UnwindPlan::Row::RegisterLocation pc_reginfo; 1092 UnwindPlan::Row::RegisterLocation sp_reginfo; 1093 UnwindPlan::Row::RegisterLocation fp_reginfo; 1094 unwind_plan.SetRegisterKind (eRegisterKindLLDB); 1095 1096 if (!func.GetBaseAddress().IsValid()) 1097 return false; 1098 1099 Target *target = m_exe_ctx.GetTargetPtr(); 1100 1101 uint8_t bytebuf[4]; 1102 Error error; 1103 const bool prefer_file_cache = true; 1104 if (target->ReadMemory (func.GetBaseAddress(), prefer_file_cache, bytebuf, 1105 sizeof (bytebuf), error) == static_cast<size_t>(-1)) 1106 return false; 1107 1108 uint8_t i386_prologue[] = {0x55, 0x89, 0xe5}; 1109 uint8_t x86_64_prologue[] = {0x55, 0x48, 0x89, 0xe5}; 1110 int prologue_size; 1111 1112 if (memcmp (bytebuf, i386_prologue, sizeof (i386_prologue)) == 0) 1113 { 1114 prologue_size = sizeof (i386_prologue); 1115 } 1116 else if (memcmp (bytebuf, x86_64_prologue, sizeof (x86_64_prologue)) == 0) 1117 { 1118 prologue_size = sizeof (x86_64_prologue); 1119 } 1120 else 1121 { 1122 return false; 1123 } 1124 1125 pc_reginfo.SetAtCFAPlusOffset (-m_wordsize); 1126 row->SetRegisterInfo (m_lldb_ip_regnum, pc_reginfo); 1127 1128 sp_reginfo.SetIsCFAPlusOffset (0); 1129 row->SetRegisterInfo (m_lldb_sp_regnum, sp_reginfo); 1130 1131 // Zero instructions into the function 1132 row->SetCFARegister (m_lldb_sp_regnum); 1133 row->SetCFAOffset (m_wordsize); 1134 row->SetOffset (0); 1135 unwind_plan.AppendRow (row); 1136 UnwindPlan::Row *newrow = new UnwindPlan::Row; 1137 *newrow = *row.get(); 1138 row.reset(newrow); 1139 1140 // push %rbp has executed - stack moved, rbp now saved 1141 row->SetCFAOffset (2 * m_wordsize); 1142 fp_reginfo.SetAtCFAPlusOffset (2 * -m_wordsize); 1143 row->SetRegisterInfo (m_lldb_fp_regnum, fp_reginfo); 1144 row->SetOffset (1); 1145 unwind_plan.AppendRow (row); 1146 1147 newrow = new UnwindPlan::Row; 1148 *newrow = *row.get(); 1149 row.reset(newrow); 1150 1151 // mov %rsp, %rbp has executed 1152 row->SetCFARegister (m_lldb_fp_regnum); 1153 row->SetCFAOffset (2 * m_wordsize); 1154 row->SetOffset (prologue_size); /// 3 or 4 bytes depending on arch 1155 unwind_plan.AppendRow (row); 1156 1157 newrow = new UnwindPlan::Row; 1158 *newrow = *row.get(); 1159 row.reset(newrow); 1160 1161 unwind_plan.SetPlanValidAddressRange (func); 1162 unwind_plan.SetSourceName ("fast unwind assembly profiling"); 1163 unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); 1164 unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); 1165 return true; 1166 } 1167 1168 bool 1169 AssemblyParse_x86::find_first_non_prologue_insn (Address &address) 1170 { 1171 m_cur_insn = m_func_bounds.GetBaseAddress (); 1172 if (!m_cur_insn.IsValid()) 1173 { 1174 return false; 1175 } 1176 1177 const bool prefer_file_cache = true; 1178 Target *target = m_exe_ctx.GetTargetPtr(); 1179 while (m_func_bounds.ContainsFileAddress (m_cur_insn)) 1180 { 1181 Error error; 1182 int insn_len, offset, regno; 1183 if (!instruction_length (m_cur_insn, insn_len) || insn_len > kMaxInstructionByteSize || insn_len == 0) 1184 { 1185 // An error parsing the instruction, i.e. probably data/garbage - stop scanning 1186 break; 1187 } 1188 if (target->ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes, 1189 insn_len, error) == static_cast<size_t>(-1)) 1190 { 1191 // Error reading the instruction out of the file, stop scanning 1192 break; 1193 } 1194 1195 if (push_rbp_pattern_p () || mov_rsp_rbp_pattern_p () || sub_rsp_pattern_p (offset) 1196 || push_reg_p (regno) || mov_reg_to_local_stack_frame_p (regno, offset)) 1197 { 1198 m_cur_insn.SetOffset (m_cur_insn.GetOffset() + insn_len); 1199 continue; 1200 } 1201 1202 // Unknown non-prologue instruction - stop scanning 1203 break; 1204 } 1205 1206 address = m_cur_insn; 1207 return true; 1208 } 1209 1210 1211 1212 1213 1214 1215 //----------------------------------------------------------------------------------------------- 1216 // UnwindAssemblyParser_x86 method definitions 1217 //----------------------------------------------------------------------------------------------- 1218 1219 UnwindAssembly_x86::UnwindAssembly_x86 (const ArchSpec &arch, int cpu) : 1220 lldb_private::UnwindAssembly(arch), 1221 m_cpu(cpu), 1222 m_arch(arch) 1223 { 1224 } 1225 1226 1227 UnwindAssembly_x86::~UnwindAssembly_x86 () 1228 { 1229 } 1230 1231 bool 1232 UnwindAssembly_x86::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& func, Thread& thread, UnwindPlan& unwind_plan) 1233 { 1234 ExecutionContext exe_ctx (thread.shared_from_this()); 1235 AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func); 1236 return asm_parse.get_non_call_site_unwind_plan (unwind_plan); 1237 } 1238 1239 bool 1240 UnwindAssembly_x86::AugmentUnwindPlanFromCallSite (AddressRange& func, Thread& thread, UnwindPlan& unwind_plan) 1241 { 1242 ExecutionContext exe_ctx (thread.shared_from_this()); 1243 AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func); 1244 return asm_parse.augment_unwind_plan_from_call_site (func, unwind_plan); 1245 } 1246 1247 bool 1248 UnwindAssembly_x86::GetFastUnwindPlan (AddressRange& func, Thread& thread, UnwindPlan &unwind_plan) 1249 { 1250 ExecutionContext exe_ctx (thread.shared_from_this()); 1251 AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func); 1252 return asm_parse.get_fast_unwind_plan (func, unwind_plan); 1253 } 1254 1255 bool 1256 UnwindAssembly_x86::FirstNonPrologueInsn (AddressRange& func, const ExecutionContext &exe_ctx, Address& first_non_prologue_insn) 1257 { 1258 AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func); 1259 return asm_parse.find_first_non_prologue_insn (first_non_prologue_insn); 1260 } 1261 1262 UnwindAssembly * 1263 UnwindAssembly_x86::CreateInstance (const ArchSpec &arch) 1264 { 1265 const llvm::Triple::ArchType cpu = arch.GetMachine (); 1266 if (cpu == llvm::Triple::x86) 1267 return new UnwindAssembly_x86 (arch, k_i386); 1268 else if (cpu == llvm::Triple::x86_64) 1269 return new UnwindAssembly_x86 (arch, k_x86_64); 1270 return NULL; 1271 } 1272 1273 1274 //------------------------------------------------------------------ 1275 // PluginInterface protocol in UnwindAssemblyParser_x86 1276 //------------------------------------------------------------------ 1277 1278 ConstString 1279 UnwindAssembly_x86::GetPluginName() 1280 { 1281 return GetPluginNameStatic(); 1282 } 1283 1284 1285 uint32_t 1286 UnwindAssembly_x86::GetPluginVersion() 1287 { 1288 return 1; 1289 } 1290 1291 void 1292 UnwindAssembly_x86::Initialize() 1293 { 1294 PluginManager::RegisterPlugin (GetPluginNameStatic(), 1295 GetPluginDescriptionStatic(), 1296 CreateInstance); 1297 } 1298 1299 void 1300 UnwindAssembly_x86::Terminate() 1301 { 1302 PluginManager::UnregisterPlugin (CreateInstance); 1303 } 1304 1305 1306 lldb_private::ConstString 1307 UnwindAssembly_x86::GetPluginNameStatic() 1308 { 1309 static ConstString g_name("x86"); 1310 return g_name; 1311 } 1312 1313 const char * 1314 UnwindAssembly_x86::GetPluginDescriptionStatic() 1315 { 1316 return "i386 and x86_64 assembly language profiler plugin."; 1317 } 1318