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