1 //===-- DWARFExpressionTest.cpp -------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Expression/DWARFExpression.h"
10 #include "Plugins/Platform/Linux/PlatformLinux.h"
11 #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
12 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
13 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
14 #include "TestingSupport/Symbol/YAMLModuleTester.h"
15 #include "lldb/Core/Debugger.h"
16 #include "lldb/Core/PluginManager.h"
17 #include "lldb/Core/Value.h"
18 #include "lldb/Core/dwarf.h"
19 #include "lldb/Host/HostInfo.h"
20 #include "lldb/Symbol/ObjectFile.h"
21 #include "lldb/Utility/StreamString.h"
22 #include "llvm/ADT/StringExtras.h"
23 #include "llvm/Testing/Support/Error.h"
24 #include "gtest/gtest.h"
26 using namespace lldb_private
;
27 using namespace lldb_private::dwarf
;
29 static llvm::Expected
<Scalar
> Evaluate(llvm::ArrayRef
<uint8_t> expr
,
30 lldb::ModuleSP module_sp
= {},
31 DWARFUnit
*unit
= nullptr,
32 ExecutionContext
*exe_ctx
= nullptr) {
33 DataExtractor
extractor(expr
.data(), expr
.size(), lldb::eByteOrderLittle
,
37 if (!DWARFExpression::Evaluate(exe_ctx
, /*reg_ctx*/ nullptr, module_sp
,
38 extractor
, unit
, lldb::eRegisterKindLLDB
,
39 /*initial_value_ptr*/ nullptr,
40 /*object_address_ptr*/ nullptr, result
,
42 return status
.ToError();
44 switch (result
.GetValueType()) {
45 case Value::ValueType::Scalar
:
46 return result
.GetScalar();
47 case Value::ValueType::LoadAddress
:
48 return LLDB_INVALID_ADDRESS
;
49 case Value::ValueType::HostAddress
: {
50 // Convert small buffers to scalars to simplify the tests.
51 DataBufferHeap
&buf
= result
.GetBuffer();
52 if (buf
.GetByteSize() <= 8) {
54 memcpy(&val
, buf
.GetBytes(), buf
.GetByteSize());
55 return Scalar(llvm::APInt(buf
.GetByteSize()*8, val
, false));
60 return status
.ToError();
64 class DWARFExpressionTester
: public YAMLModuleTester
{
66 DWARFExpressionTester(llvm::StringRef yaml_data
, size_t cu_index
) :
67 YAMLModuleTester(yaml_data
, cu_index
) {}
69 using YAMLModuleTester::YAMLModuleTester
;
70 llvm::Expected
<Scalar
> Eval(llvm::ArrayRef
<uint8_t> expr
) {
71 return ::Evaluate(expr
, m_module_sp
, m_dwarf_unit
);
75 /// Unfortunately Scalar's operator==() is really picky.
76 static Scalar
GetScalar(unsigned bits
, uint64_t value
, bool sign
) {
78 scalar
.TruncOrExtendTo(bits
, sign
);
82 /// This is needed for the tests that use a mock process.
83 class DWARFExpressionMockProcessTest
: public ::testing::Test
{
85 void SetUp() override
{
86 FileSystem::Initialize();
87 HostInfo::Initialize();
88 platform_linux::PlatformLinux::Initialize();
90 void TearDown() override
{
91 platform_linux::PlatformLinux::Terminate();
92 HostInfo::Terminate();
93 FileSystem::Terminate();
97 TEST(DWARFExpression
, DW_OP_pick
) {
98 EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit1
, DW_OP_lit0
, DW_OP_pick
, 0}),
100 EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit1
, DW_OP_lit0
, DW_OP_pick
, 1}),
102 EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit1
, DW_OP_lit0
, DW_OP_pick
, 2}),
106 TEST(DWARFExpression
, DW_OP_const
) {
107 // Extend to address size.
108 EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const1u
, 0x88}), llvm::HasValue(0x88));
109 EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const1s
, 0x88}),
110 llvm::HasValue(0xffffff88));
111 EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const2u
, 0x47, 0x88}),
112 llvm::HasValue(0x8847));
113 EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const2s
, 0x47, 0x88}),
114 llvm::HasValue(0xffff8847));
115 EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const4u
, 0x44, 0x42, 0x47, 0x88}),
116 llvm::HasValue(0x88474244));
117 EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const4s
, 0x44, 0x42, 0x47, 0x88}),
118 llvm::HasValue(0x88474244));
120 // Truncate to address size.
121 EXPECT_THAT_EXPECTED(
122 Evaluate({DW_OP_const8u
, 0x00, 0x11, 0x22, 0x33, 0x44, 0x42, 0x47, 0x88}),
123 llvm::HasValue(0x33221100));
124 EXPECT_THAT_EXPECTED(
125 Evaluate({DW_OP_const8s
, 0x00, 0x11, 0x22, 0x33, 0x44, 0x42, 0x47, 0x88}),
126 llvm::HasValue(0x33221100));
128 // Don't truncate to address size for compatibility with clang (pr48087).
129 EXPECT_THAT_EXPECTED(
130 Evaluate({DW_OP_constu
, 0x81, 0x82, 0x84, 0x88, 0x90, 0xa0, 0x40}),
131 llvm::HasValue(0x01010101010101));
132 EXPECT_THAT_EXPECTED(
133 Evaluate({DW_OP_consts
, 0x81, 0x82, 0x84, 0x88, 0x90, 0xa0, 0x40}),
134 llvm::HasValue(0xffff010101010101));
137 TEST(DWARFExpression
, DW_OP_skip
) {
138 EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const1u
, 0x42, DW_OP_skip
, 0x02, 0x00,
139 DW_OP_const1u
, 0xff}),
140 llvm::HasValue(0x42));
143 TEST(DWARFExpression
, DW_OP_bra
) {
144 EXPECT_THAT_EXPECTED(
147 DW_OP_const1u
, 0x42, // push 0x42
148 DW_OP_const1u
, 0x1, // push 0x1
149 DW_OP_bra
, 0x02, 0x00, // if 0x1 > 0, then skip 0x0002 opcodes
150 DW_OP_const1u
, 0xff, // push 0xff
153 llvm::HasValue(0x42));
156 TEST(DWARFExpression
, DW_OP_convert
) {
157 /// Auxiliary debug info.
158 const char *yamldata
= R
"(
169 Tag: DW_TAG_compile_unit
170 Children: DW_CHILDREN_yes
172 - Attribute: DW_AT_language
175 Tag: DW_TAG_base_type
176 Children: DW_CHILDREN_no
178 - Attribute: DW_AT_encoding
180 - Attribute: DW_AT_byte_size
188 - AbbrCode: 0x00000001
190 - Value: 0x000000000000000C
191 - AbbrCode: 0x00000000
197 - AbbrCode: 0x00000001
199 - Value: 0x000000000000000C
201 - AbbrCode: 0x00000002
203 - Value: 0x0000000000000007 # DW_ATE_unsigned
204 - Value: 0x0000000000000004
206 - AbbrCode: 0x00000002
208 - Value: 0x0000000000000007 # DW_ATE_unsigned
209 - Value: 0x0000000000000008
211 - AbbrCode: 0x00000002
213 - Value: 0x0000000000000005 # DW_ATE_signed
214 - Value: 0x0000000000000008
216 - AbbrCode: 0x00000002
218 - Value: 0x0000000000000008 # DW_ATE_unsigned_char
219 - Value: 0x0000000000000001
221 - AbbrCode: 0x00000002
223 - Value: 0x0000000000000006 # DW_ATE_signed_char
224 - Value: 0x0000000000000001
226 - AbbrCode: 0x00000002
228 - Value: 0x000000000000000b # DW_ATE_numeric_string
229 - Value: 0x0000000000000001
230 - AbbrCode: 0x00000000
233 // Compile unit relative offsets to each DW_TAG_base_type
234 uint8_t offs_uint32_t
= 0x0000000e;
235 uint8_t offs_uint64_t
= 0x00000011;
236 uint8_t offs_sint64_t
= 0x00000014;
237 uint8_t offs_uchar
= 0x00000017;
238 uint8_t offs_schar
= 0x0000001a;
240 DWARFExpressionTester
t(yamldata
, /*cu_index=*/1);
241 ASSERT_TRUE((bool)t
.GetDwarfUnit());
243 // Constant is given as little-endian.
244 bool is_signed
= true;
245 bool not_signed
= false;
252 EXPECT_THAT_EXPECTED(
253 t
.Eval({DW_OP_const4u
, 0x11, 0x22, 0x33, 0x44, //
254 DW_OP_convert
, offs_uint32_t
, DW_OP_stack_value
}),
255 llvm::HasValue(GetScalar(64, 0x44332211, not_signed
)));
257 // Zero-extend to 64 bits.
258 EXPECT_THAT_EXPECTED(
259 t
.Eval({DW_OP_const4u
, 0x11, 0x22, 0x33, 0x44, //
260 DW_OP_convert
, offs_uint64_t
, DW_OP_stack_value
}),
261 llvm::HasValue(GetScalar(64, 0x44332211, not_signed
)));
263 // Sign-extend to 64 bits.
264 EXPECT_THAT_EXPECTED(
265 t
.Eval({DW_OP_const4s
, 0xcc, 0xdd, 0xee, 0xff, //
266 DW_OP_convert
, offs_sint64_t
, DW_OP_stack_value
}),
267 llvm::HasValue(GetScalar(64, 0xffffffffffeeddcc, is_signed
)));
269 // Sign-extend, then truncate.
270 EXPECT_THAT_EXPECTED(
271 t
.Eval({DW_OP_const4s
, 0xcc, 0xdd, 0xee, 0xff, //
272 DW_OP_convert
, offs_sint64_t
, //
273 DW_OP_convert
, offs_uint32_t
, DW_OP_stack_value
}),
274 llvm::HasValue(GetScalar(32, 0xffeeddcc, not_signed
)));
276 // Truncate to default unspecified (pointer-sized) type.
277 EXPECT_THAT_EXPECTED(t
.Eval({DW_OP_const4s
, 0xcc, 0xdd, 0xee, 0xff, //
278 DW_OP_convert
, offs_sint64_t
, //
279 DW_OP_convert
, 0x00, DW_OP_stack_value
}),
280 llvm::HasValue(GetScalar(32, 0xffeeddcc, not_signed
)));
282 // Truncate to 8 bits.
283 EXPECT_THAT_EXPECTED(t
.Eval({DW_OP_const4s
, 'A', 'B', 'C', 'D', DW_OP_convert
,
284 offs_uchar
, DW_OP_stack_value
}),
285 llvm::HasValue(GetScalar(8, 'A', not_signed
)));
287 // Also truncate to 8 bits.
288 EXPECT_THAT_EXPECTED(t
.Eval({DW_OP_const4s
, 'A', 'B', 'C', 'D', DW_OP_convert
,
289 offs_schar
, DW_OP_stack_value
}),
290 llvm::HasValue(GetScalar(8, 'A', is_signed
)));
297 EXPECT_THAT_ERROR(Evaluate({DW_OP_const1s
, 'X', DW_OP_convert
, 0x00}, nullptr,
304 t
.Eval({DW_OP_const1s
, 'X', DW_OP_convert
, 0x01}).takeError(),
309 t
.Eval({DW_OP_const1s
, 'X', DW_OP_convert
, 0x1d}).takeError(),
313 TEST(DWARFExpression
, DW_OP_stack_value
) {
314 EXPECT_THAT_EXPECTED(Evaluate({DW_OP_stack_value
}), llvm::Failed());
317 TEST(DWARFExpression
, DW_OP_piece
) {
318 EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const2u
, 0x11, 0x22, DW_OP_piece
, 2,
319 DW_OP_const2u
, 0x33, 0x44, DW_OP_piece
, 2}),
320 llvm::HasValue(GetScalar(32, 0x44332211, true)));
321 EXPECT_THAT_EXPECTED(
322 Evaluate({DW_OP_piece
, 1, DW_OP_const1u
, 0xff, DW_OP_piece
, 1}),
323 // Note that the "00" should really be "undef", but we can't
324 // represent that yet.
325 llvm::HasValue(GetScalar(16, 0xff00, true)));
328 TEST(DWARFExpression
, DW_OP_implicit_value
) {
329 unsigned char bytes
= 4;
331 EXPECT_THAT_EXPECTED(
332 Evaluate({DW_OP_implicit_value
, bytes
, 0x11, 0x22, 0x33, 0x44}),
333 llvm::HasValue(GetScalar(8 * bytes
, 0x44332211, true)));
336 TEST(DWARFExpression
, DW_OP_unknown
) {
337 EXPECT_THAT_EXPECTED(
339 llvm::FailedWithMessage(
340 "Unhandled opcode DW_OP_unknown_ff in DWARFExpression"));
343 TEST_F(DWARFExpressionMockProcessTest
, DW_OP_deref
) {
344 EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit0
, DW_OP_deref
}), llvm::Failed());
346 struct MockProcess
: Process
{
347 MockProcess(lldb::TargetSP target_sp
, lldb::ListenerSP listener_sp
)
348 : Process(target_sp
, listener_sp
) {}
350 llvm::StringRef
GetPluginName() override
{ return "mock process"; }
351 bool CanDebug(lldb::TargetSP target
,
352 bool plugin_specified_by_name
) override
{
355 Status
DoDestroy() override
{ return {}; }
356 void RefreshStateAfterStop() override
{}
357 bool DoUpdateThreadList(ThreadList
&old_thread_list
,
358 ThreadList
&new_thread_list
) override
{
361 size_t DoReadMemory(lldb::addr_t vm_addr
, void *buf
, size_t size
,
362 Status
&error
) override
{
363 for (size_t i
= 0; i
< size
; ++i
)
364 ((char *)buf
)[i
] = (vm_addr
+ i
) & 0xff;
370 // Set up a mock process.
371 ArchSpec
arch("i386-pc-linux");
372 Platform::SetHostPlatform(
373 platform_linux::PlatformLinux::CreateInstance(true, &arch
));
374 lldb::DebuggerSP debugger_sp
= Debugger::CreateInstance();
375 ASSERT_TRUE(debugger_sp
);
376 lldb::TargetSP target_sp
;
377 lldb::PlatformSP platform_sp
;
378 debugger_sp
->GetTargetList().CreateTarget(
379 *debugger_sp
, "", arch
, eLoadDependentsNo
, platform_sp
, target_sp
);
380 ASSERT_TRUE(target_sp
);
381 ASSERT_TRUE(target_sp
->GetArchitecture().IsValid());
382 ASSERT_TRUE(platform_sp
);
383 lldb::ListenerSP
listener_sp(Listener::MakeListener("dummy"));
384 lldb::ProcessSP process_sp
=
385 std::make_shared
<MockProcess
>(target_sp
, listener_sp
);
386 ASSERT_TRUE(process_sp
);
388 ExecutionContext
exe_ctx(process_sp
);
389 // Implicit location: *0x4.
390 EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit4
, DW_OP_deref
, DW_OP_stack_value
},
392 llvm::HasValue(GetScalar(32, 0x07060504, false)));
393 // Memory location: *(*0x4).
394 // Evaluate returns LLDB_INVALID_ADDRESS for all load addresses.
395 EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit4
, DW_OP_deref
}, {}, {}, &exe_ctx
),
396 llvm::HasValue(Scalar(LLDB_INVALID_ADDRESS
)));
397 // Memory location: *0x4.
398 // Evaluate returns LLDB_INVALID_ADDRESS for all load addresses.
399 EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit4
}, {}, {}, &exe_ctx
),
400 llvm::HasValue(Scalar(4)));
401 // Implicit location: *0x4.
402 // Evaluate returns LLDB_INVALID_ADDRESS for all load addresses.
403 EXPECT_THAT_EXPECTED(
404 Evaluate({DW_OP_lit4
, DW_OP_deref
, DW_OP_stack_value
}, {}, {}, &exe_ctx
),
405 llvm::HasValue(GetScalar(32, 0x07060504, false)));
408 TEST_F(DWARFExpressionMockProcessTest
, WASM_DW_OP_addr
) {
409 // Set up a wasm target
410 ArchSpec
arch("wasm32-unknown-unknown-wasm");
411 lldb::PlatformSP host_platform_sp
=
412 platform_linux::PlatformLinux::CreateInstance(true, &arch
);
413 ASSERT_TRUE(host_platform_sp
);
414 Platform::SetHostPlatform(host_platform_sp
);
415 lldb::DebuggerSP debugger_sp
= Debugger::CreateInstance();
416 ASSERT_TRUE(debugger_sp
);
417 lldb::TargetSP target_sp
;
418 lldb::PlatformSP platform_sp
;
419 debugger_sp
->GetTargetList().CreateTarget(*debugger_sp
, "", arch
,
420 lldb_private::eLoadDependentsNo
,
421 platform_sp
, target_sp
);
423 ExecutionContext
exe_ctx(target_sp
, false);
424 // DW_OP_addr takes a single operand of address size width:
425 uint8_t expr
[] = {DW_OP_addr
, 0x40, 0x0, 0x0, 0x0};
426 DataExtractor
extractor(expr
, sizeof(expr
), lldb::eByteOrderLittle
,
430 ASSERT_TRUE(DWARFExpression::Evaluate(
431 &exe_ctx
, /*reg_ctx*/ nullptr, /*module_sp*/ {}, extractor
,
432 /*unit*/ nullptr, lldb::eRegisterKindLLDB
,
433 /*initial_value_ptr*/ nullptr,
434 /*object_address_ptr*/ nullptr, result
, &status
))
437 ASSERT_EQ(result
.GetValueType(), Value::ValueType::LoadAddress
);
440 TEST_F(DWARFExpressionMockProcessTest
, WASM_DW_OP_addr_index
) {
441 const char *yamldata
= R
"(
452 Tag: DW_TAG_compile_unit
453 Children: DW_CHILDREN_no
455 - Attribute: DW_AT_addr_base
456 Form: DW_FORM_sec_offset
461 UnitType: DW_UT_compile
463 - AbbrCode: 0x00000001
465 - Value: 0x8 # Offset of the first Address past the header
476 // Can't use DWARFExpressionTester from above because subsystems overlap with
478 SubsystemRAII
<ObjectFileELF
, SymbolFileDWARF
> subsystems
;
479 llvm::Expected
<TestFile
> file
= TestFile::fromYaml(yamldata
);
480 EXPECT_THAT_EXPECTED(file
, llvm::Succeeded());
481 auto module_sp
= std::make_shared
<Module
>(file
->moduleSpec());
482 auto *dwarf_cu
= llvm::cast
<SymbolFileDWARF
>(module_sp
->GetSymbolFile())
485 ASSERT_TRUE(dwarf_cu
);
486 dwarf_cu
->ExtractDIEsIfNeeded();
488 // Set up a wasm target
489 ArchSpec
arch("wasm32-unknown-unknown-wasm");
490 lldb::PlatformSP host_platform_sp
=
491 platform_linux::PlatformLinux::CreateInstance(true, &arch
);
492 ASSERT_TRUE(host_platform_sp
);
493 Platform::SetHostPlatform(host_platform_sp
);
494 lldb::DebuggerSP debugger_sp
= Debugger::CreateInstance();
495 ASSERT_TRUE(debugger_sp
);
496 lldb::TargetSP target_sp
;
497 lldb::PlatformSP platform_sp
;
498 debugger_sp
->GetTargetList().CreateTarget(*debugger_sp
, "", arch
,
499 lldb_private::eLoadDependentsNo
,
500 platform_sp
, target_sp
);
502 ExecutionContext
exe_ctx(target_sp
, false);
503 // DW_OP_addrx takes a single leb128 operand, the index in the addr table:
504 uint8_t expr
[] = {DW_OP_addrx
, 0x01};
505 DataExtractor
extractor(expr
, sizeof(expr
), lldb::eByteOrderLittle
,
509 ASSERT_TRUE(DWARFExpression::Evaluate(
510 &exe_ctx
, /*reg_ctx*/ nullptr, /*module_sp*/ {}, extractor
, dwarf_cu
,
511 lldb::eRegisterKindLLDB
,
512 /*initial_value_ptr*/ nullptr,
513 /*object_address_ptr*/ nullptr, result
, &status
))
516 ASSERT_EQ(result
.GetValueType(), Value::ValueType::LoadAddress
);
517 ASSERT_EQ(result
.GetScalar().UInt(), 0x5678u
);
520 class CustomSymbolFileDWARF
: public SymbolFileDWARF
{
524 using SymbolFileDWARF::SymbolFileDWARF
;
526 bool isA(const void *ClassID
) const override
{
527 return ClassID
== &ID
|| SymbolFile::isA(ClassID
);
529 static bool classof(const SymbolFile
*obj
) { return obj
->isA(&ID
); }
531 static llvm::StringRef
GetPluginNameStatic() { return "custom_dwarf"; }
533 static llvm::StringRef
GetPluginDescriptionStatic() {
534 return "Symbol file reader with expression extensions.";
537 static void Initialize() {
538 PluginManager::RegisterPlugin(GetPluginNameStatic(),
539 GetPluginDescriptionStatic(), CreateInstance
,
540 SymbolFileDWARF::DebuggerInitialize
);
543 static void Terminate() { PluginManager::UnregisterPlugin(CreateInstance
); }
545 static lldb_private::SymbolFile
*
546 CreateInstance(lldb::ObjectFileSP objfile_sp
) {
547 return new CustomSymbolFileDWARF(std::move(objfile_sp
),
548 /*dwo_section_list*/ nullptr);
552 GetVendorDWARFOpcodeSize(const lldb_private::DataExtractor
&data
,
553 const lldb::offset_t data_offset
,
554 const uint8_t op
) const final
{
555 auto offset
= data_offset
;
556 if (op
!= DW_OP_WASM_location
) {
557 return LLDB_INVALID_OFFSET
;
560 // DW_OP_WASM_location WASM_GLOBAL:0x03 index:u32
561 // Called with "arguments" 0x03 and 0x04
563 if (data
.GetU8(&offset
) != /* global */ 0x03) {
564 return LLDB_INVALID_OFFSET
;
568 if (data
.GetU32(&offset
) != 0x04) {
569 return LLDB_INVALID_OFFSET
;
572 // Report the skipped distance:
573 return offset
- data_offset
;
577 ParseVendorDWARFOpcode(uint8_t op
, const lldb_private::DataExtractor
&opcodes
,
578 lldb::offset_t
&offset
,
579 std::vector
<lldb_private::Value
> &stack
) const final
{
580 if (op
!= DW_OP_WASM_location
) {
584 // DW_OP_WASM_location WASM_GLOBAL:0x03 index:u32
585 // Called with "arguments" 0x03 and 0x04
587 if (opcodes
.GetU8(&offset
) != /* global */ 0x03) {
592 if (opcodes
.GetU32(&offset
) != 0x04) {
596 // Return some value:
597 stack
.push_back({GetScalar(32, 42, false)});
602 char CustomSymbolFileDWARF::ID
;
604 static auto testExpressionVendorExtensions(lldb::ModuleSP module_sp
,
605 DWARFUnit
&dwarf_unit
) {
606 // Test that expression extensions can be evaluated, for example
607 // DW_OP_WASM_location which is not currently handled by DWARFExpression:
608 EXPECT_THAT_EXPECTED(Evaluate({DW_OP_WASM_location
, 0x03, // WASM_GLOBAL:0x03
609 0x04, 0x00, 0x00, // index:u32
610 0x00, DW_OP_stack_value
},
611 module_sp
, &dwarf_unit
),
612 llvm::HasValue(GetScalar(32, 42, false)));
614 // Test that searches for opcodes work in the presence of extensions:
615 uint8_t expr
[] = {DW_OP_WASM_location
, 0x03, 0x04, 0x00, 0x00, 0x00,
616 DW_OP_form_tls_address
};
617 DataExtractor
extractor(expr
, sizeof(expr
), lldb::eByteOrderLittle
,
619 DWARFExpression
dwarf_expr(extractor
);
620 ASSERT_TRUE(dwarf_expr
.ContainsThreadLocalStorage(&dwarf_unit
));
623 TEST(DWARFExpression
, Extensions
) {
624 const char *yamldata
= R
"(
635 Tag: DW_TAG_compile_unit
636 Children: DW_CHILDREN_no
645 SubsystemRAII
<FileSystem
, HostInfo
, TypeSystemClang
, ObjectFileELF
,
646 CustomSymbolFileDWARF
>
649 llvm::Expected
<TestFile
> file
= TestFile::fromYaml(yamldata
);
650 EXPECT_THAT_EXPECTED(file
, llvm::Succeeded());
652 auto module_sp
= std::make_shared
<Module
>(file
->moduleSpec());
654 *llvm::cast
<CustomSymbolFileDWARF
>(module_sp
->GetSymbolFile());
655 auto *dwarf_unit
= symfile
.DebugInfo().GetUnitAtIndex(0);
657 testExpressionVendorExtensions(module_sp
, *dwarf_unit
);
660 TEST(DWARFExpression
, ExtensionsDWO
) {
661 const char *skeleton_yamldata
= R
"(
672 Tag: DW_TAG_skeleton_unit
673 Children: DW_CHILDREN_no
675 - Attribute: DW_AT_dwo_name
677 - Attribute: DW_AT_dwo_id
690 // .dwo sections aren't currently supported by dwarfyaml. The dwo_yamldata
691 // contents where generated by roundtripping the following yaml through
692 // yaml2obj | obj2yaml and renaming the sections. This works because the
693 // structure of the .dwo and non-.dwo sections is identical.
702 // debug_abbrev: #.dwo
704 // - Code: 0x00000001
705 // Tag: DW_TAG_compile_unit
706 // Children: DW_CHILDREN_no
708 // - Attribute: DW_AT_dwo_id
709 // Form: DW_FORM_data4
716 // - Value: 0x0120304
718 const char *dwo_yamldata
= R
"(
726 - Name: .debug_abbrev.dwo
729 Content: '0111007506000000'
730 - Name: .debug_info.dwo
733 Content: 0D00000004000000000004010403020100
736 SubsystemRAII
<FileSystem
, HostInfo
, ObjectFileELF
, CustomSymbolFileDWARF
>
739 llvm::Expected
<TestFile
> skeleton_file
=
740 TestFile::fromYaml(skeleton_yamldata
);
741 EXPECT_THAT_EXPECTED(skeleton_file
, llvm::Succeeded());
742 llvm::Expected
<TestFile
> dwo_file
= TestFile::fromYaml(dwo_yamldata
);
743 EXPECT_THAT_EXPECTED(dwo_file
, llvm::Succeeded());
745 auto skeleton_module_sp
=
746 std::make_shared
<Module
>(skeleton_file
->moduleSpec());
747 auto &skeleton_symfile
=
748 *llvm::cast
<CustomSymbolFileDWARF
>(skeleton_module_sp
->GetSymbolFile());
750 auto dwo_module_sp
= std::make_shared
<Module
>(dwo_file
->moduleSpec());
751 SymbolFileDWARFDwo
dwo_symfile(
752 skeleton_symfile
, dwo_module_sp
->GetObjectFile()->shared_from_this(),
754 auto *dwo_dwarf_unit
= dwo_symfile
.DebugInfo().GetUnitAtIndex(0);
756 testExpressionVendorExtensions(dwo_module_sp
, *dwo_dwarf_unit
);