[Lldb-commits] [lldb] [lldb][NFC] Simplify code in UnwindAssemblyInstruction (PR #167914)
Felipe de Azevedo Piovezan via lldb-commits
lldb-commits at lists.llvm.org
Thu Nov 13 09:07:49 PST 2025
https://github.com/felipepiovezan created https://github.com/llvm/llvm-project/pull/167914
This is a series of patches aimed at simplifying the main loop in UnwindAssemblyInstruction.
In a future PR, I would like to fix a bug whereby a mid function epilogue causes the unwinder to produce incorrect results, and these changes will make the fix easier to follow.
While this does pollute the git blame a bit, this code hasn't changed in close to ten years, and even the latest changes were already of a reformatting nature. As such, I believe this is acceptable.
Please look at each commit individually.
>From ca467ef88dfe990e799d9ec69ec35dd68a2a42a4 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Thu, 13 Nov 2025 13:53:53 +0000
Subject: [PATCH 1/6] [lldb][nfc] Fix comment in UnwindAssemblyInstruction
---
.../InstEmulation/UnwindAssemblyInstEmulation.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index 397c693fc498a..7db7efcccee7f 100644
--- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -144,7 +144,7 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
"Unwind row for the function entry missing");
--it; // Move it to the row corresponding to the current offset
- // If the offset of m_curr_row don't match with the offset we see in
+ // 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.
>From e76ba78d0ebd604862051e15ed873e89e1d141b9 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Thu, 13 Nov 2025 14:05:38 +0000
Subject: [PATCH 2/6] [lldb][nfc] Reduce indentation in
UnwindAssemblyInstruction
---
.../UnwindAssemblyInstEmulation.cpp | 219 +++++++++---------
1 file changed, 113 insertions(+), 106 deletions(-)
diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index 7db7efcccee7f..ec050a14fbb4a 100644
--- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -50,6 +50,18 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
range, function_text.data(), function_text.size(), unwind_plan);
}
+static void DumpUnwindRowsToLog(Log *log, AddressRange range,
+ const UnwindPlan &unwind_plan) {
+ if (!log || !log->GetVerbose())
+ return;
+ StreamString strm;
+ lldb::addr_t base_addr = range.GetBaseAddress().GetFileAddress();
+ strm.Printf("Resulting unwind rows for [0x%" PRIx64 " - 0x%" PRIx64 "):",
+ base_addr, base_addr + range.GetByteSize());
+ unwind_plan.Dump(strm, nullptr, base_addr);
+ log->PutString(strm.GetString());
+}
+
bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
AddressRange &range, uint8_t *opcode_data, size_t opcode_size,
UnwindPlan &unwind_plan) {
@@ -105,123 +117,118 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
const InstructionList &inst_list = disasm_sp->GetInstructionList();
const size_t num_instructions = inst_list.GetSize();
- if (num_instructions > 0) {
- Instruction *inst = inst_list.GetInstructionAtIndex(0).get();
- const lldb::addr_t base_addr = inst->GetAddress().GetFileAddress();
-
- // Map for storing the unwind state at a given offset. When we see a forward
- // branch we add a new entry to this map with the actual unwind plan row and
- // register context for the target address of the branch as the current data
- // have to be valid for the target address of the branch too if we are in
- // the same function.
- std::map<lldb::addr_t, UnwindState> saved_unwind_states;
-
- // Make a copy of the current instruction Row and save it in m_state so
- // we can add updates as we process the instructions.
- m_state.row = *unwind_plan.GetLastRow();
-
- // Add the initial state to the save list with offset 0.
- auto condition_block_start_state =
- saved_unwind_states.emplace(0, m_state).first;
-
- // The architecture dependent condition code of the last processed
- // instruction.
- EmulateInstruction::InstructionCondition last_condition =
- EmulateInstruction::UnconditionalCondition;
-
- for (size_t idx = 0; idx < num_instructions; ++idx) {
- m_curr_row_modified = false;
- m_forward_branch_offset = 0;
-
- inst = inst_list.GetInstructionAtIndex(idx).get();
- if (!inst)
- continue;
-
- lldb::addr_t current_offset =
- 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.
- if (it->second.row.GetOffset() != m_state.row.GetOffset())
- m_state = it->second;
-
- m_inst_emulator_up->SetInstruction(inst->GetOpcode(), inst->GetAddress(),
- nullptr);
-
- if (last_condition != m_inst_emulator_up->GetInstructionCondition()) {
- // If the last instruction was conditional with a different condition
- // than the current condition then restore the state.
- if (last_condition != EmulateInstruction::UnconditionalCondition) {
- m_state = condition_block_start_state->second;
- m_state.row.SetOffset(current_offset);
- // The last instruction might already created a row for this offset
- // and we want to overwrite it.
- saved_unwind_states.insert_or_assign(current_offset, m_state);
- }
+ if (num_instructions == 0) {
+ DumpUnwindRowsToLog(log, range, unwind_plan);
+ return unwind_plan.GetRowCount() > 0;
+ }
- // We are starting a new conditional block at the actual offset
- condition_block_start_state = it;
- }
+ Instruction *inst = inst_list.GetInstructionAtIndex(0).get();
+ const lldb::addr_t base_addr = inst->GetAddress().GetFileAddress();
- if (log && log->GetVerbose()) {
- StreamString strm;
- lldb_private::FormatEntity::Entry format;
- FormatEntity::Parse("${frame.pc}: ", format);
- inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize(), show_address,
- show_bytes, show_control_flow_kind, nullptr, nullptr,
- nullptr, &format, 0);
- log->PutString(strm.GetString());
- }
+ // Map for storing the unwind state at a given offset. When we see a forward
+ // branch we add a new entry to this map with the actual unwind plan row and
+ // register context for the target address of the branch as the current data
+ // have to be valid for the target address of the branch too if we are in
+ // the same function.
+ std::map<lldb::addr_t, UnwindState> saved_unwind_states;
- last_condition = m_inst_emulator_up->GetInstructionCondition();
+ // Make a copy of the current instruction Row and save it in m_state so
+ // we can add updates as we process the instructions.
+ m_state.row = *unwind_plan.GetLastRow();
- m_inst_emulator_up->EvaluateInstruction(
- eEmulateInstructionOptionIgnoreConditions);
+ // Add the initial state to the save list with offset 0.
+ auto condition_block_start_state =
+ saved_unwind_states.emplace(0, m_state).first;
- // If the current instruction is a branch forward then save the current
- // CFI information for the offset where we are branching.
- if (m_forward_branch_offset != 0 &&
- range.ContainsFileAddress(inst->GetAddress().GetFileAddress() +
- m_forward_branch_offset)) {
- if (auto [it, inserted] = saved_unwind_states.emplace(
- current_offset + m_forward_branch_offset, m_state);
- inserted)
- it->second.row.SetOffset(current_offset + m_forward_branch_offset);
+ // The architecture dependent condition code of the last processed
+ // instruction.
+ EmulateInstruction::InstructionCondition last_condition =
+ EmulateInstruction::UnconditionalCondition;
+
+ for (size_t idx = 0; idx < num_instructions; ++idx) {
+ m_curr_row_modified = false;
+ m_forward_branch_offset = 0;
+
+ inst = inst_list.GetInstructionAtIndex(idx).get();
+ if (!inst)
+ continue;
+
+ lldb::addr_t current_offset =
+ 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.
+ if (it->second.row.GetOffset() != m_state.row.GetOffset())
+ m_state = it->second;
+
+ m_inst_emulator_up->SetInstruction(inst->GetOpcode(), inst->GetAddress(),
+ nullptr);
+
+ if (last_condition != m_inst_emulator_up->GetInstructionCondition()) {
+ // If the last instruction was conditional with a different condition
+ // than the current condition then restore the state.
+ if (last_condition != EmulateInstruction::UnconditionalCondition) {
+ m_state = condition_block_start_state->second;
+ m_state.row.SetOffset(current_offset);
+ // The last instruction might already created a row for this offset
+ // and we want to overwrite it.
+ saved_unwind_states.insert_or_assign(current_offset, m_state);
}
- // Were there any changes to the CFI while evaluating this instruction?
- if (m_curr_row_modified) {
- // Save the modified row if we don't already have a CFI row in the
- // current address
- if (saved_unwind_states.count(current_offset +
- inst->GetOpcode().GetByteSize()) == 0) {
- m_state.row.SetOffset(current_offset +
- inst->GetOpcode().GetByteSize());
- saved_unwind_states.emplace(
- current_offset + inst->GetOpcode().GetByteSize(), m_state);
- }
- }
+ // We are starting a new conditional block at the actual offset
+ condition_block_start_state = it;
}
- for (auto &[_, state] : saved_unwind_states) {
- unwind_plan.InsertRow(std::move(state.row),
- /*replace_existing=*/true);
+
+ if (log && log->GetVerbose()) {
+ StreamString strm;
+ lldb_private::FormatEntity::Entry format;
+ FormatEntity::Parse("${frame.pc}: ", format);
+ inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize(), show_address,
+ show_bytes, show_control_flow_kind, nullptr, nullptr, nullptr,
+ &format, 0);
+ log->PutString(strm.GetString());
}
- }
- if (log && log->GetVerbose()) {
- StreamString strm;
- lldb::addr_t base_addr = range.GetBaseAddress().GetFileAddress();
- strm.Printf("Resulting unwind rows for [0x%" PRIx64 " - 0x%" PRIx64 "):",
- base_addr, base_addr + range.GetByteSize());
- unwind_plan.Dump(strm, nullptr, base_addr);
- log->PutString(strm.GetString());
+ last_condition = m_inst_emulator_up->GetInstructionCondition();
+
+ m_inst_emulator_up->EvaluateInstruction(
+ eEmulateInstructionOptionIgnoreConditions);
+
+ // If the current instruction is a branch forward then save the current
+ // CFI information for the offset where we are branching.
+ if (m_forward_branch_offset != 0 &&
+ range.ContainsFileAddress(inst->GetAddress().GetFileAddress() +
+ m_forward_branch_offset)) {
+ if (auto [it, inserted] = saved_unwind_states.emplace(
+ current_offset + m_forward_branch_offset, m_state);
+ inserted)
+ it->second.row.SetOffset(current_offset + m_forward_branch_offset);
+ }
+
+ // Were there any changes to the CFI while evaluating this instruction?
+ if (m_curr_row_modified) {
+ // Save the modified row if we don't already have a CFI row in the
+ // current address
+ if (saved_unwind_states.count(current_offset +
+ inst->GetOpcode().GetByteSize()) == 0) {
+ m_state.row.SetOffset(current_offset + inst->GetOpcode().GetByteSize());
+ saved_unwind_states.emplace(
+ current_offset + inst->GetOpcode().GetByteSize(), m_state);
+ }
+ }
}
+
+ for (auto &[_, state] : saved_unwind_states)
+ unwind_plan.InsertRow(std::move(state.row),
+ /*replace_existing=*/true);
+
+ DumpUnwindRowsToLog(log, range, unwind_plan);
return unwind_plan.GetRowCount() > 0;
}
>From 25e777f7ea42bfe4ee844a295a697890b1ce3425 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Thu, 13 Nov 2025 14:16:50 +0000
Subject: [PATCH 3/6] [lldb][nfc] Add helper function for logging in
UnwindAssemblyInstruction
---
.../UnwindAssemblyInstEmulation.cpp | 29 ++++++++++---------
1 file changed, 16 insertions(+), 13 deletions(-)
diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index ec050a14fbb4a..a857a0cd839b7 100644
--- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -62,6 +62,21 @@ static void DumpUnwindRowsToLog(Log *log, AddressRange range,
log->PutString(strm.GetString());
}
+static void DumpInstToLog(Log *log, Instruction &inst,
+ InstructionList inst_list) {
+ if (!log || !log->GetVerbose())
+ return;
+ const bool show_address = true;
+ const bool show_bytes = true;
+ const bool show_control_flow_kind = false;
+ StreamString strm;
+ lldb_private::FormatEntity::Entry format;
+ FormatEntity::Parse("${frame.pc}: ", format);
+ inst.Dump(&strm, inst_list.GetMaxOpcocdeByteSize(), show_address, show_bytes,
+ show_control_flow_kind, nullptr, nullptr, nullptr, &format, 0);
+ log->PutString(strm.GetString());
+}
+
bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
AddressRange &range, uint8_t *opcode_data, size_t opcode_size,
UnwindPlan &unwind_plan) {
@@ -95,9 +110,6 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
m_unwind_plan_ptr = &unwind_plan;
const uint32_t addr_byte_size = m_arch.GetAddressByteSize();
- const bool show_address = true;
- const bool show_bytes = true;
- const bool show_control_flow_kind = false;
m_state.cfa_reg_info = *m_inst_emulator_up->GetRegisterInfo(
unwind_plan.GetRegisterKind(), unwind_plan.GetInitialCFARegister());
@@ -152,6 +164,7 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
inst = inst_list.GetInstructionAtIndex(idx).get();
if (!inst)
continue;
+ DumpInstToLog(log, *inst, inst_list);
lldb::addr_t current_offset =
inst->GetAddress().GetFileAddress() - base_addr;
@@ -185,16 +198,6 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
condition_block_start_state = it;
}
- if (log && log->GetVerbose()) {
- StreamString strm;
- lldb_private::FormatEntity::Entry format;
- FormatEntity::Parse("${frame.pc}: ", format);
- inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize(), show_address,
- show_bytes, show_control_flow_kind, nullptr, nullptr, nullptr,
- &format, 0);
- log->PutString(strm.GetString());
- }
-
last_condition = m_inst_emulator_up->GetInstructionCondition();
m_inst_emulator_up->EvaluateInstruction(
>From 94d25919e2bae5b9016c3a8a34a44c5ccbfc80db Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Thu, 13 Nov 2025 14:23:57 +0000
Subject: [PATCH 4/6] [lldb][nfc] Reduce scope of loop variable in
UnwindAssemblyInstEmulation
---
.../InstEmulation/UnwindAssemblyInstEmulation.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index a857a0cd839b7..9506e17a28e6e 100644
--- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -134,8 +134,8 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
return unwind_plan.GetRowCount() > 0;
}
- Instruction *inst = inst_list.GetInstructionAtIndex(0).get();
- const lldb::addr_t base_addr = inst->GetAddress().GetFileAddress();
+ Instruction &first_inst = *inst_list.GetInstructionAtIndex(0).get();
+ const lldb::addr_t base_addr = first_inst.GetAddress().GetFileAddress();
// Map for storing the unwind state at a given offset. When we see a forward
// branch we add a new entry to this map with the actual unwind plan row and
@@ -161,7 +161,7 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
m_curr_row_modified = false;
m_forward_branch_offset = 0;
- inst = inst_list.GetInstructionAtIndex(idx).get();
+ Instruction *inst = inst_list.GetInstructionAtIndex(idx).get();
if (!inst)
continue;
DumpInstToLog(log, *inst, inst_list);
>From e2d9e8bd3eba1302256f164ef99f60e0a81cdfd8 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Thu, 13 Nov 2025 15:03:27 +0000
Subject: [PATCH 5/6] [lldb][nfc] Initialize m_initial_sp in ctor for
UnwindAssemblyInstEmulation
Also rename the "sp" suffix (originally intended to mean "Stack
Pointer") to "cfa", as "sp" generally means Shared Pointer.
---
.../UnwindAssemblyInstEmulation.cpp | 18 ++++++------------
.../UnwindAssemblyInstEmulation.h | 8 ++++++--
2 files changed, 12 insertions(+), 14 deletions(-)
diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index 9506e17a28e6e..b64126d25c19d 100644
--- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -109,8 +109,6 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
m_range_ptr = ⦥
m_unwind_plan_ptr = &unwind_plan;
- const uint32_t addr_byte_size = m_arch.GetAddressByteSize();
-
m_state.cfa_reg_info = *m_inst_emulator_up->GetRegisterInfo(
unwind_plan.GetRegisterKind(), unwind_plan.GetInitialCFARegister());
m_state.fp_is_cfa = false;
@@ -118,12 +116,8 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
m_pushed_regs.clear();
- // Initialize the CFA with a known value. In the 32 bit case it will be
- // 0x80000000, and in the 64 bit case 0x8000000000000000. We use the address
- // byte size to be safe for any future address sizes
- m_initial_sp = (1ull << ((addr_byte_size * 8) - 1));
RegisterValue cfa_reg_value;
- cfa_reg_value.SetUInt(m_initial_sp, m_state.cfa_reg_info.byte_size);
+ cfa_reg_value.SetUInt(m_initial_cfa, m_state.cfa_reg_info.byte_size);
SetRegisterValue(m_state.cfa_reg_info, cfa_reg_value);
const InstructionList &inst_list = disasm_sp->GetInstructionList();
@@ -392,7 +386,7 @@ size_t UnwindAssemblyInstEmulation::WriteMemory(
if (reg_num != LLDB_INVALID_REGNUM &&
generic_regnum != LLDB_REGNUM_GENERIC_SP) {
if (m_pushed_regs.try_emplace(reg_num, addr).second) {
- const int32_t offset = addr - m_initial_sp;
+ const int32_t offset = addr - m_initial_cfa;
m_state.row.SetRegisterLocationToAtCFAPlusOffset(reg_num, offset,
/*can_replace=*/true);
m_curr_row_modified = true;
@@ -559,7 +553,7 @@ bool UnwindAssemblyInstEmulation::WriteRegister(
sp_reg_info.kinds[m_unwind_plan_ptr->GetRegisterKind()];
assert(cfa_reg_num != LLDB_INVALID_REGNUM);
m_state.row.GetCFAValue().SetIsRegisterPlusOffset(
- cfa_reg_num, m_initial_sp - sp_reg_val.GetAsUInt64());
+ cfa_reg_num, m_initial_cfa - sp_reg_val.GetAsUInt64());
}
}
}
@@ -590,7 +584,7 @@ bool UnwindAssemblyInstEmulation::WriteRegister(
reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
assert(cfa_reg_num != LLDB_INVALID_REGNUM);
m_state.row.GetCFAValue().SetIsRegisterPlusOffset(
- cfa_reg_num, m_initial_sp - reg_value.GetAsUInt64());
+ cfa_reg_num, m_initial_cfa - reg_value.GetAsUInt64());
m_curr_row_modified = true;
}
break;
@@ -603,7 +597,7 @@ bool UnwindAssemblyInstEmulation::WriteRegister(
reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
assert(cfa_reg_num != LLDB_INVALID_REGNUM);
m_state.row.GetCFAValue().SetIsRegisterPlusOffset(
- cfa_reg_num, m_initial_sp - reg_value.GetAsUInt64());
+ cfa_reg_num, m_initial_cfa - reg_value.GetAsUInt64());
m_curr_row_modified = true;
}
break;
@@ -614,7 +608,7 @@ bool UnwindAssemblyInstEmulation::WriteRegister(
if (!m_state.fp_is_cfa) {
m_state.row.GetCFAValue().SetIsRegisterPlusOffset(
m_state.row.GetCFAValue().GetRegisterNumber(),
- m_initial_sp - reg_value.GetAsUInt64());
+ m_initial_cfa - reg_value.GetAsUInt64());
m_curr_row_modified = true;
}
break;
diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
index 96a0881eaee9d..6c0492f5dfc66 100644
--- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
+++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
@@ -63,13 +63,17 @@ class UnwindAssemblyInstEmulation : public lldb_private::UnwindAssembly {
UnwindAssemblyInstEmulation(const lldb_private::ArchSpec &arch,
lldb_private::EmulateInstruction *inst_emulator)
: UnwindAssembly(arch), m_inst_emulator_up(inst_emulator),
- m_range_ptr(nullptr), m_unwind_plan_ptr(nullptr), m_initial_sp(0),
+ m_range_ptr(nullptr), m_unwind_plan_ptr(nullptr),
m_curr_row_modified(false), m_forward_branch_offset(0) {
if (m_inst_emulator_up) {
m_inst_emulator_up->SetBaton(this);
m_inst_emulator_up->SetCallbacks(ReadMemory, WriteMemory, ReadRegister,
WriteRegister);
}
+ // Initialize the CFA with a known value. In the 32 bit case it will be
+ // 0x80000000, and in the 64 bit case 0x8000000000000000. We use the address
+ // byte size to be safe for any future address sizes
+ m_initial_cfa = (1ull << ((m_arch.GetAddressByteSize() * 8) - 1));
}
static size_t
@@ -134,8 +138,8 @@ class UnwindAssemblyInstEmulation : public lldb_private::UnwindAssembly {
lldb_private::AddressRange *m_range_ptr;
lldb_private::UnwindPlan *m_unwind_plan_ptr;
UnwindState m_state;
+ uint64_t m_initial_cfa;
typedef std::map<uint64_t, uint64_t> PushedRegisterToAddrMap;
- uint64_t m_initial_sp;
PushedRegisterToAddrMap m_pushed_regs;
// While processing the instruction stream, we need to communicate some state
>From 717467b648bfc65ee8e662ffec3d7f39799510fd Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Thu, 13 Nov 2025 16:41:34 +0000
Subject: [PATCH 6/6] [lldb][nfc] Simplify instruction iteration in
UnwindAssemblyInstEmulation
---
lldb/include/lldb/Core/Disassembler.h | 4 ++++
.../UnwindAssemblyInstEmulation.cpp | 16 +++++++---------
2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/lldb/include/lldb/Core/Disassembler.h b/lldb/include/lldb/Core/Disassembler.h
index db186dd33d774..daa7b3d25f11b 100644
--- a/lldb/include/lldb/Core/Disassembler.h
+++ b/lldb/include/lldb/Core/Disassembler.h
@@ -297,6 +297,10 @@ class InstructionList {
lldb::InstructionSP GetInstructionAtIndex(size_t idx) const;
+ llvm::ArrayRef<lldb::InstructionSP> Instructions() const {
+ return m_instructions;
+ }
+
/// Get the instruction at the given address.
///
/// \return
diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index b64126d25c19d..68a18bc39249a 100644
--- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -120,15 +120,14 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
cfa_reg_value.SetUInt(m_initial_cfa, m_state.cfa_reg_info.byte_size);
SetRegisterValue(m_state.cfa_reg_info, cfa_reg_value);
- const InstructionList &inst_list = disasm_sp->GetInstructionList();
- const size_t num_instructions = inst_list.GetSize();
+ InstructionList inst_list = disasm_sp->GetInstructionList();
- if (num_instructions == 0) {
+ if (inst_list.GetSize()) {
DumpUnwindRowsToLog(log, range, unwind_plan);
return unwind_plan.GetRowCount() > 0;
}
- Instruction &first_inst = *inst_list.GetInstructionAtIndex(0).get();
+ Instruction &first_inst = *inst_list.GetInstructionAtIndex(0);
const lldb::addr_t base_addr = first_inst.GetAddress().GetFileAddress();
// Map for storing the unwind state at a given offset. When we see a forward
@@ -151,15 +150,14 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
EmulateInstruction::InstructionCondition last_condition =
EmulateInstruction::UnconditionalCondition;
- for (size_t idx = 0; idx < num_instructions; ++idx) {
- m_curr_row_modified = false;
- m_forward_branch_offset = 0;
-
- Instruction *inst = inst_list.GetInstructionAtIndex(idx).get();
+ for (InstructionSP inst : inst_list.Instructions()) {
if (!inst)
continue;
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;
auto it = saved_unwind_states.upper_bound(current_offset);
More information about the lldb-commits
mailing list