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