Skip to content

Commit 582d826

Browse files
authored
Merge pull request #605 from adrian-prantl/46262998-5.2
Cherry-pick rdar://problem/46262998
2 parents a38b5b1 + c3120c0 commit 582d826

File tree

2 files changed

+133
-85
lines changed

2 files changed

+133
-85
lines changed

lldb/source/Expression/DWARFExpression.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2320,6 +2320,10 @@ bool DWARFExpression::Evaluate(
23202320
// not available. Fill with zeros for now by resizing the data and
23212321
// appending it
23222322
curr_piece.ResizeData(piece_byte_size);
2323+
// Note that "0" is not a correct value for the unknown bits.
2324+
// It would be better to also return a mask of valid bits together
2325+
// with the expression result, so the debugger can print missing
2326+
// members as "<optimized out>" or something.
23232327
::memset(curr_piece.GetBuffer().GetBytes(), 0, piece_byte_size);
23242328
pieces.AppendDataToHostBuffer(curr_piece);
23252329
} else {
@@ -2377,7 +2381,8 @@ bool DWARFExpression::Evaluate(
23772381
case Value::eValueTypeScalar: {
23782382
uint32_t bit_size = piece_byte_size * 8;
23792383
uint32_t bit_offset = 0;
2380-
if (!curr_piece_source_value.GetScalar().ExtractBitfield(
2384+
Scalar &scalar = curr_piece_source_value.GetScalar();
2385+
if (!scalar.ExtractBitfield(
23812386
bit_size, bit_offset)) {
23822387
if (error_ptr)
23832388
error_ptr->SetErrorStringWithFormat(
@@ -2388,7 +2393,14 @@ bool DWARFExpression::Evaluate(
23882393
.GetByteSize());
23892394
return false;
23902395
}
2391-
curr_piece = curr_piece_source_value;
2396+
// Create curr_piece with bit_size. By default Scalar
2397+
// grows to the nearest host integer type.
2398+
llvm::APInt fail_value(1, 0, false);
2399+
llvm::APInt ap_int = scalar.UInt128(fail_value);
2400+
assert(ap_int.getBitWidth() >= bit_size);
2401+
llvm::ArrayRef<uint64_t> buf{ap_int.getRawData(),
2402+
ap_int.getNumWords()};
2403+
curr_piece.GetScalar() = Scalar(llvm::APInt(bit_size, buf));
23922404
} break;
23932405

23942406
case Value::eValueTypeVector: {
@@ -2410,15 +2422,15 @@ bool DWARFExpression::Evaluate(
24102422
if (op_piece_offset == 0) {
24112423
// This is the first piece, we should push it back onto the stack
24122424
// so subsequent pieces will be able to access this piece and add
2413-
// to it
2425+
// to it.
24142426
if (pieces.AppendDataToHostBuffer(curr_piece) == 0) {
24152427
if (error_ptr)
24162428
error_ptr->SetErrorString("failed to append piece data");
24172429
return false;
24182430
}
24192431
} else {
24202432
// If this is the second or later piece there should be a value on
2421-
// the stack
2433+
// the stack.
24222434
if (pieces.GetBuffer().GetByteSize() != op_piece_offset) {
24232435
if (error_ptr)
24242436
error_ptr->SetErrorStringWithFormat(
@@ -2434,8 +2446,8 @@ bool DWARFExpression::Evaluate(
24342446
return false;
24352447
}
24362448
}
2437-
op_piece_offset += piece_byte_size;
24382449
}
2450+
op_piece_offset += piece_byte_size;
24392451
}
24402452
} break;
24412453

lldb/unittests/Expression/DWARFExpressionTest.cpp

Lines changed: 116 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,38 @@
2222

2323
using namespace lldb_private;
2424

25+
static llvm::Expected<Scalar> Evaluate(llvm::ArrayRef<uint8_t> expr,
26+
lldb::ModuleSP module_sp = {},
27+
DWARFUnit *unit = nullptr) {
28+
DataExtractor extractor(expr.data(), expr.size(), lldb::eByteOrderLittle,
29+
/*addr_size*/ 4);
30+
Value result;
31+
Status status;
32+
if (!DWARFExpression::Evaluate(
33+
/*exe_ctx*/ nullptr, /*reg_ctx*/ nullptr, module_sp, extractor, unit,
34+
lldb::eRegisterKindLLDB,
35+
/*initial_value_ptr*/ nullptr,
36+
/*object_address_ptr*/ nullptr, result, &status))
37+
return status.ToError();
38+
39+
switch (result.GetValueType()) {
40+
case Value::eValueTypeScalar:
41+
return result.GetScalar();
42+
case Value::eValueTypeHostAddress: {
43+
// Convert small buffers to scalars to simplify the tests.
44+
DataBufferHeap &buf = result.GetBuffer();
45+
if (buf.GetByteSize() <= 8) {
46+
uint64_t val = 0;
47+
memcpy(&val, buf.GetBytes(), buf.GetByteSize());
48+
return Scalar(llvm::APInt(buf.GetByteSize()*8, val, false));
49+
}
50+
}
51+
LLVM_FALLTHROUGH;
52+
default:
53+
return status.ToError();
54+
}
55+
}
56+
2557
/// A mock module holding an object file parsed from YAML.
2658
class YAMLModule : public lldb_private::Module {
2759
public:
@@ -99,22 +131,51 @@ class YAMLObjectFile : public lldb_private::ObjectFile {
99131
/// \}
100132
};
101133

102-
static llvm::Expected<Scalar> Evaluate(llvm::ArrayRef<uint8_t> expr,
103-
lldb::ModuleSP module_sp = {},
104-
DWARFUnit *unit = nullptr) {
105-
DataExtractor extractor(expr.data(), expr.size(), lldb::eByteOrderLittle,
106-
/*addr_size*/ 4);
107-
Value result;
108-
Status status;
109-
if (!DWARFExpression::Evaluate(
110-
/*exe_ctx*/ nullptr, /*reg_ctx*/ nullptr, module_sp, extractor, unit,
111-
lldb::eRegisterKindLLDB,
112-
/*initial_value_ptr*/ nullptr,
113-
/*object_address_ptr*/ nullptr, result, &status))
114-
return status.ToError();
134+
/// Helper class that can construct a module from YAML and evaluate
135+
/// DWARF expressions on it.
136+
class YAMLModuleTester {
137+
llvm::StringMap<std::unique_ptr<llvm::MemoryBuffer>> m_sections_map;
138+
lldb::ModuleSP m_module_sp;
139+
lldb::ObjectFileSP m_objfile_sp;
140+
DWARFUnitSP m_dwarf_unit;
141+
std::unique_ptr<SymbolFileDWARF> m_symfile_dwarf;
115142

116-
return result.GetScalar();
117-
}
143+
public:
144+
/// Parse the debug info sections from the YAML description.
145+
YAMLModuleTester(llvm::StringRef yaml_data, llvm::StringRef triple) {
146+
FileSystem::Initialize();
147+
148+
auto sections_map = llvm::DWARFYAML::EmitDebugSections(yaml_data, true);
149+
if (!sections_map)
150+
return;
151+
m_sections_map = std::move(*sections_map);
152+
ArchSpec arch(triple);
153+
m_module_sp = std::make_shared<YAMLModule>(arch);
154+
m_objfile_sp = std::make_shared<YAMLObjectFile>(m_module_sp, m_sections_map);
155+
static_cast<YAMLModule *>(m_module_sp.get())->SetObjectFile(m_objfile_sp);
156+
157+
lldb::user_id_t uid = 0;
158+
llvm::StringRef raw_debug_info = m_sections_map["debug_info"]->getBuffer();
159+
lldb_private::DataExtractor debug_info(
160+
raw_debug_info.data(), raw_debug_info.size(),
161+
m_objfile_sp->GetByteOrder(), m_objfile_sp->GetAddressByteSize());
162+
lldb::offset_t offset_ptr = 0;
163+
m_symfile_dwarf = std::make_unique<SymbolFileDWARF>(m_objfile_sp, nullptr);
164+
llvm::Expected<DWARFUnitSP> dwarf_unit = DWARFUnit::extract(
165+
*m_symfile_dwarf, uid,
166+
*static_cast<lldb_private::DWARFDataExtractor *>(&debug_info),
167+
DIERef::DebugInfo, &offset_ptr);
168+
if (dwarf_unit)
169+
m_dwarf_unit = dwarf_unit.get();
170+
}
171+
~YAMLModuleTester() { FileSystem::Terminate(); }
172+
DWARFUnitSP GetDwarfUnit() { return m_dwarf_unit; }
173+
174+
// Evaluate a raw DWARF expression.
175+
llvm::Expected<Scalar> Eval(llvm::ArrayRef<uint8_t> expr) {
176+
return ::Evaluate(expr, m_module_sp, m_dwarf_unit.get());
177+
}
178+
};
118179

119180
/// Unfortunately Scalar's operator==() is really picky.
120181
static Scalar GetScalar(unsigned bits, uint64_t value, bool sign) {
@@ -226,103 +287,78 @@ TEST(DWARFExpression, DW_OP_convert) {
226287
uint8_t offs_uchar = 0x00000017;
227288
uint8_t offs_schar = 0x0000001a;
228289

229-
//
230-
// Setup. Parse the debug info sections from the YAML description.
231-
//
232-
auto sections_map = llvm::DWARFYAML::EmitDebugSections(yamldata, true);
233-
ASSERT_TRUE((bool)sections_map);
234-
ArchSpec arch("i386-unknown-linux");
235-
FileSystem::Initialize();
236-
auto module_sp = std::make_shared<YAMLModule>(arch);
237-
lldb::ObjectFileSP objfile_sp =
238-
std::make_shared<YAMLObjectFile>(module_sp, *sections_map);
239-
module_sp->SetObjectFile(objfile_sp);
240-
SymbolFileDWARF symfile_dwarf(objfile_sp, nullptr);
241-
242-
lldb::user_id_t uid = 0;
243-
llvm::StringRef raw_debug_info = (*sections_map)["debug_info"]->getBuffer();
244-
lldb_private::DataExtractor debug_info(
245-
raw_debug_info.data(), raw_debug_info.size(), objfile_sp->GetByteOrder(),
246-
objfile_sp->GetAddressByteSize());
247-
lldb::offset_t offset_ptr = 0;
248-
llvm::Expected<DWARFUnitSP> dwarf_unit = DWARFUnit::extract(
249-
symfile_dwarf, uid,
250-
*static_cast<lldb_private::DWARFDataExtractor *>(&debug_info),
251-
DIERef::DebugInfo, &offset_ptr);
252-
ASSERT_TRUE((bool)dwarf_unit);
253-
254-
//
255-
// Actual tests.
256-
//
290+
YAMLModuleTester t(yamldata, "i386-unknown-linux");
291+
ASSERT_TRUE((bool)t.GetDwarfUnit());
257292

258293
// Constant is given as little-endian.
259294
bool is_signed = true;
260295
bool not_signed = false;
261296

297+
//
298+
// Positive tests.
299+
//
300+
262301
// Truncate to default unspecified (pointer-sized) type.
263-
EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const8u, 0x11, 0x22, 0x33, 0x44, 0x55,
264-
0x66, 0x77, 0x88, DW_OP_convert, 0x00},
265-
module_sp, dwarf_unit->get()),
266-
llvm::HasValue(GetScalar(32, 0x44332211, not_signed)));
267-
// Truncate to 32 bits.
268302
EXPECT_THAT_EXPECTED(
269-
Evaluate({DW_OP_const8u, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
270-
DW_OP_convert, offs_uint32_t},
271-
module_sp, dwarf_unit->get()),
303+
t.Eval({DW_OP_const8u, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, //
304+
DW_OP_convert, 0x00}),
272305
llvm::HasValue(GetScalar(32, 0x44332211, not_signed)));
306+
// Truncate to 32 bits.
307+
EXPECT_THAT_EXPECTED(t.Eval({DW_OP_const8u, //
308+
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,//
309+
DW_OP_convert, offs_uint32_t}),
310+
llvm::HasValue(GetScalar(32, 0x44332211, not_signed)));
273311

274312
// Leave as is.
275313
EXPECT_THAT_EXPECTED(
276-
Evaluate({DW_OP_const8u, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
277-
DW_OP_convert, offs_uint64_t},
278-
module_sp, dwarf_unit->get()),
314+
t.Eval({DW_OP_const8u, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, //
315+
DW_OP_convert, offs_uint64_t}),
279316
llvm::HasValue(GetScalar(64, 0x8877665544332211, not_signed)));
280317

281318
// Sign-extend to 64 bits.
282319
EXPECT_THAT_EXPECTED(
283-
Evaluate({DW_OP_const4s, 0xcc, 0xdd, 0xee, 0xff, //
284-
DW_OP_convert, offs_sint64_t},
285-
module_sp, dwarf_unit->get()),
320+
t.Eval({DW_OP_const4s, 0xcc, 0xdd, 0xee, 0xff, //
321+
DW_OP_convert, offs_sint64_t}),
286322
llvm::HasValue(GetScalar(64, 0xffffffffffeeddcc, is_signed)));
287323

288324
// Truncate to 8 bits.
289-
EXPECT_THAT_EXPECTED(
290-
Evaluate({DW_OP_const4s, 'A', 'B', 'C', 'D', 0xee, 0xff, //
291-
DW_OP_convert, offs_uchar},
292-
module_sp, dwarf_unit->get()),
293-
llvm::HasValue(GetScalar(8, 'A', not_signed)));
325+
EXPECT_THAT_EXPECTED(t.Eval({DW_OP_const4s, 'A', 'B', 'C', 'D', 0xee, 0xff, //
326+
DW_OP_convert, offs_uchar}),
327+
llvm::HasValue(GetScalar(8, 'A', not_signed)));
294328

295329
// Also truncate to 8 bits.
296-
EXPECT_THAT_EXPECTED(
297-
Evaluate({DW_OP_const4s, 'A', 'B', 'C', 'D', 0xee, 0xff, //
298-
DW_OP_convert, offs_schar},
299-
module_sp, dwarf_unit->get()),
300-
llvm::HasValue(GetScalar(8, 'A', is_signed)));
330+
EXPECT_THAT_EXPECTED(t.Eval({DW_OP_const4s, 'A', 'B', 'C', 'D', 0xee, 0xff, //
331+
DW_OP_convert, offs_schar}),
332+
llvm::HasValue(GetScalar(8, 'A', is_signed)));
301333

302334
//
303335
// Errors.
304336
//
305337

306338
// No Module.
307339
EXPECT_THAT_ERROR(Evaluate({DW_OP_const1s, 'X', DW_OP_convert, 0x00}, nullptr,
308-
dwarf_unit->get())
340+
t.GetDwarfUnit().get())
309341
.takeError(),
310342
llvm::Failed());
311343

312344
// No DIE.
313-
EXPECT_THAT_ERROR(Evaluate({DW_OP_const1s, 'X', DW_OP_convert, 0x01},
314-
module_sp, dwarf_unit->get())
315-
.takeError(),
316-
llvm::Failed());
345+
EXPECT_THAT_ERROR(
346+
t.Eval({DW_OP_const1s, 'X', DW_OP_convert, 0x01}).takeError(),
347+
llvm::Failed());
317348

318349
// Unsupported.
319-
EXPECT_THAT_ERROR(Evaluate({DW_OP_const1s, 'X', DW_OP_convert, 0x1d}, nullptr,
320-
dwarf_unit->get())
321-
.takeError(),
322-
llvm::Failed());
350+
EXPECT_THAT_ERROR(
351+
t.Eval({DW_OP_const1s, 'X', DW_OP_convert, 0x1d}).takeError(),
352+
llvm::Failed());
353+
}
323354

324-
//
325-
// Tear down.
326-
//
327-
FileSystem::Terminate();
355+
TEST(DWARFExpression, DW_OP_piece) {
356+
EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const2u, 0x11, 0x22, DW_OP_piece, 2,
357+
DW_OP_const2u, 0x33, 0x44, DW_OP_piece, 2}),
358+
llvm::HasValue(GetScalar(32, 0x44332211, true)));
359+
EXPECT_THAT_EXPECTED(
360+
Evaluate({DW_OP_piece, 1, DW_OP_const1u, 0xff, DW_OP_piece, 1}),
361+
// Note that the "00" should really be "undef", but we can't
362+
// represent that yet.
363+
llvm::HasValue(GetScalar(16, 0xff00, true)));
328364
}

0 commit comments

Comments
 (0)