303 lines · cpp
1//===- DWARFAcceleratorTableTest.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"10#include "llvm/DebugInfo/DWARF/DWARFContext.h"11#include "llvm/ObjectYAML/DWARFEmitter.h"12#include "llvm/Testing/Support/Error.h"13#include "gtest/gtest.h"14 15using namespace llvm;16 17static Error ExtractDebugNames(StringRef NamesSecData, StringRef StrSecData) {18 DWARFDataExtractor NamesExtractor(NamesSecData,19 /*isLittleEndian=*/true,20 /*AddrSize=*/4);21 DataExtractor StrExtractor(StrSecData,22 /*isLittleEndian=*/true,23 /*AddrSize=*/4);24 DWARFDebugNames Table(NamesExtractor, StrExtractor);25 return Table.extract();26}27 28namespace {29 30TEST(DWARFDebugNames, ReservedUnitLength) {31 static const char NamesSecData[64] =32 "\xf0\xff\xff\xff"; // Reserved unit length value33 EXPECT_THAT_ERROR(34 ExtractDebugNames(StringRef(NamesSecData, sizeof(NamesSecData)),35 StringRef()),36 FailedWithMessage("parsing .debug_names header at 0x0: unsupported "37 "reserved unit length of value 0xfffffff0"));38}39 40TEST(DWARFDebugNames, TooSmallForDWARF64) {41 // DWARF64 header takes at least 44 bytes.42 static const char NamesSecData[43] = "\xff\xff\xff\xff"; // DWARF64 mark43 EXPECT_THAT_ERROR(44 ExtractDebugNames(StringRef(NamesSecData, sizeof(NamesSecData)),45 StringRef()),46 FailedWithMessage("parsing .debug_names header at 0x0: unexpected end of "47 "data at offset 0x2b while reading [0x28, 0x2c)"));48}49 50TEST(DWARFDebugNames, BasicTestEntries) {51 const char *Yamldata = R"(52--- !ELF53 debug_str:54 - 'NameType1'55 - 'NameType2'56 57 debug_names:58 Abbreviations:59 - Code: 0x160 Tag: DW_TAG_namespace61 Indices:62 - Idx: DW_IDX_compile_unit63 Form: DW_FORM_data464 - Idx: DW_IDX_die_offset65 Form: DW_FORM_ref466 Entries:67 - Name: 0x0 # strp to NameType168 Code: 0x169 Values:70 - 0x0 # Compile unit71 - 0x0 # DIE Offset72 - Name: 0xa # strp to NameType273 Code: 0x174 Values:75 - 0x1 # Compile unit76 - 0x1 # DIE Offset77 - Name: 0x0 # strp to NameType178 Code: 0x179 Values:80 - 0x2 # Compile unit81 - 0x2 # DIE Offset82 83)";84 85 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =86 DWARFYAML::emitDebugSections(Yamldata,87 /*IsLittleEndian=*/true,88 /*Is64BitAddrSize=*/true);89 ASSERT_THAT_EXPECTED(Sections, Succeeded());90 auto Ctx = DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true);91 const DWARFDebugNames &DebugNames = Ctx->getDebugNames();92 ASSERT_NE(DebugNames.begin(), DebugNames.end());93 const DWARFDebugNames::NameIndex &NameIndex = *DebugNames.begin();94 95 ASSERT_EQ(NameIndex.getNameCount(), 2u);96 ASSERT_EQ(NameIndex.getBucketCount(), 0u);97 ASSERT_EQ(NameIndex.getCUCount(), 1u);98 ASSERT_EQ(NameIndex.getCUOffset(0), 0u);99 ASSERT_EQ(NameIndex.getForeignTUCount(), 0u);100 ASSERT_EQ(NameIndex.getLocalTUCount(), 0u);101 102 // Check "NameEntries": there should be one per unique name.103 // These are indexed starting on 1.104 DWARFDebugNames::NameTableEntry FirstEntry = NameIndex.getNameTableEntry(1);105 ASSERT_EQ(FirstEntry.getString(), StringRef("NameType1"));106 DWARFDebugNames::NameTableEntry SecondEntry = NameIndex.getNameTableEntry(2);107 ASSERT_EQ(SecondEntry.getString(), StringRef("NameType2"));108 109 SmallVector<DWARFDebugNames::Entry> FirstNameEntries =110 to_vector_of<DWARFDebugNames::Entry>(NameIndex.equal_range("NameType1"));111 ASSERT_EQ(FirstNameEntries.size(), 2u);112 ASSERT_EQ(FirstNameEntries[0].getCUIndex(), 0u);113 ASSERT_EQ(FirstNameEntries[1].getCUIndex(), 0x2);114 ASSERT_EQ(FirstNameEntries[0].getDIEUnitOffset(), 0x0);115 ASSERT_EQ(FirstNameEntries[1].getDIEUnitOffset(), 0x2);116 117 SmallVector<DWARFDebugNames::Entry> SecondNameEntries =118 to_vector_of<DWARFDebugNames::Entry>(NameIndex.equal_range("NameType2"));119 ASSERT_EQ(SecondNameEntries.size(), 1u);120 ASSERT_EQ(SecondNameEntries[0].getCUIndex(), 0x1);121 ASSERT_EQ(SecondNameEntries[0].getDIEUnitOffset(), 0x1);122}123 124TEST(DWARFDebugNames, ParentEntries) {125 const char *Yamldata = R"(126--- !ELF127 debug_str:128 - 'Name1'129 - 'Name2'130 - 'Name3'131 - 'Name4'132 debug_names:133 Abbreviations:134 - Code: 0x11135 Tag: DW_TAG_namespace136 Indices:137 - Idx: DW_IDX_parent138 Form: DW_FORM_flag_present139 - Idx: DW_IDX_die_offset140 Form: DW_FORM_ref4141 - Code: 0x22142 Tag: DW_TAG_namespace143 Indices:144 - Idx: DW_IDX_parent145 Form: DW_FORM_ref4146 - Idx: DW_IDX_die_offset147 Form: DW_FORM_ref4148 - Code: 0x33149 Tag: DW_TAG_namespace150 Indices:151 - Idx: DW_IDX_die_offset152 Form: DW_FORM_ref4153 Entries:154 - Name: 0x0 # strp to Name1155 Code: 0x11156 Values:157 - 0x0 # Die offset158 - Name: 0x6 # strp to Name2159 Code: 0x22160 Values:161 - 0x0 # Parent = First entry162 - 0x1 # Die offset163 - Name: 0xc # strp to Name3164 Code: 0x22165 Values:166 - 0x6 # Parent = Second entry167 - 0x1 # Die offset168 - Name: 0x12 # strp to Name4169 Code: 0x33170 Values:171 - 0x1 # Die offset172)";173 174 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =175 DWARFYAML::emitDebugSections(Yamldata,176 /*IsLittleEndian=*/true,177 /*Is64BitAddrSize=*/true);178 ASSERT_THAT_EXPECTED(Sections, Succeeded());179 auto Ctx = DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true);180 const DWARFDebugNames &DebugNames = Ctx->getDebugNames();181 ASSERT_NE(DebugNames.begin(), DebugNames.end());182 const DWARFDebugNames::NameIndex &NameIndex = *DebugNames.begin();183 184 SmallVector<DWARFDebugNames::Entry> Name1Entries =185 to_vector_of<DWARFDebugNames::Entry>(NameIndex.equal_range("Name1"));186 ASSERT_EQ(Name1Entries.size(), 1u);187 Expected<std::optional<DWARFDebugNames::Entry>> Name1Parent =188 Name1Entries[0].getParentDIEEntry();189 ASSERT_THAT_EXPECTED(Name1Parent, Succeeded());190 ASSERT_EQ(*Name1Parent, std::nullopt); // Name1 has no parent191 192 SmallVector<DWARFDebugNames::Entry> Name2Entries =193 to_vector_of<DWARFDebugNames::Entry>(NameIndex.equal_range("Name2"));194 ASSERT_EQ(Name2Entries.size(), 1u);195 Expected<std::optional<DWARFDebugNames::Entry>> Name2Parent =196 Name2Entries[0].getParentDIEEntry();197 ASSERT_THAT_EXPECTED(Name2Parent, Succeeded());198 ASSERT_EQ((**Name2Parent).getDIEUnitOffset(), 0x0); // Name2 parent == Name1199 200 SmallVector<DWARFDebugNames::Entry> Name3Entries =201 to_vector_of<DWARFDebugNames::Entry>(NameIndex.equal_range("Name3"));202 ASSERT_EQ(Name3Entries.size(), 1u);203 Expected<std::optional<DWARFDebugNames::Entry>> Name3Parent =204 Name3Entries[0].getParentDIEEntry();205 ASSERT_THAT_EXPECTED(Name3Parent, Succeeded());206 ASSERT_EQ((**Name3Parent).getDIEUnitOffset(), 0x1); // Name3 parent == Name2207 208 SmallVector<DWARFDebugNames::Entry> Name4Entries =209 to_vector_of<DWARFDebugNames::Entry>(NameIndex.equal_range("Name4"));210 ASSERT_EQ(Name4Entries.size(), 1u);211 ASSERT_FALSE(Name4Entries[0].hasParentInformation());212}213 214TEST(DWARFDebugNames, InvalidAbbrevCode) {215 const char *Yamldata = R"(216--- !ELF217 debug_str:218 - 'NameType1'219 220 debug_names:221 Abbreviations:222 - Code: 0x1223 Tag: DW_TAG_namespace224 Indices:225 - Idx: DW_IDX_compile_unit226 Form: DW_FORM_data4227 Entries:228 - Name: 0x0 # strp to NameType1229 Code: 0x123456230 Values:231 - 0x0 # Compile unit232)";233 234 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =235 DWARFYAML::emitDebugSections(Yamldata,236 /*IsLittleEndian=*/true,237 /*Is64BitAddrSize=*/true);238 ASSERT_THAT_EXPECTED(239 Sections,240 FailedWithMessage("did not find an Abbreviation for this code"));241}242 243TEST(DWARFDebugNames, InvalidNumOfValues) {244 const char *Yamldata = R"(245--- !ELF246 debug_str:247 - 'NameType1'248 249 debug_names:250 Abbreviations:251 - Code: 0x1252 Tag: DW_TAG_namespace253 Indices:254 - Idx: DW_IDX_compile_unit255 Form: DW_FORM_data4256 Entries:257 - Name: 0x0 # strp to NameType1258 Code: 0x1259 Values:260 - 0x0 # Compile unit261 - 0x0 # Compile unit262 - 0x0 # Compile unit263)";264 265 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =266 DWARFYAML::emitDebugSections(Yamldata,267 /*IsLittleEndian=*/true,268 /*Is64BitAddrSize=*/true);269 ASSERT_THAT_EXPECTED(270 Sections, FailedWithMessage(271 "mismatch between provided and required number of values"));272}273 274TEST(DWARFDebugNames, UnsupportedForm) {275 const char *Yamldata = R"(276--- !ELF277 debug_str:278 - 'NameType1'279 280 debug_names:281 Abbreviations:282 - Code: 0x1283 Tag: DW_TAG_namespace284 Indices:285 - Idx: DW_IDX_compile_unit286 Form: DW_FORM_strx287 Entries:288 - Name: 0x0 # strp to NameType1289 Code: 0x1290 Values:291 - 0x0 # Compile unit292)";293 294 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =295 DWARFYAML::emitDebugSections(Yamldata,296 /*IsLittleEndian=*/true,297 /*Is64BitAddrSize=*/true);298 ASSERT_THAT_EXPECTED(299 Sections,300 FailedWithMessage("unsupported Form for YAML debug_names emitter"));301}302} // end anonymous namespace303