forked from OSchip/llvm-project
Change code for reading emulation data files to read the new file
format. (The newly formatted files will go in as a separate commit in a few minutes). llvm-svn: 129981
This commit is contained in:
parent
22a19816f6
commit
de2fb9cf76
|
@ -22,6 +22,7 @@
|
|||
#include "lldb/Core/EmulateInstruction.h"
|
||||
#include "lldb/Core/Opcode.h"
|
||||
#include "lldb/Core/PluginInterface.h"
|
||||
#include "lldb/Interpreter/NamedOptionValue.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
|
@ -71,6 +72,12 @@ public:
|
|||
virtual void
|
||||
SetDescription (const char *) {}; // May be overridden in sub-classes that have descriptions.
|
||||
|
||||
lldb::OptionValueSP
|
||||
ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type);
|
||||
|
||||
lldb::OptionValueSP
|
||||
ReadDictionary (FILE *in_file, Stream *out_stream);
|
||||
|
||||
bool
|
||||
DumpEmulation (const ArchSpec &arch);
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "lldb/Core/ArchSpec.h"
|
||||
#include "lldb/Core/PluginInterface.h"
|
||||
#include "lldb/Core/Opcode.h"
|
||||
#include "lldb/Interpreter/NamedOptionValue.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/// @class EmulateInstruction EmulateInstruction.h "lldb/Core/EmulateInstruction.h"
|
||||
|
@ -418,7 +419,7 @@ public:
|
|||
EvaluateInstruction () = 0;
|
||||
|
||||
virtual bool
|
||||
TestEmulation (Stream *out_stream, FILE *test_file, ArchSpec &arch) = 0;
|
||||
TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) = 0;
|
||||
|
||||
bool
|
||||
GetAdvancePC () { return m_advance_pc; }
|
||||
|
|
|
@ -109,6 +109,12 @@ namespace lldb_private {
|
|||
OptionValueDictionary *
|
||||
GetAsDictionaryValue();
|
||||
|
||||
const char *
|
||||
GetStringValue ();
|
||||
|
||||
uint64_t
|
||||
GetUInt64Value ();
|
||||
|
||||
protected:
|
||||
bool m_value_was_set; // This can be used to see if a value has been set
|
||||
// by a call to SetValueFromCString(). It is often
|
||||
|
@ -116,6 +122,7 @@ namespace lldb_private {
|
|||
// the command line or as a setting, versus if we
|
||||
// just have the default value that was already
|
||||
// populated in the option value.
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
#include "lldb/Core/EmulateInstruction.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
#include "lldb/Core/RegularExpression.h"
|
||||
#include "lldb/Core/Timer.h"
|
||||
#include "lldb/Interpreter/NamedOptionValue.h"
|
||||
#include "lldb/Symbol/ObjectFile.h"
|
||||
#include "lldb/Target/ExecutionContext.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
|
@ -502,6 +504,187 @@ Instruction::DumpEmulation (const ArchSpec &arch)
|
|||
return false;
|
||||
}
|
||||
|
||||
OptionValueSP
|
||||
Instruction::ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type)
|
||||
{
|
||||
bool done = false;
|
||||
char buffer[1024];
|
||||
|
||||
OptionValueSP option_value_sp (new OptionValueArray (1u << data_type));
|
||||
|
||||
int idx = 0;
|
||||
while (!done)
|
||||
{
|
||||
if (!fgets (buffer, 1023, in_file))
|
||||
{
|
||||
out_stream->Printf ("Instruction::ReadArray: Erroe reading file (fgets).\n");
|
||||
option_value_sp.reset ();
|
||||
return option_value_sp;
|
||||
}
|
||||
|
||||
std::string line (buffer);
|
||||
|
||||
int len = line.size();
|
||||
if (line[len-1] == '\n')
|
||||
{
|
||||
line[len-1] = '\0';
|
||||
line.resize (len-1);
|
||||
}
|
||||
|
||||
if ((line.size() == 1) && line[0] == ']')
|
||||
{
|
||||
done = true;
|
||||
line.clear();
|
||||
}
|
||||
|
||||
if (line.size() > 0)
|
||||
{
|
||||
std::string value;
|
||||
RegularExpression reg_exp ("^[ \t]*([^ \t]+)[ \t]*$");
|
||||
bool reg_exp_success = reg_exp.Execute (line.c_str(), 1);
|
||||
if (reg_exp_success)
|
||||
reg_exp.GetMatchAtIndex (line.c_str(), 1, value);
|
||||
else
|
||||
value = line;
|
||||
|
||||
OptionValueSP data_value_sp;
|
||||
switch (data_type)
|
||||
{
|
||||
case OptionValue::eTypeUInt64:
|
||||
data_value_sp.reset (new OptionValueUInt64 (0, 0));
|
||||
data_value_sp->SetValueFromCString (value.c_str());
|
||||
break;
|
||||
// Other types can be added later as needed.
|
||||
default:
|
||||
data_value_sp.reset (new OptionValueString (value.c_str(), ""));
|
||||
break;
|
||||
}
|
||||
|
||||
option_value_sp->GetAsArrayValue()->InsertValue (idx, data_value_sp);
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
|
||||
return option_value_sp;
|
||||
}
|
||||
|
||||
OptionValueSP
|
||||
Instruction::ReadDictionary (FILE *in_file, Stream *out_stream)
|
||||
{
|
||||
bool done = false;
|
||||
char buffer[1024];
|
||||
|
||||
OptionValueSP option_value_sp (new OptionValueDictionary());
|
||||
static ConstString encoding_key ("data_encoding");
|
||||
OptionValue::Type data_type = OptionValue::eTypeInvalid;
|
||||
|
||||
|
||||
while (!done)
|
||||
{
|
||||
// Read the next line in the file
|
||||
if (!fgets (buffer, 1023, in_file))
|
||||
{
|
||||
out_stream->Printf ("Instruction::ReadDictionary: Error reading file (fgets).\n");
|
||||
option_value_sp.reset ();
|
||||
return option_value_sp;
|
||||
}
|
||||
|
||||
// Check to see if the line contains the end-of-dictionary marker ("}")
|
||||
std::string line (buffer);
|
||||
|
||||
int len = line.size();
|
||||
if (line[len-1] == '\n')
|
||||
{
|
||||
line[len-1] = '\0';
|
||||
line.resize (len-1);
|
||||
}
|
||||
|
||||
if ((line.size() == 1) && (line[0] == '}'))
|
||||
{
|
||||
done = true;
|
||||
line.clear();
|
||||
}
|
||||
|
||||
// Try to find a key-value pair in the current line and add it to the dictionary.
|
||||
if (line.size() > 0)
|
||||
{
|
||||
RegularExpression reg_exp ("^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$");
|
||||
bool reg_exp_success = reg_exp.Execute (line.c_str(), 2);
|
||||
std::string key;
|
||||
std::string value;
|
||||
if (reg_exp_success)
|
||||
{
|
||||
reg_exp.GetMatchAtIndex (line.c_str(), 1, key);
|
||||
reg_exp.GetMatchAtIndex (line.c_str(), 2, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_stream->Printf ("Instruction::ReadDictionary: Failure executing regular expression.\n");
|
||||
option_value_sp.reset();
|
||||
return option_value_sp;
|
||||
}
|
||||
|
||||
ConstString const_key (key.c_str());
|
||||
// Check value to see if it's the start of an array or dictionary.
|
||||
|
||||
lldb::OptionValueSP value_sp;
|
||||
assert (value.empty() == false);
|
||||
assert (key.empty() == false);
|
||||
|
||||
if (value[0] == '{')
|
||||
{
|
||||
assert (value.size() == 1);
|
||||
// value is a dictionary
|
||||
value_sp = ReadDictionary (in_file, out_stream);
|
||||
if (value_sp.get() == NULL)
|
||||
{
|
||||
option_value_sp.reset ();
|
||||
return option_value_sp;
|
||||
}
|
||||
}
|
||||
else if (value[0] == '[')
|
||||
{
|
||||
assert (value.size() == 1);
|
||||
// value is an array
|
||||
value_sp = ReadArray (in_file, out_stream, data_type);
|
||||
if (value_sp.get() == NULL)
|
||||
{
|
||||
option_value_sp.reset ();
|
||||
return option_value_sp;
|
||||
}
|
||||
// We've used the data_type to read an array; re-set the type to Invalid
|
||||
data_type = OptionValue::eTypeInvalid;
|
||||
}
|
||||
else if ((value[0] == '0') && (value[1] == 'x'))
|
||||
{
|
||||
value_sp.reset (new OptionValueUInt64 (0, 0));
|
||||
value_sp->SetValueFromCString (value.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
int len = value.size();
|
||||
if ((value[0] == '"') && (value[len-1] == '"'))
|
||||
value = value.substr (1, len-2);
|
||||
value_sp.reset (new OptionValueString (value.c_str(), ""));
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (const_key == encoding_key)
|
||||
{
|
||||
// A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data indicating the
|
||||
// data type of an upcoming array (usually the next bit of data to be read in).
|
||||
if (strcmp (value.c_str(), "uint32_t") == 0)
|
||||
data_type = OptionValue::eTypeUInt64;
|
||||
}
|
||||
else
|
||||
option_value_sp->GetAsDictionaryValue()->SetValueForKey (const_key, value_sp, false);
|
||||
}
|
||||
}
|
||||
|
||||
return option_value_sp;
|
||||
}
|
||||
|
||||
bool
|
||||
Instruction::TestEmulation (Stream *out_stream, const char *file_name)
|
||||
{
|
||||
|
@ -521,33 +704,63 @@ Instruction::TestEmulation (Stream *out_stream, const char *file_name)
|
|||
return false;
|
||||
}
|
||||
|
||||
ArchSpec arch;
|
||||
char buffer[256];
|
||||
if (!fgets (buffer,255, test_file)) // Read/skip first line of file, which should be a comment line (description).
|
||||
if (!fgets (buffer, 255, test_file))
|
||||
{
|
||||
out_stream->Printf ("Instruction::TestEmulation: Read comment line failed.");
|
||||
fclose (test_file);
|
||||
return false;
|
||||
}
|
||||
SetDescription (buffer);
|
||||
|
||||
if (fscanf (test_file, "%s", buffer) != 1) // Read the arch or arch-triple from the file
|
||||
{
|
||||
out_stream->Printf ("Instruction::TestEmulation: Read arch failed.");
|
||||
out_stream->Printf ("Instruction::TestEmulation: Error reading first line of test file.\n");
|
||||
fclose (test_file);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *cptr = buffer;
|
||||
arch.SetTriple (llvm::Triple (cptr));
|
||||
if (strncmp (buffer, "InstructionEmulationState={", 27) != 0)
|
||||
{
|
||||
out_stream->Printf ("Instructin::TestEmulation: Test file does not contain emulation state dictionary\n");
|
||||
fclose (test_file);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read all the test information from the test file into an OptionValueDictionary.
|
||||
|
||||
OptionValueSP data_dictionary_sp (ReadDictionary (test_file, out_stream));
|
||||
if (data_dictionary_sp.get() == NULL)
|
||||
{
|
||||
out_stream->Printf ("Instruction::TestEmulation: Error reading Dictionary Object.\n");
|
||||
fclose (test_file);
|
||||
return false;
|
||||
}
|
||||
|
||||
fclose (test_file);
|
||||
|
||||
OptionValueDictionary *data_dictionary = data_dictionary_sp->GetAsDictionaryValue();
|
||||
static ConstString description_key ("assembly_string");
|
||||
static ConstString triple_key ("triple");
|
||||
|
||||
OptionValueSP value_sp = data_dictionary->GetValueForKey (description_key);
|
||||
|
||||
if (value_sp.get() == NULL)
|
||||
{
|
||||
out_stream->Printf ("Instruction::TestEmulation: Test file does not contain description string.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
SetDescription (value_sp->GetStringValue());
|
||||
|
||||
|
||||
value_sp = data_dictionary->GetValueForKey (triple_key);
|
||||
if (value_sp.get() == NULL)
|
||||
{
|
||||
out_stream->Printf ("Instruction::TestEmulation: Test file does not contain triple.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ArchSpec arch;
|
||||
arch.SetTriple (llvm::Triple (value_sp->GetStringValue()));
|
||||
|
||||
bool success = false;
|
||||
std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, NULL));
|
||||
if (insn_emulator_ap.get())
|
||||
success = insn_emulator_ap->TestEmulation (out_stream, test_file, arch);
|
||||
success = insn_emulator_ap->TestEmulation (out_stream, arch, data_dictionary);
|
||||
|
||||
fclose (test_file);
|
||||
|
||||
if (success)
|
||||
out_stream->Printf ("Emulation test succeeded.");
|
||||
else
|
||||
|
|
|
@ -102,6 +102,21 @@ OptionValue::GetAsDictionaryValue ()
|
|||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
OptionValue::GetStringValue ()
|
||||
{
|
||||
if (GetType () == OptionValue::eTypeString)
|
||||
return static_cast<OptionValueString *>(this)->GetCurrentValue();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
OptionValue::GetUInt64Value ()
|
||||
{
|
||||
if (GetType () == OptionValue::eTypeUInt64)
|
||||
return static_cast<OptionValueUInt64 *>(this)->GetCurrentValue();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// OptionValueCollection
|
||||
|
|
|
@ -13309,25 +13309,31 @@ EmulateInstructionARM::EvaluateInstruction ()
|
|||
}
|
||||
|
||||
bool
|
||||
EmulateInstructionARM::TestEmulation (Stream *out_stream, FILE *test_file, ArchSpec &arch)
|
||||
EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)
|
||||
{
|
||||
if (!test_file)
|
||||
if (!test_data)
|
||||
{
|
||||
out_stream->Printf ("TestEmulation: Missing test file.\n");
|
||||
out_stream->Printf ("TestEmulation: Missing test data.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
static ConstString opcode_key ("opcode");
|
||||
static ConstString before_key ("before_state");
|
||||
static ConstString after_key ("after_state");
|
||||
|
||||
OptionValueSP value_sp = test_data->GetValueForKey (opcode_key);
|
||||
|
||||
uint32_t test_opcode;
|
||||
if (fscanf (test_file, "%x", &test_opcode) != 1)
|
||||
if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64))
|
||||
{
|
||||
out_stream->Printf ("Test Emulation: Error reading opcode from test file.\n");
|
||||
out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n");
|
||||
return false;
|
||||
}
|
||||
test_opcode = value_sp->GetUInt64Value ();
|
||||
|
||||
char buffer[256];
|
||||
fgets (buffer, 255, test_file); // consume the newline after reading the opcode.
|
||||
|
||||
SetAdvancePC (true);
|
||||
// If the instruction emulation does not directly update the PC, advance the PC to the next instruction after
|
||||
// performing the emulation.
|
||||
SetAdvancePC (true);
|
||||
|
||||
if (arch.GetTriple().getArch() == llvm::Triple::arm)
|
||||
{
|
||||
|
@ -13345,60 +13351,41 @@ EmulateInstructionARM::TestEmulation (Stream *out_stream, FILE *test_file, ArchS
|
|||
}
|
||||
else
|
||||
{
|
||||
out_stream->Printf ("Test Emulation: Invalid arch.\n");
|
||||
out_stream->Printf ("TestEmulation: Invalid arch.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
EmulationStateARM before_state;
|
||||
EmulationStateARM after_state;
|
||||
|
||||
// Read Memory info & load into before_state
|
||||
if (!fgets (buffer, 255, test_file))
|
||||
value_sp = test_data->GetValueForKey (before_key);
|
||||
if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
|
||||
{
|
||||
out_stream->Printf ("Test Emulation: Error attempting to read from test file.\n");
|
||||
out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strncmp (buffer, "Memory-Begin", 12) != 0)
|
||||
|
||||
OptionValueDictionary *state_dictionary = value_sp->GetAsDictionaryValue ();
|
||||
if (!before_state.LoadStateFromDictionary (state_dictionary))
|
||||
{
|
||||
out_stream->Printf ("Test Emulation: Cannot find Memory-Begin in test file.\n");
|
||||
out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool done = false;
|
||||
while (!done)
|
||||
value_sp = test_data->GetValueForKey (after_key);
|
||||
if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
|
||||
{
|
||||
if (fgets (buffer, 255, test_file))
|
||||
{
|
||||
if (strncmp (buffer, "Memory-End", 10) == 0)
|
||||
done = true;
|
||||
else
|
||||
{
|
||||
uint32_t addr;
|
||||
uint32_t value;
|
||||
if (sscanf (buffer, "%x %x", &addr, &value) == 2)
|
||||
before_state.StoreToPseudoAddress ((addr_t) addr, (uint64_t) value, 4);
|
||||
else
|
||||
{
|
||||
out_stream->Printf ("Test Emulation: Error attempting to sscanf address/value pair.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out_stream->Printf ("Test Emulation: Error attemping to read test file.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EmulationStateARM::LoadRegisterStatesFromTestFile (test_file, before_state, after_state))
|
||||
{
|
||||
out_stream->Printf ("Test Emulation: Error occurred while attempting to load the register data.\n");
|
||||
out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
state_dictionary = value_sp->GetAsDictionaryValue ();
|
||||
if (!after_state.LoadStateFromDictionary (state_dictionary))
|
||||
{
|
||||
out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
SetBaton ((void *) &before_state);
|
||||
SetCallbacks (&EmulationStateARM::ReadPseudoMemory,
|
||||
&EmulationStateARM::WritePseudoMemory,
|
||||
|
@ -13408,11 +13395,14 @@ EmulateInstructionARM::TestEmulation (Stream *out_stream, FILE *test_file, ArchS
|
|||
bool success = EvaluateInstruction ();
|
||||
if (!success)
|
||||
{
|
||||
out_stream->Printf ("Test Emulation: EvaluateInstruction() failed.\n");
|
||||
out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
success = before_state.CompareState (after_state);
|
||||
if (!success)
|
||||
out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n");
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "lldb/Core/EmulateInstruction.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Interpreter/NamedOptionValue.h"
|
||||
#include "Plugins/Process/Utility/ARMDefines.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
@ -150,7 +151,7 @@ public:
|
|||
EvaluateInstruction ();
|
||||
|
||||
virtual bool
|
||||
TestEmulation (Stream *out_stream, FILE *test_file, ArchSpec &arch);
|
||||
TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data);
|
||||
|
||||
uint32_t
|
||||
ArchVersion();
|
||||
|
|
|
@ -314,82 +314,6 @@ EmulationStateARM::WritePseudoRegister (void *baton,
|
|||
return pseudo_state->StorePseudoRegisterValue (reg_num, reg_value);
|
||||
}
|
||||
|
||||
bool
|
||||
EmulationStateARM::LoadState (FILE *test_file)
|
||||
{
|
||||
if (!test_file)
|
||||
return false;
|
||||
|
||||
uint32_t num_regs;
|
||||
uint32_t value32;
|
||||
uint64_t value64;
|
||||
|
||||
/* Load general register state */
|
||||
if (fscanf (test_file, "%d", &num_regs) != 1)
|
||||
return false;
|
||||
|
||||
|
||||
for (int i = 0; i < num_regs; ++i)
|
||||
{
|
||||
if (fscanf (test_file, "%x", &value32) == 1)
|
||||
{
|
||||
if (i < 17) // We only have 17 general registers, but if for some reason the file contains more
|
||||
// we need to read them all, to get to the next set of register values.
|
||||
m_gpr[i] = value32;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Load d register state */
|
||||
if (fscanf (test_file, "%d", &num_regs) != 1)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < num_regs; ++i)
|
||||
{
|
||||
if (fscanf (test_file, "%x", &value64) == 1)
|
||||
{
|
||||
if (i < 32)
|
||||
{
|
||||
if (i < 16)
|
||||
m_vfp_regs.sd_regs[i].d_reg = value64;
|
||||
else
|
||||
m_vfp_regs.d_regs[i - 16] = value64;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Load s register state */
|
||||
if (fscanf (test_file, "%d", &num_regs) != 1)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < num_regs; ++i)
|
||||
{
|
||||
if (fscanf (test_file, "%x", &value32) == 1)
|
||||
m_vfp_regs.sd_regs[i / 2].s_reg[i % 2] = value32;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
EmulationStateARM::LoadRegisterStatesFromTestFile (FILE *test_file,
|
||||
EmulationStateARM &before_state,
|
||||
EmulationStateARM &after_state)
|
||||
{
|
||||
if (test_file)
|
||||
{
|
||||
if (before_state.LoadState (test_file))
|
||||
return after_state.LoadState (test_file);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
EmulationStateARM::CompareState (EmulationStateARM &other_state)
|
||||
{
|
||||
|
@ -426,3 +350,93 @@ EmulationStateARM::CompareState (EmulationStateARM &other_state)
|
|||
|
||||
return match;
|
||||
}
|
||||
|
||||
bool
|
||||
EmulationStateARM::LoadStateFromDictionary (OptionValueDictionary *test_data)
|
||||
{
|
||||
static ConstString memory_key ("memory");
|
||||
static ConstString registers_key ("registers");
|
||||
|
||||
if (!test_data)
|
||||
return false;
|
||||
|
||||
OptionValueSP value_sp = test_data->GetValueForKey (memory_key);
|
||||
|
||||
// Load memory, if present.
|
||||
|
||||
if (value_sp.get() != NULL)
|
||||
{
|
||||
static ConstString address_key ("address");
|
||||
static ConstString data_key ("data");
|
||||
uint64_t start_address = 0;
|
||||
|
||||
OptionValueDictionary *mem_dict = value_sp->GetAsDictionaryValue();
|
||||
value_sp = mem_dict->GetValueForKey (address_key);
|
||||
if (value_sp.get() == NULL)
|
||||
return false;
|
||||
else
|
||||
start_address = value_sp->GetUInt64Value ();
|
||||
|
||||
value_sp = mem_dict->GetValueForKey (data_key);
|
||||
OptionValueArray *mem_array = value_sp->GetAsArrayValue();
|
||||
if (!mem_array)
|
||||
return false;
|
||||
|
||||
uint32_t num_elts = mem_array->GetSize();
|
||||
uint32_t address = (uint32_t) start_address;
|
||||
|
||||
for (int i = 0; i < num_elts; ++i)
|
||||
{
|
||||
value_sp = mem_array->GetValueAtIndex (i);
|
||||
if (value_sp.get() == NULL)
|
||||
return false;
|
||||
uint64_t value = value_sp->GetUInt64Value();
|
||||
StoreToPseudoAddress (address, value, 4);
|
||||
address = address + 4;
|
||||
}
|
||||
}
|
||||
|
||||
value_sp = test_data->GetValueForKey (registers_key);
|
||||
if (value_sp.get() == NULL)
|
||||
return false;
|
||||
|
||||
|
||||
// Load General Registers
|
||||
|
||||
OptionValueDictionary *reg_dict = value_sp->GetAsDictionaryValue ();
|
||||
|
||||
StreamString sstr;
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
sstr.Clear();
|
||||
sstr.Printf ("r%d", i);
|
||||
ConstString reg_name (sstr.GetData());
|
||||
value_sp = reg_dict->GetValueForKey (reg_name);
|
||||
if (value_sp.get() == NULL)
|
||||
return false;
|
||||
uint64_t reg_value = value_sp->GetUInt64Value();
|
||||
StorePseudoRegisterValue (dwarf_r0 + i, reg_value);
|
||||
}
|
||||
|
||||
static ConstString cpsr_name ("cpsr");
|
||||
value_sp = reg_dict->GetValueForKey (cpsr_name);
|
||||
if (value_sp.get() == NULL)
|
||||
return false;
|
||||
StorePseudoRegisterValue (dwarf_cpsr, value_sp->GetUInt64Value());
|
||||
|
||||
// Load s/d Registers
|
||||
for (int i = 0; i < 32; ++i)
|
||||
{
|
||||
sstr.Clear();
|
||||
sstr.Printf ("s%d", i);
|
||||
ConstString reg_name (sstr.GetData());
|
||||
value_sp = reg_dict->GetValueForKey (reg_name);
|
||||
if (value_sp.get() == NULL)
|
||||
return false;
|
||||
uint64_t reg_value = value_sp->GetUInt64Value();
|
||||
StorePseudoRegisterValue (dwarf_s0 + i, reg_value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "lldb/Core/EmulateInstruction.h"
|
||||
#include "lldb/Core/Opcode.h"
|
||||
#include "lldb/Interpreter/NamedOptionValue.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
|
@ -47,11 +48,8 @@ public:
|
|||
LoadPseudoRegistersFromFrame (StackFrame &frame);
|
||||
|
||||
bool
|
||||
LoadState (FILE *test_file);
|
||||
|
||||
static bool
|
||||
LoadRegisterStatesFromTestFile (FILE *test_file, EmulationStateARM &before_state, EmulationStateARM &after_state);
|
||||
|
||||
LoadStateFromDictionary (OptionValueDictionary *test_data);
|
||||
|
||||
bool
|
||||
CompareState (EmulationStateARM &other_state);
|
||||
|
||||
|
|
Loading…
Reference in New Issue