38 std::vector<uint8_t> function_text(range.GetByteSize());
39 ProcessSP process_sp(thread.GetProcess());
42 const bool force_live_memory =
true;
43 if (process_sp->GetTarget().ReadMemory(
44 range.GetBaseAddress(), function_text.data(), range.GetByteSize(),
45 error, force_live_memory) != range.GetByteSize()) {
49 return GetNonCallSiteUnwindPlanFromAssembly(
50 range, function_text.data(), function_text.size(), unwind_plan);
54 AddressRange &range, uint8_t *opcode_data,
size_t opcode_size,
56 if (opcode_data ==
nullptr || opcode_size == 0)
60 m_inst_emulator_up.get()) {
64 m_inst_emulator_up->CreateFunctionEntryUnwind(unwind_plan);
71 const bool prefer_file_cache =
true;
72 DisassemblerSP disasm_sp(Disassembler::DisassembleBytes(
74 opcode_size, 99999, prefer_file_cache));
81 m_unwind_plan_ptr = &unwind_plan;
83 const uint32_t addr_byte_size = m_arch.GetAddressByteSize();
84 const bool show_address =
true;
85 const bool show_bytes =
true;
86 const bool show_control_flow_kind =
true;
87 m_cfa_reg_info = *m_inst_emulator_up->GetRegisterInfo(
90 m_register_values.clear();
91 m_pushed_regs.clear();
96 m_initial_sp = (1ull << ((addr_byte_size * 8) - 1));
98 cfa_reg_value.
SetUInt(m_initial_sp, m_cfa_reg_info.byte_size);
99 SetRegisterValue(m_cfa_reg_info, cfa_reg_value);
102 const size_t num_instructions = inst_list.
GetSize();
104 if (num_instructions > 0) {
114 std::map<lldb::addr_t, std::pair<UnwindPlan::RowSP, RegisterValueMap>>
122 *newrow = *last_row.get();
123 m_curr_row.reset(newrow);
126 saved_unwind_states.insert({0, {last_row, m_register_values}});
137 EmulateInstruction::UnconditionalCondition;
140 for (
size_t idx = 0; idx < num_instructions; ++idx) {
141 m_curr_row_modified =
false;
142 m_forward_branch_offset = 0;
148 auto it = saved_unwind_states.upper_bound(current_offset);
149 assert(it != saved_unwind_states.begin() &&
150 "Unwind row for the function entry missing");
158 if (it->second.first->GetOffset() != m_curr_row->GetOffset()) {
160 *newrow = *it->second.first;
161 m_curr_row.reset(newrow);
162 m_register_values = it->second.second;
165 if (sp_reg_info.name &&
166 m_curr_row->GetCFAValue().IsRegisterPlusOffset()) {
168 m_curr_row->GetCFAValue().GetRegisterNumber();
170 m_unwind_plan_ptr->GetRegisterKind();
172 m_cfa_reg_info = *m_inst_emulator_up->GetRegisterInfo(
173 row_kind, row_cfa_regnum);
175 if (sp_reg_info.kinds[row_kind] == row_cfa_regnum)
182 m_inst_emulator_up->SetInstruction(inst->
GetOpcode(),
185 if (last_condition !=
186 m_inst_emulator_up->GetInstructionCondition()) {
187 if (m_inst_emulator_up->GetInstructionCondition() !=
188 EmulateInstruction::UnconditionalCondition &&
189 saved_unwind_states.count(current_offset) == 0) {
194 std::make_shared<UnwindPlan::Row>(*m_curr_row.get());
195 saved_unwind_states.insert(
196 {current_offset, {new_row, m_register_values}});
202 if (last_condition !=
203 EmulateInstruction::UnconditionalCondition) {
204 const auto &saved_state =
205 saved_unwind_states.at(condition_block_start_offset);
207 std::make_shared<UnwindPlan::Row>(*saved_state.first);
208 m_curr_row->SetOffset(current_offset);
209 m_register_values = saved_state.second;
212 if (sp_reg_info.name &&
213 m_curr_row->GetCFAValue().IsRegisterPlusOffset()) {
215 m_curr_row->GetCFAValue().GetRegisterNumber();
217 m_unwind_plan_ptr->GetRegisterKind();
219 m_cfa_reg_info = *m_inst_emulator_up->GetRegisterInfo(
220 row_kind, row_cfa_regnum);
222 if (sp_reg_info.kinds[row_kind] == row_cfa_regnum)
227 bool replace_existing =
232 std::make_shared<UnwindPlan::Row>(*m_curr_row),
237 condition_block_start_offset = current_offset;
243 FormatEntity::Parse(
"${frame.pc}: ", format);
245 show_bytes, show_control_flow_kind,
nullptr,
nullptr,
246 nullptr, &format, 0);
250 last_condition = m_inst_emulator_up->GetInstructionCondition();
252 m_inst_emulator_up->EvaluateInstruction(
253 eEmulateInstructionOptionIgnoreConditions);
257 if (m_forward_branch_offset != 0 &&
259 m_forward_branch_offset)) {
261 std::make_shared<UnwindPlan::Row>(*m_curr_row.get());
262 newrow->
SetOffset(current_offset + m_forward_branch_offset);
263 saved_unwind_states.insert(
264 {current_offset + m_forward_branch_offset,
265 {newrow, m_register_values}});
271 if (m_curr_row_modified) {
274 if (saved_unwind_states.count(
276 m_curr_row->SetOffset(current_offset +
279 saved_unwind_states.insert(
280 {current_offset + inst->
GetOpcode().GetByteSize(),
281 {m_curr_row, m_register_values}});
286 *newrow = *m_curr_row.get();
287 m_curr_row.reset(newrow);
298 strm.
Printf(
"Resulting unwind rows for [0x%" PRIx64
" - 0x%" PRIx64
"):",
300 unwind_plan.
Dump(strm,
nullptr, base_addr);
321 Address &first_non_prologue_insn) {
327 std::unique_ptr<EmulateInstruction> inst_emulator_up(
331 if (inst_emulator_up)
337 PluginManager::RegisterPlugin(GetPluginNameStatic(),
338 GetPluginDescriptionStatic(), CreateInstance);
342 PluginManager::UnregisterPlugin(CreateInstance);
346 return "Instruction emulation based unwind information.";
350 const RegisterInfo ®_info) {
353 if (EmulateInstruction::GetBestRegisterKindAndNumber(®_info, reg_kind,
355 return (uint64_t)reg_kind << 24 | reg_num;
360 const RegisterInfo ®_info,
const RegisterValue ®_value) {
361 m_register_values[MakeRegisterKindValuePair(reg_info)] = reg_value;
366 const uint64_t reg_id = MakeRegisterKindValuePair(reg_info);
367 RegisterValueMap::const_iterator pos = m_register_values.find(reg_id);
368 if (pos != m_register_values.end()) {
369 reg_value = pos->second;
374 reg_value.
SetUInt(reg_id, reg_info.byte_size);
387 "UnwindAssemblyInstEmulation::ReadMemory (addr = 0x%16.16" PRIx64
388 ", dst = %p, dst_len = %" PRIu64
", context = ",
389 addr, dst, (uint64_t)dst_len);
390 context.
Dump(strm, instruction);
393 memset(dst, 0, dst_len);
400 const void *dst,
size_t dst_len) {
401 if (baton && dst && dst_len)
403 ->WriteMemory(instruction, context, addr, dst, dst_len);
419 strm.
PutCString(
"UnwindAssemblyInstEmulation::WriteMemory (");
423 context.
Dump(strm, instruction);
427 const bool cant_replace =
false;
429 switch (context.
type) {
431 case EmulateInstruction::eContextInvalid:
432 case EmulateInstruction::eContextReadOpcode:
433 case EmulateInstruction::eContextImmediate:
434 case EmulateInstruction::eContextAdjustBaseRegister:
435 case EmulateInstruction::eContextRegisterPlusOffset:
436 case EmulateInstruction::eContextAdjustPC:
437 case EmulateInstruction::eContextRegisterStore:
438 case EmulateInstruction::eContextRegisterLoad:
439 case EmulateInstruction::eContextRelativeBranchImmediate:
440 case EmulateInstruction::eContextAbsoluteBranchRegister:
441 case EmulateInstruction::eContextSupervisorCall:
442 case EmulateInstruction::eContextTableBranchReadMemory:
443 case EmulateInstruction::eContextWriteRegisterRandomBits:
444 case EmulateInstruction::eContextWriteMemoryRandomBits:
445 case EmulateInstruction::eContextArithmetic:
446 case EmulateInstruction::eContextAdvancePC:
447 case EmulateInstruction::eContextReturnFromException:
448 case EmulateInstruction::eContextPopRegisterOffStack:
449 case EmulateInstruction::eContextAdjustStackPointer:
452 case EmulateInstruction::eContextPushRegisterOnStack: {
456 EmulateInstruction::eInfoTypeRegisterToRegisterPlusOffset &&
457 "unhandled case, add code to handle this!");
458 const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind();
460 .kinds[unwind_reg_kind];
466 if (m_pushed_regs.find(reg_num) == m_pushed_regs.end()) {
467 m_pushed_regs[reg_num] = addr;
468 const int32_t offset = addr - m_initial_sp;
469 m_curr_row->SetRegisterLocationToAtCFAPlusOffset(reg_num, offset,
471 m_curr_row_modified =
true;
482 const RegisterInfo *reg_info,
485 if (baton && reg_info)
487 ->ReadRegister(instruction, reg_info, reg_value);
491 const RegisterInfo *reg_info,
493 bool synthetic = GetRegisterValue(*reg_info, reg_value);
500 strm.
Printf(
"UnwindAssemblyInstEmulation::ReadRegister (name = \"%s\") => "
501 "synthetic_value = %i, value = ",
502 reg_info->name, synthetic);
513 if (baton && reg_info)
515 ->WriteRegister(instruction, context, reg_info, reg_value);
520 const RegisterInfo *reg_info,
const RegisterValue ®_value) {
527 "UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ",
531 context.
Dump(strm, instruction);
535 SetRegisterValue(*reg_info, reg_value);
537 switch (context.
type) {
538 case EmulateInstruction::eContextInvalid:
539 case EmulateInstruction::eContextReadOpcode:
540 case EmulateInstruction::eContextImmediate:
541 case EmulateInstruction::eContextAdjustBaseRegister:
542 case EmulateInstruction::eContextRegisterPlusOffset:
543 case EmulateInstruction::eContextAdjustPC:
544 case EmulateInstruction::eContextRegisterStore:
545 case EmulateInstruction::eContextSupervisorCall:
546 case EmulateInstruction::eContextTableBranchReadMemory:
547 case EmulateInstruction::eContextWriteRegisterRandomBits:
548 case EmulateInstruction::eContextWriteMemoryRandomBits:
549 case EmulateInstruction::eContextAdvancePC:
550 case EmulateInstruction::eContextReturnFromException:
551 case EmulateInstruction::eContextPushRegisterOnStack:
552 case EmulateInstruction::eContextRegisterLoad:
568 case EmulateInstruction::eContextArithmetic: {
573 if (m_fp_is_cfa && reg_info->kinds[kind] == m_cfa_reg_info.kinds[kind] &&
575 EmulateInstruction::eInfoTypeRegisterPlusOffset &&
577 m_cfa_reg_info.kinds[kind]) {
579 m_curr_row->GetCFAValue().IncOffset(-1 * offset);
580 m_curr_row_modified =
true;
584 case EmulateInstruction::eContextAbsoluteBranchRegister:
585 case EmulateInstruction::eContextRelativeBranchImmediate: {
586 if (context.
GetInfoType() == EmulateInstruction::eInfoTypeISAAndImmediate &&
588 m_forward_branch_offset =
591 EmulateInstruction::eInfoTypeISAAndImmediateSigned &&
595 EmulateInstruction::eInfoTypeImmediate &&
599 EmulateInstruction::eInfoTypeImmediateSigned &&
605 case EmulateInstruction::eContextPopRegisterOffStack: {
607 reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
612 case EmulateInstruction::eInfoTypeAddress:
613 if (m_pushed_regs.find(reg_num) != m_pushed_regs.end() &&
615 m_curr_row->SetRegisterLocationToSame(reg_num,
617 m_curr_row_modified =
true;
625 RegisterInfo sp_reg_info =
626 *m_inst_emulator_up->GetRegisterInfo(sp_reg_kind, sp_reg_num);
628 if (GetRegisterValue(sp_reg_info, sp_reg_val)) {
629 m_cfa_reg_info = sp_reg_info;
631 sp_reg_info.kinds[m_unwind_plan_ptr->GetRegisterKind()];
633 m_curr_row->GetCFAValue().SetIsRegisterPlusOffset(
634 cfa_reg_num, m_initial_sp - sp_reg_val.
GetAsUInt64());
639 case EmulateInstruction::eInfoTypeISA:
643 "eInfoTypeISA used for popping a register other the PC/FLAGS");
645 m_curr_row->SetRegisterLocationToSame(reg_num,
647 m_curr_row_modified =
true;
651 assert(
false &&
"unhandled case, add code to handle this!");
657 case EmulateInstruction::eContextSetFramePointer:
660 m_cfa_reg_info = *reg_info;
662 reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
664 m_curr_row->GetCFAValue().SetIsRegisterPlusOffset(
665 cfa_reg_num, m_initial_sp - reg_value.
GetAsUInt64());
666 m_curr_row_modified =
true;
670 case EmulateInstruction::eContextRestoreStackPointer:
673 m_cfa_reg_info = *reg_info;
675 reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
677 m_curr_row->GetCFAValue().SetIsRegisterPlusOffset(
678 cfa_reg_num, m_initial_sp - reg_value.
GetAsUInt64());
679 m_curr_row_modified =
true;
683 case EmulateInstruction::eContextAdjustStackPointer:
687 m_curr_row->GetCFAValue().SetIsRegisterPlusOffset(
688 m_curr_row->GetCFAValue().GetRegisterNumber(),
690 m_curr_row_modified =
true;