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