1 //===-- UnwindAssemblyInstEmulation.cpp --------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "UnwindAssemblyInstEmulation.h"
11 
12 #include "llvm-c/EnhancedDisassembly.h"
13 
14 #include "lldb/Core/Address.h"
15 #include "lldb/Core/ArchSpec.h"
16 #include "lldb/Core/DataBufferHeap.h"
17 #include "lldb/Core/DataExtractor.h"
18 #include "lldb/Core/Disassembler.h"
19 #include "lldb/Core/Error.h"
20 #include "lldb/Core/Log.h"
21 #include "lldb/Core/PluginManager.h"
22 #include "lldb/Core/StreamString.h"
23 #include "lldb/Target/ExecutionContext.h"
24 #include "lldb/Target/Process.h"
25 #include "lldb/Target/Thread.h"
26 #include "lldb/Target/Target.h"
27 
28 using namespace lldb;
29 using namespace lldb_private;
30 
31 
32 
33 //-----------------------------------------------------------------------------------------------
34 //  UnwindAssemblyInstEmulation method definitions
35 //-----------------------------------------------------------------------------------------------
36 
37 bool
38 UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& range,
39                                                                    Thread& thread,
40                                                                    UnwindPlan& unwind_plan)
41 {
42     if (range.GetByteSize() > 0 &&
43         range.GetBaseAddress().IsValid() &&
44         m_inst_emulator_ap.get())
45     {
46 
47         // The the instruction emulation subclass setup the unwind plan for the
48         // first instruction.
49         m_inst_emulator_ap->CreateFunctionEntryUnwind (unwind_plan);
50 
51         // CreateFunctionEntryUnwind should have created the first row. If it
52         // doesn't, then we are done.
53         if (unwind_plan.GetRowCount() == 0)
54             return false;
55 
56         ExecutionContext exe_ctx;
57         thread.CalculateExecutionContext(exe_ctx);
58         DisassemblerSP disasm_sp (Disassembler::DisassembleRange (m_arch,
59                                                                   NULL,
60                                                                   exe_ctx,
61                                                                   range));
62 
63         LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
64 
65         if (disasm_sp)
66         {
67 
68             m_range_ptr = ⦥
69             m_thread_ptr = &thread;
70             m_unwind_plan_ptr = &unwind_plan;
71 
72             const uint32_t addr_byte_size = m_arch.GetAddressByteSize();
73             const bool show_address = true;
74             const bool show_bytes = true;
75             m_inst_emulator_ap->GetRegisterInfo (unwind_plan.GetRegisterKind(),
76                                                  unwind_plan.GetInitialCFARegister(),
77                                                  m_cfa_reg_info);
78 
79             m_fp_is_cfa = false;
80             m_register_values.clear();
81             m_pushed_regs.clear();
82 
83             // Initialize the CFA with a known value. In the 32 bit case
84             // it will be 0x80000000, and in the 64 bit case 0x8000000000000000.
85             // We use the address byte size to be safe for any future addresss sizes
86             m_initial_sp = (1ull << ((addr_byte_size * 8) - 1));
87             RegisterValue cfa_reg_value;
88             cfa_reg_value.SetUInt (m_initial_sp, m_cfa_reg_info.byte_size);
89             SetRegisterValue (m_cfa_reg_info, cfa_reg_value);
90 
91             const InstructionList &inst_list = disasm_sp->GetInstructionList ();
92             const size_t num_instructions = inst_list.GetSize();
93 
94             if (num_instructions > 0)
95             {
96                 Instruction *inst = inst_list.GetInstructionAtIndex (0).get();
97                 const addr_t base_addr = inst->GetAddress().GetFileAddress();
98 
99                 // Make a copy of the current instruction Row and save it in m_curr_row
100                 // so we can add updates as we process the instructions.
101                 UnwindPlan::RowSP last_row = unwind_plan.GetLastRow();
102                 UnwindPlan::Row *newrow = new UnwindPlan::Row;
103                 if (last_row.get())
104                     *newrow = *last_row.get();
105                 m_curr_row.reset(newrow);
106 
107                 // Once we've seen the initial prologue instructions complete, save a
108                 // copy of the CFI at that point into prologue_completed_row for possible
109                 // use later.
110                 int instructions_since_last_prologue_insn = 0;     // # of insns since last CFI was update
111                 bool prologue_complete = false;                    // true if we have finished prologue setup
112 
113                 bool reinstate_prologue_next_instruction = false;  // Next iteration, re-install the prologue row of CFI
114 
115                 bool last_instruction_restored_return_addr_reg = false;  // re-install the prologue row of CFI if the next instruction is a branch immediate
116 
117                 UnwindPlan::RowSP prologue_completed_row;          // copy of prologue row of CFI
118 
119                 // cache the pc register number (in whatever register numbering this UnwindPlan uses) for
120                 // quick reference during instruction parsing.
121                 uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
122                 RegisterInfo pc_reg_info;
123                 if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info))
124                     pc_reg_num = pc_reg_info.kinds[unwind_plan.GetRegisterKind()];
125                 else
126                     pc_reg_num = LLDB_INVALID_REGNUM;
127 
128                 // cache the return address register number (in whatever register numbering this UnwindPlan uses) for
129                 // quick reference during instruction parsing.
130                 uint32_t ra_reg_num = LLDB_INVALID_REGNUM;
131                 RegisterInfo ra_reg_info;
132                 if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, ra_reg_info))
133                     ra_reg_num = ra_reg_info.kinds[unwind_plan.GetRegisterKind()];
134                 else
135                     ra_reg_num = LLDB_INVALID_REGNUM;
136 
137                 for (size_t idx=0; idx<num_instructions; ++idx)
138                 {
139                     m_curr_row_modified = false;
140                     inst = inst_list.GetInstructionAtIndex (idx).get();
141                     if (inst)
142                     {
143                         if (log && log->GetVerbose ())
144                         {
145                             StreamString strm;
146                             inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL);
147                             log->PutCString (strm.GetData());
148                         }
149 
150                         m_inst_emulator_ap->SetInstruction (inst->GetOpcode(),
151                                                             inst->GetAddress(),
152                                                             exe_ctx.GetTargetPtr());
153 
154                         m_inst_emulator_ap->EvaluateInstruction (eEmulateInstructionOptionIgnoreConditions);
155 
156                         // Were there any changes to the CFI while evaluating this instruction?
157                         if (m_curr_row_modified)
158                         {
159                             reinstate_prologue_next_instruction = false;
160                             m_curr_row->SetOffset (inst->GetAddress().GetFileAddress() + inst->GetOpcode().GetByteSize() - base_addr);
161                             // Append the new row
162                             unwind_plan.AppendRow (m_curr_row);
163 
164                             // Allocate a new Row for m_curr_row, copy the current state into it
165                             UnwindPlan::Row *newrow = new UnwindPlan::Row;
166                             *newrow = *m_curr_row.get();
167                             m_curr_row.reset(newrow);
168 
169                             instructions_since_last_prologue_insn = 0;
170 
171                             // If the caller's pc is "same", we've just executed an epilogue and we return to the caller
172                             // after this instruction completes executing.
173                             // If there are any instructions past this, there must have been flow control over this
174                             // epilogue so we'll reinstate the original prologue setup instructions.
175                             UnwindPlan::Row::RegisterLocation pc_regloc;
176                             UnwindPlan::Row::RegisterLocation ra_regloc;
177                             if (prologue_complete
178                                 && pc_reg_num != LLDB_INVALID_REGNUM
179                                 && m_curr_row->GetRegisterInfo (pc_reg_num, pc_regloc)
180                                 && pc_regloc.IsSame())
181                             {
182                                 if (log && log->GetVerbose())
183                                     log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- pc is <same>, restore prologue instructions.");
184                                 reinstate_prologue_next_instruction = true;
185                             }
186                             else if (prologue_complete
187                                      && ra_reg_num != LLDB_INVALID_REGNUM
188                                      && m_curr_row->GetRegisterInfo (ra_reg_num, ra_regloc)
189                                      && ra_regloc.IsSame())
190                             {
191                                 if (log && log->GetVerbose())
192                                     log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- lr is <same>, restore prologue instruction if the next instruction is a branch immediate.");
193                                 last_instruction_restored_return_addr_reg = true;
194                             }
195                         }
196                         else
197                         {
198                             // If the previous instruction was a return-to-caller (epilogue), and we're still executing
199                             // instructions in this function, there must be a code path that jumps over that epilogue.
200                             // Also detect the case where we epilogue & branch imm to another function (tail-call opt)
201                             // instead of a normal pop lr-into-pc exit.
202                             // Reinstate the frame setup from the prologue.
203                             if (reinstate_prologue_next_instruction
204                                 || (m_curr_insn_is_branch_immediate && last_instruction_restored_return_addr_reg))
205                             {
206                                 if (log && log->GetVerbose())
207                                     log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- Reinstating prologue instruction set");
208                                 UnwindPlan::Row *newrow = new UnwindPlan::Row;
209                                 *newrow = *prologue_completed_row.get();
210                                 m_curr_row.reset(newrow);
211                                 m_curr_row->SetOffset (inst->GetAddress().GetFileAddress() + inst->GetOpcode().GetByteSize() - base_addr);
212                                 unwind_plan.AppendRow(m_curr_row);
213 
214                                 newrow = new UnwindPlan::Row;
215                                 *newrow = *m_curr_row.get();
216                                 m_curr_row.reset(newrow);
217 
218                                 reinstate_prologue_next_instruction = false;
219                                 last_instruction_restored_return_addr_reg = false;
220                                 m_curr_insn_is_branch_immediate = false;
221                             }
222 
223                             // clear both of these if either one wasn't set
224                             if (last_instruction_restored_return_addr_reg)
225                             {
226                                 last_instruction_restored_return_addr_reg = false;
227                             }
228                             if (m_curr_insn_is_branch_immediate)
229                             {
230                                 m_curr_insn_is_branch_immediate = false;
231                             }
232 
233                             // If we haven't seen any prologue instructions for a while (4 instructions in a row),
234                             // the function prologue has probably completed.  Save a copy of that Row.
235                             if (prologue_complete == false && instructions_since_last_prologue_insn++ > 3)
236                             {
237                                 prologue_complete = true;
238                                 UnwindPlan::Row *newrow = new UnwindPlan::Row;
239                                 *newrow = *m_curr_row.get();
240                                 prologue_completed_row.reset(newrow);
241                                 if (log && log->GetVerbose())
242                                     log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- prologue has been set up, saving a copy.");
243                             }
244                         }
245                     }
246                 }
247             }
248         }
249 
250         if (log && log->GetVerbose ())
251         {
252             StreamString strm;
253             lldb::addr_t base_addr = range.GetBaseAddress().GetLoadAddress(thread.CalculateTarget().get());
254             strm.Printf ("Resulting unwind rows for [0x%llx - 0x%llx):", base_addr, base_addr + range.GetByteSize());
255             unwind_plan.Dump(strm, &thread, base_addr);
256             log->PutCString (strm.GetData());
257         }
258         return unwind_plan.GetRowCount() > 0;
259     }
260     return false;
261 }
262 
263 bool
264 UnwindAssemblyInstEmulation::GetFastUnwindPlan (AddressRange& func,
265                                                 Thread& thread,
266                                                 UnwindPlan &unwind_plan)
267 {
268     return false;
269 }
270 
271 bool
272 UnwindAssemblyInstEmulation::FirstNonPrologueInsn (AddressRange& func,
273                                                    const ExecutionContext &exe_ctx,
274                                                    Address& first_non_prologue_insn)
275 {
276     return false;
277 }
278 
279 UnwindAssembly *
280 UnwindAssemblyInstEmulation::CreateInstance (const ArchSpec &arch)
281 {
282     std::auto_ptr<EmulateInstruction> inst_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypePrologueEpilogue, NULL));
283     // Make sure that all prologue instructions are handled
284     if (inst_emulator_ap.get())
285         return new UnwindAssemblyInstEmulation (arch, inst_emulator_ap.release());
286     return NULL;
287 }
288 
289 
290 //------------------------------------------------------------------
291 // PluginInterface protocol in UnwindAssemblyParser_x86
292 //------------------------------------------------------------------
293 
294 const char *
295 UnwindAssemblyInstEmulation::GetPluginName()
296 {
297     return "UnwindAssemblyInstEmulation";
298 }
299 
300 const char *
301 UnwindAssemblyInstEmulation::GetShortPluginName()
302 {
303     return "unwindassembly.inst-emulation";
304 }
305 
306 
307 uint32_t
308 UnwindAssemblyInstEmulation::GetPluginVersion()
309 {
310     return 1;
311 }
312 
313 void
314 UnwindAssemblyInstEmulation::Initialize()
315 {
316     PluginManager::RegisterPlugin (GetPluginNameStatic(),
317                                    GetPluginDescriptionStatic(),
318                                    CreateInstance);
319 }
320 
321 void
322 UnwindAssemblyInstEmulation::Terminate()
323 {
324     PluginManager::UnregisterPlugin (CreateInstance);
325 }
326 
327 
328 const char *
329 UnwindAssemblyInstEmulation::GetPluginNameStatic()
330 {
331     return "UnwindAssemblyInstEmulation";
332 }
333 
334 const char *
335 UnwindAssemblyInstEmulation::GetPluginDescriptionStatic()
336 {
337     return "Instruction emulation based unwind information.";
338 }
339 
340 
341 uint64_t
342 UnwindAssemblyInstEmulation::MakeRegisterKindValuePair (const RegisterInfo &reg_info)
343 {
344     uint32_t reg_kind, reg_num;
345     if (EmulateInstruction::GetBestRegisterKindAndNumber (&reg_info, reg_kind, reg_num))
346         return (uint64_t)reg_kind << 24 | reg_num;
347     return 0ull;
348 }
349 
350 void
351 UnwindAssemblyInstEmulation::SetRegisterValue (const RegisterInfo &reg_info, const RegisterValue &reg_value)
352 {
353     m_register_values[MakeRegisterKindValuePair (reg_info)] = reg_value;
354 }
355 
356 bool
357 UnwindAssemblyInstEmulation::GetRegisterValue (const RegisterInfo &reg_info, RegisterValue &reg_value)
358 {
359     const uint64_t reg_id = MakeRegisterKindValuePair (reg_info);
360     RegisterValueMap::const_iterator pos = m_register_values.find(reg_id);
361     if (pos != m_register_values.end())
362     {
363         reg_value = pos->second;
364         return true; // We had a real value that comes from an opcode that wrote
365                      // to it...
366     }
367     // We are making up a value that is recognizable...
368     reg_value.SetUInt(reg_id, reg_info.byte_size);
369     return false;
370 }
371 
372 
373 size_t
374 UnwindAssemblyInstEmulation::ReadMemory (EmulateInstruction *instruction,
375                                          void *baton,
376                                          const EmulateInstruction::Context &context,
377                                          lldb::addr_t addr,
378                                          void *dst,
379                                          size_t dst_len)
380 {
381     LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
382 
383     if (log && log->GetVerbose ())
384     {
385         StreamString strm;
386         strm.Printf ("UnwindAssemblyInstEmulation::ReadMemory    (addr = 0x%16.16llx, dst = %p, dst_len = %llu, context = ",
387                      addr,
388                      dst,
389                      (uint64_t)dst_len);
390         context.Dump(strm, instruction);
391         log->PutCString (strm.GetData ());
392     }
393     memset (dst, 0, dst_len);
394     return dst_len;
395 }
396 
397 size_t
398 UnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction,
399                                           void *baton,
400                                           const EmulateInstruction::Context &context,
401                                           lldb::addr_t addr,
402                                           const void *dst,
403                                           size_t dst_len)
404 {
405     if (baton && dst && dst_len)
406         return ((UnwindAssemblyInstEmulation *)baton)->WriteMemory (instruction, context, addr, dst, dst_len);
407     return 0;
408 }
409 
410 size_t
411 UnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction,
412                                           const EmulateInstruction::Context &context,
413                                           lldb::addr_t addr,
414                                           const void *dst,
415                                           size_t dst_len)
416 {
417     DataExtractor data (dst,
418                         dst_len,
419                         instruction->GetArchitecture ().GetByteOrder(),
420                         instruction->GetArchitecture ().GetAddressByteSize());
421 
422     LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
423 
424     if (log && log->GetVerbose ())
425     {
426         StreamString strm;
427 
428         strm.PutCString ("UnwindAssemblyInstEmulation::WriteMemory   (");
429         data.Dump(&strm, 0, eFormatBytes, 1, dst_len, UINT32_MAX, addr, 0, 0);
430         strm.PutCString (", context = ");
431         context.Dump(strm, instruction);
432         log->PutCString (strm.GetData());
433     }
434 
435     const bool can_replace = true;
436     const bool cant_replace = false;
437 
438     switch (context.type)
439     {
440         default:
441         case EmulateInstruction::eContextInvalid:
442         case EmulateInstruction::eContextReadOpcode:
443         case EmulateInstruction::eContextImmediate:
444         case EmulateInstruction::eContextAdjustBaseRegister:
445         case EmulateInstruction::eContextRegisterPlusOffset:
446         case EmulateInstruction::eContextAdjustPC:
447         case EmulateInstruction::eContextRegisterStore:
448         case EmulateInstruction::eContextRegisterLoad:
449         case EmulateInstruction::eContextRelativeBranchImmediate:
450         case EmulateInstruction::eContextAbsoluteBranchRegister:
451         case EmulateInstruction::eContextSupervisorCall:
452         case EmulateInstruction::eContextTableBranchReadMemory:
453         case EmulateInstruction::eContextWriteRegisterRandomBits:
454         case EmulateInstruction::eContextWriteMemoryRandomBits:
455         case EmulateInstruction::eContextArithmetic:
456         case EmulateInstruction::eContextAdvancePC:
457         case EmulateInstruction::eContextReturnFromException:
458         case EmulateInstruction::eContextPopRegisterOffStack:
459         case EmulateInstruction::eContextAdjustStackPointer:
460             break;
461 
462         case EmulateInstruction::eContextPushRegisterOnStack:
463             {
464                 uint32_t reg_num = LLDB_INVALID_REGNUM;
465                 bool is_return_address_reg = false;
466                 const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind();
467                 if (context.info_type == EmulateInstruction::eInfoTypeRegisterToRegisterPlusOffset)
468                 {
469                     reg_num = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[unwind_reg_kind];
470                     if (context.info.RegisterToRegisterPlusOffset.data_reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_RA)
471                         is_return_address_reg = true;
472                 }
473                 else
474                 {
475                     assert (!"unhandled case, add code to handle this!");
476                 }
477 
478                 if (reg_num != LLDB_INVALID_REGNUM)
479                 {
480                     if (m_pushed_regs.find (reg_num) == m_pushed_regs.end())
481                     {
482                         m_pushed_regs[reg_num] = addr;
483                         const int32_t offset = addr - m_initial_sp;
484                         m_curr_row->SetRegisterLocationToAtCFAPlusOffset (reg_num, offset, cant_replace);
485                         m_curr_row_modified = true;
486                         if (is_return_address_reg)
487                         {
488                             // This push was pushing the return address register,
489                             // so this is also how we will unwind the PC...
490                             RegisterInfo pc_reg_info;
491                             if (instruction->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info))
492                             {
493                                 uint32_t pc_reg_num = pc_reg_info.kinds[unwind_reg_kind];
494                                 if (pc_reg_num != LLDB_INVALID_REGNUM)
495                                 {
496                                     m_curr_row->SetRegisterLocationToAtCFAPlusOffset (pc_reg_num, offset, can_replace);
497                                     m_curr_row_modified = true;
498                                 }
499                             }
500                         }
501                     }
502                 }
503             }
504             break;
505 
506     }
507 
508     return dst_len;
509 }
510 
511 bool
512 UnwindAssemblyInstEmulation::ReadRegister (EmulateInstruction *instruction,
513                                            void *baton,
514                                            const RegisterInfo *reg_info,
515                                            RegisterValue &reg_value)
516 {
517 
518     if (baton && reg_info)
519         return ((UnwindAssemblyInstEmulation *)baton)->ReadRegister (instruction, reg_info, reg_value);
520     return false;
521 }
522 bool
523 UnwindAssemblyInstEmulation::ReadRegister (EmulateInstruction *instruction,
524                                            const RegisterInfo *reg_info,
525                                            RegisterValue &reg_value)
526 {
527     bool synthetic = GetRegisterValue (*reg_info, reg_value);
528 
529     LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
530 
531     if (log && log->GetVerbose ())
532     {
533 
534         StreamString strm;
535         strm.Printf ("UnwindAssemblyInstEmulation::ReadRegister  (name = \"%s\") => synthetic_value = %i, value = ", reg_info->name, synthetic);
536         reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
537         log->PutCString(strm.GetData());
538     }
539     return true;
540 }
541 
542 bool
543 UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
544                                             void *baton,
545                                             const EmulateInstruction::Context &context,
546                                             const RegisterInfo *reg_info,
547                                             const RegisterValue &reg_value)
548 {
549     if (baton && reg_info)
550         return ((UnwindAssemblyInstEmulation *)baton)->WriteRegister (instruction, context, reg_info, reg_value);
551     return false;
552 }
553 bool
554 UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
555                                             const EmulateInstruction::Context &context,
556                                             const RegisterInfo *reg_info,
557                                             const RegisterValue &reg_value)
558 {
559     LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
560 
561     if (log && log->GetVerbose ())
562     {
563 
564         StreamString strm;
565         strm.Printf ("UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ", reg_info->name);
566         reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
567         strm.PutCString (", context = ");
568         context.Dump(strm, instruction);
569         log->PutCString(strm.GetData());
570     }
571 
572     const bool must_replace = true;
573     SetRegisterValue (*reg_info, reg_value);
574 
575     switch (context.type)
576     {
577         default:
578         case EmulateInstruction::eContextInvalid:
579         case EmulateInstruction::eContextReadOpcode:
580         case EmulateInstruction::eContextImmediate:
581         case EmulateInstruction::eContextAdjustBaseRegister:
582         case EmulateInstruction::eContextRegisterPlusOffset:
583         case EmulateInstruction::eContextAdjustPC:
584         case EmulateInstruction::eContextRegisterStore:
585         case EmulateInstruction::eContextRegisterLoad:
586         case EmulateInstruction::eContextAbsoluteBranchRegister:
587         case EmulateInstruction::eContextSupervisorCall:
588         case EmulateInstruction::eContextTableBranchReadMemory:
589         case EmulateInstruction::eContextWriteRegisterRandomBits:
590         case EmulateInstruction::eContextWriteMemoryRandomBits:
591         case EmulateInstruction::eContextArithmetic:
592         case EmulateInstruction::eContextAdvancePC:
593         case EmulateInstruction::eContextReturnFromException:
594         case EmulateInstruction::eContextPushRegisterOnStack:
595 //            {
596 //                const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
597 //                if (reg_num != LLDB_INVALID_REGNUM)
598 //                {
599 //                    const bool can_replace_only_if_unspecified = true;
600 //
601 //                    m_curr_row.SetRegisterLocationToUndefined (reg_num,
602 //                                                               can_replace_only_if_unspecified,
603 //                                                               can_replace_only_if_unspecified);
604 //                    m_curr_row_modified = true;
605 //                }
606 //            }
607             break;
608 
609         case EmulateInstruction::eContextRelativeBranchImmediate:
610             {
611 
612                 {
613                     m_curr_insn_is_branch_immediate = true;
614                 }
615             }
616             break;
617 
618         case EmulateInstruction::eContextPopRegisterOffStack:
619             {
620                 const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
621                 if (reg_num != LLDB_INVALID_REGNUM)
622                 {
623                     m_curr_row->SetRegisterLocationToSame (reg_num, must_replace);
624                     m_curr_row_modified = true;
625                 }
626             }
627             break;
628 
629         case EmulateInstruction::eContextSetFramePointer:
630             if (!m_fp_is_cfa)
631             {
632                 m_fp_is_cfa = true;
633                 m_cfa_reg_info = *reg_info;
634                 const uint32_t cfa_reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
635                 assert (cfa_reg_num != LLDB_INVALID_REGNUM);
636                 m_curr_row->SetCFARegister(cfa_reg_num);
637                 m_curr_row->SetCFAOffset(m_initial_sp - reg_value.GetAsUInt64());
638                 m_curr_row_modified = true;
639             }
640             break;
641 
642         case EmulateInstruction::eContextAdjustStackPointer:
643             // If we have created a frame using the frame pointer, don't follow
644             // subsequent adjustments to the stack pointer.
645             if (!m_fp_is_cfa)
646             {
647                 m_curr_row->SetCFAOffset (m_initial_sp - reg_value.GetAsUInt64());
648                 m_curr_row_modified = true;
649             }
650             break;
651     }
652     return true;
653 }
654 
655 
656