Skip to content

Commit dace67e

Browse files
authored
[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.
1 parent 49d5dd3 commit dace67e

File tree

8 files changed

+122
-25
lines changed

8 files changed

+122
-25
lines changed

lldb/include/lldb/Utility/Scalar.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,15 @@ class Scalar {
8484
/// Store the binary representation of this value into the given storage.
8585
/// Exactly GetByteSize() bytes will be stored, and the buffer must be large
8686
/// enough to hold this data.
87+
void GetBytes(uint8_t *storage, size_t length) const;
8788
void GetBytes(llvm::MutableArrayRef<uint8_t> storage) const;
8889

8990
size_t GetByteSize() const;
9091

91-
bool GetData(DataExtractor &data, size_t limit_byte_size = UINT32_MAX) const;
92+
/// Get data with a byte size of GetByteSize().
93+
bool GetData(DataExtractor &data) const;
94+
/// Get data with a byte size forced to \p result_byte_size.
95+
bool GetData(DataExtractor &data, size_t result_byte_size) const;
9296

9397
size_t GetAsMemoryData(void *dst, size_t dst_len,
9498
lldb::ByteOrder dst_byte_order, Status &error) const;

lldb/include/lldb/ValueObject/ValueObject.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,12 @@ class ValueObject {
737737
CreateValueObjectFromAPFloat(lldb::TargetSP target, const llvm::APFloat &v,
738738
CompilerType type, llvm::StringRef name);
739739

740+
/// Create a value object containing the given Scalar value.
741+
static lldb::ValueObjectSP CreateValueObjectFromScalar(lldb::TargetSP target,
742+
Scalar &s,
743+
CompilerType type,
744+
llvm::StringRef name);
745+
740746
/// Create a value object containing the given boolean value.
741747
static lldb::ValueObjectSP CreateValueObjectFromBool(lldb::TargetSP target,
742748
bool value,

lldb/include/lldb/ValueObject/ValueObjectConstResult.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ class ValueObjectConstResult : public ValueObject {
6060
Value &value, ConstString name,
6161
Module *module = nullptr);
6262

63+
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
64+
const CompilerType &compiler_type,
65+
Scalar &scalar, ConstString name,
66+
Module *module = nullptr);
67+
6368
// When an expression fails to evaluate, we return an error
6469
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
6570
Status &&error);
@@ -145,6 +150,12 @@ class ValueObjectConstResult : public ValueObject {
145150
ValueObjectManager &manager, const Value &value,
146151
ConstString name, Module *module = nullptr);
147152

153+
ValueObjectConstResult(ExecutionContextScope *exe_scope,
154+
ValueObjectManager &manager,
155+
const CompilerType &compiler_type,
156+
const Scalar &scalar, ConstString name,
157+
Module *module = nullptr);
158+
148159
ValueObjectConstResult(ExecutionContextScope *exe_scope,
149160
ValueObjectManager &manager, Status &&error);
150161

lldb/source/Core/Value.cpp

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -347,15 +347,9 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
347347
else
348348
data.SetAddressByteSize(sizeof(void *));
349349

350-
uint32_t limit_byte_size = UINT32_MAX;
351-
352-
if (type_size)
353-
limit_byte_size = *type_size;
354-
355-
if (limit_byte_size <= m_value.GetByteSize()) {
356-
if (m_value.GetData(data, limit_byte_size))
357-
return error; // Success;
358-
}
350+
uint32_t result_byte_size = *type_size;
351+
if (m_value.GetData(data, result_byte_size))
352+
return error; // Success;
359353

360354
error = Status::FromErrorString("extracting data from value failed");
361355
break;

lldb/source/Utility/Scalar.cpp

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -82,35 +82,65 @@ Scalar::Type Scalar::PromoteToMaxType(Scalar &lhs, Scalar &rhs) {
8282
return Scalar::e_void;
8383
}
8484

85-
bool Scalar::GetData(DataExtractor &data, size_t limit_byte_size) const {
85+
bool Scalar::GetData(DataExtractor &data) const {
8686
size_t byte_size = GetByteSize();
8787
if (byte_size == 0) {
8888
data.Clear();
8989
return false;
9090
}
9191
auto buffer_up = std::make_unique<DataBufferHeap>(byte_size, 0);
9292
GetBytes(buffer_up->GetData());
93-
lldb::offset_t offset = 0;
94-
95-
if (limit_byte_size < byte_size) {
96-
if (endian::InlHostByteOrder() == eByteOrderLittle) {
97-
// On little endian systems if we want fewer bytes from the current
98-
// type we just specify fewer bytes since the LSByte is first...
99-
byte_size = limit_byte_size;
100-
} else if (endian::InlHostByteOrder() == eByteOrderBig) {
101-
// On big endian systems if we want fewer bytes from the current type
102-
// have to advance our initial byte pointer and trim down the number of
103-
// bytes since the MSByte is first
104-
offset = byte_size - limit_byte_size;
105-
byte_size = limit_byte_size;
93+
data.SetData(std::move(buffer_up), 0, byte_size);
94+
data.SetByteOrder(endian::InlHostByteOrder());
95+
return true;
96+
}
97+
98+
bool Scalar::GetData(DataExtractor &data, size_t result_byte_size) const {
99+
size_t byte_size = GetByteSize();
100+
if (byte_size == 0 || result_byte_size == 0) {
101+
data.Clear();
102+
return false;
103+
}
104+
105+
if (endian::InlHostByteOrder() == lldb::eByteOrderBig) {
106+
// On big endian systems if we want fewer bytes from the current type
107+
// we have to advance our initial byte pointer since the MSByte is
108+
// first.
109+
if (result_byte_size <= byte_size) {
110+
auto buffer_up = std::make_unique<DataBufferHeap>(byte_size, 0);
111+
GetBytes(buffer_up->GetData());
112+
auto offset = byte_size - result_byte_size;
113+
data.SetData(std::move(buffer_up), offset, result_byte_size);
114+
data.SetByteOrder(endian::InlHostByteOrder());
115+
} else {
116+
// Extend created buffer size and insert the data bytes with an offset
117+
auto buffer_up = std::make_unique<DataBufferHeap>(result_byte_size, 0);
118+
auto offset = result_byte_size - byte_size;
119+
GetBytes(buffer_up->GetBytes() + offset, byte_size);
120+
data.SetData(std::move(buffer_up), 0, result_byte_size);
121+
data.SetByteOrder(endian::InlHostByteOrder());
106122
}
123+
return true;
107124
}
108125

109-
data.SetData(std::move(buffer_up), offset, byte_size);
126+
// On little endian systems MSBytes get trimmed or extended automatically by
127+
// size.
128+
if (byte_size < result_byte_size)
129+
byte_size = result_byte_size;
130+
auto buffer_up = std::make_unique<DataBufferHeap>(byte_size, 0);
131+
GetBytes(buffer_up->GetData());
132+
data.SetData(std::move(buffer_up), 0, result_byte_size);
110133
data.SetByteOrder(endian::InlHostByteOrder());
134+
111135
return true;
112136
}
113137

138+
void Scalar::GetBytes(uint8_t *storage, size_t size) const {
139+
assert(size >= GetByteSize());
140+
llvm::MutableArrayRef<uint8_t> storage_ref(storage, size);
141+
GetBytes(storage_ref);
142+
}
143+
114144
void Scalar::GetBytes(llvm::MutableArrayRef<uint8_t> storage) const {
115145
assert(storage.size() >= GetByteSize());
116146

lldb/source/ValueObject/ValueObject.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3590,6 +3590,13 @@ lldb::ValueObjectSP ValueObject::CreateValueObjectFromAPFloat(
35903590
return CreateValueObjectFromAPInt(target, v.bitcastToAPInt(), type, name);
35913591
}
35923592

3593+
lldb::ValueObjectSP ValueObject::CreateValueObjectFromScalar(
3594+
lldb::TargetSP target, Scalar &s, CompilerType type, llvm::StringRef name) {
3595+
ExecutionContext exe_ctx(target.get(), false);
3596+
return ValueObjectConstResult::Create(exe_ctx.GetBestExecutionContextScope(),
3597+
type, s, ConstString(name));
3598+
}
3599+
35933600
lldb::ValueObjectSP
35943601
ValueObject::CreateValueObjectFromBool(lldb::TargetSP target, bool value,
35953602
llvm::StringRef name) {

lldb/source/ValueObject/ValueObjectConstResult.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,16 @@ ValueObjectSP ValueObjectConstResult::Create(ExecutionContextScope *exe_scope,
105105
->GetSP();
106106
}
107107

108+
ValueObjectSP ValueObjectConstResult::Create(ExecutionContextScope *exe_scope,
109+
const CompilerType &compiler_type,
110+
Scalar &scalar, ConstString name,
111+
Module *module) {
112+
auto manager_sp = ValueObjectManager::Create();
113+
return (new ValueObjectConstResult(exe_scope, *manager_sp, compiler_type,
114+
scalar, name, module))
115+
->GetSP();
116+
}
117+
108118
ValueObjectConstResult::ValueObjectConstResult(
109119
ExecutionContextScope *exe_scope, ValueObjectManager &manager,
110120
const CompilerType &compiler_type, ConstString name,
@@ -193,6 +203,23 @@ ValueObjectConstResult::ValueObjectConstResult(ExecutionContextScope *exe_scope,
193203
m_error = m_value.GetValueAsData(&exe_ctx, m_data, module);
194204
}
195205

206+
ValueObjectConstResult::ValueObjectConstResult(
207+
ExecutionContextScope *exe_scope, ValueObjectManager &manager,
208+
const CompilerType &compiler_type, const Scalar &scalar, ConstString name,
209+
Module *module)
210+
: ValueObject(exe_scope, manager), m_impl(this) {
211+
m_value = Value(scalar);
212+
m_value.SetCompilerType(compiler_type);
213+
m_value.SetValueType(Value::ValueType::Scalar);
214+
m_name = name;
215+
ExecutionContext exe_ctx;
216+
exe_scope->CalculateExecutionContext(exe_ctx);
217+
m_error = m_value.GetValueAsData(&exe_ctx, m_data, module);
218+
SetIsConstant();
219+
SetValueIsValid(true);
220+
SetAddressTypeOfChildren(eAddressTypeLoad);
221+
}
222+
196223
ValueObjectConstResult::~ValueObjectConstResult() = default;
197224

198225
CompilerType ValueObjectConstResult::GetCompilerTypeImpl() {

lldb/unittests/Utility/ScalarTest.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,24 @@ TEST(ScalarTest, GetData) {
191191
EXPECT_THAT(
192192
get_data(llvm::APSInt::getMaxValue(/*numBits=*/9, /*Unsigned=*/true)),
193193
vec({0x01, 0xff}));
194+
195+
auto get_data_with_size = [](llvm::APInt v, size_t size) {
196+
DataExtractor data;
197+
Scalar(v).GetData(data, size);
198+
return data.GetData().vec();
199+
};
200+
201+
EXPECT_THAT(get_data_with_size(llvm::APInt(16, 0x0123), 8),
202+
vec({0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x23}));
203+
204+
EXPECT_THAT(get_data_with_size(llvm::APInt(32, 0x01234567), 4),
205+
vec({0x01, 0x23, 0x45, 0x67}));
206+
207+
EXPECT_THAT(get_data_with_size(llvm::APInt(48, 0xABCD01234567UL), 4),
208+
vec({0x01, 0x23, 0x45, 0x67}));
209+
210+
EXPECT_THAT(get_data_with_size(llvm::APInt(64, 0xABCDEF0123456789UL), 2),
211+
vec({0x67, 0x89}));
194212
}
195213

196214
TEST(ScalarTest, SetValueFromData) {

0 commit comments

Comments
 (0)