@@ -125,6 +125,10 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange&
125
125
RegisterInfo ra_reg_info;
126
126
m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, ra_reg_info);
127
127
128
+ // The architecture dependent condition code of the last processed instruction.
129
+ EmulateInstruction::InstructionCondition last_condition = EmulateInstruction::UnconditionalCondition;
130
+ lldb::addr_t condition_block_start_offset = 0 ;
131
+
128
132
for (size_t idx=0 ; idx<num_instructions; ++idx)
129
133
{
130
134
m_curr_row_modified = false ;
@@ -146,7 +150,41 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange&
146
150
UnwindPlan::Row *newrow = new UnwindPlan::Row;
147
151
*newrow = *it->second .first ;
148
152
m_curr_row.reset (newrow);
149
- m_register_values = it->second .second ;;
153
+ m_register_values = it->second .second ;
154
+ }
155
+
156
+ m_inst_emulator_ap->SetInstruction (inst->GetOpcode (),
157
+ inst->GetAddress (),
158
+ exe_ctx.GetTargetPtr ());
159
+
160
+ if (last_condition != m_inst_emulator_ap->GetInstructionCondition ())
161
+ {
162
+ if (m_inst_emulator_ap->GetInstructionCondition () != EmulateInstruction::UnconditionalCondition &&
163
+ saved_unwind_states.count (current_offset) == 0 )
164
+ {
165
+ // If we don't have a saved row for the current offset then save our
166
+ // current state because we will have to restore it after the
167
+ // conditional block.
168
+ auto new_row = std::make_shared<UnwindPlan::Row>(*m_curr_row.get ());
169
+ saved_unwind_states.insert ({current_offset, {new_row, m_register_values}});
170
+ }
171
+
172
+ // If the last instruction was conditional with a different condition
173
+ // then the then current condition then restore the condition.
174
+ if (last_condition != EmulateInstruction::UnconditionalCondition)
175
+ {
176
+ const auto & saved_state = saved_unwind_states.at (condition_block_start_offset);
177
+ m_curr_row = std::make_shared<UnwindPlan::Row>(*saved_state.first );
178
+ m_curr_row->SetOffset (current_offset);
179
+ m_register_values = saved_state.second ;
180
+ bool replace_existing = true ; // The last instruction might already
181
+ // created a row for this offset and
182
+ // we want to overwrite it.
183
+ unwind_plan.InsertRow (std::make_shared<UnwindPlan::Row>(*m_curr_row), replace_existing);
184
+ }
185
+
186
+ // We are starting a new conditional block at the catual offset
187
+ condition_block_start_offset = current_offset;
150
188
}
151
189
152
190
if (log && log ->GetVerbose ())
@@ -158,9 +196,7 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange&
158
196
log ->PutCString (strm.GetData ());
159
197
}
160
198
161
- m_inst_emulator_ap->SetInstruction (inst->GetOpcode (),
162
- inst->GetAddress (),
163
- exe_ctx.GetTargetPtr ());
199
+ last_condition = m_inst_emulator_ap->GetInstructionCondition ();
164
200
165
201
m_inst_emulator_ap->EvaluateInstruction (eEmulateInstructionOptionIgnoreConditions);
166
202
@@ -503,8 +539,7 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
503
539
log ->PutCString (strm.GetData ());
504
540
}
505
541
506
- if (!instruction->IsInstructionConditional ())
507
- SetRegisterValue (*reg_info, reg_value);
542
+ SetRegisterValue (*reg_info, reg_value);
508
543
509
544
switch (context.type )
510
545
{
@@ -566,45 +601,42 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
566
601
567
602
case EmulateInstruction::eContextPopRegisterOffStack:
568
603
{
569
- if (!instruction->IsInstructionConditional ())
604
+ const uint32_t reg_num = reg_info->kinds [m_unwind_plan_ptr->GetRegisterKind ()];
605
+ const uint32_t generic_regnum = reg_info->kinds [eRegisterKindGeneric];
606
+ if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP)
570
607
{
571
- const uint32_t reg_num = reg_info->kinds [m_unwind_plan_ptr->GetRegisterKind ()];
572
- const uint32_t generic_regnum = reg_info->kinds [eRegisterKindGeneric];
573
- if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP)
608
+ switch (context.info_type )
574
609
{
575
- switch (context.info_type )
576
- {
577
- case EmulateInstruction::eInfoTypeAddress:
578
- if (m_pushed_regs.find (reg_num) != m_pushed_regs.end () &&
579
- context.info .address == m_pushed_regs[reg_num])
580
- {
581
- m_curr_row->SetRegisterLocationToSame (reg_num,
582
- false /* must_replace*/ );
583
- m_curr_row_modified = true ;
584
- }
585
- break ;
586
- case EmulateInstruction::eInfoTypeISA:
587
- assert ((generic_regnum == LLDB_REGNUM_GENERIC_PC ||
588
- generic_regnum == LLDB_REGNUM_GENERIC_FLAGS) &&
589
- " eInfoTypeISA used for poping a register other the the PC/FLAGS" );
590
- if (generic_regnum != LLDB_REGNUM_GENERIC_FLAGS)
591
- {
592
- m_curr_row->SetRegisterLocationToSame (reg_num,
593
- false /* must_replace*/ );
594
- m_curr_row_modified = true ;
595
- }
596
- break ;
597
- default :
598
- assert (false && " unhandled case, add code to handle this!" );
599
- break ;
600
- }
610
+ case EmulateInstruction::eInfoTypeAddress:
611
+ if (m_pushed_regs.find (reg_num) != m_pushed_regs.end () &&
612
+ context.info .address == m_pushed_regs[reg_num])
613
+ {
614
+ m_curr_row->SetRegisterLocationToSame (reg_num,
615
+ false /* must_replace*/ );
616
+ m_curr_row_modified = true ;
617
+ }
618
+ break ;
619
+ case EmulateInstruction::eInfoTypeISA:
620
+ assert ((generic_regnum == LLDB_REGNUM_GENERIC_PC ||
621
+ generic_regnum == LLDB_REGNUM_GENERIC_FLAGS) &&
622
+ " eInfoTypeISA used for poping a register other the the PC/FLAGS" );
623
+ if (generic_regnum != LLDB_REGNUM_GENERIC_FLAGS)
624
+ {
625
+ m_curr_row->SetRegisterLocationToSame (reg_num,
626
+ false /* must_replace*/ );
627
+ m_curr_row_modified = true ;
628
+ }
629
+ break ;
630
+ default :
631
+ assert (false && " unhandled case, add code to handle this!" );
632
+ break ;
601
633
}
602
634
}
603
635
}
604
636
break ;
605
637
606
638
case EmulateInstruction::eContextSetFramePointer:
607
- if (!m_fp_is_cfa && !instruction-> IsInstructionConditional () )
639
+ if (!m_fp_is_cfa)
608
640
{
609
641
m_fp_is_cfa = true ;
610
642
m_cfa_reg_info = *reg_info;
@@ -619,7 +651,7 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
619
651
case EmulateInstruction::eContextAdjustStackPointer:
620
652
// If we have created a frame using the frame pointer, don't follow
621
653
// subsequent adjustments to the stack pointer.
622
- if (!m_fp_is_cfa && !instruction-> IsInstructionConditional () )
654
+ if (!m_fp_is_cfa)
623
655
{
624
656
m_curr_row->GetCFAValue ().SetIsRegisterPlusOffset (
625
657
m_curr_row->GetCFAValue ().GetRegisterNumber (),
0 commit comments