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