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