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 609 const uint32_t max_op_byte_size = m_arch.GetMaximumOpcodeByteSize(); 610 llvm::SmallVector<uint8_t, 32> opcode_data; 611 opcode_data.resize(max_op_byte_size); 612 613 char out_string[512]; 614 const size_t inst_size = 615 ::LLVMDisasmInstruction(m_disasm_context, insn_p, max_op_byte_size, 0, 616 out_string, sizeof(out_string)); 617 618 length = inst_size; 619 return true; 620 } 621 622 bool x86AssemblyInspectionEngine::machine_regno_to_lldb_regno( 623 int machine_regno, uint32_t &lldb_regno) { 624 MachineRegnumToNameAndLLDBRegnum::iterator it = m_reg_map.find(machine_regno); 625 if (it != m_reg_map.end()) { 626 lldb_regno = it->second.lldb_regnum; 627 return true; 628 } 629 return false; 630 return false; 631 } 632 633 bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( 634 uint8_t *data, size_t size, AddressRange &func_range, 635 UnwindPlan &unwind_plan) { 636 unwind_plan.Clear(); 637 638 if (data == nullptr || size == 0) 639 return false; 640 641 if (m_register_map_initialized == false) 642 return false; 643 644 addr_t current_func_text_offset = 0; 645 int current_sp_bytes_offset_from_cfa = 0; 646 UnwindPlan::Row::RegisterLocation initial_regloc; 647 UnwindPlan::RowSP row(new UnwindPlan::Row); 648 649 unwind_plan.SetPlanValidAddressRange(func_range); 650 unwind_plan.SetRegisterKind(eRegisterKindLLDB); 651 652 // At the start of the function, find the CFA by adding wordsize to the SP 653 // register 654 row->SetOffset(current_func_text_offset); 655 row->GetCFAValue().SetIsRegisterPlusOffset(m_lldb_sp_regnum, m_wordsize); 656 657 // caller's stack pointer value before the call insn is the CFA address 658 initial_regloc.SetIsCFAPlusOffset(0); 659 row->SetRegisterInfo(m_lldb_sp_regnum, initial_regloc); 660 661 // saved instruction pointer can be found at CFA - wordsize. 662 current_sp_bytes_offset_from_cfa = m_wordsize; 663 initial_regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_cfa); 664 row->SetRegisterInfo(m_lldb_ip_regnum, initial_regloc); 665 666 unwind_plan.AppendRow(row); 667 668 // Allocate a new Row, populate it with the existing Row contents. 669 UnwindPlan::Row *newrow = new UnwindPlan::Row; 670 *newrow = *row.get(); 671 row.reset(newrow); 672 673 // Track which registers have been saved so far in the prologue. 674 // If we see another push of that register, it's not part of the prologue. 675 // The register numbers used here are the machine register #'s 676 // (i386_register_numbers, x86_64_register_numbers). 677 std::vector<bool> saved_registers(32, false); 678 679 // Once the prologue has completed we'll save a copy of the unwind 680 // instructions 681 // If there is an epilogue in the middle of the function, after that epilogue 682 // we'll reinstate 683 // the unwind setup -- we assume that some code path jumps over the 684 // mid-function epilogue 685 686 UnwindPlan::RowSP prologue_completed_row; // copy of prologue row of CFI 687 int prologue_completed_sp_bytes_offset_from_cfa; // The sp value before the 688 // epilogue started executed 689 std::vector<bool> prologue_completed_saved_registers; 690 691 while (current_func_text_offset < size) { 692 int stack_offset, insn_len; 693 int machine_regno; // register numbers masked directly out of instructions 694 uint32_t lldb_regno; // register numbers in lldb's eRegisterKindLLDB 695 // numbering scheme 696 697 bool in_epilogue = false; // we're in the middle of an epilogue sequence 698 bool row_updated = false; // The UnwindPlan::Row 'row' has been updated 699 700 m_cur_insn = data + current_func_text_offset; 701 if (!instruction_length(m_cur_insn, insn_len) || insn_len == 0 || 702 insn_len > kMaxInstructionByteSize) { 703 // An unrecognized/junk instruction 704 break; 705 } 706 707 if (push_rbp_pattern_p()) { 708 current_sp_bytes_offset_from_cfa += m_wordsize; 709 row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); 710 UnwindPlan::Row::RegisterLocation regloc; 711 regloc.SetAtCFAPlusOffset(-row->GetCFAValue().GetOffset()); 712 row->SetRegisterInfo(m_lldb_fp_regnum, regloc); 713 saved_registers[m_machine_fp_regnum] = true; 714 row_updated = true; 715 } 716 717 else if (mov_rsp_rbp_pattern_p()) { 718 row->GetCFAValue().SetIsRegisterPlusOffset( 719 m_lldb_fp_regnum, row->GetCFAValue().GetOffset()); 720 row_updated = true; 721 } 722 723 // This is the start() function (or a pthread equivalent), it starts with a 724 // pushl $0x0 which puts the 725 // saved pc value of 0 on the stack. In this case we want to pretend we 726 // didn't see a stack movement at all -- 727 // normally the saved pc value is already on the stack by the time the 728 // function starts executing. 729 else if (push_0_pattern_p()) { 730 } 731 732 else if (push_reg_p(machine_regno)) { 733 current_sp_bytes_offset_from_cfa += m_wordsize; 734 // the PUSH instruction has moved the stack pointer - if the CFA is set in 735 // terms of the stack pointer, 736 // we need to add a new row of instructions. 737 if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) { 738 row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); 739 row_updated = true; 740 } 741 // record where non-volatile (callee-saved, spilled) registers are saved 742 // on the stack 743 if (nonvolatile_reg_p(machine_regno) && 744 machine_regno_to_lldb_regno(machine_regno, lldb_regno) && 745 saved_registers[machine_regno] == false) { 746 UnwindPlan::Row::RegisterLocation regloc; 747 regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_cfa); 748 row->SetRegisterInfo(lldb_regno, regloc); 749 saved_registers[machine_regno] = true; 750 row_updated = true; 751 } 752 } 753 754 else if (pop_reg_p(machine_regno)) { 755 current_sp_bytes_offset_from_cfa -= m_wordsize; 756 757 if (nonvolatile_reg_p(machine_regno) && 758 machine_regno_to_lldb_regno(machine_regno, lldb_regno) && 759 saved_registers[machine_regno] == true) { 760 saved_registers[machine_regno] = false; 761 row->RemoveRegisterInfo(lldb_regno); 762 763 if (machine_regno == (int)m_machine_fp_regnum) { 764 row->GetCFAValue().SetIsRegisterPlusOffset( 765 m_lldb_sp_regnum, row->GetCFAValue().GetOffset()); 766 } 767 768 in_epilogue = true; 769 row_updated = true; 770 } 771 772 // the POP instruction has moved the stack pointer - if the CFA is set in 773 // terms of the stack pointer, 774 // we need to add a new row of instructions. 775 if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) { 776 row->GetCFAValue().SetIsRegisterPlusOffset( 777 m_lldb_sp_regnum, current_sp_bytes_offset_from_cfa); 778 row_updated = true; 779 } 780 } 781 782 else if (pop_misc_reg_p()) { 783 current_sp_bytes_offset_from_cfa -= m_wordsize; 784 if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) { 785 row->GetCFAValue().SetIsRegisterPlusOffset( 786 m_lldb_sp_regnum, current_sp_bytes_offset_from_cfa); 787 row_updated = true; 788 } 789 } 790 791 // The LEAVE instruction moves the value from rbp into rsp and pops 792 // a value off the stack into rbp (restoring the caller's rbp value). 793 // It is the opposite of ENTER, or 'push rbp, mov rsp rbp'. 794 else if (leave_pattern_p()) { 795 // We're going to copy the value in rbp into rsp, so re-set the sp offset 796 // based on the CFAValue. Also, adjust it to recognize that we're popping 797 // the saved rbp value off the stack. 798 current_sp_bytes_offset_from_cfa = row->GetCFAValue().GetOffset(); 799 current_sp_bytes_offset_from_cfa -= m_wordsize; 800 row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); 801 802 // rbp is restored to the caller's value 803 saved_registers[m_machine_fp_regnum] = false; 804 row->RemoveRegisterInfo(m_lldb_fp_regnum); 805 806 // cfa is now in terms of rsp again. 807 row->GetCFAValue().SetIsRegisterPlusOffset( 808 m_lldb_sp_regnum, row->GetCFAValue().GetOffset()); 809 row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); 810 811 in_epilogue = true; 812 row_updated = true; 813 } 814 815 else if (mov_reg_to_local_stack_frame_p(machine_regno, stack_offset) && 816 nonvolatile_reg_p(machine_regno) && 817 machine_regno_to_lldb_regno(machine_regno, lldb_regno) && 818 saved_registers[machine_regno] == false) { 819 saved_registers[machine_regno] = true; 820 821 UnwindPlan::Row::RegisterLocation regloc; 822 823 // stack_offset for 'movq %r15, -80(%rbp)' will be 80. 824 // In the Row, we want to express this as the offset from the CFA. If the 825 // frame base 826 // is rbp (like the above instruction), the CFA offset for rbp is probably 827 // 16. So we 828 // want to say that the value is stored at the CFA address - 96. 829 regloc.SetAtCFAPlusOffset( 830 -(stack_offset + row->GetCFAValue().GetOffset())); 831 832 row->SetRegisterInfo(lldb_regno, regloc); 833 834 row_updated = true; 835 } 836 837 else if (sub_rsp_pattern_p(stack_offset)) { 838 current_sp_bytes_offset_from_cfa += stack_offset; 839 if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) { 840 row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); 841 row_updated = true; 842 } 843 } 844 845 else if (add_rsp_pattern_p(stack_offset)) { 846 current_sp_bytes_offset_from_cfa -= stack_offset; 847 if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) { 848 row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); 849 row_updated = true; 850 } 851 in_epilogue = true; 852 } 853 854 else if (push_extended_pattern_p() || push_imm_pattern_p() || 855 push_misc_reg_p()) { 856 current_sp_bytes_offset_from_cfa += m_wordsize; 857 if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) { 858 row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); 859 row_updated = true; 860 } 861 } 862 863 else if (lea_rsp_pattern_p(stack_offset)) { 864 current_sp_bytes_offset_from_cfa -= stack_offset; 865 if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) { 866 row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); 867 row_updated = true; 868 } 869 if (stack_offset > 0) 870 in_epilogue = true; 871 } 872 873 else if (lea_rbp_rsp_pattern_p(stack_offset) && 874 row->GetCFAValue().GetRegisterNumber() == m_lldb_fp_regnum) { 875 current_sp_bytes_offset_from_cfa = 876 row->GetCFAValue().GetOffset() - stack_offset; 877 } 878 879 else if (ret_pattern_p() && prologue_completed_row.get()) { 880 // Reinstate the saved prologue setup for any instructions 881 // that come after the ret instruction 882 883 UnwindPlan::Row *newrow = new UnwindPlan::Row; 884 *newrow = *prologue_completed_row.get(); 885 row.reset(newrow); 886 current_sp_bytes_offset_from_cfa = 887 prologue_completed_sp_bytes_offset_from_cfa; 888 889 saved_registers.clear(); 890 saved_registers.resize(prologue_completed_saved_registers.size(), false); 891 for (size_t i = 0; i < prologue_completed_saved_registers.size(); ++i) { 892 saved_registers[i] = prologue_completed_saved_registers[i]; 893 } 894 895 in_epilogue = true; 896 row_updated = true; 897 } 898 899 // call next instruction 900 // call 0 901 // => pop %ebx 902 // This is used in i386 programs to get the PIC base address for finding 903 // global data 904 else if (call_next_insn_pattern_p()) { 905 current_sp_bytes_offset_from_cfa += m_wordsize; 906 if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) { 907 row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); 908 row_updated = true; 909 } 910 } 911 912 if (row_updated) { 913 if (current_func_text_offset + insn_len < size) { 914 row->SetOffset(current_func_text_offset + insn_len); 915 unwind_plan.AppendRow(row); 916 // Allocate a new Row, populate it with the existing Row contents. 917 newrow = new UnwindPlan::Row; 918 *newrow = *row.get(); 919 row.reset(newrow); 920 } 921 } 922 923 if (in_epilogue == false && row_updated) { 924 // If we're not in an epilogue sequence, save the updated Row 925 UnwindPlan::Row *newrow = new UnwindPlan::Row; 926 *newrow = *row.get(); 927 prologue_completed_row.reset(newrow); 928 929 prologue_completed_saved_registers.clear(); 930 prologue_completed_saved_registers.resize(saved_registers.size(), false); 931 for (size_t i = 0; i < saved_registers.size(); ++i) { 932 prologue_completed_saved_registers[i] = saved_registers[i]; 933 } 934 } 935 936 // We may change the sp value without adding a new Row necessarily -- keep 937 // track of it either way. 938 if (in_epilogue == false) { 939 prologue_completed_sp_bytes_offset_from_cfa = 940 current_sp_bytes_offset_from_cfa; 941 } 942 943 m_cur_insn = m_cur_insn + insn_len; 944 current_func_text_offset += insn_len; 945 } 946 947 unwind_plan.SetSourceName("assembly insn profiling"); 948 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 949 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); 950 951 return true; 952 } 953 954 bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite( 955 uint8_t *data, size_t size, AddressRange &func_range, 956 UnwindPlan &unwind_plan, RegisterContextSP ®_ctx) { 957 Address addr_start = func_range.GetBaseAddress(); 958 if (!addr_start.IsValid()) 959 return false; 960 961 // We either need a live RegisterContext, or we need the UnwindPlan to already 962 // be in the lldb register numbering scheme. 963 if (reg_ctx.get() == nullptr && 964 unwind_plan.GetRegisterKind() != eRegisterKindLLDB) 965 return false; 966 967 // Is original unwind_plan valid? 968 // unwind_plan should have at least one row which is ABI-default (CFA register 969 // is sp), 970 // and another row in mid-function. 971 if (unwind_plan.GetRowCount() < 2) 972 return false; 973 974 UnwindPlan::RowSP first_row = unwind_plan.GetRowAtIndex(0); 975 if (first_row->GetOffset() != 0) 976 return false; 977 uint32_t cfa_reg = first_row->GetCFAValue().GetRegisterNumber(); 978 if (unwind_plan.GetRegisterKind() != eRegisterKindLLDB) { 979 cfa_reg = reg_ctx->ConvertRegisterKindToRegisterNumber( 980 unwind_plan.GetRegisterKind(), 981 first_row->GetCFAValue().GetRegisterNumber()); 982 } 983 if (cfa_reg != m_lldb_sp_regnum || 984 first_row->GetCFAValue().GetOffset() != m_wordsize) 985 return false; 986 987 UnwindPlan::RowSP original_last_row = unwind_plan.GetRowForFunctionOffset(-1); 988 989 size_t offset = 0; 990 int row_id = 1; 991 bool unwind_plan_updated = false; 992 UnwindPlan::RowSP row(new UnwindPlan::Row(*first_row)); 993 m_cur_insn = data + offset; 994 995 // After a mid-function epilogue we will need to re-insert the original unwind 996 // rules 997 // so unwinds work for the remainder of the function. These aren't common 998 // with clang/gcc 999 // on x86 but it is possible. 1000 bool reinstate_unwind_state = false; 1001 1002 while (offset < size) { 1003 m_cur_insn = data + offset; 1004 int insn_len; 1005 if (!instruction_length(m_cur_insn, insn_len) || insn_len == 0 || 1006 insn_len > kMaxInstructionByteSize) { 1007 // An unrecognized/junk instruction. 1008 break; 1009 } 1010 1011 // Advance offsets. 1012 offset += insn_len; 1013 m_cur_insn = data + offset; 1014 1015 // offset is pointing beyond the bounds of the 1016 // function; stop looping. 1017 if (offset >= size) 1018 continue; 1019 1020 if (reinstate_unwind_state) { 1021 UnwindPlan::RowSP new_row(new UnwindPlan::Row()); 1022 *new_row = *original_last_row; 1023 new_row->SetOffset(offset); 1024 unwind_plan.AppendRow(new_row); 1025 row.reset(new UnwindPlan::Row()); 1026 *row = *new_row; 1027 reinstate_unwind_state = false; 1028 unwind_plan_updated = true; 1029 continue; 1030 } 1031 1032 // If we already have one row for this instruction, we can continue. 1033 while (row_id < unwind_plan.GetRowCount() && 1034 unwind_plan.GetRowAtIndex(row_id)->GetOffset() <= offset) { 1035 row_id++; 1036 } 1037 UnwindPlan::RowSP original_row = unwind_plan.GetRowAtIndex(row_id - 1); 1038 if (original_row->GetOffset() == offset) { 1039 *row = *original_row; 1040 continue; 1041 } 1042 1043 if (row_id == 0) { 1044 // If we are here, compiler didn't generate CFI for prologue. 1045 // This won't happen to GCC or clang. 1046 // In this case, bail out directly. 1047 return false; 1048 } 1049 1050 // Inspect the instruction to check if we need a new row for it. 1051 cfa_reg = row->GetCFAValue().GetRegisterNumber(); 1052 if (unwind_plan.GetRegisterKind() != eRegisterKindLLDB) { 1053 cfa_reg = reg_ctx->ConvertRegisterKindToRegisterNumber( 1054 unwind_plan.GetRegisterKind(), 1055 row->GetCFAValue().GetRegisterNumber()); 1056 } 1057 if (cfa_reg == m_lldb_sp_regnum) { 1058 // CFA register is sp. 1059 1060 // call next instruction 1061 // call 0 1062 // => pop %ebx 1063 if (call_next_insn_pattern_p()) { 1064 row->SetOffset(offset); 1065 row->GetCFAValue().IncOffset(m_wordsize); 1066 1067 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); 1068 unwind_plan.InsertRow(new_row); 1069 unwind_plan_updated = true; 1070 continue; 1071 } 1072 1073 // push/pop register 1074 int regno; 1075 if (push_reg_p(regno)) { 1076 row->SetOffset(offset); 1077 row->GetCFAValue().IncOffset(m_wordsize); 1078 1079 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); 1080 unwind_plan.InsertRow(new_row); 1081 unwind_plan_updated = true; 1082 continue; 1083 } 1084 if (pop_reg_p(regno)) { 1085 // Technically, this might be a nonvolatile register recover in 1086 // epilogue. 1087 // We should reset RegisterInfo for the register. 1088 // But in practice, previous rule for the register is still valid... 1089 // So we ignore this case. 1090 1091 row->SetOffset(offset); 1092 row->GetCFAValue().IncOffset(-m_wordsize); 1093 1094 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); 1095 unwind_plan.InsertRow(new_row); 1096 unwind_plan_updated = true; 1097 continue; 1098 } 1099 1100 if (pop_misc_reg_p()) { 1101 row->SetOffset(offset); 1102 row->GetCFAValue().IncOffset(-m_wordsize); 1103 1104 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); 1105 unwind_plan.InsertRow(new_row); 1106 unwind_plan_updated = true; 1107 continue; 1108 } 1109 1110 // push imm 1111 if (push_imm_pattern_p()) { 1112 row->SetOffset(offset); 1113 row->GetCFAValue().IncOffset(m_wordsize); 1114 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); 1115 unwind_plan.InsertRow(new_row); 1116 unwind_plan_updated = true; 1117 continue; 1118 } 1119 1120 // push extended 1121 if (push_extended_pattern_p() || push_misc_reg_p()) { 1122 row->SetOffset(offset); 1123 row->GetCFAValue().IncOffset(m_wordsize); 1124 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); 1125 unwind_plan.InsertRow(new_row); 1126 unwind_plan_updated = true; 1127 continue; 1128 } 1129 1130 // add/sub %rsp/%esp 1131 int amount; 1132 if (add_rsp_pattern_p(amount)) { 1133 row->SetOffset(offset); 1134 row->GetCFAValue().IncOffset(-amount); 1135 1136 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); 1137 unwind_plan.InsertRow(new_row); 1138 unwind_plan_updated = true; 1139 continue; 1140 } 1141 if (sub_rsp_pattern_p(amount)) { 1142 row->SetOffset(offset); 1143 row->GetCFAValue().IncOffset(amount); 1144 1145 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); 1146 unwind_plan.InsertRow(new_row); 1147 unwind_plan_updated = true; 1148 continue; 1149 } 1150 1151 // lea %rsp, [%rsp + $offset] 1152 if (lea_rsp_pattern_p(amount)) { 1153 row->SetOffset(offset); 1154 row->GetCFAValue().IncOffset(-amount); 1155 1156 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); 1157 unwind_plan.InsertRow(new_row); 1158 unwind_plan_updated = true; 1159 continue; 1160 } 1161 1162 if (ret_pattern_p()) { 1163 reinstate_unwind_state = true; 1164 continue; 1165 } 1166 } else if (cfa_reg == m_lldb_fp_regnum) { 1167 // CFA register is fp. 1168 1169 // The only case we care about is epilogue: 1170 // [0x5d] pop %rbp/%ebp 1171 // => [0xc3] ret 1172 if (pop_rbp_pattern_p() || leave_pattern_p()) { 1173 offset += 1; 1174 row->SetOffset(offset); 1175 row->GetCFAValue().SetIsRegisterPlusOffset( 1176 first_row->GetCFAValue().GetRegisterNumber(), m_wordsize); 1177 1178 UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); 1179 unwind_plan.InsertRow(new_row); 1180 unwind_plan_updated = true; 1181 reinstate_unwind_state = true; 1182 continue; 1183 } 1184 } else { 1185 // CFA register is not sp or fp. 1186 1187 // This must be hand-written assembly. 1188 // Just trust eh_frame and assume we have finished. 1189 break; 1190 } 1191 } 1192 1193 unwind_plan.SetPlanValidAddressRange(func_range); 1194 if (unwind_plan_updated) { 1195 std::string unwind_plan_source(unwind_plan.GetSourceName().AsCString()); 1196 unwind_plan_source += " plus augmentation from assembly parsing"; 1197 unwind_plan.SetSourceName(unwind_plan_source.c_str()); 1198 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 1199 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); 1200 } 1201 return true; 1202 } 1203 1204 bool x86AssemblyInspectionEngine::FindFirstNonPrologueInstruction( 1205 uint8_t *data, size_t size, size_t &offset) { 1206 offset = 0; 1207 1208 if (m_register_map_initialized == false) 1209 return false; 1210 1211 while (offset < size) { 1212 int regno; 1213 int insn_len; 1214 int scratch; 1215 1216 m_cur_insn = data + offset; 1217 if (!instruction_length(m_cur_insn, insn_len) || 1218 insn_len > kMaxInstructionByteSize || insn_len == 0) { 1219 // An error parsing the instruction, i.e. probably data/garbage - stop 1220 // scanning 1221 break; 1222 } 1223 1224 if (push_rbp_pattern_p() || mov_rsp_rbp_pattern_p() || 1225 sub_rsp_pattern_p(scratch) || push_reg_p(regno) || 1226 mov_reg_to_local_stack_frame_p(regno, scratch) || 1227 (lea_rsp_pattern_p(scratch) && offset == 0)) { 1228 offset += insn_len; 1229 continue; 1230 } 1231 // 1232 // Unknown non-prologue instruction - stop scanning 1233 break; 1234 } 1235 1236 return true; 1237 } 1238