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