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