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