1 //===-- DWARFASTParserClangTests.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 "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h" 10 #include "Plugins/SymbolFile/DWARF/DWARFCompileUnit.h" 11 #include "Plugins/SymbolFile/DWARF/DWARFDIE.h" 12 #include "TestingSupport/Symbol/YAMLModuleTester.h" 13 #include "gmock/gmock.h" 14 #include "gtest/gtest.h" 15 16 using namespace lldb; 17 using namespace lldb_private; 18 19 namespace { 20 class DWARFASTParserClangTests : public testing::Test {}; 21 22 class DWARFASTParserClangStub : public DWARFASTParserClang { 23 public: 24 using DWARFASTParserClang::DWARFASTParserClang; 25 using DWARFASTParserClang::LinkDeclContextToDIE; 26 27 std::vector<const clang::DeclContext *> GetDeclContextToDIEMapKeys() { 28 std::vector<const clang::DeclContext *> keys; 29 for (const auto &it : m_decl_ctx_to_die) 30 keys.push_back(it.first); 31 return keys; 32 } 33 }; 34 } // namespace 35 36 // If your implementation needs to dereference the dummy pointers we are 37 // defining here, causing this test to fail, feel free to delete it. 38 TEST_F(DWARFASTParserClangTests, 39 EnsureAllDIEsInDeclContextHaveBeenParsedParsesOnlyMatchingEntries) { 40 41 /// Auxiliary debug info. 42 const char *yamldata = R"( 43 --- !ELF 44 FileHeader: 45 Class: ELFCLASS64 46 Data: ELFDATA2LSB 47 Type: ET_EXEC 48 Machine: EM_386 49 DWARF: 50 debug_abbrev: 51 - Table: 52 - Code: 0x00000001 53 Tag: DW_TAG_compile_unit 54 Children: DW_CHILDREN_yes 55 Attributes: 56 - Attribute: DW_AT_language 57 Form: DW_FORM_data2 58 - Code: 0x00000002 59 Tag: DW_TAG_base_type 60 Children: DW_CHILDREN_no 61 Attributes: 62 - Attribute: DW_AT_encoding 63 Form: DW_FORM_data1 64 - Attribute: DW_AT_byte_size 65 Form: DW_FORM_data1 66 debug_info: 67 - Version: 4 68 AddrSize: 8 69 Entries: 70 - AbbrCode: 0x00000001 71 Values: 72 - Value: 0x000000000000000C 73 - AbbrCode: 0x00000002 74 Values: 75 - Value: 0x0000000000000007 # DW_ATE_unsigned 76 - Value: 0x0000000000000004 77 - AbbrCode: 0x00000002 78 Values: 79 - Value: 0x0000000000000007 # DW_ATE_unsigned 80 - Value: 0x0000000000000008 81 - AbbrCode: 0x00000002 82 Values: 83 - Value: 0x0000000000000005 # DW_ATE_signed 84 - Value: 0x0000000000000008 85 - AbbrCode: 0x00000002 86 Values: 87 - Value: 0x0000000000000008 # DW_ATE_unsigned_char 88 - Value: 0x0000000000000001 89 - AbbrCode: 0x00000000 90 )"; 91 92 YAMLModuleTester t(yamldata); 93 ASSERT_TRUE((bool)t.GetDwarfUnit()); 94 95 TypeSystemClang ast_ctx("dummy ASTContext", HostInfoBase::GetTargetTriple()); 96 DWARFASTParserClangStub ast_parser(ast_ctx); 97 98 DWARFUnit *unit = t.GetDwarfUnit(); 99 const DWARFDebugInfoEntry *die_first = unit->DIE().GetDIE(); 100 const DWARFDebugInfoEntry *die_child0 = die_first->GetFirstChild(); 101 const DWARFDebugInfoEntry *die_child1 = die_child0->GetSibling(); 102 const DWARFDebugInfoEntry *die_child2 = die_child1->GetSibling(); 103 const DWARFDebugInfoEntry *die_child3 = die_child2->GetSibling(); 104 std::vector<DWARFDIE> dies = { 105 DWARFDIE(unit, die_child0), DWARFDIE(unit, die_child1), 106 DWARFDIE(unit, die_child2), DWARFDIE(unit, die_child3)}; 107 std::vector<clang::DeclContext *> decl_ctxs = { 108 (clang::DeclContext *)1LL, (clang::DeclContext *)2LL, 109 (clang::DeclContext *)2LL, (clang::DeclContext *)3LL}; 110 for (int i = 0; i < 4; ++i) 111 ast_parser.LinkDeclContextToDIE(decl_ctxs[i], dies[i]); 112 ast_parser.EnsureAllDIEsInDeclContextHaveBeenParsed( 113 CompilerDeclContext(nullptr, decl_ctxs[1])); 114 115 EXPECT_THAT(ast_parser.GetDeclContextToDIEMapKeys(), 116 testing::UnorderedElementsAre(decl_ctxs[0], decl_ctxs[3])); 117 } 118 119 TEST_F(DWARFASTParserClangTests, TestCallingConventionParsing) { 120 // Tests parsing DW_AT_calling_convention values. 121 122 // The DWARF below just declares a list of function types with 123 // DW_AT_calling_convention on them. 124 const char *yamldata = R"( 125 --- !ELF 126 FileHeader: 127 Class: ELFCLASS32 128 Data: ELFDATA2LSB 129 Type: ET_EXEC 130 Machine: EM_386 131 DWARF: 132 debug_str: 133 - func1 134 - func2 135 - func3 136 - func4 137 - func5 138 - func6 139 - func7 140 - func8 141 - func9 142 debug_abbrev: 143 - ID: 0 144 Table: 145 - Code: 0x1 146 Tag: DW_TAG_compile_unit 147 Children: DW_CHILDREN_yes 148 Attributes: 149 - Attribute: DW_AT_language 150 Form: DW_FORM_data2 151 - Code: 0x2 152 Tag: DW_TAG_subprogram 153 Children: DW_CHILDREN_no 154 Attributes: 155 - Attribute: DW_AT_low_pc 156 Form: DW_FORM_addr 157 - Attribute: DW_AT_high_pc 158 Form: DW_FORM_data4 159 - Attribute: DW_AT_name 160 Form: DW_FORM_strp 161 - Attribute: DW_AT_calling_convention 162 Form: DW_FORM_data1 163 - Attribute: DW_AT_external 164 Form: DW_FORM_flag_present 165 debug_info: 166 - Version: 4 167 AddrSize: 4 168 Entries: 169 - AbbrCode: 0x1 170 Values: 171 - Value: 0xC 172 - AbbrCode: 0x2 173 Values: 174 - Value: 0x0 175 - Value: 0x5 176 - Value: 0x00 177 - Value: 0xCB 178 - Value: 0x1 179 - AbbrCode: 0x2 180 Values: 181 - Value: 0x10 182 - Value: 0x5 183 - Value: 0x06 184 - Value: 0xB3 185 - Value: 0x1 186 - AbbrCode: 0x2 187 Values: 188 - Value: 0x20 189 - Value: 0x5 190 - Value: 0x0C 191 - Value: 0xB1 192 - Value: 0x1 193 - AbbrCode: 0x2 194 Values: 195 - Value: 0x30 196 - Value: 0x5 197 - Value: 0x12 198 - Value: 0xC0 199 - Value: 0x1 200 - AbbrCode: 0x2 201 Values: 202 - Value: 0x40 203 - Value: 0x5 204 - Value: 0x18 205 - Value: 0xB2 206 - Value: 0x1 207 - AbbrCode: 0x2 208 Values: 209 - Value: 0x50 210 - Value: 0x5 211 - Value: 0x1E 212 - Value: 0xC1 213 - Value: 0x1 214 - AbbrCode: 0x2 215 Values: 216 - Value: 0x60 217 - Value: 0x5 218 - Value: 0x24 219 - Value: 0xC2 220 - Value: 0x1 221 - AbbrCode: 0x2 222 Values: 223 - Value: 0x70 224 - Value: 0x5 225 - Value: 0x2a 226 - Value: 0xEE 227 - Value: 0x1 228 - AbbrCode: 0x2 229 Values: 230 - Value: 0x80 231 - Value: 0x5 232 - Value: 0x30 233 - Value: 0x01 234 - Value: 0x1 235 - AbbrCode: 0x0 236 ... 237 )"; 238 YAMLModuleTester t(yamldata); 239 240 DWARFUnit *unit = t.GetDwarfUnit(); 241 ASSERT_NE(unit, nullptr); 242 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); 243 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); 244 DWARFDIE cu_die(unit, cu_entry); 245 246 TypeSystemClang ast_ctx("dummy ASTContext", HostInfoBase::GetTargetTriple()); 247 DWARFASTParserClangStub ast_parser(ast_ctx); 248 249 std::vector<std::string> found_function_types; 250 // The DWARF above is just a list of functions. Parse all of them to 251 // extract the function types and their calling convention values. 252 for (DWARFDIE func : cu_die.children()) { 253 ASSERT_EQ(func.Tag(), DW_TAG_subprogram); 254 SymbolContext sc; 255 bool new_type = false; 256 lldb::TypeSP type = ast_parser.ParseTypeFromDWARF(sc, func, &new_type); 257 found_function_types.push_back( 258 type->GetForwardCompilerType().GetTypeName().AsCString()); 259 } 260 261 // Compare the parsed function types against the expected list of types. 262 const std::vector<std::string> expected_function_types = { 263 "void () __attribute__((regcall))", 264 "void () __attribute__((fastcall))", 265 "void () __attribute__((stdcall))", 266 "void () __attribute__((vectorcall))", 267 "void () __attribute__((pascal))", 268 "void () __attribute__((ms_abi))", 269 "void () __attribute__((sysv_abi))", 270 "void ()", // invalid calling convention. 271 "void ()", // DW_CC_normal -> no attribute 272 }; 273 ASSERT_EQ(found_function_types, expected_function_types); 274 } 275