1 //===-- PDBFPOProgramToDWARFExpressionTests.cpp -----------------*- C++ -*-===//
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/Core/StreamBuffer.h"
14 #include "lldb/Expression/DWARFExpression.h"
15 #include "lldb/Utility/ArchSpec.h"
16 #include "lldb/Utility/DataBufferHeap.h"
17 #include "lldb/Utility/DataExtractor.h"
18 #include "lldb/Utility/StreamString.h"
19 
20 using namespace lldb;
21 using namespace lldb_private;
22 using namespace lldb_private::npdb;
23 
24 /// Valid programs tests
25 
26 static void
27 CheckValidProgramTranslation(llvm::StringRef fpo_program,
28                              llvm::StringRef target_register_name,
29                              llvm::StringRef expected_dwarf_expression) {
30   // initial setup
31   ArchSpec arch_spec("i686-pc-windows");
32   llvm::Triple::ArchType arch_type = arch_spec.GetMachine();
33   ByteOrder byte_order = arch_spec.GetByteOrder();
34   uint32_t address_size = arch_spec.GetAddressByteSize();
35   uint32_t byte_size = arch_spec.GetDataByteSize();
36 
37   // program translation
38   StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
39   ASSERT_TRUE(TranslateFPOProgramToDWARFExpression(
40       fpo_program, target_register_name, arch_type, stream));
41 
42   // print dwarf expression to comparable textual representation
43   DataBufferSP buffer =
44       std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
45   DataExtractor extractor(buffer, byte_order, address_size, byte_size);
46 
47   StreamString result_dwarf_expression;
48   ASSERT_TRUE(DWARFExpression::PrintDWARFExpression(
49       result_dwarf_expression, extractor, address_size, 4, false));
50 
51   // actual check
52   ASSERT_STREQ(expected_dwarf_expression.data(),
53                result_dwarf_expression.GetString().data());
54 }
55 
56 TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentConst) {
57   CheckValidProgramTranslation("$T0 0 = ", "$T0", "DW_OP_constu 0x0");
58 }
59 
60 TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentRegisterRef) {
61   CheckValidProgramTranslation("$T0 $ebp = ", "$T0", "DW_OP_breg6 +0");
62 }
63 
64 TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentExpressionPlus) {
65   CheckValidProgramTranslation("$T0 $ebp 4 + = ", "$T0",
66                                "DW_OP_breg6 +0, DW_OP_constu 0x4, DW_OP_plus ");
67 }
68 
69 TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentExpressionDeref) {
70   CheckValidProgramTranslation("$T0 $ebp ^ = ", "$T0",
71                                "DW_OP_breg6 +0, DW_OP_deref ");
72 }
73 
74 TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentExpressionMinus) {
75   CheckValidProgramTranslation(
76       "$T0 $ebp 4 - = ", "$T0",
77       "DW_OP_breg6 +0, DW_OP_constu 0x4, DW_OP_minus ");
78 }
79 
80 TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentExpressionAlign) {
81   CheckValidProgramTranslation("$T0 $ebp 128 @ = ", "$T0",
82                                "DW_OP_breg6 +0, DW_OP_constu 0x80, DW_OP_lit1 "
83                                ", DW_OP_minus , DW_OP_not , DW_OP_and ");
84 }
85 
86 TEST(PDBFPOProgramToDWARFExpressionTests, MultipleIndependentAssignments) {
87   CheckValidProgramTranslation("$T1 1 = $T0 0 =", "$T0", "DW_OP_constu 0x0");
88 }
89 
90 TEST(PDBFPOProgramToDWARFExpressionTests, MultipleDependentAssignments) {
91   CheckValidProgramTranslation(
92       "$T1 $ebp 4 + = $T0 $T1 8 - 128 @ = ", "$T0",
93       "DW_OP_breg6 +0, DW_OP_constu 0x4, DW_OP_plus , DW_OP_constu 0x8, "
94       "DW_OP_minus , DW_OP_constu 0x80, DW_OP_lit1 , DW_OP_minus , DW_OP_not , "
95       "DW_OP_and ");
96 }
97 
98 TEST(PDBFPOProgramToDWARFExpressionTests, DependencyChain) {
99   CheckValidProgramTranslation("$T1 0 = $T0 $T1 = $ebp $T0 =", "$ebp",
100                                "DW_OP_constu 0x0");
101 }
102 
103 /// Invalid programs tests
104 static void
105 CheckInvalidProgramTranslation(llvm::StringRef fpo_program,
106                                llvm::StringRef target_register_name) {
107   // initial setup
108   ArchSpec arch_spec("i686-pc-windows");
109   llvm::Triple::ArchType arch_type = arch_spec.GetMachine();
110   ByteOrder byte_order = arch_spec.GetByteOrder();
111   uint32_t address_size = arch_spec.GetAddressByteSize();
112 
113   // program translation
114   StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
115   EXPECT_FALSE(TranslateFPOProgramToDWARFExpression(
116       fpo_program, target_register_name, arch_type, stream));
117   EXPECT_EQ((size_t)0, stream.GetSize());
118 }
119 
120 TEST(PDBFPOProgramToDWARFExpressionTests, InvalidAssignmentSingle) {
121   CheckInvalidProgramTranslation("$T0 0", "$T0");
122 }
123 
124 TEST(PDBFPOProgramToDWARFExpressionTests, InvalidAssignmentMultiple) {
125   CheckInvalidProgramTranslation("$T1 0 = $T0 0", "$T0");
126 }
127 
128 TEST(PDBFPOProgramToDWARFExpressionTests, UnknownOp) {
129   CheckInvalidProgramTranslation("$T0 $ebp 0 & = ", "$T0");
130 }
131 
132 TEST(PDBFPOProgramToDWARFExpressionTests, InvalidOpBinary) {
133   CheckInvalidProgramTranslation("$T0 0 + = ", "$T0");
134 }
135 
136 TEST(PDBFPOProgramToDWARFExpressionTests, InvalidOpUnary) {
137   CheckInvalidProgramTranslation("$T0 ^ = ", "$T0");
138 }
139 
140 TEST(PDBFPOProgramToDWARFExpressionTests, MissingTargetRegister) {
141   CheckInvalidProgramTranslation("$T1 0 = ", "$T0");
142 }
143 
144 TEST(PDBFPOProgramToDWARFExpressionTests, UnresolvedRegisterReference) {
145   CheckInvalidProgramTranslation("$T0 $abc = ", "$T0");
146 }
147 
148 TEST(PDBFPOProgramToDWARFExpressionTests,
149      UnresolvedRegisterAssignmentReference) {
150   CheckInvalidProgramTranslation("$T2 0 = $T0 $T1 = ", "$T0");
151 }
152 
153 TEST(PDBFPOProgramToDWARFExpressionTests,
154      UnresolvedCyclicRegisterAssignmentReference) {
155   CheckInvalidProgramTranslation("$T1 $T0 = $T0 $T1 = ", "$T0");
156 }
157 
158 TEST(PDBFPOProgramToDWARFExpressionTests,
159      UnresolvedDependentCyclicRegisterAssignmentReference) {
160   CheckInvalidProgramTranslation("$T1 $T0 = $T0 $T1 = $T2 $T1 =", "$T2");
161 }
162 
163 TEST(PDBFPOProgramToDWARFExpressionTests, UnsupportedRASearch) {
164   CheckInvalidProgramTranslation("$T0 .raSearch = ", "$T0");
165 }
166