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