1//===-- PDBFPOProgramToDWARFExpressionTests.cpp ---------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#include "gtest/gtest.h"
10
11#include "Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h"
12
13#include "lldb/Utility/ArchSpec.h"
14#include "lldb/Utility/DataBufferHeap.h"
15#include "lldb/Utility/DataExtractor.h"
16#include "lldb/Utility/StreamBuffer.h"
17#include "lldb/Utility/StreamString.h"
18#include "llvm/DebugInfo/DIContext.h"
19#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
20#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
21
22using namespace lldb;
23using namespace lldb_private;
24using namespace lldb_private::npdb;
25
26/// Valid programs tests
27
28static void
29CheckValidProgramTranslation(llvm::StringRef fpo_program,
30 llvm::StringRef target_register_name,
31 llvm::StringRef expected_dwarf_expression) {
32 // program translation
33 StreamBuffer<32> stream(Stream::eBinary, 4, eByteOrderLittle);
34 ASSERT_TRUE(TranslateFPOProgramToDWARFExpression(
35 fpo_program, target_register_name, llvm::Triple::x86, stream));
36
37 // print dwarf expression to comparable textual representation
38 llvm::DataExtractor extractor({stream.GetData(), stream.GetSize()},
39 /*IsLittleEndian=*/true, /*AddressSize=*/4);
40
41 std::string result;
42 llvm::raw_string_ostream os(result);
43 llvm::DWARFExpression E(extractor, /*AddressSize=*/4, llvm::dwarf::DWARF32);
44 llvm::printDwarfExpression(E: &E, OS&: os, DumpOpts: llvm::DIDumpOptions(), U: nullptr);
45
46 // actual check
47 ASSERT_EQ(expected_dwarf_expression, result);
48}
49
50TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentRegisterRef) {
51 CheckValidProgramTranslation(fpo_program: "$T0 $ebp = ", target_register_name: "$T0", expected_dwarf_expression: "DW_OP_breg6 +0");
52}
53
54TEST(PDBFPOProgramToDWARFExpressionTests, MultipleIndependentAssignments) {
55 CheckValidProgramTranslation(fpo_program: "$T1 1 = $T0 0 =", target_register_name: "$T0", expected_dwarf_expression: "DW_OP_consts +0");
56}
57
58TEST(PDBFPOProgramToDWARFExpressionTests, MultipleDependentAssignments) {
59 CheckValidProgramTranslation(
60 fpo_program: "$T1 $ebp 4 + = $T0 $T1 8 - 128 @ = ", target_register_name: "$T0",
61 expected_dwarf_expression: "DW_OP_breg6 +0, DW_OP_consts +4, DW_OP_plus, DW_OP_consts +8, "
62 "DW_OP_minus, DW_OP_consts +128, DW_OP_lit1, DW_OP_minus, DW_OP_not, "
63 "DW_OP_and");
64}
65
66TEST(PDBFPOProgramToDWARFExpressionTests, DependencyChain) {
67 CheckValidProgramTranslation(fpo_program: "$T1 0 = $T0 $T1 = $ebp $T0 =", target_register_name: "$ebp",
68 expected_dwarf_expression: "DW_OP_consts +0");
69}
70
71/// Invalid programs tests
72static void
73CheckInvalidProgramTranslation(llvm::StringRef fpo_program,
74 llvm::StringRef target_register_name) {
75 // initial setup
76 ArchSpec arch_spec("i686-pc-windows");
77 llvm::Triple::ArchType arch_type = arch_spec.GetMachine();
78 ByteOrder byte_order = arch_spec.GetByteOrder();
79 uint32_t address_size = arch_spec.GetAddressByteSize();
80
81 // program translation
82 StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
83 EXPECT_FALSE(TranslateFPOProgramToDWARFExpression(
84 fpo_program, target_register_name, arch_type, stream));
85 EXPECT_EQ((size_t)0, stream.GetSize());
86}
87
88TEST(PDBFPOProgramToDWARFExpressionTests, InvalidAssignmentSingle) {
89 CheckInvalidProgramTranslation(fpo_program: "$T0 0", target_register_name: "$T0");
90}
91
92TEST(PDBFPOProgramToDWARFExpressionTests, InvalidAssignmentMultiple) {
93 CheckInvalidProgramTranslation(fpo_program: "$T1 0 = $T0 0", target_register_name: "$T0");
94}
95
96TEST(PDBFPOProgramToDWARFExpressionTests, UnknownOp) {
97 CheckInvalidProgramTranslation(fpo_program: "$T0 $ebp 0 & = ", target_register_name: "$T0");
98}
99
100TEST(PDBFPOProgramToDWARFExpressionTests, InvalidOpBinary) {
101 CheckInvalidProgramTranslation(fpo_program: "$T0 0 + = ", target_register_name: "$T0");
102}
103
104TEST(PDBFPOProgramToDWARFExpressionTests, InvalidOpUnary) {
105 CheckInvalidProgramTranslation(fpo_program: "$T0 ^ = ", target_register_name: "$T0");
106}
107
108TEST(PDBFPOProgramToDWARFExpressionTests, MissingTargetRegister) {
109 CheckInvalidProgramTranslation(fpo_program: "$T1 0 = ", target_register_name: "$T0");
110}
111
112TEST(PDBFPOProgramToDWARFExpressionTests, UnresolvedRegisterReference) {
113 CheckInvalidProgramTranslation(fpo_program: "$T0 $abc = ", target_register_name: "$T0");
114}
115
116TEST(PDBFPOProgramToDWARFExpressionTests,
117 UnresolvedRegisterAssignmentReference) {
118 CheckInvalidProgramTranslation(fpo_program: "$T2 0 = $T0 $T1 = ", target_register_name: "$T0");
119}
120
121TEST(PDBFPOProgramToDWARFExpressionTests,
122 UnresolvedCyclicRegisterAssignmentReference) {
123 CheckInvalidProgramTranslation(fpo_program: "$T1 $T0 = $T0 $T1 = ", target_register_name: "$T0");
124}
125
126TEST(PDBFPOProgramToDWARFExpressionTests,
127 UnresolvedDependentCyclicRegisterAssignmentReference) {
128 CheckInvalidProgramTranslation(fpo_program: "$T1 $T0 = $T0 $T1 = $T2 $T1 =", target_register_name: "$T2");
129}
130
131TEST(PDBFPOProgramToDWARFExpressionTests, UnsupportedRASearch) {
132 CheckInvalidProgramTranslation(fpo_program: "$T0 .raSearch = ", target_register_name: "$T0");
133}
134

source code of lldb/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp