bool EmulateInstructionARM64::EvaluateInstruction(uint32_t evaluate_options) {
  const uint32_t opcode = m_opcode.GetOpcode32();
  Opcode *opcode_data = GetOpcodeForInstruction(opcode);
  if (opcode_data == NULL)
    return false;

  // printf ("opcode template for 0x%8.8x: %s\n", opcode, opcode_data->name);
  const bool auto_advance_pc =
      evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
  m_ignore_conditions =
      evaluate_options & eEmulateInstructionOptionIgnoreConditions;

  bool success = false;
  //    if (m_opcode_cpsr == 0 || m_ignore_conditions == false)
  //    {
  //        m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindLLDB,
  //                                              gpr_cpsr_arm64,
  //                                              0,
  //                                              &success);
  //    }

  // Only return false if we are unable to read the CPSR if we care about
  // conditions
  if (!success && !m_ignore_conditions)
    return false;

  uint32_t orig_pc_value = 0;
  if (auto_advance_pc) {
    orig_pc_value =
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_arm64, 0, &success);
    if (!success)
      return false;
  }

  // Call the Emulate... function.
  success = (this->*opcode_data->callback)(opcode);
  if (!success)
    return false;

  if (auto_advance_pc) {
    uint32_t new_pc_value =
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_arm64, 0, &success);
    if (!success)
      return false;

    if (auto_advance_pc && (new_pc_value == orig_pc_value)) {
      EmulateInstruction::Context context;
      context.type = eContextAdvancePC;
      context.SetNoArgs();
      if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_pc_arm64,
                                 orig_pc_value + 4))
        return false;
    }
  }
  return true;
}
Exemplo n.º 2
0
size_t UnwindAssemblyInstEmulation::ReadMemory(
    EmulateInstruction *instruction, void *baton,
    const EmulateInstruction::Context &context, lldb::addr_t addr, void *dst,
    size_t dst_len) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));

  if (log && log->GetVerbose()) {
    StreamString strm;
    strm.Printf(
        "UnwindAssemblyInstEmulation::ReadMemory    (addr = 0x%16.16" PRIx64
        ", dst = %p, dst_len = %" PRIu64 ", context = ",
        addr, dst, (uint64_t)dst_len);
    context.Dump(strm, instruction);
    log->PutString(strm.GetString());
  }
  memset(dst, 0, dst_len);
  return dst_len;
}
Exemplo n.º 3
0
size_t
UnwindAssemblyInstEmulation::ReadMemory (EmulateInstruction *instruction,
                                         void *baton,
                                         const EmulateInstruction::Context &context, 
                                         lldb::addr_t addr, 
                                         void *dst,
                                         size_t dst_len)
{
    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));

    if (log && log->GetVerbose ())
    {
        StreamString strm;
        strm.Printf ("UnwindAssemblyInstEmulation::ReadMemory    (addr = 0x%16.16llx, dst = %p, dst_len = %zu, context = ", 
                     addr,
                     dst,
                     dst_len);
        context.Dump(strm, instruction);
        log->PutCString (strm.GetData ());
    }
    return dst_len;
}
bool
UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
                                            const EmulateInstruction::Context &context, 
                                            const RegisterInfo *reg_info,
                                            const RegisterValue &reg_value)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));

    if (log && log->GetVerbose ())
    {
        
        StreamString strm;
        strm.Printf ("UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ", reg_info->name);
        reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
        strm.PutCString (", context = ");
        context.Dump(strm, instruction);
        log->PutCString(strm.GetData());
    }

    if (!instruction->IsInstructionConditional())
        SetRegisterValue (*reg_info, reg_value);

    switch (context.type)
    {
        case EmulateInstruction::eContextInvalid:
        case EmulateInstruction::eContextReadOpcode:
        case EmulateInstruction::eContextImmediate:
        case EmulateInstruction::eContextAdjustBaseRegister:
        case EmulateInstruction::eContextRegisterPlusOffset:
        case EmulateInstruction::eContextAdjustPC:
        case EmulateInstruction::eContextRegisterStore:
        case EmulateInstruction::eContextSupervisorCall:
        case EmulateInstruction::eContextTableBranchReadMemory:
        case EmulateInstruction::eContextWriteRegisterRandomBits:
        case EmulateInstruction::eContextWriteMemoryRandomBits:
        case EmulateInstruction::eContextArithmetic:
        case EmulateInstruction::eContextAdvancePC:    
        case EmulateInstruction::eContextReturnFromException:
        case EmulateInstruction::eContextPushRegisterOnStack:
        case EmulateInstruction::eContextRegisterLoad:
//            {
//                const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
//                if (reg_num != LLDB_INVALID_REGNUM)
//                {
//                    const bool can_replace_only_if_unspecified = true;
//
//                    m_curr_row.SetRegisterLocationToUndefined (reg_num, 
//                                                               can_replace_only_if_unspecified, 
//                                                               can_replace_only_if_unspecified);
//                    m_curr_row_modified = true;
//                }
//            }
            break;

        case EmulateInstruction::eContextAbsoluteBranchRegister:
        case EmulateInstruction::eContextRelativeBranchImmediate:
            {
                if (context.info_type == EmulateInstruction::eInfoTypeISAAndImmediate &&
                    context.info.ISAAndImmediate.unsigned_data32 > 0)
                {
                    m_forward_branch_offset = context.info.ISAAndImmediateSigned.signed_data32;
                }
                else if (context.info_type == EmulateInstruction::eInfoTypeISAAndImmediateSigned &&
                         context.info.ISAAndImmediateSigned.signed_data32 > 0)
                {
                    m_forward_branch_offset = context.info.ISAAndImmediate.unsigned_data32;
                }
                else if (context.info_type == EmulateInstruction::eInfoTypeImmediate &&
                         context.info.unsigned_immediate > 0)
                {
                    m_forward_branch_offset = context.info.unsigned_immediate;
                }
                else if (context.info_type == EmulateInstruction::eInfoTypeImmediateSigned &&
                         context.info.signed_immediate > 0)
                {
                    m_forward_branch_offset = context.info.signed_immediate;
                }
            }
            break;

        case EmulateInstruction::eContextPopRegisterOffStack:
            {
                if (!instruction->IsInstructionConditional())
                {
                    const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
                    const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric];
                    if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP)
                    {
                        switch (context.info_type)
                        {
                            case EmulateInstruction::eInfoTypeAddress:
                                if (m_pushed_regs.find(reg_num) != m_pushed_regs.end() &&
                                    context.info.address == m_pushed_regs[reg_num])
                                {
                                    m_curr_row->SetRegisterLocationToSame(reg_num,
                                                                          false /*must_replace*/);
                                    m_curr_row_modified = true;
                                }
                                break;
                            case EmulateInstruction::eInfoTypeISA:
                                assert((generic_regnum == LLDB_REGNUM_GENERIC_PC ||
                                        generic_regnum == LLDB_REGNUM_GENERIC_FLAGS) &&
                                       "eInfoTypeISA used for poping a register other the the PC/FLAGS");
                                if (generic_regnum != LLDB_REGNUM_GENERIC_FLAGS)
                                {
                                    m_curr_row->SetRegisterLocationToSame(reg_num,
                                                                          false /*must_replace*/);
                                    m_curr_row_modified = true;
                                }
                                break;
                            default:
                                assert(false && "unhandled case, add code to handle this!");
                                break;
                        }
                    }
                }
            }
            break;

        case EmulateInstruction::eContextSetFramePointer:
            if (!m_fp_is_cfa && !instruction->IsInstructionConditional())
            {
                m_fp_is_cfa = true;
                m_cfa_reg_info = *reg_info;
                const uint32_t cfa_reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
                assert (cfa_reg_num != LLDB_INVALID_REGNUM);
                m_curr_row->GetCFAValue().SetIsRegisterPlusOffset(cfa_reg_num, m_initial_sp -
                        reg_value.GetAsUInt64());
                m_curr_row_modified = true;
            }
            break;

        case EmulateInstruction::eContextAdjustStackPointer:
            // If we have created a frame using the frame pointer, don't follow
            // subsequent adjustments to the stack pointer.
            if (!m_fp_is_cfa && !instruction->IsInstructionConditional())
            {
                m_curr_row->GetCFAValue().SetIsRegisterPlusOffset(
                        m_curr_row->GetCFAValue().GetRegisterNumber(),
                        m_initial_sp - reg_value.GetAsUInt64());
                m_curr_row_modified = true;
            }
            break;
    }
    return true;
}
size_t
UnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction,
                                          const EmulateInstruction::Context &context, 
                                          lldb::addr_t addr, 
                                          const void *dst,
                                          size_t dst_len)
{
    DataExtractor data (dst, 
                        dst_len, 
                        instruction->GetArchitecture ().GetByteOrder(), 
                        instruction->GetArchitecture ().GetAddressByteSize());

    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));

    if (log && log->GetVerbose ())
    {
        StreamString strm;

        strm.PutCString ("UnwindAssemblyInstEmulation::WriteMemory   (");
        data.Dump(&strm, 0, eFormatBytes, 1, dst_len, UINT32_MAX, addr, 0, 0);
        strm.PutCString (", context = ");
        context.Dump(strm, instruction);
        log->PutCString (strm.GetData());
    }

    const bool cant_replace = false;

    switch (context.type)
    {
        default:
        case EmulateInstruction::eContextInvalid:
        case EmulateInstruction::eContextReadOpcode:
        case EmulateInstruction::eContextImmediate:
        case EmulateInstruction::eContextAdjustBaseRegister:
        case EmulateInstruction::eContextRegisterPlusOffset:
        case EmulateInstruction::eContextAdjustPC:
        case EmulateInstruction::eContextRegisterStore:
        case EmulateInstruction::eContextRegisterLoad:  
        case EmulateInstruction::eContextRelativeBranchImmediate:
        case EmulateInstruction::eContextAbsoluteBranchRegister:
        case EmulateInstruction::eContextSupervisorCall:
        case EmulateInstruction::eContextTableBranchReadMemory:
        case EmulateInstruction::eContextWriteRegisterRandomBits:
        case EmulateInstruction::eContextWriteMemoryRandomBits:
        case EmulateInstruction::eContextArithmetic:
        case EmulateInstruction::eContextAdvancePC:    
        case EmulateInstruction::eContextReturnFromException:
        case EmulateInstruction::eContextPopRegisterOffStack:
        case EmulateInstruction::eContextAdjustStackPointer:
            break;
            
        case EmulateInstruction::eContextPushRegisterOnStack:
            {
                uint32_t reg_num = LLDB_INVALID_REGNUM;
                uint32_t generic_regnum = LLDB_INVALID_REGNUM;
                if (context.info_type == EmulateInstruction::eInfoTypeRegisterToRegisterPlusOffset)
                {
                    const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind();
                    reg_num = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[unwind_reg_kind];
                    generic_regnum = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[eRegisterKindGeneric];
                }
                else
                    assert (!"unhandled case, add code to handle this!");

                if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP)
                {
                    if (m_pushed_regs.find (reg_num) == m_pushed_regs.end())
                    {
                        m_pushed_regs[reg_num] = addr;
                        const int32_t offset = addr - m_initial_sp;
                        m_curr_row->SetRegisterLocationToAtCFAPlusOffset (reg_num, offset, cant_replace);
                        m_curr_row_modified = true;
                    }
                }
            }
            break;
            
    }

    return dst_len;
}
Exemplo n.º 6
0
bool
UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
                                            const EmulateInstruction::Context &context, 
                                            const RegisterInfo *reg_info,
                                            const RegisterValue &reg_value)
{
    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));

    if (log && log->GetVerbose ())
    {
        
        StreamString strm;
        strm.Printf ("UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ", reg_info->name);
        reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
        strm.PutCString (", context = ");
        context.Dump(strm, instruction);
        log->PutCString(strm.GetData());
    }

    const bool must_replace = true;
    SetRegisterValue (*reg_info, reg_value);

    switch (context.type)
    {
        default:
        case EmulateInstruction::eContextInvalid:
        case EmulateInstruction::eContextReadOpcode:
        case EmulateInstruction::eContextImmediate:
        case EmulateInstruction::eContextAdjustBaseRegister:
        case EmulateInstruction::eContextRegisterPlusOffset:
        case EmulateInstruction::eContextAdjustPC:
        case EmulateInstruction::eContextRegisterStore:
        case EmulateInstruction::eContextRegisterLoad:  
        case EmulateInstruction::eContextRelativeBranchImmediate:
        case EmulateInstruction::eContextAbsoluteBranchRegister:
        case EmulateInstruction::eContextSupervisorCall:
        case EmulateInstruction::eContextTableBranchReadMemory:
        case EmulateInstruction::eContextWriteRegisterRandomBits:
        case EmulateInstruction::eContextWriteMemoryRandomBits:
        case EmulateInstruction::eContextArithmetic:
        case EmulateInstruction::eContextAdvancePC:    
        case EmulateInstruction::eContextReturnFromException:
        case EmulateInstruction::eContextPushRegisterOnStack:
//            {
//                const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
//                if (reg_num != LLDB_INVALID_REGNUM)
//                {
//                    const bool can_replace_only_if_unspecified = true;
//
//                    m_curr_row.SetRegisterLocationToUndefined (reg_num, 
//                                                               can_replace_only_if_unspecified, 
//                                                               can_replace_only_if_unspecified);
//                }
//            }
            break;

        case EmulateInstruction::eContextPopRegisterOffStack:
            {
                const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
                if (reg_num != LLDB_INVALID_REGNUM)
                {
                    m_curr_row.SetRegisterLocationToSame (reg_num, must_replace);
                }
            }
            break;

        case EmulateInstruction::eContextSetFramePointer:
            if (!m_fp_is_cfa)
            {
                m_fp_is_cfa = true;
                m_cfa_reg_info = *reg_info;
                const uint32_t cfa_reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
                assert (cfa_reg_num != LLDB_INVALID_REGNUM);
                m_curr_row.SetCFARegister(cfa_reg_num);
                m_curr_row.SetCFAOffset(m_initial_sp - reg_value.GetAsUInt64());
            }
            break;

        case EmulateInstruction::eContextAdjustStackPointer:
            // If we have created a frame using the frame pointer, don't follow
            // subsequent adjustments to the stack pointer.
            if (!m_fp_is_cfa)
            {
                m_curr_row.SetCFAOffset (m_initial_sp - reg_value.GetAsUInt64());
            }
            break;
    }
    return true;
}