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 RegisterInfo pc_reg_info; 121 m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info); 122 123 // cache the return address register number (in whatever register numbering this UnwindPlan uses) for 124 // quick reference during instruction parsing. 125 RegisterInfo ra_reg_info; 126 m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, ra_reg_info); 127 128 // The architecture dependent condition code of the last processed instruction. 129 EmulateInstruction::InstructionCondition last_condition = EmulateInstruction::UnconditionalCondition; 130 lldb::addr_t condition_block_start_offset = 0; 131 132 for (size_t idx=0; idx<num_instructions; ++idx) 133 { 134 m_curr_row_modified = false; 135 m_forward_branch_offset = 0; 136 137 inst = inst_list.GetInstructionAtIndex (idx).get(); 138 if (inst) 139 { 140 lldb::addr_t current_offset = inst->GetAddress().GetFileAddress() - base_addr; 141 auto it = saved_unwind_states.upper_bound(current_offset); 142 assert(it != saved_unwind_states.begin() && "Unwind row for the function entry missing"); 143 --it; // Move it to the row corresponding to the current offset 144 145 // If the offset of m_curr_row don't match with the offset we see in saved_unwind_states 146 // then we have to update m_curr_row and m_register_values based on the saved values. It 147 // is happenning after we processed an epilogue and a return to caller instruction. 148 if (it->second.first->GetOffset() != m_curr_row->GetOffset()) 149 { 150 UnwindPlan::Row *newrow = new UnwindPlan::Row; 151 *newrow = *it->second.first; 152 m_curr_row.reset(newrow); 153 m_register_values = it->second.second; 154 } 155 156 m_inst_emulator_ap->SetInstruction (inst->GetOpcode(), 157 inst->GetAddress(), 158 exe_ctx.GetTargetPtr()); 159 160 if (last_condition != m_inst_emulator_ap->GetInstructionCondition()) 161 { 162 if (m_inst_emulator_ap->GetInstructionCondition() != EmulateInstruction::UnconditionalCondition && 163 saved_unwind_states.count(current_offset) == 0) 164 { 165 // If we don't have a saved row for the current offset then save our 166 // current state because we will have to restore it after the 167 // conditional block. 168 auto new_row = std::make_shared<UnwindPlan::Row>(*m_curr_row.get()); 169 saved_unwind_states.insert({current_offset, {new_row, m_register_values}}); 170 } 171 172 // If the last instruction was conditional with a different condition 173 // then the then current condition then restore the condition. 174 if (last_condition != EmulateInstruction::UnconditionalCondition) 175 { 176 const auto& saved_state = saved_unwind_states.at(condition_block_start_offset); 177 m_curr_row = std::make_shared<UnwindPlan::Row>(*saved_state.first); 178 m_curr_row->SetOffset(current_offset); 179 m_register_values = saved_state.second; 180 bool replace_existing = true; // The last instruction might already 181 // created a row for this offset and 182 // we want to overwrite it. 183 unwind_plan.InsertRow(std::make_shared<UnwindPlan::Row>(*m_curr_row), replace_existing); 184 } 185 186 // We are starting a new conditional block at the catual offset 187 condition_block_start_offset = current_offset; 188 } 189 190 if (log && log->GetVerbose ()) 191 { 192 StreamString strm; 193 lldb_private::FormatEntity::Entry format; 194 FormatEntity::Parse("${frame.pc}: ", format); 195 inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL, NULL, NULL, &format, 0); 196 log->PutCString (strm.GetData()); 197 } 198 199 last_condition = m_inst_emulator_ap->GetInstructionCondition(); 200 201 m_inst_emulator_ap->EvaluateInstruction (eEmulateInstructionOptionIgnoreConditions); 202 203 // If the current instruction is a branch forward then save the current CFI information 204 // for the offset where we are branching. 205 if (m_forward_branch_offset != 0 && range.ContainsFileAddress(inst->GetAddress().GetFileAddress() + m_forward_branch_offset)) 206 { 207 auto newrow = std::make_shared<UnwindPlan::Row>(*m_curr_row.get()); 208 newrow->SetOffset(current_offset + m_forward_branch_offset); 209 saved_unwind_states.insert({current_offset + m_forward_branch_offset, {newrow, m_register_values}}); 210 unwind_plan.InsertRow(newrow); 211 } 212 213 // Were there any changes to the CFI while evaluating this instruction? 214 if (m_curr_row_modified) 215 { 216 // Save the modified row if we don't already have a CFI row in the currennt address 217 if (saved_unwind_states.count(current_offset + inst->GetOpcode().GetByteSize()) == 0) 218 { 219 m_curr_row->SetOffset (current_offset + inst->GetOpcode().GetByteSize()); 220 unwind_plan.InsertRow (m_curr_row); 221 saved_unwind_states.insert({current_offset + inst->GetOpcode().GetByteSize(), {m_curr_row, m_register_values}}); 222 223 // Allocate a new Row for m_curr_row, copy the current state into it 224 UnwindPlan::Row *newrow = new UnwindPlan::Row; 225 *newrow = *m_curr_row.get(); 226 m_curr_row.reset(newrow); 227 } 228 } 229 } 230 } 231 } 232 } 233 234 if (log && log->GetVerbose ()) 235 { 236 StreamString strm; 237 lldb::addr_t base_addr = range.GetBaseAddress().GetLoadAddress(thread.CalculateTarget().get()); 238 strm.Printf ("Resulting unwind rows for [0x%" PRIx64 " - 0x%" PRIx64 "):", base_addr, base_addr + range.GetByteSize()); 239 unwind_plan.Dump(strm, &thread, base_addr); 240 log->PutCString (strm.GetData()); 241 } 242 return unwind_plan.GetRowCount() > 0; 243 } 244 return false; 245 } 246 247 bool 248 UnwindAssemblyInstEmulation::AugmentUnwindPlanFromCallSite (AddressRange& func, 249 Thread& thread, 250 UnwindPlan& unwind_plan) 251 { 252 return false; 253 } 254 255 bool 256 UnwindAssemblyInstEmulation::GetFastUnwindPlan (AddressRange& func, 257 Thread& thread, 258 UnwindPlan &unwind_plan) 259 { 260 return false; 261 } 262 263 bool 264 UnwindAssemblyInstEmulation::FirstNonPrologueInsn (AddressRange& func, 265 const ExecutionContext &exe_ctx, 266 Address& first_non_prologue_insn) 267 { 268 return false; 269 } 270 271 UnwindAssembly * 272 UnwindAssemblyInstEmulation::CreateInstance (const ArchSpec &arch) 273 { 274 std::unique_ptr<EmulateInstruction> inst_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypePrologueEpilogue, NULL)); 275 // Make sure that all prologue instructions are handled 276 if (inst_emulator_ap.get()) 277 return new UnwindAssemblyInstEmulation (arch, inst_emulator_ap.release()); 278 return NULL; 279 } 280 281 282 //------------------------------------------------------------------ 283 // PluginInterface protocol in UnwindAssemblyParser_x86 284 //------------------------------------------------------------------ 285 ConstString 286 UnwindAssemblyInstEmulation::GetPluginName() 287 { 288 return GetPluginNameStatic(); 289 } 290 291 uint32_t 292 UnwindAssemblyInstEmulation::GetPluginVersion() 293 { 294 return 1; 295 } 296 297 void 298 UnwindAssemblyInstEmulation::Initialize() 299 { 300 PluginManager::RegisterPlugin (GetPluginNameStatic(), 301 GetPluginDescriptionStatic(), 302 CreateInstance); 303 } 304 305 void 306 UnwindAssemblyInstEmulation::Terminate() 307 { 308 PluginManager::UnregisterPlugin (CreateInstance); 309 } 310 311 312 ConstString 313 UnwindAssemblyInstEmulation::GetPluginNameStatic() 314 { 315 static ConstString g_name("inst-emulation"); 316 return g_name; 317 } 318 319 const char * 320 UnwindAssemblyInstEmulation::GetPluginDescriptionStatic() 321 { 322 return "Instruction emulation based unwind information."; 323 } 324 325 326 uint64_t 327 UnwindAssemblyInstEmulation::MakeRegisterKindValuePair (const RegisterInfo ®_info) 328 { 329 lldb::RegisterKind reg_kind; 330 uint32_t reg_num; 331 if (EmulateInstruction::GetBestRegisterKindAndNumber (®_info, reg_kind, reg_num)) 332 return (uint64_t)reg_kind << 24 | reg_num; 333 return 0ull; 334 } 335 336 void 337 UnwindAssemblyInstEmulation::SetRegisterValue (const RegisterInfo ®_info, const RegisterValue ®_value) 338 { 339 m_register_values[MakeRegisterKindValuePair (reg_info)] = reg_value; 340 } 341 342 bool 343 UnwindAssemblyInstEmulation::GetRegisterValue (const RegisterInfo ®_info, RegisterValue ®_value) 344 { 345 const uint64_t reg_id = MakeRegisterKindValuePair (reg_info); 346 RegisterValueMap::const_iterator pos = m_register_values.find(reg_id); 347 if (pos != m_register_values.end()) 348 { 349 reg_value = pos->second; 350 return true; // We had a real value that comes from an opcode that wrote 351 // to it... 352 } 353 // We are making up a value that is recognizable... 354 reg_value.SetUInt(reg_id, reg_info.byte_size); 355 return false; 356 } 357 358 359 size_t 360 UnwindAssemblyInstEmulation::ReadMemory (EmulateInstruction *instruction, 361 void *baton, 362 const EmulateInstruction::Context &context, 363 lldb::addr_t addr, 364 void *dst, 365 size_t dst_len) 366 { 367 Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); 368 369 if (log && log->GetVerbose ()) 370 { 371 StreamString strm; 372 strm.Printf ("UnwindAssemblyInstEmulation::ReadMemory (addr = 0x%16.16" PRIx64 ", dst = %p, dst_len = %" PRIu64 ", context = ", 373 addr, 374 dst, 375 (uint64_t)dst_len); 376 context.Dump(strm, instruction); 377 log->PutCString (strm.GetData ()); 378 } 379 memset (dst, 0, dst_len); 380 return dst_len; 381 } 382 383 size_t 384 UnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction, 385 void *baton, 386 const EmulateInstruction::Context &context, 387 lldb::addr_t addr, 388 const void *dst, 389 size_t dst_len) 390 { 391 if (baton && dst && dst_len) 392 return ((UnwindAssemblyInstEmulation *)baton)->WriteMemory (instruction, context, addr, dst, dst_len); 393 return 0; 394 } 395 396 size_t 397 UnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction, 398 const EmulateInstruction::Context &context, 399 lldb::addr_t addr, 400 const void *dst, 401 size_t dst_len) 402 { 403 DataExtractor data (dst, 404 dst_len, 405 instruction->GetArchitecture ().GetByteOrder(), 406 instruction->GetArchitecture ().GetAddressByteSize()); 407 408 Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); 409 410 if (log && log->GetVerbose ()) 411 { 412 StreamString strm; 413 414 strm.PutCString ("UnwindAssemblyInstEmulation::WriteMemory ("); 415 data.Dump(&strm, 0, eFormatBytes, 1, dst_len, UINT32_MAX, addr, 0, 0); 416 strm.PutCString (", context = "); 417 context.Dump(strm, instruction); 418 log->PutCString (strm.GetData()); 419 } 420 421 const bool cant_replace = false; 422 423 switch (context.type) 424 { 425 default: 426 case EmulateInstruction::eContextInvalid: 427 case EmulateInstruction::eContextReadOpcode: 428 case EmulateInstruction::eContextImmediate: 429 case EmulateInstruction::eContextAdjustBaseRegister: 430 case EmulateInstruction::eContextRegisterPlusOffset: 431 case EmulateInstruction::eContextAdjustPC: 432 case EmulateInstruction::eContextRegisterStore: 433 case EmulateInstruction::eContextRegisterLoad: 434 case EmulateInstruction::eContextRelativeBranchImmediate: 435 case EmulateInstruction::eContextAbsoluteBranchRegister: 436 case EmulateInstruction::eContextSupervisorCall: 437 case EmulateInstruction::eContextTableBranchReadMemory: 438 case EmulateInstruction::eContextWriteRegisterRandomBits: 439 case EmulateInstruction::eContextWriteMemoryRandomBits: 440 case EmulateInstruction::eContextArithmetic: 441 case EmulateInstruction::eContextAdvancePC: 442 case EmulateInstruction::eContextReturnFromException: 443 case EmulateInstruction::eContextPopRegisterOffStack: 444 case EmulateInstruction::eContextAdjustStackPointer: 445 break; 446 447 case EmulateInstruction::eContextPushRegisterOnStack: 448 { 449 uint32_t reg_num = LLDB_INVALID_REGNUM; 450 uint32_t generic_regnum = LLDB_INVALID_REGNUM; 451 if (context.info_type == EmulateInstruction::eInfoTypeRegisterToRegisterPlusOffset) 452 { 453 const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind(); 454 reg_num = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[unwind_reg_kind]; 455 generic_regnum = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[eRegisterKindGeneric]; 456 } 457 else 458 assert (!"unhandled case, add code to handle this!"); 459 460 if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP) 461 { 462 if (m_pushed_regs.find (reg_num) == m_pushed_regs.end()) 463 { 464 m_pushed_regs[reg_num] = addr; 465 const int32_t offset = addr - m_initial_sp; 466 m_curr_row->SetRegisterLocationToAtCFAPlusOffset (reg_num, offset, cant_replace); 467 m_curr_row_modified = true; 468 } 469 } 470 } 471 break; 472 473 } 474 475 return dst_len; 476 } 477 478 bool 479 UnwindAssemblyInstEmulation::ReadRegister (EmulateInstruction *instruction, 480 void *baton, 481 const RegisterInfo *reg_info, 482 RegisterValue ®_value) 483 { 484 485 if (baton && reg_info) 486 return ((UnwindAssemblyInstEmulation *)baton)->ReadRegister (instruction, reg_info, reg_value); 487 return false; 488 } 489 bool 490 UnwindAssemblyInstEmulation::ReadRegister (EmulateInstruction *instruction, 491 const RegisterInfo *reg_info, 492 RegisterValue ®_value) 493 { 494 bool synthetic = GetRegisterValue (*reg_info, reg_value); 495 496 Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); 497 498 if (log && log->GetVerbose ()) 499 { 500 501 StreamString strm; 502 strm.Printf ("UnwindAssemblyInstEmulation::ReadRegister (name = \"%s\") => synthetic_value = %i, value = ", reg_info->name, synthetic); 503 reg_value.Dump(&strm, reg_info, false, false, eFormatDefault); 504 log->PutCString(strm.GetData()); 505 } 506 return true; 507 } 508 509 bool 510 UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction, 511 void *baton, 512 const EmulateInstruction::Context &context, 513 const RegisterInfo *reg_info, 514 const RegisterValue ®_value) 515 { 516 if (baton && reg_info) 517 return ((UnwindAssemblyInstEmulation *)baton)->WriteRegister (instruction, context, reg_info, reg_value); 518 return false; 519 } 520 bool 521 UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction, 522 const EmulateInstruction::Context &context, 523 const RegisterInfo *reg_info, 524 const RegisterValue ®_value) 525 { 526 Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); 527 528 if (log && log->GetVerbose ()) 529 { 530 531 StreamString strm; 532 strm.Printf ("UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ", reg_info->name); 533 reg_value.Dump(&strm, reg_info, false, false, eFormatDefault); 534 strm.PutCString (", context = "); 535 context.Dump(strm, instruction); 536 log->PutCString(strm.GetData()); 537 } 538 539 SetRegisterValue (*reg_info, reg_value); 540 541 switch (context.type) 542 { 543 case EmulateInstruction::eContextInvalid: 544 case EmulateInstruction::eContextReadOpcode: 545 case EmulateInstruction::eContextImmediate: 546 case EmulateInstruction::eContextAdjustBaseRegister: 547 case EmulateInstruction::eContextRegisterPlusOffset: 548 case EmulateInstruction::eContextAdjustPC: 549 case EmulateInstruction::eContextRegisterStore: 550 case EmulateInstruction::eContextSupervisorCall: 551 case EmulateInstruction::eContextTableBranchReadMemory: 552 case EmulateInstruction::eContextWriteRegisterRandomBits: 553 case EmulateInstruction::eContextWriteMemoryRandomBits: 554 case EmulateInstruction::eContextAdvancePC: 555 case EmulateInstruction::eContextReturnFromException: 556 case EmulateInstruction::eContextPushRegisterOnStack: 557 case EmulateInstruction::eContextRegisterLoad: 558 // { 559 // const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; 560 // if (reg_num != LLDB_INVALID_REGNUM) 561 // { 562 // const bool can_replace_only_if_unspecified = true; 563 // 564 // m_curr_row.SetRegisterLocationToUndefined (reg_num, 565 // can_replace_only_if_unspecified, 566 // can_replace_only_if_unspecified); 567 // m_curr_row_modified = true; 568 // } 569 // } 570 break; 571 572 case EmulateInstruction::eContextArithmetic: 573 { 574 // If we adjusted the current frame pointer by a constant then adjust the CFA offset 575 // with the same amount. 576 lldb::RegisterKind kind = m_unwind_plan_ptr->GetRegisterKind(); 577 if (m_fp_is_cfa && reg_info->kinds[kind] == m_cfa_reg_info.kinds[kind] && 578 context.info_type == EmulateInstruction::eInfoTypeRegisterPlusOffset && 579 context.info.RegisterPlusOffset.reg.kinds[kind] == m_cfa_reg_info.kinds[kind]) 580 { 581 const int64_t offset = context.info.RegisterPlusOffset.signed_offset; 582 m_curr_row->GetCFAValue().IncOffset(-1 * offset); 583 m_curr_row_modified = true; 584 } 585 } 586 break; 587 588 case EmulateInstruction::eContextAbsoluteBranchRegister: 589 case EmulateInstruction::eContextRelativeBranchImmediate: 590 { 591 if (context.info_type == EmulateInstruction::eInfoTypeISAAndImmediate && 592 context.info.ISAAndImmediate.unsigned_data32 > 0) 593 { 594 m_forward_branch_offset = context.info.ISAAndImmediateSigned.signed_data32; 595 } 596 else if (context.info_type == EmulateInstruction::eInfoTypeISAAndImmediateSigned && 597 context.info.ISAAndImmediateSigned.signed_data32 > 0) 598 { 599 m_forward_branch_offset = context.info.ISAAndImmediate.unsigned_data32; 600 } 601 else if (context.info_type == EmulateInstruction::eInfoTypeImmediate && 602 context.info.unsigned_immediate > 0) 603 { 604 m_forward_branch_offset = context.info.unsigned_immediate; 605 } 606 else if (context.info_type == EmulateInstruction::eInfoTypeImmediateSigned && 607 context.info.signed_immediate > 0) 608 { 609 m_forward_branch_offset = context.info.signed_immediate; 610 } 611 } 612 break; 613 614 case EmulateInstruction::eContextPopRegisterOffStack: 615 { 616 const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; 617 const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric]; 618 if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP) 619 { 620 switch (context.info_type) 621 { 622 case EmulateInstruction::eInfoTypeAddress: 623 if (m_pushed_regs.find(reg_num) != m_pushed_regs.end() && 624 context.info.address == m_pushed_regs[reg_num]) 625 { 626 m_curr_row->SetRegisterLocationToSame(reg_num, 627 false /*must_replace*/); 628 m_curr_row_modified = true; 629 } 630 break; 631 case EmulateInstruction::eInfoTypeISA: 632 assert((generic_regnum == LLDB_REGNUM_GENERIC_PC || 633 generic_regnum == LLDB_REGNUM_GENERIC_FLAGS) && 634 "eInfoTypeISA used for poping a register other the the PC/FLAGS"); 635 if (generic_regnum != LLDB_REGNUM_GENERIC_FLAGS) 636 { 637 m_curr_row->SetRegisterLocationToSame(reg_num, 638 false /*must_replace*/); 639 m_curr_row_modified = true; 640 } 641 break; 642 default: 643 assert(false && "unhandled case, add code to handle this!"); 644 break; 645 } 646 } 647 } 648 break; 649 650 case EmulateInstruction::eContextSetFramePointer: 651 if (!m_fp_is_cfa) 652 { 653 m_fp_is_cfa = true; 654 m_cfa_reg_info = *reg_info; 655 const uint32_t cfa_reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; 656 assert (cfa_reg_num != LLDB_INVALID_REGNUM); 657 m_curr_row->GetCFAValue().SetIsRegisterPlusOffset(cfa_reg_num, m_initial_sp - 658 reg_value.GetAsUInt64()); 659 m_curr_row_modified = true; 660 } 661 break; 662 663 case EmulateInstruction::eContextAdjustStackPointer: 664 // If we have created a frame using the frame pointer, don't follow 665 // subsequent adjustments to the stack pointer. 666 if (!m_fp_is_cfa) 667 { 668 m_curr_row->GetCFAValue().SetIsRegisterPlusOffset( 669 m_curr_row->GetCFAValue().GetRegisterNumber(), 670 m_initial_sp - reg_value.GetAsUInt64()); 671 m_curr_row_modified = true; 672 } 673 break; 674 } 675 return true; 676 } 677 678 679