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/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, SingleAssignmentRegisterRef) {
57   CheckValidProgramTranslation("$T0 $ebp = ", "$T0", "DW_OP_breg6 +0");
58 }
59 
60 TEST(PDBFPOProgramToDWARFExpressionTests, MultipleIndependentAssignments) {
61   CheckValidProgramTranslation("$T1 1 = $T0 0 =", "$T0", "DW_OP_consts +0");
62 }
63 
64 TEST(PDBFPOProgramToDWARFExpressionTests, MultipleDependentAssignments) {
65   CheckValidProgramTranslation(
66       "$T1 $ebp 4 + = $T0 $T1 8 - 128 @ = ", "$T0",
67       "DW_OP_breg6 +0, DW_OP_consts +4, DW_OP_plus , DW_OP_consts +8, "
68       "DW_OP_minus , DW_OP_consts +128, DW_OP_lit1 , DW_OP_minus , DW_OP_not , "
69       "DW_OP_and ");
70 }
71 
72 TEST(PDBFPOProgramToDWARFExpressionTests, DependencyChain) {
73   CheckValidProgramTranslation("$T1 0 = $T0 $T1 = $ebp $T0 =", "$ebp",
74                                "DW_OP_consts +0");
75 }
76 
77 /// Invalid programs tests
78 static void
79 CheckInvalidProgramTranslation(llvm::StringRef fpo_program,
80                                llvm::StringRef target_register_name) {
81   // initial setup
82   ArchSpec arch_spec("i686-pc-windows");
83   llvm::Triple::ArchType arch_type = arch_spec.GetMachine();
84   ByteOrder byte_order = arch_spec.GetByteOrder();
85   uint32_t address_size = arch_spec.GetAddressByteSize();
86 
87   // program translation
88   StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
89   EXPECT_FALSE(TranslateFPOProgramToDWARFExpression(
90       fpo_program, target_register_name, arch_type, stream));
91   EXPECT_EQ((size_t)0, stream.GetSize());
92 }
93 
94 TEST(PDBFPOProgramToDWARFExpressionTests, InvalidAssignmentSingle) {
95   CheckInvalidProgramTranslation("$T0 0", "$T0");
96 }
97 
98 TEST(PDBFPOProgramToDWARFExpressionTests, InvalidAssignmentMultiple) {
99   CheckInvalidProgramTranslation("$T1 0 = $T0 0", "$T0");
100 }
101 
102 TEST(PDBFPOProgramToDWARFExpressionTests, UnknownOp) {
103   CheckInvalidProgramTranslation("$T0 $ebp 0 & = ", "$T0");
104 }
105 
106 TEST(PDBFPOProgramToDWARFExpressionTests, InvalidOpBinary) {
107   CheckInvalidProgramTranslation("$T0 0 + = ", "$T0");
108 }
109 
110 TEST(PDBFPOProgramToDWARFExpressionTests, InvalidOpUnary) {
111   CheckInvalidProgramTranslation("$T0 ^ = ", "$T0");
112 }
113 
114 TEST(PDBFPOProgramToDWARFExpressionTests, MissingTargetRegister) {
115   CheckInvalidProgramTranslation("$T1 0 = ", "$T0");
116 }
117 
118 TEST(PDBFPOProgramToDWARFExpressionTests, UnresolvedRegisterReference) {
119   CheckInvalidProgramTranslation("$T0 $abc = ", "$T0");
120 }
121 
122 TEST(PDBFPOProgramToDWARFExpressionTests,
123      UnresolvedRegisterAssignmentReference) {
124   CheckInvalidProgramTranslation("$T2 0 = $T0 $T1 = ", "$T0");
125 }
126 
127 TEST(PDBFPOProgramToDWARFExpressionTests,
128      UnresolvedCyclicRegisterAssignmentReference) {
129   CheckInvalidProgramTranslation("$T1 $T0 = $T0 $T1 = ", "$T0");
130 }
131 
132 TEST(PDBFPOProgramToDWARFExpressionTests,
133      UnresolvedDependentCyclicRegisterAssignmentReference) {
134   CheckInvalidProgramTranslation("$T1 $T0 = $T0 $T1 = $T2 $T1 =", "$T2");
135 }
136 
137 TEST(PDBFPOProgramToDWARFExpressionTests, UnsupportedRASearch) {
138   CheckInvalidProgramTranslation("$T0 .raSearch = ", "$T0");
139 }
140