@@ -86,19 +86,21 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
8686 const bool show_address = true ;
8787 const bool show_bytes = true ;
8888 const bool show_control_flow_kind = false ;
89- m_cfa_reg_info = *m_inst_emulator_up->GetRegisterInfo (
89+
90+ m_state.cfa_reg_info = *m_inst_emulator_up->GetRegisterInfo (
9091 unwind_plan.GetRegisterKind (), unwind_plan.GetInitialCFARegister ());
91- m_fp_is_cfa = false ;
92- m_register_values.clear ();
92+ m_state.fp_is_cfa = false ;
93+ m_state.register_values .clear ();
94+
9395 m_pushed_regs.clear ();
9496
9597 // Initialize the CFA with a known value. In the 32 bit case it will be
9698 // 0x80000000, and in the 64 bit case 0x8000000000000000. We use the address
9799 // byte size to be safe for any future address sizes
98100 m_initial_sp = (1ull << ((addr_byte_size * 8 ) - 1 ));
99101 RegisterValue cfa_reg_value;
100- cfa_reg_value.SetUInt (m_initial_sp, m_cfa_reg_info .byte_size );
101- SetRegisterValue (m_cfa_reg_info , cfa_reg_value);
102+ cfa_reg_value.SetUInt (m_initial_sp, m_state. cfa_reg_info .byte_size );
103+ SetRegisterValue (m_state. cfa_reg_info , cfa_reg_value);
102104
103105 const InstructionList &inst_list = disasm_sp->GetInstructionList ();
104106 const size_t num_instructions = inst_list.GetSize ();
@@ -107,33 +109,25 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
107109 Instruction *inst = inst_list.GetInstructionAtIndex (0 ).get ();
108110 const lldb::addr_t base_addr = inst->GetAddress ().GetFileAddress ();
109111
110- // Map for storing the unwind plan row and the value of the registers at a
111- // given offset. When we see a forward branch we add a new entry to this map
112- // with the actual unwind plan row and register context for the target
113- // address of the branch as the current data have to be valid for the target
114- // address of the branch too if we are in the same function.
115- std::map<lldb::addr_t , std::pair<UnwindPlan::RowSP, RegisterValueMap>>
116- saved_unwind_states;
112+ // Map for storing the unwind state at a given offset. When we see a forward
113+ // branch we add a new entry to this map with the actual unwind plan row and
114+ // register context for the target address of the branch as the current data
115+ // have to be valid for the target address of the branch too if we are in
116+ // the same function.
117+ std::map<lldb::addr_t , UnwindState> saved_unwind_states;
117118
118- // Make a copy of the current instruction Row and save it in m_curr_row so
119+ // Make a copy of the current instruction Row and save it in m_state so
119120 // we can add updates as we process the instructions.
120- UnwindPlan::RowSP last_row =
121- std::make_shared<UnwindPlan::Row>(*unwind_plan.GetLastRow ());
122- m_curr_row = std::make_shared<UnwindPlan::Row>(*last_row);
121+ m_state.row = *unwind_plan.GetLastRow ();
123122
124123 // Add the initial state to the save list with offset 0.
125- saved_unwind_states.insert ({0 , {last_row, m_register_values}});
126-
127- // cache the stack pointer register number (in whatever register numbering
128- // this UnwindPlan uses) for quick reference during instruction parsing.
129- RegisterInfo sp_reg_info = *m_inst_emulator_up->GetRegisterInfo (
130- eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
124+ auto condition_block_start_state =
125+ saved_unwind_states.emplace (0 , m_state).first ;
131126
132127 // The architecture dependent condition code of the last processed
133128 // instruction.
134129 EmulateInstruction::InstructionCondition last_condition =
135130 EmulateInstruction::UnconditionalCondition;
136- lldb::addr_t condition_block_start_offset = 0 ;
137131
138132 for (size_t idx = 0 ; idx < num_instructions; ++idx) {
139133 m_curr_row_modified = false ;
@@ -151,78 +145,28 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
151145 --it; // Move it to the row corresponding to the current offset
152146
153147 // If the offset of m_curr_row don't match with the offset we see in
154- // saved_unwind_states then we have to update m_curr_row and
155- // m_register_values based on the saved values. It is happening after we
156- // processed an epilogue and a return to caller instruction.
157- if (it->second .first ->GetOffset () != m_curr_row->GetOffset ()) {
158- UnwindPlan::Row *newrow = new UnwindPlan::Row;
159- *newrow = *it->second .first ;
160- m_curr_row.reset (newrow);
161- m_register_values = it->second .second ;
162- // re-set the CFA register ivars to match the new m_curr_row.
163- if (sp_reg_info.name &&
164- m_curr_row->GetCFAValue ().IsRegisterPlusOffset ()) {
165- uint32_t row_cfa_regnum =
166- m_curr_row->GetCFAValue ().GetRegisterNumber ();
167- lldb::RegisterKind row_kind = m_unwind_plan_ptr->GetRegisterKind ();
168- // set m_cfa_reg_info to the row's CFA reg.
169- m_cfa_reg_info =
170- *m_inst_emulator_up->GetRegisterInfo (row_kind, row_cfa_regnum);
171- // set m_fp_is_cfa.
172- if (sp_reg_info.kinds [row_kind] == row_cfa_regnum)
173- m_fp_is_cfa = false ;
174- else
175- m_fp_is_cfa = true ;
176- }
177- }
148+ // saved_unwind_states then we have to update current unwind state to
149+ // the saved values. It is happening after we processed an epilogue and a
150+ // return to caller instruction.
151+ if (it->second .row .GetOffset () != m_state.row .GetOffset ())
152+ m_state = it->second ;
178153
179154 m_inst_emulator_up->SetInstruction (inst->GetOpcode (), inst->GetAddress (),
180155 nullptr );
181156
182157 if (last_condition != m_inst_emulator_up->GetInstructionCondition ()) {
183- if (m_inst_emulator_up->GetInstructionCondition () !=
184- EmulateInstruction::UnconditionalCondition &&
185- saved_unwind_states.count (current_offset) == 0 ) {
186- // If we don't have a saved row for the current offset then save our
187- // current state because we will have to restore it after the
188- // conditional block.
189- auto new_row = std::make_shared<UnwindPlan::Row>(*m_curr_row.get ());
190- saved_unwind_states.insert (
191- {current_offset, {new_row, m_register_values}});
192- }
193-
194158 // If the last instruction was conditional with a different condition
195- // then the then current condition then restore the condition .
159+ // than the current condition then restore the state .
196160 if (last_condition != EmulateInstruction::UnconditionalCondition) {
197- const auto &saved_state =
198- saved_unwind_states.at (condition_block_start_offset);
199- m_curr_row = std::make_shared<UnwindPlan::Row>(*saved_state.first );
200- m_curr_row->SetOffset (current_offset);
201- m_register_values = saved_state.second ;
202- // re-set the CFA register ivars to match the new m_curr_row.
203- if (sp_reg_info.name &&
204- m_curr_row->GetCFAValue ().IsRegisterPlusOffset ()) {
205- uint32_t row_cfa_regnum =
206- m_curr_row->GetCFAValue ().GetRegisterNumber ();
207- lldb::RegisterKind row_kind = m_unwind_plan_ptr->GetRegisterKind ();
208- // set m_cfa_reg_info to the row's CFA reg.
209- m_cfa_reg_info =
210- *m_inst_emulator_up->GetRegisterInfo (row_kind, row_cfa_regnum);
211- // set m_fp_is_cfa.
212- if (sp_reg_info.kinds [row_kind] == row_cfa_regnum)
213- m_fp_is_cfa = false ;
214- else
215- m_fp_is_cfa = true ;
216- }
161+ m_state = condition_block_start_state->second ;
162+ m_state.row .SetOffset (current_offset);
217163 // The last instruction might already created a row for this offset
218164 // and we want to overwrite it.
219- bool replace_existing = true ;
220- unwind_plan.InsertRow (std::make_shared<UnwindPlan::Row>(*m_curr_row),
221- replace_existing);
165+ saved_unwind_states.insert_or_assign (current_offset, m_state);
222166 }
223167
224168 // We are starting a new conditional block at the actual offset
225- condition_block_start_offset = current_offset ;
169+ condition_block_start_state = it ;
226170 }
227171
228172 if (log && log->GetVerbose ()) {
@@ -245,11 +189,10 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
245189 if (m_forward_branch_offset != 0 &&
246190 range.ContainsFileAddress (inst->GetAddress ().GetFileAddress () +
247191 m_forward_branch_offset)) {
248- auto newrow = std::make_shared<UnwindPlan::Row>(*m_curr_row.get ());
249- newrow->SetOffset (current_offset + m_forward_branch_offset);
250- saved_unwind_states.insert ({current_offset + m_forward_branch_offset,
251- {newrow, m_register_values}});
252- unwind_plan.InsertRow (newrow);
192+ if (auto [it, inserted] = saved_unwind_states.emplace (
193+ current_offset + m_forward_branch_offset, m_state);
194+ inserted)
195+ it->second .row .SetOffset (current_offset + m_forward_branch_offset);
253196 }
254197
255198 // Were there any changes to the CFI while evaluating this instruction?
@@ -258,21 +201,18 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
258201 // current address
259202 if (saved_unwind_states.count (current_offset +
260203 inst->GetOpcode ().GetByteSize ()) == 0 ) {
261- m_curr_row-> SetOffset (current_offset +
204+ m_state. row . SetOffset (current_offset +
262205 inst->GetOpcode ().GetByteSize ());
263- unwind_plan.InsertRow (m_curr_row);
264- saved_unwind_states.insert (
265- {current_offset + inst->GetOpcode ().GetByteSize (),
266- {m_curr_row, m_register_values}});
267-
268- // Allocate a new Row for m_curr_row, copy the current state
269- // into it
270- UnwindPlan::Row *newrow = new UnwindPlan::Row;
271- *newrow = *m_curr_row.get ();
272- m_curr_row.reset (newrow);
206+ saved_unwind_states.emplace (
207+ current_offset + inst->GetOpcode ().GetByteSize (), m_state);
273208 }
274209 }
275210 }
211+ for (auto &[_, state] : saved_unwind_states) {
212+ unwind_plan.InsertRow (
213+ std::make_shared<UnwindPlan::Row>(std::move (state.row )),
214+ /* replace_existing=*/ true );
215+ }
276216 }
277217
278218 if (log && log->GetVerbose ()) {
@@ -339,14 +279,14 @@ uint64_t UnwindAssemblyInstEmulation::MakeRegisterKindValuePair(
339279
340280void UnwindAssemblyInstEmulation::SetRegisterValue (
341281 const RegisterInfo ®_info, const RegisterValue ®_value) {
342- m_register_values [MakeRegisterKindValuePair (reg_info)] = reg_value;
282+ m_state. register_values [MakeRegisterKindValuePair (reg_info)] = reg_value;
343283}
344284
345285bool UnwindAssemblyInstEmulation::GetRegisterValue (const RegisterInfo ®_info,
346286 RegisterValue ®_value) {
347287 const uint64_t reg_id = MakeRegisterKindValuePair (reg_info);
348- RegisterValueMap::const_iterator pos = m_register_values .find (reg_id);
349- if (pos != m_register_values .end ()) {
288+ RegisterValueMap::const_iterator pos = m_state. register_values .find (reg_id);
289+ if (pos != m_state. register_values .end ()) {
350290 reg_value = pos->second ;
351291 return true ; // We had a real value that comes from an opcode that wrote
352292 // to it...
@@ -444,7 +384,7 @@ size_t UnwindAssemblyInstEmulation::WriteMemory(
444384 generic_regnum != LLDB_REGNUM_GENERIC_SP) {
445385 if (m_pushed_regs.try_emplace (reg_num, addr).second ) {
446386 const int32_t offset = addr - m_initial_sp;
447- m_curr_row-> SetRegisterLocationToAtCFAPlusOffset (reg_num, offset,
387+ m_state. row . SetRegisterLocationToAtCFAPlusOffset (reg_num, offset,
448388 /* can_replace=*/ true );
449389 m_curr_row_modified = true ;
450390 }
@@ -548,13 +488,14 @@ bool UnwindAssemblyInstEmulation::WriteRegister(
548488 // CFA offset
549489 // with the same amount.
550490 lldb::RegisterKind kind = m_unwind_plan_ptr->GetRegisterKind ();
551- if (m_fp_is_cfa && reg_info->kinds [kind] == m_cfa_reg_info.kinds [kind] &&
491+ if (m_state.fp_is_cfa &&
492+ reg_info->kinds [kind] == m_state.cfa_reg_info .kinds [kind] &&
552493 context.GetInfoType () ==
553494 EmulateInstruction::eInfoTypeRegisterPlusOffset &&
554495 context.info .RegisterPlusOffset .reg .kinds [kind] ==
555- m_cfa_reg_info .kinds [kind]) {
496+ m_state. cfa_reg_info .kinds [kind]) {
556497 const int64_t offset = context.info .RegisterPlusOffset .signed_offset ;
557- m_curr_row-> GetCFAValue ().IncOffset (-1 * offset);
498+ m_state. row . GetCFAValue ().IncOffset (-1 * offset);
558499 m_curr_row_modified = true ;
559500 }
560501 } break ;
@@ -590,25 +531,25 @@ bool UnwindAssemblyInstEmulation::WriteRegister(
590531 case EmulateInstruction::eInfoTypeAddress:
591532 if (auto it = m_pushed_regs.find (reg_num);
592533 it != m_pushed_regs.end () && context.info .address == it->second ) {
593- m_curr_row-> SetRegisterLocationToSame (reg_num,
534+ m_state. row . SetRegisterLocationToSame (reg_num,
594535 false /* must_replace*/ );
595536 m_curr_row_modified = true ;
596537
597538 // FP has been restored to its original value, we are back
598539 // to using SP to calculate the CFA.
599- if (m_fp_is_cfa ) {
600- m_fp_is_cfa = false ;
540+ if (m_state. fp_is_cfa ) {
541+ m_state. fp_is_cfa = false ;
601542 lldb::RegisterKind sp_reg_kind = eRegisterKindGeneric;
602543 uint32_t sp_reg_num = LLDB_REGNUM_GENERIC_SP;
603544 RegisterInfo sp_reg_info =
604545 *m_inst_emulator_up->GetRegisterInfo (sp_reg_kind, sp_reg_num);
605546 RegisterValue sp_reg_val;
606547 if (GetRegisterValue (sp_reg_info, sp_reg_val)) {
607- m_cfa_reg_info = sp_reg_info;
548+ m_state. cfa_reg_info = sp_reg_info;
608549 const uint32_t cfa_reg_num =
609550 sp_reg_info.kinds [m_unwind_plan_ptr->GetRegisterKind ()];
610551 assert (cfa_reg_num != LLDB_INVALID_REGNUM);
611- m_curr_row-> GetCFAValue ().SetIsRegisterPlusOffset (
552+ m_state. row . GetCFAValue ().SetIsRegisterPlusOffset (
612553 cfa_reg_num, m_initial_sp - sp_reg_val.GetAsUInt64 ());
613554 }
614555 }
@@ -620,7 +561,7 @@ bool UnwindAssemblyInstEmulation::WriteRegister(
620561 generic_regnum == LLDB_REGNUM_GENERIC_FLAGS) &&
621562 " eInfoTypeISA used for popping a register other the PC/FLAGS" );
622563 if (generic_regnum != LLDB_REGNUM_GENERIC_FLAGS) {
623- m_curr_row-> SetRegisterLocationToSame (reg_num,
564+ m_state. row . SetRegisterLocationToSame (reg_num,
624565 false /* must_replace*/ );
625566 m_curr_row_modified = true ;
626567 }
@@ -633,26 +574,26 @@ bool UnwindAssemblyInstEmulation::WriteRegister(
633574 } break ;
634575
635576 case EmulateInstruction::eContextSetFramePointer:
636- if (!m_fp_is_cfa ) {
637- m_fp_is_cfa = true ;
638- m_cfa_reg_info = *reg_info;
577+ if (!m_state. fp_is_cfa ) {
578+ m_state. fp_is_cfa = true ;
579+ m_state. cfa_reg_info = *reg_info;
639580 const uint32_t cfa_reg_num =
640581 reg_info->kinds [m_unwind_plan_ptr->GetRegisterKind ()];
641582 assert (cfa_reg_num != LLDB_INVALID_REGNUM);
642- m_curr_row-> GetCFAValue ().SetIsRegisterPlusOffset (
583+ m_state. row . GetCFAValue ().SetIsRegisterPlusOffset (
643584 cfa_reg_num, m_initial_sp - reg_value.GetAsUInt64 ());
644585 m_curr_row_modified = true ;
645586 }
646587 break ;
647588
648589 case EmulateInstruction::eContextRestoreStackPointer:
649- if (m_fp_is_cfa ) {
650- m_fp_is_cfa = false ;
651- m_cfa_reg_info = *reg_info;
590+ if (m_state. fp_is_cfa ) {
591+ m_state. fp_is_cfa = false ;
592+ m_state. cfa_reg_info = *reg_info;
652593 const uint32_t cfa_reg_num =
653594 reg_info->kinds [m_unwind_plan_ptr->GetRegisterKind ()];
654595 assert (cfa_reg_num != LLDB_INVALID_REGNUM);
655- m_curr_row-> GetCFAValue ().SetIsRegisterPlusOffset (
596+ m_state. row . GetCFAValue ().SetIsRegisterPlusOffset (
656597 cfa_reg_num, m_initial_sp - reg_value.GetAsUInt64 ());
657598 m_curr_row_modified = true ;
658599 }
@@ -661,9 +602,9 @@ bool UnwindAssemblyInstEmulation::WriteRegister(
661602 case EmulateInstruction::eContextAdjustStackPointer:
662603 // If we have created a frame using the frame pointer, don't follow
663604 // subsequent adjustments to the stack pointer.
664- if (!m_fp_is_cfa ) {
665- m_curr_row-> GetCFAValue ().SetIsRegisterPlusOffset (
666- m_curr_row-> GetCFAValue ().GetRegisterNumber (),
605+ if (!m_state. fp_is_cfa ) {
606+ m_state. row . GetCFAValue ().SetIsRegisterPlusOffset (
607+ m_state. row . GetCFAValue ().GetRegisterNumber (),
667608 m_initial_sp - reg_value.GetAsUInt64 ());
668609 m_curr_row_modified = true ;
669610 }
0 commit comments