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 277 struct ExtractIntFromFormValueTest : public testing::Test { 278 SubsystemRAII<FileSystem, HostInfo> subsystems; 279 TypeSystemClang ts; 280 DWARFASTParserClang parser; 281 ExtractIntFromFormValueTest() 282 : ts("dummy ASTContext", HostInfoBase::GetTargetTriple()), parser(ts) {} 283 284 /// Takes the given integer value, stores it in a DWARFFormValue and then 285 /// tries to extract the value back via 286 /// DWARFASTParserClang::ExtractIntFromFormValue. 287 /// Returns the string representation of the extracted value or the error 288 /// that was returned from ExtractIntFromFormValue. 289 llvm::Expected<std::string> Extract(clang::QualType qt, uint64_t value) { 290 DWARFFormValue form_value; 291 form_value.SetUnsigned(value); 292 llvm::Expected<llvm::APInt> result = 293 parser.ExtractIntFromFormValue(ts.GetType(qt), form_value); 294 if (!result) 295 return result.takeError(); 296 llvm::SmallString<16> result_str; 297 result->toStringUnsigned(result_str); 298 return std::string(result_str.str()); 299 } 300 301 /// Same as ExtractIntFromFormValueTest::Extract but takes a signed integer 302 /// and treats the result as a signed integer. 303 llvm::Expected<std::string> ExtractS(clang::QualType qt, int64_t value) { 304 DWARFFormValue form_value; 305 form_value.SetSigned(value); 306 llvm::Expected<llvm::APInt> result = 307 parser.ExtractIntFromFormValue(ts.GetType(qt), form_value); 308 if (!result) 309 return result.takeError(); 310 llvm::SmallString<16> result_str; 311 result->toStringSigned(result_str); 312 return std::string(result_str.str()); 313 } 314 }; 315 316 TEST_F(ExtractIntFromFormValueTest, TestBool) { 317 using namespace llvm; 318 clang::ASTContext &ast = ts.getASTContext(); 319 320 EXPECT_THAT_EXPECTED(Extract(ast.BoolTy, 0), HasValue("0")); 321 EXPECT_THAT_EXPECTED(Extract(ast.BoolTy, 1), HasValue("1")); 322 EXPECT_THAT_EXPECTED(Extract(ast.BoolTy, 2), Failed()); 323 EXPECT_THAT_EXPECTED(Extract(ast.BoolTy, 3), Failed()); 324 } 325 326 TEST_F(ExtractIntFromFormValueTest, TestInt) { 327 using namespace llvm; 328 329 clang::ASTContext &ast = ts.getASTContext(); 330 331 // Find the min/max values for 'int' on the current host target. 332 constexpr int64_t int_max = std::numeric_limits<int>::max(); 333 constexpr int64_t int_min = std::numeric_limits<int>::min(); 334 335 // Check that the bit width of int matches the int width in our type system. 336 ASSERT_EQ(sizeof(int) * 8, ast.getIntWidth(ast.IntTy)); 337 338 // Check values around int_min. 339 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_min - 2), llvm::Failed()); 340 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_min - 1), llvm::Failed()); 341 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_min), 342 HasValue(std::to_string(int_min))); 343 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_min + 1), 344 HasValue(std::to_string(int_min + 1))); 345 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_min + 2), 346 HasValue(std::to_string(int_min + 2))); 347 348 // Check values around 0. 349 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, -128), HasValue("-128")); 350 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, -10), HasValue("-10")); 351 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, -1), HasValue("-1")); 352 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, 0), HasValue("0")); 353 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, 1), HasValue("1")); 354 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, 10), HasValue("10")); 355 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, 128), HasValue("128")); 356 357 // Check values around int_max. 358 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_max - 2), 359 HasValue(std::to_string(int_max - 2))); 360 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_max - 1), 361 HasValue(std::to_string(int_max - 1))); 362 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_max), 363 HasValue(std::to_string(int_max))); 364 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_max + 1), llvm::Failed()); 365 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_max + 5), llvm::Failed()); 366 367 // Check some values not near an edge case. 368 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_max / 2), 369 HasValue(std::to_string(int_max / 2))); 370 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_min / 2), 371 HasValue(std::to_string(int_min / 2))); 372 } 373 374 TEST_F(ExtractIntFromFormValueTest, TestUnsignedInt) { 375 using namespace llvm; 376 377 clang::ASTContext &ast = ts.getASTContext(); 378 constexpr uint64_t uint_max = std::numeric_limits<uint32_t>::max(); 379 380 // Check values around 0. 381 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, 0), HasValue("0")); 382 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, 1), HasValue("1")); 383 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, 1234), HasValue("1234")); 384 385 // Check some values not near an edge case. 386 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, uint_max / 2), 387 HasValue(std::to_string(uint_max / 2))); 388 389 // Check values around uint_max. 390 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, uint_max - 2), 391 HasValue(std::to_string(uint_max - 2))); 392 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, uint_max - 1), 393 HasValue(std::to_string(uint_max - 1))); 394 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, uint_max), 395 HasValue(std::to_string(uint_max))); 396 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, uint_max + 1), 397 llvm::Failed()); 398 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, uint_max + 2), 399 llvm::Failed()); 400 } 401