2011-01-21 22:02:52 +00:00
|
|
|
//===-- EmulateInstruction.h ------------------------------------*- C++ -*-===//
|
|
|
|
|
//
|
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
|
//
|
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
2011-02-05 02:56:16 +00:00
|
|
|
#include "lldb/Core/EmulateInstruction.h"
|
2011-01-21 22:02:52 +00:00
|
|
|
|
2011-04-05 18:46:00 +00:00
|
|
|
#include "lldb/Core/DataBufferHeap.h"
|
2011-01-21 22:02:52 +00:00
|
|
|
#include "lldb/Core/DataExtractor.h"
|
2011-04-05 18:46:00 +00:00
|
|
|
#include "lldb/Core/Error.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 02:24:04 +00:00
|
|
|
#include "lldb/Core/PluginManager.h"
|
2011-01-21 22:02:52 +00:00
|
|
|
#include "lldb/Core/StreamString.h"
|
2011-02-01 01:31:41 +00:00
|
|
|
#include "lldb/Host/Endian.h"
|
2011-04-05 18:46:00 +00:00
|
|
|
#include "lldb/Target/Process.h"
|
|
|
|
|
#include "lldb/Target/RegisterContext.h"
|
|
|
|
|
#include "lldb/Target/Thread.h"
|
|
|
|
|
|
|
|
|
|
#include "Plugins/Instruction/ARM/EmulateInstructionARM.h"
|
|
|
|
|
|
2011-01-21 22:02:52 +00:00
|
|
|
using namespace lldb;
|
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
|
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 02:24:04 +00:00
|
|
|
EmulateInstruction*
|
2011-02-15 21:59:32 +00:00
|
|
|
EmulateInstruction::FindPlugin (const ArchSpec &arch, const char *plugin_name)
|
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 02:24:04 +00:00
|
|
|
{
|
|
|
|
|
EmulateInstructionCreateInstance create_callback = NULL;
|
|
|
|
|
if (plugin_name)
|
|
|
|
|
{
|
|
|
|
|
create_callback = PluginManager::GetEmulateInstructionCreateCallbackForPluginName (plugin_name);
|
|
|
|
|
if (create_callback)
|
|
|
|
|
{
|
2011-04-05 18:46:00 +00:00
|
|
|
EmulateInstruction *emulate_insn_ptr = create_callback(arch);
|
|
|
|
|
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 02:24:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (uint32_t idx = 0; (create_callback = PluginManager::GetEmulateInstructionCreateCallbackAtIndex(idx)) != NULL; ++idx)
|
|
|
|
|
{
|
2011-04-05 18:46:00 +00:00
|
|
|
EmulateInstruction *emulate_insn_ptr = create_callback(arch);
|
|
|
|
|
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 02:24:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2011-01-21 22:02:52 +00:00
|
|
|
|
|
|
|
|
EmulateInstruction::EmulateInstruction
|
|
|
|
|
(
|
|
|
|
|
lldb::ByteOrder byte_order,
|
|
|
|
|
uint32_t addr_byte_size,
|
2011-04-05 18:46:00 +00:00
|
|
|
const ArchSpec &arch,
|
2011-01-21 22:02:52 +00:00
|
|
|
void *baton,
|
|
|
|
|
ReadMemory read_mem_callback,
|
|
|
|
|
WriteMemory write_mem_callback,
|
|
|
|
|
ReadRegister read_reg_callback,
|
|
|
|
|
WriteRegister write_reg_callback
|
|
|
|
|
) :
|
2011-02-01 01:31:41 +00:00
|
|
|
m_byte_order (endian::InlHostByteOrder()),
|
2011-04-05 18:46:00 +00:00
|
|
|
m_addr_byte_size (addr_byte_size),
|
|
|
|
|
m_arch (arch),
|
2011-01-21 22:02:52 +00:00
|
|
|
m_baton (baton),
|
|
|
|
|
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),
|
2011-03-24 23:53:38 +00:00
|
|
|
m_opcode (),
|
2011-03-24 21:19:54 +00:00
|
|
|
m_opcode_pc (LLDB_INVALID_ADDRESS)
|
2011-01-21 22:02:52 +00:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-05 18:46:00 +00:00
|
|
|
EmulateInstruction::EmulateInstruction
|
|
|
|
|
(
|
|
|
|
|
lldb::ByteOrder byte_order,
|
|
|
|
|
uint32_t addr_byte_size,
|
|
|
|
|
const ArchSpec &arch
|
|
|
|
|
) :
|
|
|
|
|
m_byte_order (endian::InlHostByteOrder()),
|
|
|
|
|
m_addr_byte_size (addr_byte_size),
|
|
|
|
|
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_opcode_pc (LLDB_INVALID_ADDRESS)
|
|
|
|
|
{
|
|
|
|
|
::memset (&m_opcode, 0, sizeof (m_opcode));
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-21 22:02:52 +00:00
|
|
|
uint64_t
|
|
|
|
|
EmulateInstruction::ReadRegisterUnsigned (uint32_t reg_kind, uint32_t reg_num, uint64_t fail_value, bool *success_ptr)
|
|
|
|
|
{
|
|
|
|
|
uint64_t uval64 = 0;
|
|
|
|
|
bool success = m_read_reg_callback (m_baton, reg_kind, reg_num, uval64);
|
|
|
|
|
if (success_ptr)
|
|
|
|
|
*success_ptr = success;
|
|
|
|
|
if (!success)
|
|
|
|
|
uval64 = fail_value;
|
|
|
|
|
return uval64;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
EmulateInstruction::WriteRegisterUnsigned (const Context &context, uint32_t reg_kind, uint32_t reg_num, uint64_t reg_value)
|
|
|
|
|
{
|
|
|
|
|
return m_write_reg_callback (m_baton, context, reg_kind, reg_num, reg_value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 (m_baton, context, addr, buf, byte_size);
|
|
|
|
|
if (bytes_read == byte_size)
|
|
|
|
|
{
|
|
|
|
|
uint32_t offset = 0;
|
|
|
|
|
DataExtractor data (buf, byte_size, m_byte_order, m_addr_byte_size);
|
|
|
|
|
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 (m_baton, context, addr, strm.GetData(), uval_byte_size);
|
|
|
|
|
if (bytes_written == uval_byte_size)
|
|
|
|
|
return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2011-04-05 18:46:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
EmulateInstruction::SetBaton (void *baton)
|
|
|
|
|
{
|
|
|
|
|
m_baton = baton;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
EmulateInstruction::SetCallbacks (ReadMemory read_mem_callback,
|
|
|
|
|
WriteMemory write_mem_callback,
|
|
|
|
|
ReadRegister read_reg_callback,
|
|
|
|
|
WriteRegister 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 (ReadMemory read_mem_callback)
|
|
|
|
|
{
|
|
|
|
|
m_read_mem_callback = read_mem_callback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
EmulateInstruction::SetWriteMemCallback (WriteMemory write_mem_callback)
|
|
|
|
|
{
|
|
|
|
|
m_write_mem_callback = write_mem_callback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
EmulateInstruction::SetReadRegCallback (ReadRegister read_reg_callback)
|
|
|
|
|
{
|
|
|
|
|
m_read_reg_callback = read_reg_callback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
EmulateInstruction::SetWriteRegCallback (WriteRegister write_reg_callback)
|
|
|
|
|
{
|
|
|
|
|
m_write_reg_callback = write_reg_callback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Read & Write Memory and Registers callback functions.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
size_t
|
2011-04-05 20:18:48 +00:00
|
|
|
EmulateInstruction::ReadMemoryFrame (void *baton,
|
|
|
|
|
const Context &context,
|
|
|
|
|
lldb::addr_t addr,
|
|
|
|
|
void *dst,
|
|
|
|
|
size_t length)
|
2011-04-05 18:46:00 +00:00
|
|
|
{
|
2011-04-05 20:18:48 +00:00
|
|
|
if (!baton)
|
2011-04-05 18:46:00 +00:00
|
|
|
return 0;
|
|
|
|
|
|
2011-04-05 20:18:48 +00:00
|
|
|
|
|
|
|
|
StackFrame *frame = (StackFrame *) baton;
|
|
|
|
|
|
2011-04-05 18:46:00 +00:00
|
|
|
DataBufferSP data_sp (new DataBufferHeap (length, '\0'));
|
|
|
|
|
Error error;
|
|
|
|
|
|
2011-04-05 20:18:48 +00:00
|
|
|
size_t bytes_read = frame->GetThread().GetProcess().ReadMemory (addr, data_sp->GetBytes(), data_sp->GetByteSize(),
|
|
|
|
|
error);
|
2011-04-05 18:46:00 +00:00
|
|
|
|
|
|
|
|
if (bytes_read > 0)
|
|
|
|
|
((DataBufferHeap *) data_sp.get())->CopyData (dst, length);
|
|
|
|
|
|
|
|
|
|
return bytes_read;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t
|
2011-04-05 20:18:48 +00:00
|
|
|
EmulateInstruction::WriteMemoryFrame (void *baton,
|
|
|
|
|
const Context &context,
|
|
|
|
|
lldb::addr_t addr,
|
|
|
|
|
const void *dst,
|
|
|
|
|
size_t length)
|
2011-04-05 18:46:00 +00:00
|
|
|
{
|
2011-04-05 20:18:48 +00:00
|
|
|
if (!baton)
|
2011-04-05 18:46:00 +00:00
|
|
|
return 0;
|
|
|
|
|
|
2011-04-05 20:18:48 +00:00
|
|
|
StackFrame *frame = (StackFrame *) baton;
|
|
|
|
|
|
2011-04-05 18:46:00 +00:00
|
|
|
lldb::DataBufferSP data_sp (new DataBufferHeap (dst, length));
|
|
|
|
|
if (data_sp)
|
|
|
|
|
{
|
|
|
|
|
length = data_sp->GetByteSize();
|
|
|
|
|
if (length > 0)
|
|
|
|
|
{
|
|
|
|
|
Error error;
|
2011-04-05 20:18:48 +00:00
|
|
|
size_t bytes_written = frame->GetThread().GetProcess().WriteMemory (addr, data_sp->GetBytes(), length,
|
|
|
|
|
error);
|
2011-04-05 18:46:00 +00:00
|
|
|
|
|
|
|
|
return bytes_written;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
2011-04-05 20:18:48 +00:00
|
|
|
EmulateInstruction::ReadRegisterFrame (void *baton,
|
|
|
|
|
uint32_t reg_kind,
|
|
|
|
|
uint32_t reg_num,
|
|
|
|
|
uint64_t ®_value)
|
2011-04-05 18:46:00 +00:00
|
|
|
{
|
2011-04-05 20:18:48 +00:00
|
|
|
if (!baton)
|
2011-04-05 18:46:00 +00:00
|
|
|
return false;
|
|
|
|
|
|
2011-04-05 20:18:48 +00:00
|
|
|
StackFrame *frame = (StackFrame *) baton;
|
|
|
|
|
RegisterContext *reg_context = frame->GetRegisterContext().get();
|
2011-04-05 18:46:00 +00:00
|
|
|
Scalar value;
|
|
|
|
|
|
2011-04-06 23:30:18 +00:00
|
|
|
uint32_t internal_reg_num = reg_context->ConvertRegisterKindToRegisterNumber (reg_kind, reg_num);
|
2011-04-05 18:46:00 +00:00
|
|
|
|
2011-04-06 23:30:18 +00:00
|
|
|
if (internal_reg_num == LLDB_INVALID_REGNUM)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (reg_context->ReadRegisterValue (internal_reg_num, value))
|
2011-04-05 18:46:00 +00:00
|
|
|
{
|
|
|
|
|
reg_value = value.GetRawBits64 (0);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
2011-04-05 20:18:48 +00:00
|
|
|
EmulateInstruction::WriteRegisterFrame (void *baton,
|
|
|
|
|
const Context &context,
|
|
|
|
|
uint32_t reg_kind,
|
|
|
|
|
uint32_t reg_num,
|
|
|
|
|
uint64_t reg_value)
|
2011-04-05 18:46:00 +00:00
|
|
|
{
|
2011-04-05 20:18:48 +00:00
|
|
|
if (!baton)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
StackFrame *frame = (StackFrame *) baton;
|
|
|
|
|
RegisterContext *reg_context = frame->GetRegisterContext().get();
|
2011-04-05 18:46:00 +00:00
|
|
|
Scalar value (reg_value);
|
|
|
|
|
|
2011-04-06 23:30:18 +00:00
|
|
|
uint32_t internal_reg_num = reg_context->ConvertRegisterKindToRegisterNumber (reg_kind, reg_num);
|
|
|
|
|
if (internal_reg_num != LLDB_INVALID_REGNUM)
|
|
|
|
|
return reg_context->WriteRegisterValue (internal_reg_num, value);
|
|
|
|
|
else
|
|
|
|
|
return false;
|
2011-04-05 18:46:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t
|
|
|
|
|
EmulateInstruction::ReadMemoryDefault (void *baton,
|
|
|
|
|
const Context &context,
|
|
|
|
|
lldb::addr_t addr,
|
|
|
|
|
void *dst,
|
|
|
|
|
size_t length)
|
|
|
|
|
{
|
|
|
|
|
PrintContext ("Read from memory", context);
|
2011-04-07 22:46:35 +00:00
|
|
|
fprintf (stdout, " Read from Memory (address = %p, length = %d)\n",(void *) addr, (uint32_t) length);
|
2011-04-05 18:46:00 +00:00
|
|
|
|
|
|
|
|
*((uint64_t *) dst) = 0xdeadbeef;
|
|
|
|
|
return length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t
|
|
|
|
|
EmulateInstruction::WriteMemoryDefault (void *baton,
|
|
|
|
|
const Context &context,
|
|
|
|
|
lldb::addr_t addr,
|
|
|
|
|
const void *dst,
|
|
|
|
|
size_t length)
|
|
|
|
|
{
|
|
|
|
|
PrintContext ("Write to memory", context);
|
2011-04-07 22:46:35 +00:00
|
|
|
fprintf (stdout, " Write to Memory (address = %p, length = %d)\n", (void *) addr, (uint32_t) length);
|
2011-04-05 18:46:00 +00:00
|
|
|
return length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
EmulateInstruction::ReadRegisterDefault (void *baton,
|
|
|
|
|
uint32_t reg_kind,
|
|
|
|
|
uint32_t reg_num,
|
|
|
|
|
uint64_t ®_value)
|
|
|
|
|
{
|
|
|
|
|
std::string reg_name;
|
|
|
|
|
TranslateRegister (reg_kind, reg_num, reg_name);
|
|
|
|
|
fprintf (stdout, " Read Register (%s)\n", reg_name.c_str());
|
|
|
|
|
|
|
|
|
|
reg_value = 24;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
EmulateInstruction::WriteRegisterDefault (void *baton,
|
|
|
|
|
const Context &context,
|
|
|
|
|
uint32_t reg_kind,
|
|
|
|
|
uint32_t reg_num,
|
|
|
|
|
uint64_t reg_value)
|
|
|
|
|
{
|
|
|
|
|
PrintContext ("Write to register", context);
|
|
|
|
|
std::string reg_name;
|
|
|
|
|
TranslateRegister (reg_kind, reg_num, reg_name);
|
|
|
|
|
fprintf (stdout, " Write to Register (%s), value = 0x%llx\n", reg_name.c_str(), reg_value);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
EmulateInstruction::PrintContext (const char *context_type, const Context &context)
|
|
|
|
|
{
|
|
|
|
|
switch (context.type)
|
|
|
|
|
{
|
|
|
|
|
case eContextReadOpcode:
|
|
|
|
|
fprintf (stdout, " %s context: Reading an Opcode\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eContextImmediate:
|
|
|
|
|
fprintf (stdout, " %s context: Immediate\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eContextPushRegisterOnStack:
|
|
|
|
|
fprintf (stdout, " %s context: Pushing a register onto the stack.\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eContextPopRegisterOffStack:
|
|
|
|
|
fprintf (stdout, " %s context: Popping a register off the stack.\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eContextAdjustStackPointer:
|
|
|
|
|
fprintf (stdout, " %s context: Adjusting the stack pointer.\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eContextAdjustBaseRegister:
|
|
|
|
|
fprintf (stdout, " %s context: Adjusting (writing value back to) a base register.\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eContextRegisterPlusOffset:
|
|
|
|
|
fprintf (stdout, " %s context: Register plus offset\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eContextRegisterStore:
|
|
|
|
|
fprintf (stdout, " %s context: Storing a register.\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eContextRegisterLoad:
|
|
|
|
|
fprintf (stdout, " %s context: Loading a register.\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eContextRelativeBranchImmediate:
|
|
|
|
|
fprintf (stdout, " %s context: Relative branch immediate\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eContextAbsoluteBranchRegister:
|
|
|
|
|
fprintf (stdout, " %s context: Absolute branch register\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eContextSupervisorCall:
|
|
|
|
|
fprintf (stdout, " %s context: Performing a supervisor call.\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eContextTableBranchReadMemory:
|
|
|
|
|
fprintf (stdout, " %s context: Table branch read memory\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eContextWriteRegisterRandomBits:
|
|
|
|
|
fprintf (stdout, " %s context: Write random bits to a register\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eContextWriteMemoryRandomBits:
|
|
|
|
|
fprintf (stdout, " %s context: Write random bits to a memory address\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eContextMultiplication:
|
|
|
|
|
fprintf (stdout, " %s context: Performing a multiplication\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eContextAddition:
|
|
|
|
|
fprintf (stdout, " %s context: Performing an addition\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eContextReturnFromException:
|
|
|
|
|
fprintf (stdout, " %s context: Returning from an exception\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
fprintf (stdout, " %s context: Unrecognized context.\n", context_type);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (context.info_type)
|
|
|
|
|
{
|
|
|
|
|
case eInfoTypeRegisterPlusOffset:
|
|
|
|
|
{
|
|
|
|
|
std::string reg_name;
|
|
|
|
|
TranslateRegister (context.info.RegisterPlusOffset.reg.kind,
|
|
|
|
|
context.info.RegisterPlusOffset.reg.num,
|
|
|
|
|
reg_name);
|
|
|
|
|
fprintf (stdout, " Info type: Register plus offset (%s +/- %lld)\n", reg_name.c_str(),
|
|
|
|
|
context.info.RegisterPlusOffset.signed_offset);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case eInfoTypeRegisterPlusIndirectOffset:
|
|
|
|
|
{
|
|
|
|
|
std::string base_reg_name;
|
|
|
|
|
std::string offset_reg_name;
|
|
|
|
|
TranslateRegister (context.info.RegisterPlusIndirectOffset.base_reg.kind,
|
|
|
|
|
context.info.RegisterPlusIndirectOffset.base_reg.num,
|
|
|
|
|
base_reg_name);
|
|
|
|
|
TranslateRegister (context.info.RegisterPlusIndirectOffset.offset_reg.kind,
|
|
|
|
|
context.info.RegisterPlusIndirectOffset.offset_reg.num,
|
|
|
|
|
offset_reg_name);
|
|
|
|
|
fprintf (stdout, " Info type: Register plus indirect offset (%s +/- %s)\n",
|
|
|
|
|
base_reg_name.c_str(),
|
|
|
|
|
offset_reg_name.c_str());
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case eInfoTypeRegisterToRegisterPlusOffset:
|
|
|
|
|
{
|
|
|
|
|
std::string base_reg_name;
|
|
|
|
|
std::string data_reg_name;
|
|
|
|
|
TranslateRegister (context.info.RegisterToRegisterPlusOffset.base_reg.kind,
|
|
|
|
|
context.info.RegisterToRegisterPlusOffset.base_reg.num,
|
|
|
|
|
base_reg_name);
|
|
|
|
|
TranslateRegister (context.info.RegisterToRegisterPlusOffset.data_reg.kind,
|
|
|
|
|
context.info.RegisterToRegisterPlusOffset.data_reg.num,
|
|
|
|
|
data_reg_name);
|
|
|
|
|
fprintf (stdout, " Info type: Register plus offset (%s +/- %lld) and data register (%s)\n",
|
|
|
|
|
base_reg_name.c_str(), context.info.RegisterToRegisterPlusOffset.offset,
|
|
|
|
|
data_reg_name.c_str());
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case eInfoTypeRegisterToRegisterPlusIndirectOffset:
|
|
|
|
|
{
|
|
|
|
|
std::string base_reg_name;
|
|
|
|
|
std::string offset_reg_name;
|
|
|
|
|
std::string data_reg_name;
|
|
|
|
|
TranslateRegister (context.info.RegisterToRegisterPlusIndirectOffset.base_reg.kind,
|
|
|
|
|
context.info.RegisterToRegisterPlusIndirectOffset.base_reg.num,
|
|
|
|
|
base_reg_name);
|
|
|
|
|
TranslateRegister (context.info.RegisterToRegisterPlusIndirectOffset.offset_reg.kind,
|
|
|
|
|
context.info.RegisterToRegisterPlusIndirectOffset.offset_reg.num,
|
|
|
|
|
offset_reg_name);
|
|
|
|
|
TranslateRegister (context.info.RegisterToRegisterPlusIndirectOffset.data_reg.kind,
|
|
|
|
|
context.info.RegisterToRegisterPlusIndirectOffset.data_reg.num,
|
|
|
|
|
data_reg_name);
|
|
|
|
|
fprintf (stdout, " Info type: Register plus indirect offset (%s +/- %s) and data register (%s)\n",
|
|
|
|
|
base_reg_name.c_str(), offset_reg_name.c_str(), data_reg_name.c_str());
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eInfoTypeRegisterRegisterOperands:
|
|
|
|
|
{
|
|
|
|
|
std::string op1_reg_name;
|
|
|
|
|
std::string op2_reg_name;
|
|
|
|
|
TranslateRegister (context.info.RegisterRegisterOperands.operand1.kind,
|
|
|
|
|
context.info.RegisterRegisterOperands.operand1.num,
|
|
|
|
|
op1_reg_name);
|
|
|
|
|
TranslateRegister (context.info.RegisterRegisterOperands.operand2.kind,
|
|
|
|
|
context.info.RegisterRegisterOperands.operand2.num,
|
|
|
|
|
op2_reg_name);
|
|
|
|
|
fprintf (stdout, " Info type: Register operands for binary op (%s, %s)\n",
|
|
|
|
|
op1_reg_name.c_str(),
|
|
|
|
|
op2_reg_name.c_str());
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case eInfoTypeOffset:
|
|
|
|
|
fprintf (stdout, " Info type: signed offset (%lld)\n", context.info.signed_offset);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eInfoTypeRegister:
|
|
|
|
|
{
|
|
|
|
|
std::string reg_name;
|
|
|
|
|
TranslateRegister (context.info.reg.kind, context.info.reg.num, reg_name);
|
|
|
|
|
fprintf (stdout, " Info type: Register (%s)\n", reg_name.c_str());
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eInfoTypeImmediate:
|
|
|
|
|
fprintf (stdout, " Info type: Immediate (%lld)\n", context.info.immediate);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eInfoTypeImmediateSigned:
|
|
|
|
|
fprintf (stdout, " Info type: Signed immediate (%lld)\n", context.info.signed_immediate);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eInfoTypeAddress:
|
|
|
|
|
fprintf (stdout, " Info type: Address (%p)\n", (void *) context.info.address);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eInfoTypeModeAndImmediate:
|
|
|
|
|
{
|
|
|
|
|
std::string mode_name;
|
|
|
|
|
|
|
|
|
|
if (context.info.ModeAndImmediate.mode == EmulateInstructionARM::eModeARM)
|
|
|
|
|
mode_name = "ARM";
|
|
|
|
|
else if (context.info.ModeAndImmediate.mode == EmulateInstructionARM::eModeThumb)
|
|
|
|
|
mode_name = "Thumb";
|
|
|
|
|
else
|
|
|
|
|
mode_name = "Unknown mode";
|
|
|
|
|
|
|
|
|
|
fprintf (stdout, " Info type: Mode (%s) and immediate (%d)\n", mode_name.c_str(),
|
|
|
|
|
context.info.ModeAndImmediate.data_value);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eInfoTypeModeAndImmediateSigned:
|
|
|
|
|
{
|
|
|
|
|
std::string mode_name;
|
|
|
|
|
|
|
|
|
|
if (context.info.ModeAndImmediateSigned.mode == EmulateInstructionARM::eModeARM)
|
|
|
|
|
mode_name = "ARM";
|
|
|
|
|
else if (context.info.ModeAndImmediateSigned.mode == EmulateInstructionARM::eModeThumb)
|
|
|
|
|
mode_name = "Thumb";
|
|
|
|
|
else
|
|
|
|
|
mode_name = "Unknown mode";
|
|
|
|
|
|
|
|
|
|
fprintf (stdout, " Info type: Mode (%s) and signed immediate (%d)\n", mode_name.c_str(),
|
|
|
|
|
context.info.ModeAndImmediateSigned.signed_data_value);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eInfoTypeMode:
|
|
|
|
|
{
|
|
|
|
|
std::string mode_name;
|
|
|
|
|
|
|
|
|
|
if (context.info.mode == EmulateInstructionARM::eModeARM)
|
|
|
|
|
mode_name = "ARM";
|
|
|
|
|
else if (context.info.mode == EmulateInstructionARM::eModeThumb)
|
|
|
|
|
mode_name = "Thumb";
|
|
|
|
|
else
|
|
|
|
|
mode_name = "Unknown mode";
|
|
|
|
|
|
|
|
|
|
fprintf (stdout, " Info type: Mode (%s)\n", mode_name.c_str());
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eInfoTypeNoArgs:
|
|
|
|
|
fprintf (stdout, " Info type: no arguments\n");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
EmulateInstruction::TranslateRegister (uint32_t kind, uint32_t num, std::string &name)
|
|
|
|
|
{
|
|
|
|
|
if (kind == eRegisterKindDWARF)
|
|
|
|
|
{
|
|
|
|
|
if (num == 13) //dwarf_sp NOTE: This is ARM-SPECIFIC
|
|
|
|
|
name = "sp";
|
|
|
|
|
else if (num == 14) //dwarf_lr NOTE: This is ARM-SPECIFIC
|
|
|
|
|
name = "lr";
|
|
|
|
|
else if (num == 15) //dwarf_pc NOTE: This is ARM-SPECIFIC
|
|
|
|
|
name = "pc";
|
|
|
|
|
else if (num == 16) //dwarf_cpsr NOTE: This is ARM-SPECIFIC
|
|
|
|
|
name = "cpsr";
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
StreamString sstr;
|
|
|
|
|
|
|
|
|
|
sstr.Printf ("r%d", num);
|
|
|
|
|
name = sstr.GetData();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (kind == eRegisterKindGeneric)
|
|
|
|
|
{
|
|
|
|
|
if (num == LLDB_REGNUM_GENERIC_SP)
|
|
|
|
|
name = "sp";
|
|
|
|
|
else if (num == LLDB_REGNUM_GENERIC_FLAGS)
|
|
|
|
|
name = "cpsr";
|
|
|
|
|
else if (num == LLDB_REGNUM_GENERIC_PC)
|
|
|
|
|
name = "pc";
|
|
|
|
|
else if (num == LLDB_REGNUM_GENERIC_RA)
|
|
|
|
|
name = "lr";
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
StreamString sstr;
|
|
|
|
|
|
|
|
|
|
sstr.Printf ("r%d", num);
|
|
|
|
|
name = sstr.GetData();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
StreamString sstr;
|
|
|
|
|
|
|
|
|
|
sstr.Printf ("r%d", num);
|
|
|
|
|
name = sstr.GetData();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|