1 //===-- UnwindAssemblyInstEmulation.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 "UnwindAssemblyInstEmulation.h" 11 12 #include "lldb/Core/Address.h" 13 #include "lldb/Core/ArchSpec.h" 14 #include "lldb/Core/DataBufferHeap.h" 15 #include "lldb/Core/DataExtractor.h" 16 #include "lldb/Core/Disassembler.h" 17 #include "lldb/Core/Error.h" 18 #include "lldb/Core/FormatEntity.h" 19 #include "lldb/Core/Log.h" 20 #include "lldb/Core/PluginManager.h" 21 #include "lldb/Core/StreamString.h" 22 #include "lldb/Target/ExecutionContext.h" 23 #include "lldb/Target/Process.h" 24 #include "lldb/Target/Thread.h" 25 #include "lldb/Target/Target.h" 26 27 using namespace lldb; 28 using namespace lldb_private; 29 30 31 32 //----------------------------------------------------------------------------------------------- 33 // UnwindAssemblyInstEmulation method definitions 34 //----------------------------------------------------------------------------------------------- 35 36 bool 37 UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& range, 38 Thread& thread, 39 UnwindPlan& unwind_plan) 40 { 41 if (range.GetByteSize() > 0 && 42 range.GetBaseAddress().IsValid() && 43 m_inst_emulator_ap.get()) 44 { 45 46 // The instruction emulation subclass setup the unwind plan for the 47 // first instruction. 48 m_inst_emulator_ap->CreateFunctionEntryUnwind (unwind_plan); 49 50 // CreateFunctionEntryUnwind should have created the first row. If it 51 // doesn't, then we are done. 52 if (unwind_plan.GetRowCount() == 0) 53 return false; 54 55 ExecutionContext exe_ctx; 56 thread.CalculateExecutionContext(exe_ctx); 57 const bool prefer_file_cache = true; 58 DisassemblerSP disasm_sp (Disassembler::DisassembleRange (m_arch, 59 NULL, 60 NULL, 61 exe_ctx, 62 range, 63 prefer_file_cache)); 64 65 Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); 66 67 if (disasm_sp) 68 { 69 70 m_range_ptr = ⦥ 71 m_thread_ptr = &thread; 72 m_unwind_plan_ptr = &unwind_plan; 73 74 const uint32_t addr_byte_size = m_arch.GetAddressByteSize(); 75 const bool show_address = true; 76 const bool show_bytes = true; 77 m_inst_emulator_ap->GetRegisterInfo (unwind_plan.GetRegisterKind(), 78 unwind_plan.GetInitialCFARegister(), 79 m_cfa_reg_info); 80 81 m_fp_is_cfa = false; 82 m_register_values.clear(); 83 m_pushed_regs.clear(); 84 85 // Initialize the CFA with a known value. In the 32 bit case 86 // it will be 0x80000000, and in the 64 bit case 0x8000000000000000. 87 // We use the address byte size to be safe for any future address sizes 88 m_initial_sp = (1ull << ((addr_byte_size * 8) - 1)); 89 RegisterValue cfa_reg_value; 90 cfa_reg_value.SetUInt (m_initial_sp, m_cfa_reg_info.byte_size); 91 SetRegisterValue (m_cfa_reg_info, cfa_reg_value); 92 93 const InstructionList &inst_list = disasm_sp->GetInstructionList (); 94 const size_t num_instructions = inst_list.GetSize(); 95 96 if (num_instructions > 0) 97 { 98 Instruction *inst = inst_list.GetInstructionAtIndex (0).get(); 99 const lldb::addr_t base_addr = inst->GetAddress().GetFileAddress(); 100 101 // Map for storing the unwind plan row and the value of the registers at a given offset. 102 // When we see a forward branch we add a new entry to this map with the actual unwind plan 103 // row and register context for the target address of the branch as the current data have 104 // to be valid for the target address of the branch too if we are in the same function. 105 std::map<lldb::addr_t, std::pair<UnwindPlan::RowSP, RegisterValueMap>> saved_unwind_states; 106 107 // Make a copy of the current instruction Row and save it in m_curr_row 108 // so we can add updates as we process the instructions. 109 UnwindPlan::RowSP last_row = unwind_plan.GetLastRow(); 110 UnwindPlan::Row *newrow = new UnwindPlan::Row; 111 if (last_row.get()) 112 *newrow = *last_row.get(); 113 m_curr_row.reset(newrow); 114 115 // Add the initial state to the save list with offset 0. 116 saved_unwind_states.insert({0, {last_row, m_register_values}}); 117 118 // cache the pc register number (in whatever register numbering this UnwindPlan uses) for 119 // quick reference during instruction parsing. 120 uint32_t pc_reg_num = LLDB_INVALID_REGNUM; 121 RegisterInfo pc_reg_info; 122 if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info)) 123 pc_reg_num = pc_reg_info.kinds[unwind_plan.GetRegisterKind()]; 124 else 125 pc_reg_num = LLDB_INVALID_REGNUM; 126 127 // cache the return address register number (in whatever register numbering this UnwindPlan uses) for 128 // quick reference during instruction parsing. 129 uint32_t ra_reg_num = LLDB_INVALID_REGNUM; 130 RegisterInfo ra_reg_info; 131 if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, ra_reg_info)) 132 ra_reg_num = ra_reg_info.kinds[unwind_plan.GetRegisterKind()]; 133 else 134 ra_reg_num = LLDB_INVALID_REGNUM; 135 136 for (size_t idx=0; idx<num_instructions; ++idx) 137 { 138 m_curr_row_modified = false; 139 m_forward_branch_offset = 0; 140 141 inst = inst_list.GetInstructionAtIndex (idx).get(); 142 if (inst) 143 { 144 lldb::addr_t current_offset = inst->GetAddress().GetFileAddress() - base_addr; 145 auto it = saved_unwind_states.upper_bound(current_offset); 146 assert(it != saved_unwind_states.begin() && "Unwind row for the function entry missing"); 147 --it; // Move it to the row corresponding to the current offset 148 149 // If the offset of m_curr_row don't match with the offset we see in saved_unwind_states 150 // then we have to update m_curr_row and m_register_values based on the saved values. It 151 // is happenning after we processed an epilogue and a return to caller instruction. 152 if (it->second.first->GetOffset() != m_curr_row->GetOffset()) 153 { 154 UnwindPlan::Row *newrow = new UnwindPlan::Row; 155 *newrow = *it->second.first; 156 m_curr_row.reset(newrow); 157 m_register_values = it->second.second;; 158 } 159 160 if (log && log->GetVerbose ()) 161 { 162 StreamString strm; 163 lldb_private::FormatEntity::Entry format; 164 FormatEntity::Parse("${frame.pc}: ", format); 165 inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL, NULL, NULL, &format, 0); 166 log->PutCString (strm.GetData()); 167 } 168 169 m_inst_emulator_ap->SetInstruction (inst->GetOpcode(), 170 inst->GetAddress(), 171 exe_ctx.GetTargetPtr()); 172 173 m_inst_emulator_ap->EvaluateInstruction (eEmulateInstructionOptionIgnoreConditions); 174 175 // If the current instruction is a branch forward then save the current CFI information 176 // for the offset where we are branching. 177 if (m_forward_branch_offset != 0 && range.ContainsFileAddress(inst->GetAddress().GetFileAddress() + m_forward_branch_offset)) 178 { 179 auto newrow = std::make_shared<UnwindPlan::Row>(*m_curr_row.get()); 180 newrow->SetOffset(current_offset + m_forward_branch_offset); 181 saved_unwind_states.insert({current_offset + m_forward_branch_offset, {newrow, m_register_values}}); 182 unwind_plan.InsertRow(newrow); 183 } 184 185 // Were there any changes to the CFI while evaluating this instruction? 186 if (m_curr_row_modified) 187 { 188 // Save the modified row if we don't already have a CFI row in the currennt address 189 if (saved_unwind_states.count(current_offset + inst->GetOpcode().GetByteSize()) == 0) 190 { 191 m_curr_row->SetOffset (current_offset + inst->GetOpcode().GetByteSize()); 192 unwind_plan.InsertRow (m_curr_row); 193 saved_unwind_states.insert({current_offset + inst->GetOpcode().GetByteSize(), {m_curr_row, m_register_values}}); 194 195 // Allocate a new Row for m_curr_row, copy the current state into it 196 UnwindPlan::Row *newrow = new UnwindPlan::Row; 197 *newrow = *m_curr_row.get(); 198 m_curr_row.reset(newrow); 199 } 200 } 201 } 202 } 203 } 204 // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions. 205 // I'll fix that but for now, just clear the list and it will go away nicely. 206 disasm_sp->GetInstructionList().Clear(); 207 } 208 209 if (log && log->GetVerbose ()) 210 { 211 StreamString strm; 212 lldb::addr_t base_addr = range.GetBaseAddress().GetLoadAddress(thread.CalculateTarget().get()); 213 strm.Printf ("Resulting unwind rows for [0x%" PRIx64 " - 0x%" PRIx64 "):", base_addr, base_addr + range.GetByteSize()); 214 unwind_plan.Dump(strm, &thread, base_addr); 215 log->PutCString (strm.GetData()); 216 } 217 return unwind_plan.GetRowCount() > 0; 218 } 219 return false; 220 } 221 222 bool 223 UnwindAssemblyInstEmulation::AugmentUnwindPlanFromCallSite (AddressRange& func, 224 Thread& thread, 225 UnwindPlan& unwind_plan) 226 { 227 return false; 228 } 229 230 bool 231 UnwindAssemblyInstEmulation::GetFastUnwindPlan (AddressRange& func, 232 Thread& thread, 233 UnwindPlan &unwind_plan) 234 { 235 return false; 236 } 237 238 bool 239 UnwindAssemblyInstEmulation::FirstNonPrologueInsn (AddressRange& func, 240 const ExecutionContext &exe_ctx, 241 Address& first_non_prologue_insn) 242 { 243 return false; 244 } 245 246 UnwindAssembly * 247 UnwindAssemblyInstEmulation::CreateInstance (const ArchSpec &arch) 248 { 249 std::unique_ptr<EmulateInstruction> inst_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypePrologueEpilogue, NULL)); 250 // Make sure that all prologue instructions are handled 251 if (inst_emulator_ap.get()) 252 return new UnwindAssemblyInstEmulation (arch, inst_emulator_ap.release()); 253 return NULL; 254 } 255 256 257 //------------------------------------------------------------------ 258 // PluginInterface protocol in UnwindAssemblyParser_x86 259 //------------------------------------------------------------------ 260 ConstString 261 UnwindAssemblyInstEmulation::GetPluginName() 262 { 263 return GetPluginNameStatic(); 264 } 265 266 uint32_t 267 UnwindAssemblyInstEmulation::GetPluginVersion() 268 { 269 return 1; 270 } 271 272 void 273 UnwindAssemblyInstEmulation::Initialize() 274 { 275 PluginManager::RegisterPlugin (GetPluginNameStatic(), 276 GetPluginDescriptionStatic(), 277 CreateInstance); 278 } 279 280 void 281 UnwindAssemblyInstEmulation::Terminate() 282 { 283 PluginManager::UnregisterPlugin (CreateInstance); 284 } 285 286 287 ConstString 288 UnwindAssemblyInstEmulation::GetPluginNameStatic() 289 { 290 static ConstString g_name("inst-emulation"); 291 return g_name; 292 } 293 294 const char * 295 UnwindAssemblyInstEmulation::GetPluginDescriptionStatic() 296 { 297 return "Instruction emulation based unwind information."; 298 } 299 300 301 uint64_t 302 UnwindAssemblyInstEmulation::MakeRegisterKindValuePair (const RegisterInfo ®_info) 303 { 304 lldb::RegisterKind reg_kind; 305 uint32_t reg_num; 306 if (EmulateInstruction::GetBestRegisterKindAndNumber (®_info, reg_kind, reg_num)) 307 return (uint64_t)reg_kind << 24 | reg_num; 308 return 0ull; 309 } 310 311 void 312 UnwindAssemblyInstEmulation::SetRegisterValue (const RegisterInfo ®_info, const RegisterValue ®_value) 313 { 314 m_register_values[MakeRegisterKindValuePair (reg_info)] = reg_value; 315 } 316 317 bool 318 UnwindAssemblyInstEmulation::GetRegisterValue (const RegisterInfo ®_info, RegisterValue ®_value) 319 { 320 const uint64_t reg_id = MakeRegisterKindValuePair (reg_info); 321 RegisterValueMap::const_iterator pos = m_register_values.find(reg_id); 322 if (pos != m_register_values.end()) 323 { 324 reg_value = pos->second; 325 return true; // We had a real value that comes from an opcode that wrote 326 // to it... 327 } 328 // We are making up a value that is recognizable... 329 reg_value.SetUInt(reg_id, reg_info.byte_size); 330 return false; 331 } 332 333 334 size_t 335 UnwindAssemblyInstEmulation::ReadMemory (EmulateInstruction *instruction, 336 void *baton, 337 const EmulateInstruction::Context &context, 338 lldb::addr_t addr, 339 void *dst, 340 size_t dst_len) 341 { 342 Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); 343 344 if (log && log->GetVerbose ()) 345 { 346 StreamString strm; 347 strm.Printf ("UnwindAssemblyInstEmulation::ReadMemory (addr = 0x%16.16" PRIx64 ", dst = %p, dst_len = %" PRIu64 ", context = ", 348 addr, 349 dst, 350 (uint64_t)dst_len); 351 context.Dump(strm, instruction); 352 log->PutCString (strm.GetData ()); 353 } 354 memset (dst, 0, dst_len); 355 return dst_len; 356 } 357 358 size_t 359 UnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction, 360 void *baton, 361 const EmulateInstruction::Context &context, 362 lldb::addr_t addr, 363 const void *dst, 364 size_t dst_len) 365 { 366 if (baton && dst && dst_len) 367 return ((UnwindAssemblyInstEmulation *)baton)->WriteMemory (instruction, context, addr, dst, dst_len); 368 return 0; 369 } 370 371 size_t 372 UnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction, 373 const EmulateInstruction::Context &context, 374 lldb::addr_t addr, 375 const void *dst, 376 size_t dst_len) 377 { 378 DataExtractor data (dst, 379 dst_len, 380 instruction->GetArchitecture ().GetByteOrder(), 381 instruction->GetArchitecture ().GetAddressByteSize()); 382 383 Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); 384 385 if (log && log->GetVerbose ()) 386 { 387 StreamString strm; 388 389 strm.PutCString ("UnwindAssemblyInstEmulation::WriteMemory ("); 390 data.Dump(&strm, 0, eFormatBytes, 1, dst_len, UINT32_MAX, addr, 0, 0); 391 strm.PutCString (", context = "); 392 context.Dump(strm, instruction); 393 log->PutCString (strm.GetData()); 394 } 395 396 const bool cant_replace = false; 397 398 switch (context.type) 399 { 400 default: 401 case EmulateInstruction::eContextInvalid: 402 case EmulateInstruction::eContextReadOpcode: 403 case EmulateInstruction::eContextImmediate: 404 case EmulateInstruction::eContextAdjustBaseRegister: 405 case EmulateInstruction::eContextRegisterPlusOffset: 406 case EmulateInstruction::eContextAdjustPC: 407 case EmulateInstruction::eContextRegisterStore: 408 case EmulateInstruction::eContextRegisterLoad: 409 case EmulateInstruction::eContextRelativeBranchImmediate: 410 case EmulateInstruction::eContextAbsoluteBranchRegister: 411 case EmulateInstruction::eContextSupervisorCall: 412 case EmulateInstruction::eContextTableBranchReadMemory: 413 case EmulateInstruction::eContextWriteRegisterRandomBits: 414 case EmulateInstruction::eContextWriteMemoryRandomBits: 415 case EmulateInstruction::eContextArithmetic: 416 case EmulateInstruction::eContextAdvancePC: 417 case EmulateInstruction::eContextReturnFromException: 418 case EmulateInstruction::eContextPopRegisterOffStack: 419 case EmulateInstruction::eContextAdjustStackPointer: 420 break; 421 422 case EmulateInstruction::eContextPushRegisterOnStack: 423 { 424 uint32_t reg_num = LLDB_INVALID_REGNUM; 425 uint32_t generic_regnum = LLDB_INVALID_REGNUM; 426 if (context.info_type == EmulateInstruction::eInfoTypeRegisterToRegisterPlusOffset) 427 { 428 const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind(); 429 reg_num = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[unwind_reg_kind]; 430 generic_regnum = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[eRegisterKindGeneric]; 431 } 432 else 433 assert (!"unhandled case, add code to handle this!"); 434 435 if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP) 436 { 437 if (m_pushed_regs.find (reg_num) == m_pushed_regs.end()) 438 { 439 m_pushed_regs[reg_num] = addr; 440 const int32_t offset = addr - m_initial_sp; 441 m_curr_row->SetRegisterLocationToAtCFAPlusOffset (reg_num, offset, cant_replace); 442 m_curr_row_modified = true; 443 } 444 } 445 } 446 break; 447 448 } 449 450 return dst_len; 451 } 452 453 bool 454 UnwindAssemblyInstEmulation::ReadRegister (EmulateInstruction *instruction, 455 void *baton, 456 const RegisterInfo *reg_info, 457 RegisterValue ®_value) 458 { 459 460 if (baton && reg_info) 461 return ((UnwindAssemblyInstEmulation *)baton)->ReadRegister (instruction, reg_info, reg_value); 462 return false; 463 } 464 bool 465 UnwindAssemblyInstEmulation::ReadRegister (EmulateInstruction *instruction, 466 const RegisterInfo *reg_info, 467 RegisterValue ®_value) 468 { 469 bool synthetic = GetRegisterValue (*reg_info, reg_value); 470 471 Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); 472 473 if (log && log->GetVerbose ()) 474 { 475 476 StreamString strm; 477 strm.Printf ("UnwindAssemblyInstEmulation::ReadRegister (name = \"%s\") => synthetic_value = %i, value = ", reg_info->name, synthetic); 478 reg_value.Dump(&strm, reg_info, false, false, eFormatDefault); 479 log->PutCString(strm.GetData()); 480 } 481 return true; 482 } 483 484 bool 485 UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction, 486 void *baton, 487 const EmulateInstruction::Context &context, 488 const RegisterInfo *reg_info, 489 const RegisterValue ®_value) 490 { 491 if (baton && reg_info) 492 return ((UnwindAssemblyInstEmulation *)baton)->WriteRegister (instruction, context, reg_info, reg_value); 493 return false; 494 } 495 bool 496 UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction, 497 const EmulateInstruction::Context &context, 498 const RegisterInfo *reg_info, 499 const RegisterValue ®_value) 500 { 501 Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); 502 503 if (log && log->GetVerbose ()) 504 { 505 506 StreamString strm; 507 strm.Printf ("UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ", reg_info->name); 508 reg_value.Dump(&strm, reg_info, false, false, eFormatDefault); 509 strm.PutCString (", context = "); 510 context.Dump(strm, instruction); 511 log->PutCString(strm.GetData()); 512 } 513 514 if (!instruction->IsInstructionConditional()) 515 SetRegisterValue (*reg_info, reg_value); 516 517 switch (context.type) 518 { 519 case EmulateInstruction::eContextInvalid: 520 case EmulateInstruction::eContextReadOpcode: 521 case EmulateInstruction::eContextImmediate: 522 case EmulateInstruction::eContextAdjustBaseRegister: 523 case EmulateInstruction::eContextRegisterPlusOffset: 524 case EmulateInstruction::eContextAdjustPC: 525 case EmulateInstruction::eContextRegisterStore: 526 case EmulateInstruction::eContextSupervisorCall: 527 case EmulateInstruction::eContextTableBranchReadMemory: 528 case EmulateInstruction::eContextWriteRegisterRandomBits: 529 case EmulateInstruction::eContextWriteMemoryRandomBits: 530 case EmulateInstruction::eContextArithmetic: 531 case EmulateInstruction::eContextAdvancePC: 532 case EmulateInstruction::eContextReturnFromException: 533 case EmulateInstruction::eContextPushRegisterOnStack: 534 case EmulateInstruction::eContextRegisterLoad: 535 // { 536 // const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; 537 // if (reg_num != LLDB_INVALID_REGNUM) 538 // { 539 // const bool can_replace_only_if_unspecified = true; 540 // 541 // m_curr_row.SetRegisterLocationToUndefined (reg_num, 542 // can_replace_only_if_unspecified, 543 // can_replace_only_if_unspecified); 544 // m_curr_row_modified = true; 545 // } 546 // } 547 break; 548 549 case EmulateInstruction::eContextAbsoluteBranchRegister: 550 case EmulateInstruction::eContextRelativeBranchImmediate: 551 { 552 if (context.info_type == EmulateInstruction::eInfoTypeISAAndImmediate && 553 context.info.ISAAndImmediate.unsigned_data32 > 0) 554 { 555 m_forward_branch_offset = context.info.ISAAndImmediateSigned.signed_data32; 556 } 557 else if (context.info_type == EmulateInstruction::eInfoTypeISAAndImmediateSigned && 558 context.info.ISAAndImmediateSigned.signed_data32 > 0) 559 { 560 m_forward_branch_offset = context.info.ISAAndImmediate.unsigned_data32; 561 } 562 else if (context.info_type == EmulateInstruction::eInfoTypeImmediate && 563 context.info.unsigned_immediate > 0) 564 { 565 m_forward_branch_offset = context.info.unsigned_immediate; 566 } 567 else if (context.info_type == EmulateInstruction::eInfoTypeImmediateSigned && 568 context.info.signed_immediate > 0) 569 { 570 m_forward_branch_offset = context.info.signed_immediate; 571 } 572 } 573 break; 574 575 case EmulateInstruction::eContextPopRegisterOffStack: 576 { 577 if (!instruction->IsInstructionConditional()) 578 { 579 const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; 580 const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric]; 581 if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP) 582 { 583 switch (context.info_type) 584 { 585 case EmulateInstruction::eInfoTypeAddress: 586 if (m_pushed_regs.find(reg_num) != m_pushed_regs.end() && 587 context.info.address == m_pushed_regs[reg_num]) 588 { 589 m_curr_row->SetRegisterLocationToSame(reg_num, 590 false /*must_replace*/); 591 m_curr_row_modified = true; 592 } 593 break; 594 case EmulateInstruction::eInfoTypeISA: 595 assert((generic_regnum == LLDB_REGNUM_GENERIC_PC || 596 generic_regnum == LLDB_REGNUM_GENERIC_FLAGS) && 597 "eInfoTypeISA used for poping a register other the the PC/FLAGS"); 598 if (generic_regnum != LLDB_REGNUM_GENERIC_FLAGS) 599 { 600 m_curr_row->SetRegisterLocationToSame(reg_num, 601 false /*must_replace*/); 602 m_curr_row_modified = true; 603 } 604 break; 605 default: 606 assert(false && "unhandled case, add code to handle this!"); 607 break; 608 } 609 } 610 } 611 } 612 break; 613 614 case EmulateInstruction::eContextSetFramePointer: 615 if (!m_fp_is_cfa && !instruction->IsInstructionConditional()) 616 { 617 m_fp_is_cfa = true; 618 m_cfa_reg_info = *reg_info; 619 const uint32_t cfa_reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; 620 assert (cfa_reg_num != LLDB_INVALID_REGNUM); 621 m_curr_row->GetCFAValue().SetIsRegisterPlusOffset(cfa_reg_num, m_initial_sp - 622 reg_value.GetAsUInt64()); 623 m_curr_row_modified = true; 624 } 625 break; 626 627 case EmulateInstruction::eContextAdjustStackPointer: 628 // If we have created a frame using the frame pointer, don't follow 629 // subsequent adjustments to the stack pointer. 630 if (!m_fp_is_cfa && !instruction->IsInstructionConditional()) 631 { 632 m_curr_row->GetCFAValue().SetIsRegisterPlusOffset( 633 m_curr_row->GetCFAValue().GetRegisterNumber(), 634 m_initial_sp - reg_value.GetAsUInt64()); 635 m_curr_row_modified = true; 636 } 637 break; 638 } 639 return true; 640 } 641 642 643