https://github.com/felipepiovezan updated https://github.com/llvm/llvm-project/pull/169630
>From 9295ef8614e7f2d14cb7d95c8d963e4128d5992c Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan <[email protected]> Date: Wed, 26 Nov 2025 10:55:12 +0000 Subject: [PATCH 1/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?= =?UTF-8?q?itial=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.7 --- .../UnwindAssemblyInstEmulation.cpp | 52 ++++++++++++++----- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp index b9d665902dc45..074746c0fab3d 100644 --- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -25,6 +25,8 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" +#include "llvm/ADT/SmallSet.h" +#include <deque> using namespace lldb; using namespace lldb_private; @@ -150,29 +152,38 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly( EmulateInstruction::InstructionCondition last_condition = EmulateInstruction::UnconditionalCondition; - for (const InstructionSP &inst : inst_list.Instructions()) { - if (!inst) - continue; - DumpInstToLog(log, *inst, inst_list); + std::deque<std::size_t> to_visit = {0}; + llvm::SmallSet<std::size_t, 0> enqueued = {0}; + + // Instructions reachable through jumps are inserted on the front. + // The next instruction in inserted on the back. + // Pop from the back to ensure non-branching instructions are visited + // sequentially. + while (!to_visit.empty()) { + std::size_t current_index = to_visit.back(); + Instruction &inst = *inst_list.GetInstructionAtIndex(current_index); + to_visit.pop_back(); + DumpInstToLog(log, inst, inst_list); m_curr_row_modified = false; m_forward_branch_offset = 0; lldb::addr_t current_offset = - inst->GetAddress().GetFileAddress() - base_addr; + inst.GetAddress().GetFileAddress() - base_addr; auto it = saved_unwind_states.upper_bound(current_offset); assert(it != saved_unwind_states.begin() && "Unwind row for the function entry missing"); --it; // Move it to the row corresponding to the current offset - // If the offset of m_state.row doesn't match with the offset we see in - // saved_unwind_states then we have to update current unwind state to - // the saved values. It is happening after we processed an epilogue and a - // return to caller instruction. + // When state is forwarded through a branch, the offset of m_state.row is + // different from the offset available in saved_unwind_states. Use the + // forwarded state in this case, as the previous instruction may have been + // an unconditional jump. + // FIXME: this assignment can always be done unconditionally. if (it->second.row.GetOffset() != m_state.row.GetOffset()) m_state = it->second; - m_inst_emulator_up->SetInstruction(inst->GetOpcode(), inst->GetAddress(), + m_inst_emulator_up->SetInstruction(inst.GetOpcode(), inst.GetAddress(), nullptr); const EmulateInstruction::InstructionCondition new_condition = m_inst_emulator_up->GetInstructionCondition(); @@ -199,13 +210,21 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly( // If the current instruction is a branch forward then save the current // CFI information for the offset where we are branching. + Address branch_address = inst.GetAddress(); + branch_address.Slide(m_forward_branch_offset); if (m_forward_branch_offset != 0 && - range.ContainsFileAddress(inst->GetAddress().GetFileAddress() + - m_forward_branch_offset)) { + range.ContainsFileAddress(branch_address.GetFileAddress())) { if (auto [it, inserted] = saved_unwind_states.emplace( current_offset + m_forward_branch_offset, m_state); - inserted) + inserted) { it->second.row.SetOffset(current_offset + m_forward_branch_offset); + if (std::size_t dest_instr_index = + inst_list.GetIndexOfInstructionAtAddress(branch_address); + dest_instr_index < inst_list.GetSize()) { + to_visit.push_front(dest_instr_index); + enqueued.insert(dest_instr_index); + } + } } // Were there any changes to the CFI while evaluating this instruction? @@ -213,12 +232,17 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly( // Save the modified row if we don't already have a CFI row in the // current address const lldb::addr_t next_inst_offset = - current_offset + inst->GetOpcode().GetByteSize(); + current_offset + inst.GetOpcode().GetByteSize(); if (saved_unwind_states.count(next_inst_offset) == 0) { m_state.row.SetOffset(next_inst_offset); saved_unwind_states.emplace(next_inst_offset, m_state); } } + + const size_t next_idx = current_index + 1; + const bool never_enqueued = enqueued.insert(next_idx).second; + if (never_enqueued && next_idx < inst_list.GetSize()) + to_visit.push_back(next_idx); } for (auto &[_, state] : saved_unwind_states) >From f00f52c3eb73dc3e51031c81b74108b0839c7a38 Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan <[email protected]> Date: Thu, 27 Nov 2025 09:49:07 +0000 Subject: [PATCH 2/2] Address review comments Created using spr 1.3.7 --- .../InstEmulation/UnwindAssemblyInstEmulation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp index 074746c0fab3d..c3d92f6a13d97 100644 --- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -156,11 +156,11 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly( llvm::SmallSet<std::size_t, 0> enqueued = {0}; // Instructions reachable through jumps are inserted on the front. - // The next instruction in inserted on the back. + // The next instruction is inserted on the back. // Pop from the back to ensure non-branching instructions are visited // sequentially. while (!to_visit.empty()) { - std::size_t current_index = to_visit.back(); + const std::size_t current_index = to_visit.back(); Instruction &inst = *inst_list.GetInstructionAtIndex(current_index); to_visit.pop_back(); DumpInstToLog(log, inst, inst_list); _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
