mirror of
https://github.com/intel/llvm.git
synced 2026-01-13 19:08:21 +08:00
[lldb] Add ValueObject::CreateValueObjectFromScalar and fix Scalar::GetData (#151350)
Add `ValueObject::CreateValueObjectFromScalar` function and adjust `Scalar::GetData` to be able to both extend and truncate the data bytes in Scalar to the specified size.
This commit is contained in:
@@ -84,11 +84,15 @@ public:
|
||||
/// Store the binary representation of this value into the given storage.
|
||||
/// Exactly GetByteSize() bytes will be stored, and the buffer must be large
|
||||
/// enough to hold this data.
|
||||
void GetBytes(uint8_t *storage, size_t length) const;
|
||||
void GetBytes(llvm::MutableArrayRef<uint8_t> storage) const;
|
||||
|
||||
size_t GetByteSize() const;
|
||||
|
||||
bool GetData(DataExtractor &data, size_t limit_byte_size = UINT32_MAX) const;
|
||||
/// Get data with a byte size of GetByteSize().
|
||||
bool GetData(DataExtractor &data) const;
|
||||
/// Get data with a byte size forced to \p result_byte_size.
|
||||
bool GetData(DataExtractor &data, size_t result_byte_size) const;
|
||||
|
||||
size_t GetAsMemoryData(void *dst, size_t dst_len,
|
||||
lldb::ByteOrder dst_byte_order, Status &error) const;
|
||||
|
||||
@@ -737,6 +737,12 @@ public:
|
||||
CreateValueObjectFromAPFloat(lldb::TargetSP target, const llvm::APFloat &v,
|
||||
CompilerType type, llvm::StringRef name);
|
||||
|
||||
/// Create a value object containing the given Scalar value.
|
||||
static lldb::ValueObjectSP CreateValueObjectFromScalar(lldb::TargetSP target,
|
||||
Scalar &s,
|
||||
CompilerType type,
|
||||
llvm::StringRef name);
|
||||
|
||||
/// Create a value object containing the given boolean value.
|
||||
static lldb::ValueObjectSP CreateValueObjectFromBool(lldb::TargetSP target,
|
||||
bool value,
|
||||
|
||||
@@ -60,6 +60,11 @@ public:
|
||||
Value &value, ConstString name,
|
||||
Module *module = nullptr);
|
||||
|
||||
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
|
||||
const CompilerType &compiler_type,
|
||||
Scalar &scalar, ConstString name,
|
||||
Module *module = nullptr);
|
||||
|
||||
// When an expression fails to evaluate, we return an error
|
||||
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
|
||||
Status &&error);
|
||||
@@ -145,6 +150,12 @@ private:
|
||||
ValueObjectManager &manager, const Value &value,
|
||||
ConstString name, Module *module = nullptr);
|
||||
|
||||
ValueObjectConstResult(ExecutionContextScope *exe_scope,
|
||||
ValueObjectManager &manager,
|
||||
const CompilerType &compiler_type,
|
||||
const Scalar &scalar, ConstString name,
|
||||
Module *module = nullptr);
|
||||
|
||||
ValueObjectConstResult(ExecutionContextScope *exe_scope,
|
||||
ValueObjectManager &manager, Status &&error);
|
||||
|
||||
|
||||
@@ -347,15 +347,9 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
|
||||
else
|
||||
data.SetAddressByteSize(sizeof(void *));
|
||||
|
||||
uint32_t limit_byte_size = UINT32_MAX;
|
||||
|
||||
if (type_size)
|
||||
limit_byte_size = *type_size;
|
||||
|
||||
if (limit_byte_size <= m_value.GetByteSize()) {
|
||||
if (m_value.GetData(data, limit_byte_size))
|
||||
return error; // Success;
|
||||
}
|
||||
uint32_t result_byte_size = *type_size;
|
||||
if (m_value.GetData(data, result_byte_size))
|
||||
return error; // Success;
|
||||
|
||||
error = Status::FromErrorString("extracting data from value failed");
|
||||
break;
|
||||
|
||||
@@ -82,7 +82,7 @@ Scalar::Type Scalar::PromoteToMaxType(Scalar &lhs, Scalar &rhs) {
|
||||
return Scalar::e_void;
|
||||
}
|
||||
|
||||
bool Scalar::GetData(DataExtractor &data, size_t limit_byte_size) const {
|
||||
bool Scalar::GetData(DataExtractor &data) const {
|
||||
size_t byte_size = GetByteSize();
|
||||
if (byte_size == 0) {
|
||||
data.Clear();
|
||||
@@ -90,27 +90,57 @@ bool Scalar::GetData(DataExtractor &data, size_t limit_byte_size) const {
|
||||
}
|
||||
auto buffer_up = std::make_unique<DataBufferHeap>(byte_size, 0);
|
||||
GetBytes(buffer_up->GetData());
|
||||
lldb::offset_t offset = 0;
|
||||
|
||||
if (limit_byte_size < byte_size) {
|
||||
if (endian::InlHostByteOrder() == eByteOrderLittle) {
|
||||
// On little endian systems if we want fewer bytes from the current
|
||||
// type we just specify fewer bytes since the LSByte is first...
|
||||
byte_size = limit_byte_size;
|
||||
} else if (endian::InlHostByteOrder() == eByteOrderBig) {
|
||||
// On big endian systems if we want fewer bytes from the current type
|
||||
// have to advance our initial byte pointer and trim down the number of
|
||||
// bytes since the MSByte is first
|
||||
offset = byte_size - limit_byte_size;
|
||||
byte_size = limit_byte_size;
|
||||
}
|
||||
}
|
||||
|
||||
data.SetData(std::move(buffer_up), offset, byte_size);
|
||||
data.SetData(std::move(buffer_up), 0, byte_size);
|
||||
data.SetByteOrder(endian::InlHostByteOrder());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Scalar::GetData(DataExtractor &data, size_t result_byte_size) const {
|
||||
size_t byte_size = GetByteSize();
|
||||
if (byte_size == 0 || result_byte_size == 0) {
|
||||
data.Clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (endian::InlHostByteOrder() == lldb::eByteOrderBig) {
|
||||
// On big endian systems if we want fewer bytes from the current type
|
||||
// we have to advance our initial byte pointer since the MSByte is
|
||||
// first.
|
||||
if (result_byte_size <= byte_size) {
|
||||
auto buffer_up = std::make_unique<DataBufferHeap>(byte_size, 0);
|
||||
GetBytes(buffer_up->GetData());
|
||||
auto offset = byte_size - result_byte_size;
|
||||
data.SetData(std::move(buffer_up), offset, result_byte_size);
|
||||
data.SetByteOrder(endian::InlHostByteOrder());
|
||||
} else {
|
||||
// Extend created buffer size and insert the data bytes with an offset
|
||||
auto buffer_up = std::make_unique<DataBufferHeap>(result_byte_size, 0);
|
||||
auto offset = result_byte_size - byte_size;
|
||||
GetBytes(buffer_up->GetBytes() + offset, byte_size);
|
||||
data.SetData(std::move(buffer_up), 0, result_byte_size);
|
||||
data.SetByteOrder(endian::InlHostByteOrder());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// On little endian systems MSBytes get trimmed or extended automatically by
|
||||
// size.
|
||||
if (byte_size < result_byte_size)
|
||||
byte_size = result_byte_size;
|
||||
auto buffer_up = std::make_unique<DataBufferHeap>(byte_size, 0);
|
||||
GetBytes(buffer_up->GetData());
|
||||
data.SetData(std::move(buffer_up), 0, result_byte_size);
|
||||
data.SetByteOrder(endian::InlHostByteOrder());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Scalar::GetBytes(uint8_t *storage, size_t size) const {
|
||||
assert(size >= GetByteSize());
|
||||
llvm::MutableArrayRef<uint8_t> storage_ref(storage, size);
|
||||
GetBytes(storage_ref);
|
||||
}
|
||||
|
||||
void Scalar::GetBytes(llvm::MutableArrayRef<uint8_t> storage) const {
|
||||
assert(storage.size() >= GetByteSize());
|
||||
|
||||
|
||||
@@ -3590,6 +3590,13 @@ lldb::ValueObjectSP ValueObject::CreateValueObjectFromAPFloat(
|
||||
return CreateValueObjectFromAPInt(target, v.bitcastToAPInt(), type, name);
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP ValueObject::CreateValueObjectFromScalar(
|
||||
lldb::TargetSP target, Scalar &s, CompilerType type, llvm::StringRef name) {
|
||||
ExecutionContext exe_ctx(target.get(), false);
|
||||
return ValueObjectConstResult::Create(exe_ctx.GetBestExecutionContextScope(),
|
||||
type, s, ConstString(name));
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
ValueObject::CreateValueObjectFromBool(lldb::TargetSP target, bool value,
|
||||
llvm::StringRef name) {
|
||||
|
||||
@@ -105,6 +105,16 @@ ValueObjectSP ValueObjectConstResult::Create(ExecutionContextScope *exe_scope,
|
||||
->GetSP();
|
||||
}
|
||||
|
||||
ValueObjectSP ValueObjectConstResult::Create(ExecutionContextScope *exe_scope,
|
||||
const CompilerType &compiler_type,
|
||||
Scalar &scalar, ConstString name,
|
||||
Module *module) {
|
||||
auto manager_sp = ValueObjectManager::Create();
|
||||
return (new ValueObjectConstResult(exe_scope, *manager_sp, compiler_type,
|
||||
scalar, name, module))
|
||||
->GetSP();
|
||||
}
|
||||
|
||||
ValueObjectConstResult::ValueObjectConstResult(
|
||||
ExecutionContextScope *exe_scope, ValueObjectManager &manager,
|
||||
const CompilerType &compiler_type, ConstString name,
|
||||
@@ -193,6 +203,23 @@ ValueObjectConstResult::ValueObjectConstResult(ExecutionContextScope *exe_scope,
|
||||
m_error = m_value.GetValueAsData(&exe_ctx, m_data, module);
|
||||
}
|
||||
|
||||
ValueObjectConstResult::ValueObjectConstResult(
|
||||
ExecutionContextScope *exe_scope, ValueObjectManager &manager,
|
||||
const CompilerType &compiler_type, const Scalar &scalar, ConstString name,
|
||||
Module *module)
|
||||
: ValueObject(exe_scope, manager), m_impl(this) {
|
||||
m_value = Value(scalar);
|
||||
m_value.SetCompilerType(compiler_type);
|
||||
m_value.SetValueType(Value::ValueType::Scalar);
|
||||
m_name = name;
|
||||
ExecutionContext exe_ctx;
|
||||
exe_scope->CalculateExecutionContext(exe_ctx);
|
||||
m_error = m_value.GetValueAsData(&exe_ctx, m_data, module);
|
||||
SetIsConstant();
|
||||
SetValueIsValid(true);
|
||||
SetAddressTypeOfChildren(eAddressTypeLoad);
|
||||
}
|
||||
|
||||
ValueObjectConstResult::~ValueObjectConstResult() = default;
|
||||
|
||||
CompilerType ValueObjectConstResult::GetCompilerTypeImpl() {
|
||||
|
||||
@@ -191,6 +191,24 @@ TEST(ScalarTest, GetData) {
|
||||
EXPECT_THAT(
|
||||
get_data(llvm::APSInt::getMaxValue(/*numBits=*/9, /*Unsigned=*/true)),
|
||||
vec({0x01, 0xff}));
|
||||
|
||||
auto get_data_with_size = [](llvm::APInt v, size_t size) {
|
||||
DataExtractor data;
|
||||
Scalar(v).GetData(data, size);
|
||||
return data.GetData().vec();
|
||||
};
|
||||
|
||||
EXPECT_THAT(get_data_with_size(llvm::APInt(16, 0x0123), 8),
|
||||
vec({0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x23}));
|
||||
|
||||
EXPECT_THAT(get_data_with_size(llvm::APInt(32, 0x01234567), 4),
|
||||
vec({0x01, 0x23, 0x45, 0x67}));
|
||||
|
||||
EXPECT_THAT(get_data_with_size(llvm::APInt(48, 0xABCD01234567UL), 4),
|
||||
vec({0x01, 0x23, 0x45, 0x67}));
|
||||
|
||||
EXPECT_THAT(get_data_with_size(llvm::APInt(64, 0xABCDEF0123456789UL), 2),
|
||||
vec({0x67, 0x89}));
|
||||
}
|
||||
|
||||
TEST(ScalarTest, SetValueFromData) {
|
||||
|
||||
Reference in New Issue
Block a user