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