llvm-project/lldb/source/Core/EmulateInstruction.cpp

586 lines
19 KiB
C++
Raw Normal View History

//===-- EmulateInstruction.cpp ----------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/Core/EmulateInstruction.h"
Changed the emulate instruction function to take emulate options which are defined as enumerations. Current bits include: eEmulateInstructionOptionAutoAdvancePC eEmulateInstructionOptionIgnoreConditions Modified the EmulateInstruction class to have a few more pure virtuals that can help clients understand how many instructions the emulator can handle: virtual bool SupportsEmulatingIntructionsOfType (InstructionType inst_type) = 0; Where instruction types are defined as: //------------------------------------------------------------------ /// Instruction types //------------------------------------------------------------------ typedef enum InstructionType { eInstructionTypeAny, // Support for any instructions at all (at least one) eInstructionTypePrologueEpilogue, // All prologue and epilogue instructons that push and pop register values and modify sp/fp eInstructionTypePCModifying, // Any instruction that modifies the program counter/instruction pointer eInstructionTypeAll // All instructions of any kind } InstructionType; This allows use to tell what an emulator can do and also allows us to request these abilities when we are finding the plug-in interface. Added the ability for an EmulateInstruction class to get the register names for any registers that are part of the emulation. This helps with being able to dump and log effectively. The UnwindAssembly class now stores the architecture it was created with in case it is needed later in the unwinding process. Added a function that can tell us DWARF register names for ARM that goes along with the source/Utility/ARM_DWARF_Registers.h file: source/Utility/ARM_DWARF_Registers.c Took some of plug-ins out of the lldb_private namespace. llvm-svn: 130189
2011-04-26 12:39:08 +08:00
#include "lldb/Core/Address.h"
#include "lldb/Core/DumpRegisterValue.h"
Modified the PluginManager to be ready for loading plug-ins from a system LLDB plugin directory and a user LLDB plugin directory. We currently still need to work out at what layer the plug-ins will be, but at least we are prepared for plug-ins. Plug-ins will attempt to be loaded from the "/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Plugins" folder, and from the "~/Library/Application Support/LLDB/Plugins" folder on MacOSX. Each plugin will be scanned for: extern "C" bool LLDBPluginInitialize(void); extern "C" void LLDBPluginTerminate(void); If at least LLDBPluginInitialize is found, the plug-in will be loaded. The LLDBPluginInitialize function returns a bool that indicates if the plug-in should stay loaded or not (plug-ins might check the current OS, current hardware, or anything else and determine they don't want to run on the current host). The plug-in is uniqued by path and added to a static loaded plug-in map. The plug-in scanning happens during "lldb_private::Initialize()" which calls to the PluginManager::Initialize() function. Likewise with termination lldb_private::Terminate() calls PluginManager::Terminate(). The paths for the plug-in directories is fetched through new Host calls: bool Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec); bool Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec); This way linux and other systems can define their own appropriate locations for plug-ins to be loaded. To allow dynamic shared library loading, the Host layer has also been modified to include shared library open, close and get symbol: static void * Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error); static Error Host::DynamicLibraryClose (void *dynamic_library_handle); static void * Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error); lldb_private::FileSpec also has been modified to support directory enumeration in an attempt to abstract the directory enumeration into one spot in the code. The directory enumertion function is static and takes a callback: typedef enum EnumerateDirectoryResult { eEnumerateDirectoryResultNext, // Enumerate next entry in the current directory eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not eEnumerateDirectoryResultExit, // Exit from the current directory at the current level. eEnumerateDirectoryResultQuit // Stop directory enumerations at any level }; typedef FileSpec::EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, FileSpec::FileType file_type, const FileSpec &spec); static FileSpec::EnumerateDirectoryResult FileSpec::EnumerateDirectory (const char *dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton); This allow clients to specify the directory to search, and specifies if only files, directories or other (pipe, symlink, fifo, etc) files will cause the callback to be called. The callback also gets to return with the action that should be performed after this directory entry. eEnumerateDirectoryResultNext specifies to continue enumerating through a directory with the next entry. eEnumerateDirectoryResultEnter specifies to recurse down into a directory entry, or if the file is not a directory or symlink/alias to a directory, then just iterate to the next entry. eEnumerateDirectoryResultExit specifies to exit the current directory and skip any entries that might be remaining, yet continue enumerating to the next entry in the parent directory. And finally eEnumerateDirectoryResultQuit means to abort all directory enumerations at all levels. Modified the Declaration class to not include column information currently since we don't have any compilers that currently support column based declaration information. Columns support can be re-enabled with the additions of a #define. Added the ability to find an EmulateInstruction plug-in given a target triple and optional plug-in name in the plug-in manager. Fixed a few cases where opendir/readdir was being used, but yet not closedir was being used. Soon these will be deprecated in favor of the new directory enumeration call that was added to the FileSpec class. llvm-svn: 124716
2011-02-02 10:24:04 +08:00
#include "lldb/Core/PluginManager.h"
2011-05-10 04:18:18 +08:00
#include "lldb/Core/StreamFile.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private-interfaces.h"
#include "llvm/ADT/StringRef.h"
#include <cstring>
#include <memory>
#include <inttypes.h>
#include <stdio.h>
namespace lldb_private {
class Target;
}
using namespace lldb;
using namespace lldb_private;
EmulateInstruction *
EmulateInstruction::FindPlugin(const ArchSpec &arch,
InstructionType supported_inst_type,
const char *plugin_name) {
EmulateInstructionCreateInstance create_callback = nullptr;
if (plugin_name) {
ConstString const_plugin_name(plugin_name);
create_callback =
PluginManager::GetEmulateInstructionCreateCallbackForPluginName(
const_plugin_name);
if (create_callback) {
EmulateInstruction *emulate_insn_ptr =
create_callback(arch, supported_inst_type);
if (emulate_insn_ptr)
return emulate_insn_ptr;
Modified the PluginManager to be ready for loading plug-ins from a system LLDB plugin directory and a user LLDB plugin directory. We currently still need to work out at what layer the plug-ins will be, but at least we are prepared for plug-ins. Plug-ins will attempt to be loaded from the "/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Plugins" folder, and from the "~/Library/Application Support/LLDB/Plugins" folder on MacOSX. Each plugin will be scanned for: extern "C" bool LLDBPluginInitialize(void); extern "C" void LLDBPluginTerminate(void); If at least LLDBPluginInitialize is found, the plug-in will be loaded. The LLDBPluginInitialize function returns a bool that indicates if the plug-in should stay loaded or not (plug-ins might check the current OS, current hardware, or anything else and determine they don't want to run on the current host). The plug-in is uniqued by path and added to a static loaded plug-in map. The plug-in scanning happens during "lldb_private::Initialize()" which calls to the PluginManager::Initialize() function. Likewise with termination lldb_private::Terminate() calls PluginManager::Terminate(). The paths for the plug-in directories is fetched through new Host calls: bool Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec); bool Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec); This way linux and other systems can define their own appropriate locations for plug-ins to be loaded. To allow dynamic shared library loading, the Host layer has also been modified to include shared library open, close and get symbol: static void * Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error); static Error Host::DynamicLibraryClose (void *dynamic_library_handle); static void * Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error); lldb_private::FileSpec also has been modified to support directory enumeration in an attempt to abstract the directory enumeration into one spot in the code. The directory enumertion function is static and takes a callback: typedef enum EnumerateDirectoryResult { eEnumerateDirectoryResultNext, // Enumerate next entry in the current directory eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not eEnumerateDirectoryResultExit, // Exit from the current directory at the current level. eEnumerateDirectoryResultQuit // Stop directory enumerations at any level }; typedef FileSpec::EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, FileSpec::FileType file_type, const FileSpec &spec); static FileSpec::EnumerateDirectoryResult FileSpec::EnumerateDirectory (const char *dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton); This allow clients to specify the directory to search, and specifies if only files, directories or other (pipe, symlink, fifo, etc) files will cause the callback to be called. The callback also gets to return with the action that should be performed after this directory entry. eEnumerateDirectoryResultNext specifies to continue enumerating through a directory with the next entry. eEnumerateDirectoryResultEnter specifies to recurse down into a directory entry, or if the file is not a directory or symlink/alias to a directory, then just iterate to the next entry. eEnumerateDirectoryResultExit specifies to exit the current directory and skip any entries that might be remaining, yet continue enumerating to the next entry in the parent directory. And finally eEnumerateDirectoryResultQuit means to abort all directory enumerations at all levels. Modified the Declaration class to not include column information currently since we don't have any compilers that currently support column based declaration information. Columns support can be re-enabled with the additions of a #define. Added the ability to find an EmulateInstruction plug-in given a target triple and optional plug-in name in the plug-in manager. Fixed a few cases where opendir/readdir was being used, but yet not closedir was being used. Soon these will be deprecated in favor of the new directory enumeration call that was added to the FileSpec class. llvm-svn: 124716
2011-02-02 10:24:04 +08:00
}
} else {
for (uint32_t idx = 0;
(create_callback =
PluginManager::GetEmulateInstructionCreateCallbackAtIndex(idx)) !=
nullptr;
++idx) {
EmulateInstruction *emulate_insn_ptr =
create_callback(arch, supported_inst_type);
if (emulate_insn_ptr)
return emulate_insn_ptr;
Modified the PluginManager to be ready for loading plug-ins from a system LLDB plugin directory and a user LLDB plugin directory. We currently still need to work out at what layer the plug-ins will be, but at least we are prepared for plug-ins. Plug-ins will attempt to be loaded from the "/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Plugins" folder, and from the "~/Library/Application Support/LLDB/Plugins" folder on MacOSX. Each plugin will be scanned for: extern "C" bool LLDBPluginInitialize(void); extern "C" void LLDBPluginTerminate(void); If at least LLDBPluginInitialize is found, the plug-in will be loaded. The LLDBPluginInitialize function returns a bool that indicates if the plug-in should stay loaded or not (plug-ins might check the current OS, current hardware, or anything else and determine they don't want to run on the current host). The plug-in is uniqued by path and added to a static loaded plug-in map. The plug-in scanning happens during "lldb_private::Initialize()" which calls to the PluginManager::Initialize() function. Likewise with termination lldb_private::Terminate() calls PluginManager::Terminate(). The paths for the plug-in directories is fetched through new Host calls: bool Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec); bool Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec); This way linux and other systems can define their own appropriate locations for plug-ins to be loaded. To allow dynamic shared library loading, the Host layer has also been modified to include shared library open, close and get symbol: static void * Host::DynamicLibraryOpen (const FileSpec &file_spec, Error &error); static Error Host::DynamicLibraryClose (void *dynamic_library_handle); static void * Host::DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error); lldb_private::FileSpec also has been modified to support directory enumeration in an attempt to abstract the directory enumeration into one spot in the code. The directory enumertion function is static and takes a callback: typedef enum EnumerateDirectoryResult { eEnumerateDirectoryResultNext, // Enumerate next entry in the current directory eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not eEnumerateDirectoryResultExit, // Exit from the current directory at the current level. eEnumerateDirectoryResultQuit // Stop directory enumerations at any level }; typedef FileSpec::EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, FileSpec::FileType file_type, const FileSpec &spec); static FileSpec::EnumerateDirectoryResult FileSpec::EnumerateDirectory (const char *dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton); This allow clients to specify the directory to search, and specifies if only files, directories or other (pipe, symlink, fifo, etc) files will cause the callback to be called. The callback also gets to return with the action that should be performed after this directory entry. eEnumerateDirectoryResultNext specifies to continue enumerating through a directory with the next entry. eEnumerateDirectoryResultEnter specifies to recurse down into a directory entry, or if the file is not a directory or symlink/alias to a directory, then just iterate to the next entry. eEnumerateDirectoryResultExit specifies to exit the current directory and skip any entries that might be remaining, yet continue enumerating to the next entry in the parent directory. And finally eEnumerateDirectoryResultQuit means to abort all directory enumerations at all levels. Modified the Declaration class to not include column information currently since we don't have any compilers that currently support column based declaration information. Columns support can be re-enabled with the additions of a #define. Added the ability to find an EmulateInstruction plug-in given a target triple and optional plug-in name in the plug-in manager. Fixed a few cases where opendir/readdir was being used, but yet not closedir was being used. Soon these will be deprecated in favor of the new directory enumeration call that was added to the FileSpec class. llvm-svn: 124716
2011-02-02 10:24:04 +08:00
}
}
return nullptr;
}
EmulateInstruction::EmulateInstruction(const ArchSpec &arch) : m_arch(arch) {}
bool EmulateInstruction::ReadRegister(const RegisterInfo *reg_info,
RegisterValue &reg_value) {
if (m_read_reg_callback != nullptr)
return m_read_reg_callback(this, m_baton, reg_info, reg_value);
return false;
}
bool EmulateInstruction::ReadRegister(lldb::RegisterKind reg_kind,
uint32_t reg_num,
RegisterValue &reg_value) {
RegisterInfo reg_info;
if (GetRegisterInfo(reg_kind, reg_num, reg_info))
return ReadRegister(&reg_info, reg_value);
return false;
}
uint64_t EmulateInstruction::ReadRegisterUnsigned(lldb::RegisterKind 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 != nullptr)
return m_write_reg_callback(this, m_baton, context, reg_info, reg_value);
return false;
}
bool EmulateInstruction::WriteRegister(const Context &context,
lldb::RegisterKind reg_kind,
uint32_t reg_num,
const RegisterValue &reg_value) {
RegisterInfo reg_info;
if (GetRegisterInfo(reg_kind, reg_num, reg_info))
return WriteRegister(context, &reg_info, reg_value);
return false;
}
bool EmulateInstruction::WriteRegisterUnsigned(const Context &context,
lldb::RegisterKind reg_kind,
uint32_t reg_num,
uint64_t uint_value) {
RegisterInfo reg_info;
if (GetRegisterInfo(reg_kind, reg_num, reg_info)) {
2011-05-10 04:18:18 +08:00
RegisterValue reg_value;
if (reg_value.SetUInt(uint_value, reg_info.byte_size))
return WriteRegister(context, &reg_info, reg_value);
}
return false;
}
bool EmulateInstruction::WriteRegisterUnsigned(const Context &context,
const RegisterInfo *reg_info,
uint64_t uint_value) {
if (reg_info != nullptr) {
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 != nullptr)
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) {
lldb::offset_t offset = 0;
DataExtractor data(buf, byte_size, GetByteOrder(), GetAddressByteSize());
uval64 = data.GetMaxU64(&offset, byte_size);
success = true;
2011-05-10 04:18:18 +08:00
}
}
if (success_ptr)
*success_ptr = success;
2011-05-10 04:18:18 +08:00
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.GetString().data(), uval_byte_size);
return (bytes_written == uval_byte_size);
2011-05-10 04:18:18 +08:00
}
bool EmulateInstruction::WriteMemory(const Context &context, lldb::addr_t addr,
const void *src, size_t src_len) {
if (m_write_mem_callback != nullptr)
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 == nullptr || dst == nullptr || dst_len == 0)
return 0;
StackFrame *frame = (StackFrame *)baton;
ProcessSP process_sp(frame->CalculateProcess());
if (process_sp) {
Status 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 == nullptr || src == nullptr || src_len == 0)
return 0;
StackFrame *frame = (StackFrame *)baton;
ProcessSP process_sp(frame->CalculateProcess());
if (process_sp) {
Status error;
return process_sp->WriteMemory(addr, src, src_len, error);
}
return 0;
}
bool EmulateInstruction::ReadRegisterFrame(EmulateInstruction *instruction,
void *baton,
const RegisterInfo *reg_info,
RegisterValue &reg_value) {
if (baton == nullptr)
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 &reg_value) {
if (baton == nullptr)
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%" PRIx64 ", length = %" PRIu64
", 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%" PRIx64 ", length = %" PRIu64
", 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 &reg_value) {
StreamFile strm(stdout, false);
strm.Printf(" Read Register (%s)\n", reg_info->name);
lldb::RegisterKind reg_kind;
uint32_t 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 &reg_value) {
StreamFile strm(stdout, false);
strm.Printf(" Write to Register (name = %s, value = ", reg_info->name);
DumpRegisterValue(reg_value, &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%+" PRId64 ")",
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%+" PRId64 ", 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 = %+" PRId64 ")", info.signed_offset);
break;
case eInfoTypeRegister:
strm.Printf(" (reg = %s)", info.reg.name);
break;
case eInfoTypeImmediate:
strm.Printf(" (unsigned_immediate = %" PRIu64 " (0x%16.16" PRIx64 "))",
info.unsigned_immediate, info.unsigned_immediate);
break;
case eInfoTypeImmediateSigned:
strm.Printf(" (signed_immediate = %+" PRId64 " (0x%16.16" PRIx64 "))",
info.signed_immediate, info.signed_immediate);
break;
case eInfoTypeAddress:
strm.Printf(" (address = 0x%" PRIx64 ")", 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;
}
}
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 != nullptr)
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, lldb::RegisterKind &reg_kind,
uint32_t &reg_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;
Changed the emulate instruction function to take emulate options which are defined as enumerations. Current bits include: eEmulateInstructionOptionAutoAdvancePC eEmulateInstructionOptionIgnoreConditions Modified the EmulateInstruction class to have a few more pure virtuals that can help clients understand how many instructions the emulator can handle: virtual bool SupportsEmulatingIntructionsOfType (InstructionType inst_type) = 0; Where instruction types are defined as: //------------------------------------------------------------------ /// Instruction types //------------------------------------------------------------------ typedef enum InstructionType { eInstructionTypeAny, // Support for any instructions at all (at least one) eInstructionTypePrologueEpilogue, // All prologue and epilogue instructons that push and pop register values and modify sp/fp eInstructionTypePCModifying, // Any instruction that modifies the program counter/instruction pointer eInstructionTypeAll // All instructions of any kind } InstructionType; This allows use to tell what an emulator can do and also allows us to request these abilities when we are finding the plug-in interface. Added the ability for an EmulateInstruction class to get the register names for any registers that are part of the emulation. This helps with being able to dump and log effectively. The UnwindAssembly class now stores the architecture it was created with in case it is needed later in the unwinding process. Added a function that can tell us DWARF register names for ARM that goes along with the source/Utility/ARM_DWARF_Registers.h file: source/Utility/ARM_DWARF_Registers.c Took some of plug-ins out of the lldb_private namespace. llvm-svn: 130189
2011-04-26 12:39:08 +08:00
return true;
}
Changed the emulate instruction function to take emulate options which are defined as enumerations. Current bits include: eEmulateInstructionOptionAutoAdvancePC eEmulateInstructionOptionIgnoreConditions Modified the EmulateInstruction class to have a few more pure virtuals that can help clients understand how many instructions the emulator can handle: virtual bool SupportsEmulatingIntructionsOfType (InstructionType inst_type) = 0; Where instruction types are defined as: //------------------------------------------------------------------ /// Instruction types //------------------------------------------------------------------ typedef enum InstructionType { eInstructionTypeAny, // Support for any instructions at all (at least one) eInstructionTypePrologueEpilogue, // All prologue and epilogue instructons that push and pop register values and modify sp/fp eInstructionTypePCModifying, // Any instruction that modifies the program counter/instruction pointer eInstructionTypeAll // All instructions of any kind } InstructionType; This allows use to tell what an emulator can do and also allows us to request these abilities when we are finding the plug-in interface. Added the ability for an EmulateInstruction class to get the register names for any registers that are part of the emulation. This helps with being able to dump and log effectively. The UnwindAssembly class now stores the architecture it was created with in case it is needed later in the unwinding process. Added a function that can tell us DWARF register names for ARM that goes along with the source/Utility/ARM_DWARF_Registers.h file: source/Utility/ARM_DWARF_Registers.c Took some of plug-ins out of the lldb_private namespace. llvm-svn: 130189
2011-04-26 12:39:08 +08:00
reg_num = reg_info->kinds[eRegisterKindDWARF];
if (reg_num != LLDB_INVALID_REGNUM) {
reg_kind = eRegisterKindDWARF;
return true;
}
Changed the emulate instruction function to take emulate options which are defined as enumerations. Current bits include: eEmulateInstructionOptionAutoAdvancePC eEmulateInstructionOptionIgnoreConditions Modified the EmulateInstruction class to have a few more pure virtuals that can help clients understand how many instructions the emulator can handle: virtual bool SupportsEmulatingIntructionsOfType (InstructionType inst_type) = 0; Where instruction types are defined as: //------------------------------------------------------------------ /// Instruction types //------------------------------------------------------------------ typedef enum InstructionType { eInstructionTypeAny, // Support for any instructions at all (at least one) eInstructionTypePrologueEpilogue, // All prologue and epilogue instructons that push and pop register values and modify sp/fp eInstructionTypePCModifying, // Any instruction that modifies the program counter/instruction pointer eInstructionTypeAll // All instructions of any kind } InstructionType; This allows use to tell what an emulator can do and also allows us to request these abilities when we are finding the plug-in interface. Added the ability for an EmulateInstruction class to get the register names for any registers that are part of the emulation. This helps with being able to dump and log effectively. The UnwindAssembly class now stores the architecture it was created with in case it is needed later in the unwinding process. Added a function that can tell us DWARF register names for ARM that goes along with the source/Utility/ARM_DWARF_Registers.h file: source/Utility/ARM_DWARF_Registers.c Took some of plug-ins out of the lldb_private namespace. llvm-svn: 130189
2011-04-26 12:39:08 +08:00
reg_num = reg_info->kinds[eRegisterKindLLDB];
if (reg_num != LLDB_INVALID_REGNUM) {
reg_kind = eRegisterKindLLDB;
return true;
}
reg_num = reg_info->kinds[eRegisterKindEHFrame];
if (reg_num != LLDB_INVALID_REGNUM) {
reg_kind = eRegisterKindEHFrame;
return true;
}
reg_num = reg_info->kinds[eRegisterKindProcessPlugin];
if (reg_num != LLDB_INVALID_REGNUM) {
reg_kind = eRegisterKindProcessPlugin;
return true;
}
return false;
}
uint32_t
EmulateInstruction::GetInternalRegisterNumber(RegisterContext *reg_ctx,
const RegisterInfo &reg_info) {
lldb::RegisterKind reg_kind;
uint32_t reg_num;
if (reg_ctx && GetBestRegisterKindAndNumber(&reg_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;
}