brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.0 KiB · 871dbf1 Raw
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