forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			674 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			674 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- EmulateInstruction.h ------------------------------------*- C++ -*-===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "lldb/Core/EmulateInstruction.h"
 | 
						|
 | 
						|
#include "lldb/Core/Address.h"
 | 
						|
#include "lldb/Core/DataExtractor.h"
 | 
						|
#include "lldb/Core/Error.h"
 | 
						|
#include "lldb/Core/PluginManager.h"
 | 
						|
#include "lldb/Core/RegisterValue.h"
 | 
						|
#include "lldb/Core/StreamFile.h"
 | 
						|
#include "lldb/Core/StreamString.h"
 | 
						|
#include "lldb/Host/Endian.h"
 | 
						|
#include "lldb/Symbol/UnwindPlan.h"
 | 
						|
#include "lldb/Target/Process.h"
 | 
						|
#include "lldb/Target/RegisterContext.h"
 | 
						|
#include "lldb/Target/Target.h"
 | 
						|
#include "lldb/Target/Thread.h"
 | 
						|
 | 
						|
using namespace lldb;
 | 
						|
using namespace lldb_private;
 | 
						|
 | 
						|
EmulateInstruction*
 | 
						|
EmulateInstruction::FindPlugin (const ArchSpec &arch, InstructionType supported_inst_type, const char *plugin_name)
 | 
						|
{
 | 
						|
    EmulateInstructionCreateInstance create_callback = NULL;
 | 
						|
    if (plugin_name)
 | 
						|
    {
 | 
						|
        create_callback  = PluginManager::GetEmulateInstructionCreateCallbackForPluginName (plugin_name);
 | 
						|
        if (create_callback)
 | 
						|
        {
 | 
						|
           	EmulateInstruction *emulate_insn_ptr = create_callback(arch, supported_inst_type);
 | 
						|
            if (emulate_insn_ptr)
 | 
						|
                return emulate_insn_ptr;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        for (uint32_t idx = 0; (create_callback = PluginManager::GetEmulateInstructionCreateCallbackAtIndex(idx)) != NULL; ++idx)
 | 
						|
        {
 | 
						|
            EmulateInstruction *emulate_insn_ptr = create_callback(arch, supported_inst_type);
 | 
						|
            if (emulate_insn_ptr)
 | 
						|
                return emulate_insn_ptr;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
EmulateInstruction::EmulateInstruction (const ArchSpec &arch) :
 | 
						|
    m_arch (arch),
 | 
						|
    m_baton (NULL),
 | 
						|
    m_read_mem_callback (&ReadMemoryDefault),
 | 
						|
    m_write_mem_callback (&WriteMemoryDefault),
 | 
						|
    m_read_reg_callback (&ReadRegisterDefault),
 | 
						|
    m_write_reg_callback (&WriteRegisterDefault),
 | 
						|
    m_addr (LLDB_INVALID_ADDRESS)
 | 
						|
{
 | 
						|
    ::memset (&m_opcode, 0, sizeof (m_opcode));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool
 | 
						|
EmulateInstruction::ReadRegister (const RegisterInfo *reg_info, RegisterValue& reg_value)
 | 
						|
{
 | 
						|
    if (m_read_reg_callback)
 | 
						|
        return m_read_reg_callback (this, m_baton, reg_info, reg_value);
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
EmulateInstruction::ReadRegister (uint32_t reg_kind, uint32_t reg_num, RegisterValue& reg_value)
 | 
						|
{
 | 
						|
    RegisterInfo reg_info;
 | 
						|
    if (GetRegisterInfo(reg_kind, reg_num, reg_info))
 | 
						|
        return ReadRegister (®_info, reg_value);
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
uint64_t
 | 
						|
EmulateInstruction::ReadRegisterUnsigned (uint32_t reg_kind, 
 | 
						|
                                          uint32_t reg_num,
 | 
						|
                                          uint64_t fail_value, 
 | 
						|
                                          bool *success_ptr)
 | 
						|
{
 | 
						|
    RegisterValue reg_value;
 | 
						|
    if (ReadRegister (reg_kind, reg_num, reg_value))
 | 
						|
        return reg_value.GetAsUInt64(fail_value, success_ptr);
 | 
						|
    if (success_ptr)
 | 
						|
        *success_ptr = false;
 | 
						|
    return fail_value;
 | 
						|
}
 | 
						|
 | 
						|
uint64_t
 | 
						|
EmulateInstruction::ReadRegisterUnsigned (const RegisterInfo *reg_info,
 | 
						|
                                          uint64_t fail_value, 
 | 
						|
                                          bool *success_ptr)
 | 
						|
{
 | 
						|
    RegisterValue reg_value;
 | 
						|
    if (ReadRegister (reg_info, reg_value))
 | 
						|
        return reg_value.GetAsUInt64(fail_value, success_ptr);
 | 
						|
    if (success_ptr)
 | 
						|
        *success_ptr = false;
 | 
						|
    return fail_value;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
EmulateInstruction::WriteRegister (const Context &context, 
 | 
						|
                                   const RegisterInfo *reg_info, 
 | 
						|
                                   const RegisterValue& reg_value)
 | 
						|
{
 | 
						|
    if (m_write_reg_callback)
 | 
						|
        return m_write_reg_callback (this, m_baton, context, reg_info, reg_value);
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
EmulateInstruction::WriteRegister (const Context &context, 
 | 
						|
                                   uint32_t reg_kind, 
 | 
						|
                                   uint32_t reg_num, 
 | 
						|
                                   const RegisterValue& reg_value)
 | 
						|
{
 | 
						|
    RegisterInfo reg_info;
 | 
						|
    if (GetRegisterInfo(reg_kind, reg_num, reg_info))
 | 
						|
        return WriteRegister (context, ®_info, reg_value);
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool
 | 
						|
EmulateInstruction::WriteRegisterUnsigned (const Context &context,
 | 
						|
                                           uint32_t reg_kind, 
 | 
						|
                                           uint32_t reg_num,
 | 
						|
                                           uint64_t uint_value)
 | 
						|
{
 | 
						|
    
 | 
						|
    RegisterInfo reg_info;
 | 
						|
    if (GetRegisterInfo(reg_kind, reg_num, reg_info))
 | 
						|
    {
 | 
						|
        RegisterValue reg_value;
 | 
						|
        if (reg_value.SetUInt(uint_value, reg_info.byte_size))
 | 
						|
            return WriteRegister (context, ®_info, reg_value);
 | 
						|
    }
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
EmulateInstruction::WriteRegisterUnsigned (const Context &context,
 | 
						|
                                           const RegisterInfo *reg_info,
 | 
						|
                                           uint64_t uint_value)
 | 
						|
{
 | 
						|
    
 | 
						|
    if (reg_info)
 | 
						|
    {
 | 
						|
        RegisterValue reg_value;
 | 
						|
        if (reg_value.SetUInt(uint_value, reg_info->byte_size))
 | 
						|
                return WriteRegister (context, reg_info, reg_value);
 | 
						|
    }
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
size_t
 | 
						|
EmulateInstruction::ReadMemory (const Context &context, 
 | 
						|
                                lldb::addr_t addr, 
 | 
						|
                                void *dst,
 | 
						|
                                size_t dst_len)
 | 
						|
{
 | 
						|
    if (m_read_mem_callback)
 | 
						|
        return m_read_mem_callback (this, m_baton, context, addr, dst, dst_len) == dst_len;
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
uint64_t
 | 
						|
EmulateInstruction::ReadMemoryUnsigned (const Context &context, lldb::addr_t addr, size_t byte_size, uint64_t fail_value, bool *success_ptr)
 | 
						|
{
 | 
						|
    uint64_t uval64 = 0;
 | 
						|
    bool success = false;
 | 
						|
    if (byte_size <= 8)
 | 
						|
    {
 | 
						|
        uint8_t buf[sizeof(uint64_t)];
 | 
						|
        size_t bytes_read = m_read_mem_callback (this, m_baton, context, addr, buf, byte_size);
 | 
						|
        if (bytes_read == byte_size)
 | 
						|
        {
 | 
						|
            uint32_t offset = 0;
 | 
						|
            DataExtractor data (buf, byte_size, GetByteOrder(), GetAddressByteSize());
 | 
						|
            uval64 = data.GetMaxU64 (&offset, byte_size);
 | 
						|
            success = true;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (success_ptr)
 | 
						|
        *success_ptr = success;
 | 
						|
 | 
						|
    if (!success)
 | 
						|
        uval64 = fail_value;
 | 
						|
    return uval64;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool
 | 
						|
EmulateInstruction::WriteMemoryUnsigned (const Context &context, 
 | 
						|
                                         lldb::addr_t addr, 
 | 
						|
                                         uint64_t uval,
 | 
						|
                                         size_t uval_byte_size)
 | 
						|
{
 | 
						|
    StreamString strm(Stream::eBinary, GetAddressByteSize(), GetByteOrder());
 | 
						|
    strm.PutMaxHex64 (uval, uval_byte_size);
 | 
						|
    
 | 
						|
    size_t bytes_written = m_write_mem_callback (this, m_baton, context, addr, strm.GetData(), uval_byte_size);
 | 
						|
    if (bytes_written == uval_byte_size)
 | 
						|
        return true;
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
EmulateInstruction::WriteMemory (const Context &context, 
 | 
						|
                                 lldb::addr_t addr, 
 | 
						|
                                 const void *src,
 | 
						|
                                 size_t src_len)
 | 
						|
{
 | 
						|
    if (m_write_mem_callback)
 | 
						|
        return m_write_mem_callback (this, m_baton, context, addr, src, src_len) == src_len;
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
EmulateInstruction::SetBaton (void *baton)
 | 
						|
{
 | 
						|
    m_baton = baton;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
EmulateInstruction::SetCallbacks (ReadMemoryCallback read_mem_callback,
 | 
						|
                                  WriteMemoryCallback write_mem_callback,
 | 
						|
                                  ReadRegisterCallback read_reg_callback,
 | 
						|
                                  WriteRegisterCallback write_reg_callback)
 | 
						|
{
 | 
						|
    m_read_mem_callback = read_mem_callback;
 | 
						|
    m_write_mem_callback = write_mem_callback;
 | 
						|
    m_read_reg_callback = read_reg_callback;
 | 
						|
    m_write_reg_callback = write_reg_callback;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
EmulateInstruction::SetReadMemCallback (ReadMemoryCallback read_mem_callback)
 | 
						|
{
 | 
						|
    m_read_mem_callback = read_mem_callback;
 | 
						|
}
 | 
						|
 | 
						|
                                  
 | 
						|
void
 | 
						|
EmulateInstruction::SetWriteMemCallback (WriteMemoryCallback write_mem_callback)
 | 
						|
{
 | 
						|
    m_write_mem_callback = write_mem_callback;
 | 
						|
}
 | 
						|
 | 
						|
                                  
 | 
						|
void
 | 
						|
EmulateInstruction::SetReadRegCallback (ReadRegisterCallback read_reg_callback)
 | 
						|
{
 | 
						|
    m_read_reg_callback = read_reg_callback;
 | 
						|
}
 | 
						|
 | 
						|
                                  
 | 
						|
void
 | 
						|
EmulateInstruction::SetWriteRegCallback (WriteRegisterCallback write_reg_callback)
 | 
						|
{
 | 
						|
    m_write_reg_callback = write_reg_callback;
 | 
						|
}
 | 
						|
 | 
						|
                                  
 | 
						|
                            
 | 
						|
//
 | 
						|
//  Read & Write Memory and Registers callback functions.
 | 
						|
//
 | 
						|
 | 
						|
size_t 
 | 
						|
EmulateInstruction::ReadMemoryFrame (EmulateInstruction *instruction,
 | 
						|
                                     void *baton,
 | 
						|
                                     const Context &context, 
 | 
						|
                                     lldb::addr_t addr, 
 | 
						|
                                     void *dst,
 | 
						|
                                     size_t dst_len)
 | 
						|
{
 | 
						|
    if (!baton || dst == NULL || dst_len == 0)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    StackFrame *frame = (StackFrame *) baton;
 | 
						|
 | 
						|
    ProcessSP process_sp (frame->CalculateProcess());
 | 
						|
    if (process_sp)
 | 
						|
    {
 | 
						|
        Error error;
 | 
						|
        return process_sp->ReadMemory (addr, dst, dst_len, error);
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
size_t 
 | 
						|
EmulateInstruction::WriteMemoryFrame (EmulateInstruction *instruction,
 | 
						|
                                      void *baton,
 | 
						|
                                      const Context &context, 
 | 
						|
                                      lldb::addr_t addr, 
 | 
						|
                                      const void *src,
 | 
						|
                                      size_t src_len)
 | 
						|
{
 | 
						|
    if (!baton || src == NULL || src_len == 0)
 | 
						|
        return 0;
 | 
						|
    
 | 
						|
    StackFrame *frame = (StackFrame *) baton;
 | 
						|
 | 
						|
    ProcessSP process_sp (frame->CalculateProcess());
 | 
						|
    if (process_sp)
 | 
						|
    {
 | 
						|
        Error error;
 | 
						|
        return process_sp->WriteMemory (addr, src, src_len, error);
 | 
						|
    }
 | 
						|
    
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
bool   
 | 
						|
EmulateInstruction::ReadRegisterFrame  (EmulateInstruction *instruction,
 | 
						|
                                        void *baton,
 | 
						|
                                        const RegisterInfo *reg_info,
 | 
						|
                                        RegisterValue ®_value)
 | 
						|
{
 | 
						|
    if (!baton)
 | 
						|
        return false;
 | 
						|
        
 | 
						|
    StackFrame *frame = (StackFrame *) baton;
 | 
						|
    return frame->GetRegisterContext()->ReadRegister (reg_info, reg_value);
 | 
						|
}
 | 
						|
 | 
						|
bool   
 | 
						|
EmulateInstruction::WriteRegisterFrame (EmulateInstruction *instruction,
 | 
						|
                                        void *baton,
 | 
						|
                                        const Context &context, 
 | 
						|
                                        const RegisterInfo *reg_info,
 | 
						|
                                        const RegisterValue ®_value)
 | 
						|
{
 | 
						|
    if (!baton)
 | 
						|
        return false;
 | 
						|
        
 | 
						|
    StackFrame *frame = (StackFrame *) baton;
 | 
						|
    return frame->GetRegisterContext()->WriteRegister (reg_info, reg_value);
 | 
						|
}
 | 
						|
 | 
						|
size_t 
 | 
						|
EmulateInstruction::ReadMemoryDefault (EmulateInstruction *instruction,
 | 
						|
                                       void *baton,
 | 
						|
                                       const Context &context, 
 | 
						|
                                       lldb::addr_t addr, 
 | 
						|
                                       void *dst,
 | 
						|
                                       size_t length)
 | 
						|
{
 | 
						|
    StreamFile strm (stdout, false);
 | 
						|
    strm.Printf ("    Read from Memory (address = 0x%llx, length = %llu, context = ", addr, (uint64_t)length);
 | 
						|
    context.Dump (strm, instruction);    
 | 
						|
    strm.EOL();
 | 
						|
    *((uint64_t *) dst) = 0xdeadbeef;
 | 
						|
    return length;
 | 
						|
}
 | 
						|
 | 
						|
size_t 
 | 
						|
EmulateInstruction::WriteMemoryDefault (EmulateInstruction *instruction,
 | 
						|
                                        void *baton,
 | 
						|
                                        const Context &context, 
 | 
						|
                                        lldb::addr_t addr, 
 | 
						|
                                        const void *dst,
 | 
						|
                                        size_t length)
 | 
						|
{
 | 
						|
    StreamFile strm (stdout, false);
 | 
						|
    strm.Printf ("    Write to Memory (address = 0x%llx, length = %llu, context = ", addr, (uint64_t)length);
 | 
						|
    context.Dump (strm, instruction);    
 | 
						|
    strm.EOL();
 | 
						|
    return length;
 | 
						|
}
 | 
						|
 | 
						|
bool   
 | 
						|
EmulateInstruction::ReadRegisterDefault  (EmulateInstruction *instruction,
 | 
						|
                                          void *baton,
 | 
						|
                                          const RegisterInfo *reg_info,
 | 
						|
                                          RegisterValue ®_value)
 | 
						|
{
 | 
						|
    StreamFile strm (stdout, false);
 | 
						|
    strm.Printf ("  Read Register (%s)\n", reg_info->name);
 | 
						|
    uint32_t reg_kind, reg_num;
 | 
						|
    if (GetBestRegisterKindAndNumber (reg_info, reg_kind, reg_num))
 | 
						|
        reg_value.SetUInt64((uint64_t)reg_kind << 24 | reg_num);
 | 
						|
    else
 | 
						|
        reg_value.SetUInt64(0);
 | 
						|
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
bool   
 | 
						|
EmulateInstruction::WriteRegisterDefault (EmulateInstruction *instruction,
 | 
						|
                                          void *baton,
 | 
						|
                                          const Context &context, 
 | 
						|
                                          const RegisterInfo *reg_info,
 | 
						|
                                          const RegisterValue ®_value)
 | 
						|
{
 | 
						|
    StreamFile strm (stdout, false);
 | 
						|
    strm.Printf ("    Write to Register (name = %s, value = " , reg_info->name);
 | 
						|
    reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
 | 
						|
    strm.PutCString (", context = ");
 | 
						|
    context.Dump (strm, instruction);        
 | 
						|
    strm.EOL();
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
EmulateInstruction::Context::Dump (Stream &strm, 
 | 
						|
                                   EmulateInstruction *instruction) const
 | 
						|
{
 | 
						|
    switch (type)
 | 
						|
    {
 | 
						|
        case eContextReadOpcode:
 | 
						|
            strm.PutCString ("reading opcode");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case eContextImmediate:
 | 
						|
            strm.PutCString ("immediate");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case eContextPushRegisterOnStack:
 | 
						|
            strm.PutCString ("push register");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case eContextPopRegisterOffStack:
 | 
						|
            strm.PutCString ("pop register");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case eContextAdjustStackPointer:
 | 
						|
            strm.PutCString ("adjust sp");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case eContextSetFramePointer:
 | 
						|
            strm.PutCString ("set frame pointer");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case eContextAdjustBaseRegister:
 | 
						|
            strm.PutCString ("adjusting (writing value back to) a base register");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case eContextRegisterPlusOffset:
 | 
						|
            strm.PutCString ("register + offset");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case eContextRegisterStore:
 | 
						|
            strm.PutCString ("store register");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case eContextRegisterLoad:
 | 
						|
            strm.PutCString ("load register");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case eContextRelativeBranchImmediate:
 | 
						|
            strm.PutCString ("relative branch immediate");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case eContextAbsoluteBranchRegister:
 | 
						|
            strm.PutCString ("absolute branch register");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case eContextSupervisorCall:
 | 
						|
            strm.PutCString ("supervisor call");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case eContextTableBranchReadMemory:
 | 
						|
            strm.PutCString ("table branch read memory");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case eContextWriteRegisterRandomBits:
 | 
						|
            strm.PutCString ("write random bits to a register");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case eContextWriteMemoryRandomBits:
 | 
						|
            strm.PutCString ("write random bits to a memory address");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case eContextArithmetic:
 | 
						|
            strm.PutCString ("arithmetic");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case eContextReturnFromException:
 | 
						|
            strm.PutCString ("return from exception");
 | 
						|
            break;
 | 
						|
            
 | 
						|
        default:
 | 
						|
            strm.PutCString ("unrecognized context.");
 | 
						|
            break;
 | 
						|
    }
 | 
						|
    
 | 
						|
    switch (info_type)
 | 
						|
    {
 | 
						|
    case eInfoTypeRegisterPlusOffset:
 | 
						|
        {
 | 
						|
            strm.Printf (" (reg_plus_offset = %s%+lld)",
 | 
						|
                         info.RegisterPlusOffset.reg.name,
 | 
						|
                         info.RegisterPlusOffset.signed_offset);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
 | 
						|
    case eInfoTypeRegisterPlusIndirectOffset:
 | 
						|
        {
 | 
						|
            strm.Printf (" (reg_plus_reg = %s + %s)",
 | 
						|
                         info.RegisterPlusIndirectOffset.base_reg.name,
 | 
						|
                         info.RegisterPlusIndirectOffset.offset_reg.name);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
 | 
						|
    case eInfoTypeRegisterToRegisterPlusOffset:
 | 
						|
        {
 | 
						|
            strm.Printf (" (base_and_imm_offset = %s%+lld, data_reg = %s)", 
 | 
						|
                         info.RegisterToRegisterPlusOffset.base_reg.name, 
 | 
						|
                         info.RegisterToRegisterPlusOffset.offset,
 | 
						|
                         info.RegisterToRegisterPlusOffset.data_reg.name);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
 | 
						|
    case eInfoTypeRegisterToRegisterPlusIndirectOffset:
 | 
						|
        {
 | 
						|
            strm.Printf (" (base_and_reg_offset = %s + %s, data_reg = %s)",
 | 
						|
                         info.RegisterToRegisterPlusIndirectOffset.base_reg.name, 
 | 
						|
                         info.RegisterToRegisterPlusIndirectOffset.offset_reg.name, 
 | 
						|
                         info.RegisterToRegisterPlusIndirectOffset.data_reg.name);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    
 | 
						|
    case eInfoTypeRegisterRegisterOperands:
 | 
						|
        {
 | 
						|
            strm.Printf (" (register to register binary op: %s and %s)", 
 | 
						|
                         info.RegisterRegisterOperands.operand1.name,
 | 
						|
                         info.RegisterRegisterOperands.operand2.name);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
 | 
						|
    case eInfoTypeOffset:
 | 
						|
        strm.Printf (" (signed_offset = %+lld)", info.signed_offset);
 | 
						|
        break;
 | 
						|
        
 | 
						|
    case eInfoTypeRegister:
 | 
						|
        strm.Printf (" (reg = %s)", info.reg.name);
 | 
						|
        break;
 | 
						|
        
 | 
						|
    case eInfoTypeImmediate:
 | 
						|
        strm.Printf (" (unsigned_immediate = %llu (0x%16.16llx))", 
 | 
						|
                     info.unsigned_immediate, 
 | 
						|
                     info.unsigned_immediate);
 | 
						|
        break;
 | 
						|
 | 
						|
    case eInfoTypeImmediateSigned:
 | 
						|
        strm.Printf (" (signed_immediate = %+lld (0x%16.16llx))", 
 | 
						|
                     info.signed_immediate, 
 | 
						|
                     info.signed_immediate);
 | 
						|
        break;
 | 
						|
        
 | 
						|
    case eInfoTypeAddress:
 | 
						|
        strm.Printf (" (address = 0x%llx)", info.address);
 | 
						|
        break;
 | 
						|
        
 | 
						|
    case eInfoTypeISAAndImmediate:
 | 
						|
        strm.Printf (" (isa = %u, unsigned_immediate = %u (0x%8.8x))", 
 | 
						|
                     info.ISAAndImmediate.isa,
 | 
						|
                     info.ISAAndImmediate.unsigned_data32,
 | 
						|
                     info.ISAAndImmediate.unsigned_data32);
 | 
						|
        break;
 | 
						|
        
 | 
						|
    case eInfoTypeISAAndImmediateSigned:
 | 
						|
        strm.Printf (" (isa = %u, signed_immediate = %i (0x%8.8x))", 
 | 
						|
                     info.ISAAndImmediateSigned.isa,
 | 
						|
                     info.ISAAndImmediateSigned.signed_data32,
 | 
						|
                     info.ISAAndImmediateSigned.signed_data32);
 | 
						|
        break;
 | 
						|
        
 | 
						|
    case eInfoTypeISA:
 | 
						|
        strm.Printf (" (isa = %u)", info.isa);
 | 
						|
        break;
 | 
						|
        
 | 
						|
    case eInfoTypeNoArgs:
 | 
						|
        break;
 | 
						|
 | 
						|
    default:
 | 
						|
        strm.Printf (" (unknown <info_type>)");
 | 
						|
        break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
EmulateInstruction::SetInstruction (const Opcode &opcode, const Address &inst_addr, Target *target)
 | 
						|
{
 | 
						|
    m_opcode = opcode;
 | 
						|
    m_addr = LLDB_INVALID_ADDRESS;
 | 
						|
    if (inst_addr.IsValid())
 | 
						|
    {
 | 
						|
        if (target)
 | 
						|
            m_addr = inst_addr.GetLoadAddress (target);
 | 
						|
        if (m_addr == LLDB_INVALID_ADDRESS)
 | 
						|
            m_addr = inst_addr.GetFileAddress ();
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
EmulateInstruction::GetBestRegisterKindAndNumber (const RegisterInfo *reg_info, 
 | 
						|
                                                  uint32_t ®_kind,
 | 
						|
                                                  uint32_t ®_num)
 | 
						|
{
 | 
						|
    // Generic and DWARF should be the two most popular register kinds when
 | 
						|
    // emulating instructions since they are the most platform agnostic...
 | 
						|
    reg_num = reg_info->kinds[eRegisterKindGeneric];
 | 
						|
    if (reg_num != LLDB_INVALID_REGNUM)
 | 
						|
    {
 | 
						|
        reg_kind = eRegisterKindGeneric;
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
    
 | 
						|
    reg_num = reg_info->kinds[eRegisterKindDWARF];
 | 
						|
    if (reg_num != LLDB_INVALID_REGNUM)
 | 
						|
    {
 | 
						|
        reg_kind = eRegisterKindDWARF;
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    reg_num = reg_info->kinds[eRegisterKindLLDB];
 | 
						|
    if (reg_num != LLDB_INVALID_REGNUM)
 | 
						|
    {
 | 
						|
        reg_kind = eRegisterKindLLDB;
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    reg_num = reg_info->kinds[eRegisterKindGCC];
 | 
						|
    if (reg_num != LLDB_INVALID_REGNUM)
 | 
						|
    {
 | 
						|
        reg_kind = eRegisterKindGCC;
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    reg_num = reg_info->kinds[eRegisterKindGDB];
 | 
						|
    if (reg_num != LLDB_INVALID_REGNUM)
 | 
						|
    {
 | 
						|
        reg_kind = eRegisterKindGDB;
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t
 | 
						|
EmulateInstruction::GetInternalRegisterNumber (RegisterContext *reg_ctx, const RegisterInfo ®_info)
 | 
						|
{
 | 
						|
    uint32_t reg_kind, reg_num;
 | 
						|
    if (reg_ctx && GetBestRegisterKindAndNumber (®_info, reg_kind, reg_num))
 | 
						|
        return reg_ctx->ConvertRegisterKindToRegisterNumber (reg_kind, reg_num);
 | 
						|
    return LLDB_INVALID_REGNUM;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool
 | 
						|
EmulateInstruction::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
 | 
						|
{
 | 
						|
    unwind_plan.Clear();
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
 |