@@ -86,19 +86,21 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
86
86
const bool show_address = true ;
87
87
const bool show_bytes = true ;
88
88
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 (
90
91
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
+
93
95
m_pushed_regs.clear ();
94
96
95
97
// Initialize the CFA with a known value. In the 32 bit case it will be
96
98
// 0x80000000, and in the 64 bit case 0x8000000000000000. We use the address
97
99
// byte size to be safe for any future address sizes
98
100
m_initial_sp = (1ull << ((addr_byte_size * 8 ) - 1 ));
99
101
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);
102
104
103
105
const InstructionList &inst_list = disasm_sp->GetInstructionList ();
104
106
const size_t num_instructions = inst_list.GetSize ();
@@ -107,33 +109,25 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
107
109
Instruction *inst = inst_list.GetInstructionAtIndex (0 ).get ();
108
110
const lldb::addr_t base_addr = inst->GetAddress ().GetFileAddress ();
109
111
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;
117
118
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
119
120
// 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 ();
123
122
124
123
// 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 ;
131
126
132
127
// The architecture dependent condition code of the last processed
133
128
// instruction.
134
129
EmulateInstruction::InstructionCondition last_condition =
135
130
EmulateInstruction::UnconditionalCondition;
136
- lldb::addr_t condition_block_start_offset = 0 ;
137
131
138
132
for (size_t idx = 0 ; idx < num_instructions; ++idx) {
139
133
m_curr_row_modified = false ;
@@ -151,78 +145,28 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
151
145
--it; // Move it to the row corresponding to the current offset
152
146
153
147
// 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 ;
178
153
179
154
m_inst_emulator_up->SetInstruction (inst->GetOpcode (), inst->GetAddress (),
180
155
nullptr );
181
156
182
157
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
-
194
158
// 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 .
196
160
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);
217
163
// The last instruction might already created a row for this offset
218
164
// 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);
222
166
}
223
167
224
168
// We are starting a new conditional block at the actual offset
225
- condition_block_start_offset = current_offset ;
169
+ condition_block_start_state = it ;
226
170
}
227
171
228
172
if (log && log ->GetVerbose ()) {
@@ -245,11 +189,10 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
245
189
if (m_forward_branch_offset != 0 &&
246
190
range.ContainsFileAddress (inst->GetAddress ().GetFileAddress () +
247
191
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);
253
196
}
254
197
255
198
// Were there any changes to the CFI while evaluating this instruction?
@@ -258,21 +201,18 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
258
201
// current address
259
202
if (saved_unwind_states.count (current_offset +
260
203
inst->GetOpcode ().GetByteSize ()) == 0 ) {
261
- m_curr_row-> SetOffset (current_offset +
204
+ m_state. row . SetOffset (current_offset +
262
205
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);
273
208
}
274
209
}
275
210
}
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
+ }
276
216
}
277
217
278
218
if (log && log ->GetVerbose ()) {
@@ -339,14 +279,14 @@ uint64_t UnwindAssemblyInstEmulation::MakeRegisterKindValuePair(
339
279
340
280
void UnwindAssemblyInstEmulation::SetRegisterValue (
341
281
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;
343
283
}
344
284
345
285
bool UnwindAssemblyInstEmulation::GetRegisterValue (const RegisterInfo ®_info,
346
286
RegisterValue ®_value) {
347
287
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 ()) {
350
290
reg_value = pos->second ;
351
291
return true ; // We had a real value that comes from an opcode that wrote
352
292
// to it...
@@ -444,7 +384,7 @@ size_t UnwindAssemblyInstEmulation::WriteMemory(
444
384
generic_regnum != LLDB_REGNUM_GENERIC_SP) {
445
385
if (m_pushed_regs.try_emplace (reg_num, addr).second ) {
446
386
const int32_t offset = addr - m_initial_sp;
447
- m_curr_row-> SetRegisterLocationToAtCFAPlusOffset (reg_num, offset,
387
+ m_state. row . SetRegisterLocationToAtCFAPlusOffset (reg_num, offset,
448
388
/* can_replace=*/ true );
449
389
m_curr_row_modified = true ;
450
390
}
@@ -548,13 +488,14 @@ bool UnwindAssemblyInstEmulation::WriteRegister(
548
488
// CFA offset
549
489
// with the same amount.
550
490
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] &&
552
493
context.GetInfoType () ==
553
494
EmulateInstruction::eInfoTypeRegisterPlusOffset &&
554
495
context.info .RegisterPlusOffset .reg .kinds [kind] ==
555
- m_cfa_reg_info .kinds [kind]) {
496
+ m_state. cfa_reg_info .kinds [kind]) {
556
497
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);
558
499
m_curr_row_modified = true ;
559
500
}
560
501
} break ;
@@ -590,25 +531,25 @@ bool UnwindAssemblyInstEmulation::WriteRegister(
590
531
case EmulateInstruction::eInfoTypeAddress:
591
532
if (auto it = m_pushed_regs.find (reg_num);
592
533
it != m_pushed_regs.end () && context.info .address == it->second ) {
593
- m_curr_row-> SetRegisterLocationToSame (reg_num,
534
+ m_state. row . SetRegisterLocationToSame (reg_num,
594
535
false /* must_replace*/ );
595
536
m_curr_row_modified = true ;
596
537
597
538
// FP has been restored to its original value, we are back
598
539
// 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 ;
601
542
lldb::RegisterKind sp_reg_kind = eRegisterKindGeneric;
602
543
uint32_t sp_reg_num = LLDB_REGNUM_GENERIC_SP;
603
544
RegisterInfo sp_reg_info =
604
545
*m_inst_emulator_up->GetRegisterInfo (sp_reg_kind, sp_reg_num);
605
546
RegisterValue sp_reg_val;
606
547
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;
608
549
const uint32_t cfa_reg_num =
609
550
sp_reg_info.kinds [m_unwind_plan_ptr->GetRegisterKind ()];
610
551
assert (cfa_reg_num != LLDB_INVALID_REGNUM);
611
- m_curr_row-> GetCFAValue ().SetIsRegisterPlusOffset (
552
+ m_state. row . GetCFAValue ().SetIsRegisterPlusOffset (
612
553
cfa_reg_num, m_initial_sp - sp_reg_val.GetAsUInt64 ());
613
554
}
614
555
}
@@ -620,7 +561,7 @@ bool UnwindAssemblyInstEmulation::WriteRegister(
620
561
generic_regnum == LLDB_REGNUM_GENERIC_FLAGS) &&
621
562
" eInfoTypeISA used for popping a register other the PC/FLAGS" );
622
563
if (generic_regnum != LLDB_REGNUM_GENERIC_FLAGS) {
623
- m_curr_row-> SetRegisterLocationToSame (reg_num,
564
+ m_state. row . SetRegisterLocationToSame (reg_num,
624
565
false /* must_replace*/ );
625
566
m_curr_row_modified = true ;
626
567
}
@@ -633,26 +574,26 @@ bool UnwindAssemblyInstEmulation::WriteRegister(
633
574
} break ;
634
575
635
576
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;
639
580
const uint32_t cfa_reg_num =
640
581
reg_info->kinds [m_unwind_plan_ptr->GetRegisterKind ()];
641
582
assert (cfa_reg_num != LLDB_INVALID_REGNUM);
642
- m_curr_row-> GetCFAValue ().SetIsRegisterPlusOffset (
583
+ m_state. row . GetCFAValue ().SetIsRegisterPlusOffset (
643
584
cfa_reg_num, m_initial_sp - reg_value.GetAsUInt64 ());
644
585
m_curr_row_modified = true ;
645
586
}
646
587
break ;
647
588
648
589
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;
652
593
const uint32_t cfa_reg_num =
653
594
reg_info->kinds [m_unwind_plan_ptr->GetRegisterKind ()];
654
595
assert (cfa_reg_num != LLDB_INVALID_REGNUM);
655
- m_curr_row-> GetCFAValue ().SetIsRegisterPlusOffset (
596
+ m_state. row . GetCFAValue ().SetIsRegisterPlusOffset (
656
597
cfa_reg_num, m_initial_sp - reg_value.GetAsUInt64 ());
657
598
m_curr_row_modified = true ;
658
599
}
@@ -661,9 +602,9 @@ bool UnwindAssemblyInstEmulation::WriteRegister(
661
602
case EmulateInstruction::eContextAdjustStackPointer:
662
603
// If we have created a frame using the frame pointer, don't follow
663
604
// 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 (),
667
608
m_initial_sp - reg_value.GetAsUInt64 ());
668
609
m_curr_row_modified = true ;
669
610
}
0 commit comments