While implementing unwind information using UnwindAssemblyInstEmulation I ran
into some cleanup I have been wanting to do when reading/writing registers.
Previously all RegisterContext subclasses would need to implement:
virtual bool
ReadRegisterBytes (uint32_t reg, DataExtractor &data);
virtual bool
WriteRegisterBytes (uint32_t reg, DataExtractor &data, uint32_t data_offset = 0);
There is now a new class specifically designed to hold register values:
lldb_private::RegisterValue
The new register context calls that subclasses must implement are:
virtual bool
ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) = 0;
virtual bool
WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) = 0;
The RegisterValue class must be big enough to handle any register value. The
class contains an enumeration for the value type, and then a union for the
data value. Any integer/float values are stored directly in an appropriate
host integer/float. Anything bigger is stored in a byte buffer that has a length
and byte order. The RegisterValue class also knows how to copy register value
bytes into in a buffer with a specified byte order which can be used to write
the register value down into memory, and this does the right thing when not
all bytes from the register values are needed (getting a uint8 from a uint32
register value..).
All RegiterContext and other sources have been switched over to using the new
regiter value class.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@131096 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Expression/ClangExpressionDeclMap.cpp b/source/Expression/ClangExpressionDeclMap.cpp
index fa69e49..3540a4d 100644
--- a/source/Expression/ClangExpressionDeclMap.cpp
+++ b/source/Expression/ClangExpressionDeclMap.cpp
@@ -20,6 +20,7 @@
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Expression/ASTDumper.h"
#include "lldb/Expression/ClangASTSource.h"
@@ -686,25 +687,25 @@
return false;
}
- RegisterInfo *register_info = location_value->GetRegisterInfo();
+ RegisterInfo *reg_info = location_value->GetRegisterInfo();
- if (!register_info)
+ if (!reg_info)
{
err.SetErrorStringWithFormat("Couldn't get the register information for %s", object_name.GetCString());
return false;
}
- RegisterContext *register_context = exe_ctx.GetRegisterContext();
+ RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
- if (!register_context)
+ if (!reg_ctx)
{
- err.SetErrorStringWithFormat("Couldn't read register context to read %s from %s", object_name.GetCString(), register_info->name);
+ err.SetErrorStringWithFormat("Couldn't read register context to read %s from %s", object_name.GetCString(), reg_info->name);
return false;
}
- uint32_t register_number = register_info->kinds[lldb::eRegisterKindLLDB];
+ uint32_t register_number = reg_info->kinds[lldb::eRegisterKindLLDB];
- object_ptr = register_context->ReadRegisterAsUnsigned(register_number, 0x0);
+ object_ptr = reg_ctx->ReadRegisterAsUnsigned(register_number, 0x0);
return true;
}
@@ -1328,26 +1329,27 @@
return false;
}
- lldb::addr_t mem; // The address of a spare memory area aused to hold the variable.
+ lldb::addr_t reg_addr = LLDB_INVALID_ADDRESS; // The address of a spare memory area aused to hold the variable.
- RegisterInfo *register_info = location_value->GetRegisterInfo();
+ RegisterInfo *reg_info = location_value->GetRegisterInfo();
- if (!register_info)
+ if (!reg_info)
{
err.SetErrorStringWithFormat("Couldn't get the register information for %s", name.GetCString());
return false;
}
-
- RegisterContext *register_context = exe_ctx.GetRegisterContext();
- if (!register_context)
+ RegisterValue reg_value;
+
+ RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
+
+ if (!reg_ctx)
{
- err.SetErrorStringWithFormat("Couldn't read register context to read %s from %s", name.GetCString(), register_info->name);
+ err.SetErrorStringWithFormat("Couldn't read register context to read %s from %s", name.GetCString(), reg_info->name);
return false;
}
- uint32_t register_number = register_info->kinds[lldb::eRegisterKindLLDB];
- uint32_t register_byte_size = register_info->byte_size;
+ uint32_t register_byte_size = reg_info->byte_size;
if (dematerialize)
{
@@ -1365,66 +1367,21 @@
return false;
}
- mem = expr_var->m_live_sp->GetValue().GetScalar().ULongLong();
+ reg_addr = expr_var->m_live_sp->GetValue().GetScalar().ULongLong();
- // Moving from addr into a register
- //
- // Case 1: addr_byte_size and register_byte_size are the same
- //
- // |AABBCCDD| Address contents
- // |AABBCCDD| Register contents
- //
- // Case 2: addr_byte_size is bigger than register_byte_size
- //
- // Error! (The register should always be big enough to hold the data)
- //
- // Case 3: register_byte_size is bigger than addr_byte_size
- //
- // |AABB| Address contents
- // |AABB0000| Register contents [on little-endian hardware]
- // |0000AABB| Register contents [on big-endian hardware]
-
- if (value_byte_size > register_byte_size)
- {
- err.SetErrorStringWithFormat("%s is too big to store in %s", name.GetCString(), register_info->name);
+ err = reg_ctx->ReadRegisterValueFromMemory (reg_info, reg_addr, value_byte_size, reg_value);
+ if (err.Fail())
return false;
- }
-
- uint32_t register_offset;
-
- switch (exe_ctx.process->GetByteOrder())
+
+ if (!reg_ctx->WriteRegister (reg_info, reg_value))
{
- default:
- err.SetErrorStringWithFormat("%s is stored with an unhandled byte order", name.GetCString());
- return false;
- case lldb::eByteOrderLittle:
- register_offset = 0;
- break;
- case lldb::eByteOrderBig:
- register_offset = register_byte_size - value_byte_size;
- break;
- }
-
- DataBufferHeap register_data (register_byte_size, 0);
-
- Error error;
- if (exe_ctx.process->ReadMemory (mem, register_data.GetBytes() + register_offset, value_byte_size, error) != value_byte_size)
- {
- err.SetErrorStringWithFormat ("Couldn't read %s from the target: %s", name.GetCString(), error.AsCString());
- return false;
- }
-
- DataExtractor register_extractor (register_data.GetBytes(), register_byte_size, exe_ctx.process->GetByteOrder(), exe_ctx.process->GetAddressByteSize());
-
- if (!register_context->WriteRegisterBytes(register_number, register_extractor, 0))
- {
- err.SetErrorStringWithFormat("Couldn't read %s from %s", name.GetCString(), register_info->name);
+ err.SetErrorStringWithFormat("Couldn't write %s to register %s", name.GetCString(), reg_info->name);
return false;
}
// Deallocate the spare area and clear the variable's live data.
- Error deallocate_error = exe_ctx.process->DeallocateMemory(mem);
+ Error deallocate_error = exe_ctx.process->DeallocateMemory(reg_addr);
if (!deallocate_error.Success())
{
@@ -1441,11 +1398,11 @@
Error allocate_error;
- mem = exe_ctx.process->AllocateMemory(value_byte_size,
- lldb::ePermissionsReadable | lldb::ePermissionsWritable,
- allocate_error);
+ reg_addr = exe_ctx.process->AllocateMemory (value_byte_size,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ allocate_error);
- if (mem == LLDB_INVALID_ADDRESS)
+ if (reg_addr == LLDB_INVALID_ADDRESS)
{
err.SetErrorStringWithFormat("Couldn't allocate a memory area to store %s: %s", name.GetCString(), allocate_error.AsCString());
return false;
@@ -1457,14 +1414,14 @@
type.GetASTContext(),
type.GetOpaqueQualType(),
name,
- mem,
+ reg_addr,
eAddressTypeLoad,
value_byte_size);
// Now write the location of the area into the struct.
Error write_error;
- if (!WriteAddressInto(exe_ctx, addr, mem, write_error))
+ if (!WriteAddressInto(exe_ctx, addr, reg_addr, write_error))
{
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", name.GetCString(), write_error.AsCString());
return false;
@@ -1489,7 +1446,7 @@
if (value_byte_size > register_byte_size)
{
- err.SetErrorStringWithFormat("%s is too big to store in %s", name.GetCString(), register_info->name);
+ err.SetErrorStringWithFormat("%s is too big to store in %s", name.GetCString(), reg_info->name);
return false;
}
@@ -1507,28 +1464,18 @@
register_offset = register_byte_size - value_byte_size;
break;
}
-
- DataExtractor register_extractor;
-
- if (!register_context->ReadRegisterBytes(register_number, register_extractor))
+
+ RegisterValue reg_value;
+
+ if (!reg_ctx->ReadRegister (reg_info, reg_value))
{
- err.SetErrorStringWithFormat("Couldn't read %s from %s", name.GetCString(), register_info->name);
+ err.SetErrorStringWithFormat("Couldn't read %s from %s", name.GetCString(), reg_info->name);
return false;
}
- const void *register_data = register_extractor.GetData(®ister_offset, value_byte_size);
-
- if (!register_data)
- {
- err.SetErrorStringWithFormat("Read but couldn't extract data for %s from %s", name.GetCString(), register_info->name);
+ err = reg_ctx->WriteRegisterValueToMemory(reg_info, reg_addr, value_byte_size, reg_value);
+ if (err.Fail())
return false;
- }
-
- if (exe_ctx.process->WriteMemory (mem, register_data, value_byte_size, write_error) != value_byte_size)
- {
- err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", write_error.AsCString());
- return false;
- }
}
}
}
@@ -1547,52 +1494,36 @@
Error &err
)
{
- uint32_t register_number = reg_info.kinds[lldb::eRegisterKindLLDB];
uint32_t register_byte_size = reg_info.byte_size;
-
+ RegisterValue reg_value;
if (dematerialize)
{
- DataBufferHeap register_data (register_byte_size, 0);
-
- Error read_error;
- if (exe_ctx.process->ReadMemory (addr, register_data.GetBytes(), register_byte_size, read_error) != register_byte_size)
+ Error read_error (reg_ctx.ReadRegisterValueFromMemory(®_info, addr, register_byte_size, reg_value));
+ if (read_error.Fail())
{
err.SetErrorStringWithFormat ("Couldn't read %s from the target: %s", reg_info.name, read_error.AsCString());
return false;
}
- DataExtractor register_extractor (register_data.GetBytes(), register_byte_size, exe_ctx.process->GetByteOrder(), exe_ctx.process->GetAddressByteSize());
-
- if (!reg_ctx.WriteRegisterBytes(register_number, register_extractor, 0))
+ if (!reg_ctx.WriteRegister (®_info, reg_value))
{
- err.SetErrorStringWithFormat("Couldn't read %s", reg_info.name);
+ err.SetErrorStringWithFormat("Couldn't write register %s (dematerialize)", reg_info.name);
return false;
}
}
else
{
- DataExtractor register_extractor;
- if (!reg_ctx.ReadRegisterBytes(register_number, register_extractor))
+ if (!reg_ctx.ReadRegister(®_info, reg_value))
{
- err.SetErrorStringWithFormat("Couldn't read %s", reg_info.name);
+ err.SetErrorStringWithFormat("Couldn't read %s (materialize)", reg_info.name);
return false;
}
- uint32_t register_offset = 0;
-
- const void *register_data = register_extractor.GetData(®ister_offset, register_byte_size);
-
- if (!register_data)
+ Error write_error (reg_ctx.WriteRegisterValueToMemory(®_info, addr, register_byte_size, reg_value));
+ if (write_error.Fail())
{
- err.SetErrorStringWithFormat("Read but couldn't extract data for %s", reg_info.name);
- return false;
- }
-
- Error error;
- if (exe_ctx.process->WriteMemory (addr, register_data, register_byte_size, error) != register_byte_size)
- {
- err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", error.AsCString());
+ err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", write_error.AsCString());
return false;
}
}