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