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