440 lines · cpp
1//===- llvm/unittest/DebugInfo/DWARFDebugAbbrevTest.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/DWARFDebugAbbrev.h"10#include "llvm/BinaryFormat/Dwarf.h"11#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"12#include "llvm/Support/DataExtractor.h"13#include "llvm/Support/LEB128.h"14#include "llvm/Support/MemoryBuffer.h"15#include "llvm/Testing/Support/Error.h"16#include "gtest/gtest.h"17 18using namespace llvm;19using namespace dwarf;20 21enum OrderKind : bool { InOrder, OutOfOrder };22 23void writeValidAbbreviationDeclarations(raw_ostream &OS, uint32_t FirstCode,24 OrderKind Order) {25 encodeULEB128(FirstCode, OS);26 encodeULEB128(DW_TAG_compile_unit, OS);27 OS << static_cast<uint8_t>(DW_CHILDREN_yes);28 encodeULEB128(DW_AT_name, OS);29 encodeULEB128(DW_FORM_strp, OS);30 encodeULEB128(0, OS);31 encodeULEB128(0, OS);32 33 uint32_t SecondCode =34 Order == OrderKind::InOrder ? FirstCode + 1 : FirstCode - 1;35 36 encodeULEB128(SecondCode, OS);37 encodeULEB128(DW_TAG_subprogram, OS);38 OS << static_cast<uint8_t>(DW_CHILDREN_no);39 encodeULEB128(DW_AT_name, OS);40 encodeULEB128(DW_FORM_strp, OS);41 encodeULEB128(0, OS);42 encodeULEB128(0, OS);43}44 45void writeMalformedULEB128Value(raw_ostream &OS) {46 OS << static_cast<uint8_t>(0x80);47}48 49void writeULEB128LargerThan64Bits(raw_ostream &OS) {50 static constexpr llvm::StringRef LargeULEB128 =51 "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01";52 OS << LargeULEB128;53}54 55TEST(DWARFDebugAbbrevTest, DWARFAbbrevDeclSetExtractSuccess) {56 SmallString<64> RawData;57 raw_svector_ostream OS(RawData);58 uint32_t FirstCode = 5;59 60 writeValidAbbreviationDeclarations(OS, FirstCode, InOrder);61 encodeULEB128(0, OS);62 63 uint64_t Offset = 0;64 DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));65 DWARFAbbreviationDeclarationSet AbbrevSet;66 ASSERT_THAT_ERROR(AbbrevSet.extract(Data, &Offset), Succeeded());67 // The Abbreviation Declarations are in order and contiguous, so we want to68 // make sure that FirstAbbrCode was correctly set.69 EXPECT_EQ(AbbrevSet.getFirstAbbrCode(), FirstCode);70 71 const DWARFAbbreviationDeclaration *Abbrev5 =72 AbbrevSet.getAbbreviationDeclaration(FirstCode);73 ASSERT_TRUE(Abbrev5);74 EXPECT_EQ(Abbrev5->getTag(), DW_TAG_compile_unit);75 EXPECT_TRUE(Abbrev5->hasChildren());76 EXPECT_EQ(Abbrev5->getNumAttributes(), 1u);77 78 const DWARFAbbreviationDeclaration *Abbrev6 =79 AbbrevSet.getAbbreviationDeclaration(FirstCode + 1);80 ASSERT_TRUE(Abbrev6);81 EXPECT_EQ(Abbrev6->getTag(), DW_TAG_subprogram);82 EXPECT_FALSE(Abbrev6->hasChildren());83 EXPECT_EQ(Abbrev6->getNumAttributes(), 1u);84}85 86TEST(DWARFDebugAbbrevTest, DWARFAbbrevDeclSetExtractSuccessOutOfOrder) {87 SmallString<64> RawData;88 raw_svector_ostream OS(RawData);89 uint32_t FirstCode = 2;90 91 writeValidAbbreviationDeclarations(OS, FirstCode, OutOfOrder);92 encodeULEB128(0, OS);93 94 uint64_t Offset = 0;95 DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));96 DWARFAbbreviationDeclarationSet AbbrevSet;97 ASSERT_THAT_ERROR(AbbrevSet.extract(Data, &Offset), Succeeded());98 // The declarations are out of order, ensure that FirstAbbrCode is UINT32_MAX.99 EXPECT_EQ(AbbrevSet.getFirstAbbrCode(), UINT32_MAX);100 101 const DWARFAbbreviationDeclaration *Abbrev2 =102 AbbrevSet.getAbbreviationDeclaration(FirstCode);103 ASSERT_TRUE(Abbrev2);104 EXPECT_EQ(Abbrev2->getTag(), DW_TAG_compile_unit);105 EXPECT_TRUE(Abbrev2->hasChildren());106 EXPECT_EQ(Abbrev2->getNumAttributes(), 1u);107 108 const DWARFAbbreviationDeclaration *Abbrev1 =109 AbbrevSet.getAbbreviationDeclaration(FirstCode - 1);110 ASSERT_TRUE(Abbrev1);111 EXPECT_EQ(Abbrev1->getTag(), DW_TAG_subprogram);112 EXPECT_FALSE(Abbrev1->hasChildren());113 EXPECT_EQ(Abbrev1->getNumAttributes(), 1u);114}115 116TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetCodeExtractionError) {117 SmallString<64> RawData;118 119 // Check for malformed ULEB128.120 {121 raw_svector_ostream OS(RawData);122 writeMalformedULEB128Value(OS);123 124 uint64_t Offset = 0;125 DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));126 DWARFAbbreviationDeclarationSet AbbrevSet;127 ASSERT_THAT_ERROR(128 AbbrevSet.extract(Data, &Offset),129 FailedWithMessage("unable to decode LEB128 at offset 0x00000000: "130 "malformed uleb128, extends past end"));131 EXPECT_EQ(Offset, 0u);132 }133 134 RawData.clear();135 // Check for ULEB128 too large to fit into a uin64_t.136 {137 raw_svector_ostream OS(RawData);138 writeULEB128LargerThan64Bits(OS);139 140 uint64_t Offset = 0;141 DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));142 DWARFAbbreviationDeclarationSet AbbrevSet;143 ASSERT_THAT_ERROR(144 AbbrevSet.extract(Data, &Offset),145 FailedWithMessage("unable to decode LEB128 at offset 0x00000000: "146 "uleb128 too big for uint64"));147 EXPECT_EQ(Offset, 0u);148 }149}150 151TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetTagExtractionError) {152 SmallString<64> RawData;153 const uint32_t Code = 1;154 155 // Check for malformed ULEB128.156 {157 raw_svector_ostream OS(RawData);158 encodeULEB128(Code, OS);159 writeMalformedULEB128Value(OS);160 161 uint64_t Offset = 0;162 DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));163 DWARFAbbreviationDeclarationSet AbbrevSet;164 ASSERT_THAT_ERROR(165 AbbrevSet.extract(Data, &Offset),166 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "167 "malformed uleb128, extends past end"));168 // Only the code was extracted correctly.169 EXPECT_EQ(Offset, 1u);170 }171 172 RawData.clear();173 // Check for ULEB128 too large to fit into a uint64_t.174 {175 raw_svector_ostream OS(RawData);176 encodeULEB128(Code, OS);177 writeULEB128LargerThan64Bits(OS);178 179 uint64_t Offset = 0;180 DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));181 DWARFAbbreviationDeclarationSet AbbrevSet;182 ASSERT_THAT_ERROR(183 AbbrevSet.extract(Data, &Offset),184 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "185 "uleb128 too big for uint64"));186 // Only the code was extracted correctly.187 EXPECT_EQ(Offset, 1u);188 }189}190 191TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetChildExtractionError) {192 SmallString<64> RawData;193 const uint32_t Code = 1;194 const dwarf::Tag Tag = DW_TAG_compile_unit;195 196 // We want to make sure that we fail if we reach the end of the stream before197 // reading the 'children' byte.198 raw_svector_ostream OS(RawData);199 encodeULEB128(Code, OS);200 encodeULEB128(Tag, OS);201 uint64_t Offset = 0;202 DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));203 DWARFAbbreviationDeclarationSet AbbrevSet;204 ASSERT_THAT_ERROR(205 AbbrevSet.extract(Data, &Offset),206 FailedWithMessage(207 "unexpected end of data at offset 0x2 while reading [0x2, 0x3)"));208 // The code and the tag were extracted correctly.209 EXPECT_EQ(Offset, 2u);210}211 212TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetAttributeExtractionError) {213 SmallString<64> RawData;214 const uint32_t Code = 1;215 const dwarf::Tag Tag = DW_TAG_compile_unit;216 const uint8_t Children = DW_CHILDREN_yes;217 218 // Check for malformed ULEB128.219 {220 raw_svector_ostream OS(RawData);221 encodeULEB128(Code, OS);222 encodeULEB128(Tag, OS);223 OS << Children;224 writeMalformedULEB128Value(OS);225 226 uint64_t Offset = 0;227 DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));228 DWARFAbbreviationDeclarationSet AbbrevSet;229 ASSERT_THAT_ERROR(230 AbbrevSet.extract(Data, &Offset),231 FailedWithMessage("unable to decode LEB128 at offset 0x00000003: "232 "malformed uleb128, extends past end"));233 // The code, tag, and child byte were extracted correctly.234 EXPECT_EQ(Offset, 3u);235 }236 237 RawData.clear();238 // Check for ULEB128 too large to fit into a uint64_t.239 {240 raw_svector_ostream OS(RawData);241 encodeULEB128(Code, OS);242 encodeULEB128(Tag, OS);243 OS << Children;244 writeULEB128LargerThan64Bits(OS);245 246 uint64_t Offset = 0;247 DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));248 DWARFAbbreviationDeclarationSet AbbrevSet;249 ASSERT_THAT_ERROR(250 AbbrevSet.extract(Data, &Offset),251 FailedWithMessage("unable to decode LEB128 at offset 0x00000003: "252 "uleb128 too big for uint64"));253 // The code, tag, and child byte were extracted correctly.254 EXPECT_EQ(Offset, 3u);255 }256}257 258TEST(DWARFDebugAbbrevTest, DWARFAbbreviationDeclSetFormExtractionError) {259 SmallString<64> RawData;260 const uint32_t Code = 1;261 const dwarf::Tag Tag = DW_TAG_compile_unit;262 const uint8_t Children = DW_CHILDREN_yes;263 const dwarf::Attribute Attr = DW_AT_name;264 265 // Check for malformed ULEB128.266 {267 raw_svector_ostream OS(RawData);268 encodeULEB128(Code, OS);269 encodeULEB128(Tag, OS);270 OS << Children;271 encodeULEB128(Attr, OS);272 writeMalformedULEB128Value(OS);273 274 uint64_t Offset = 0;275 DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));276 DWARFAbbreviationDeclarationSet AbbrevSet;277 ASSERT_THAT_ERROR(278 AbbrevSet.extract(Data, &Offset),279 FailedWithMessage("unable to decode LEB128 at offset 0x00000004: "280 "malformed uleb128, extends past end"));281 // The code, tag, child byte, and first attribute were extracted correctly.282 EXPECT_EQ(Offset, 4u);283 }284 285 RawData.clear();286 // Check for ULEB128 too large to fit into a uint64_t.287 {288 raw_svector_ostream OS(RawData);289 encodeULEB128(Code, OS);290 encodeULEB128(Tag, OS);291 OS << Children;292 encodeULEB128(Attr, OS);293 writeULEB128LargerThan64Bits(OS);294 295 uint64_t Offset = 0;296 DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));297 DWARFAbbreviationDeclarationSet AbbrevSet;298 ASSERT_THAT_ERROR(299 AbbrevSet.extract(Data, &Offset),300 FailedWithMessage("unable to decode LEB128 at offset 0x00000004: "301 "uleb128 too big for uint64"));302 // The code, tag, child byte, and first attribute were extracted correctly.303 EXPECT_EQ(Offset, 4u);304 }305}306 307TEST(DWARFDebugAbbrevTest, DWARFAbbrevDeclSetInvalidTag) {308 SmallString<64> RawData;309 raw_svector_ostream OS(RawData);310 uint32_t FirstCode = 1;311 // First, we're going to manually add good data.312 writeValidAbbreviationDeclarations(OS, FirstCode, InOrder);313 314 // Afterwards, we're going to write an Abbreviation Decl manually with an315 // invalid tag.316 encodeULEB128(FirstCode + 2, OS);317 encodeULEB128(0, OS); // Invalid Tag318 OS << static_cast<uint8_t>(DW_CHILDREN_no);319 encodeULEB128(DW_AT_name, OS);320 encodeULEB128(DW_FORM_strp, OS);321 encodeULEB128(0, OS);322 encodeULEB128(0, OS);323 324 encodeULEB128(0, OS);325 uint64_t Offset = 0;326 DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));327 DWARFAbbreviationDeclarationSet AbbrevSet;328 EXPECT_THAT_ERROR(329 AbbrevSet.extract(Data, &Offset),330 FailedWithMessage("abbreviation declaration requires a non-null tag"));331}332 333TEST(DWARFDebugAbbrevTest, DWARFAbbrevDeclSetInvalidAttrValidForm) {334 SmallString<64> RawData;335 raw_svector_ostream OS(RawData);336 uint32_t FirstCode = 120;337 // First, we're going to manually add good data.338 writeValidAbbreviationDeclarations(OS, FirstCode, InOrder);339 340 // Afterwards, we're going to write an Abbreviation Decl manually with an341 // invalid attribute but valid form.342 encodeULEB128(FirstCode - 5, OS);343 encodeULEB128(DW_TAG_compile_unit, OS);344 OS << static_cast<uint8_t>(DW_CHILDREN_no);345 encodeULEB128(0, OS); // Invalid attribute followed by an invalid form.346 encodeULEB128(DW_FORM_strp, OS);347 encodeULEB128(0, OS);348 encodeULEB128(0, OS);349 350 encodeULEB128(0, OS);351 352 uint64_t Offset = 0;353 DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));354 DWARFAbbreviationDeclarationSet AbbrevSet;355 EXPECT_THAT_ERROR(356 AbbrevSet.extract(Data, &Offset),357 FailedWithMessage(358 "malformed abbreviation declaration attribute. Either the "359 "attribute or the form is zero while the other is not"));360}361 362TEST(DWARFDebugAbbrevTest, DWARFAbbrevDeclSetValidAttrInvalidForm) {363 SmallString<64> RawData;364 raw_svector_ostream OS(RawData);365 uint32_t FirstCode = 120;366 // First, we're going to manually add good data.367 writeValidAbbreviationDeclarations(OS, FirstCode, InOrder);368 369 // Afterwards, we're going to write an Abbreviation Decl manually with a370 // valid attribute but invalid form.371 encodeULEB128(FirstCode - 5, OS);372 encodeULEB128(DW_TAG_compile_unit, OS);373 OS << static_cast<uint8_t>(DW_CHILDREN_no);374 encodeULEB128(DW_AT_name, OS);375 encodeULEB128(0, OS); // Invalid form after a valid attribute.376 encodeULEB128(0, OS);377 encodeULEB128(0, OS);378 379 encodeULEB128(0, OS);380 381 uint64_t Offset = 0;382 DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));383 DWARFAbbreviationDeclarationSet AbbrevSet;384 EXPECT_THAT_ERROR(385 AbbrevSet.extract(Data, &Offset),386 FailedWithMessage(387 "malformed abbreviation declaration attribute. Either the "388 "attribute or the form is zero while the other is not"));389}390 391TEST(DWARFDebugAbbrevTest, DWARFAbbrevDeclSetMissingTerminator) {392 SmallString<64> RawData;393 raw_svector_ostream OS(RawData);394 uint32_t FirstCode = 120;395 // First, we're going to manually add good data.396 writeValidAbbreviationDeclarations(OS, FirstCode, InOrder);397 398 // Afterwards, we're going to write an Abbreviation Decl manually without a399 // termintating sequence.400 encodeULEB128(FirstCode + 7, OS);401 encodeULEB128(DW_TAG_compile_unit, OS);402 OS << static_cast<uint8_t>(DW_CHILDREN_no);403 encodeULEB128(DW_AT_name, OS);404 encodeULEB128(DW_FORM_strp, OS);405 406 uint64_t Offset = 0;407 DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));408 DWARFAbbreviationDeclarationSet AbbrevSet;409 EXPECT_THAT_ERROR(410 AbbrevSet.extract(Data, &Offset),411 FailedWithMessage(412 "abbreviation declaration attribute list was not terminated with a "413 "null entry"));414}415 416TEST(DWARFDebugAbbrevTest, DWARFDebugAbbrevParseError) {417 SmallString<64> RawData;418 raw_svector_ostream OS(RawData);419 const uint32_t FirstCode = 70;420 // First, we're going to manually add good data.421 writeValidAbbreviationDeclarations(OS, FirstCode, InOrder);422 423 // Afterwards, we're going to write an Abbreviation Decl manually without a424 // termintating sequence.425 encodeULEB128(FirstCode - 1, OS);426 encodeULEB128(DW_TAG_compile_unit, OS);427 OS << static_cast<uint8_t>(DW_CHILDREN_no);428 encodeULEB128(DW_AT_name, OS);429 encodeULEB128(DW_FORM_strp, OS);430 431 // The specific error should percolate up to the DWARFDebugAbbrev::parse().432 DataExtractor Data(RawData, sys::IsLittleEndianHost, sizeof(uint64_t));433 DWARFDebugAbbrev DebugAbbrev(Data);434 EXPECT_THAT_ERROR(435 DebugAbbrev.parse(),436 FailedWithMessage(437 "abbreviation declaration attribute list was not terminated with a "438 "null entry"));439}440