228 lines · cpp
1//===- DWARFDataExtractorTest.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/DWARFDataExtractor.h"10#include "llvm/DebugInfo/DWARF/DWARFContext.h"11#include "llvm/Object/ObjectFile.h"12#include "llvm/ObjectYAML/yaml2obj.h"13#include "llvm/Testing/Support/Error.h"14#include "gtest/gtest.h"15 16using namespace llvm;17 18namespace {19 20TEST(DWARFDataExtractorTest, getRelocatedValue) {21 StringRef Yaml = R"(22!ELF23FileHeader:24 Class: ELFCLASS3225 Data: ELFDATA2LSB26 Type: ET_REL27 Machine: EM_38628Sections:29 - Name: .text30 Type: SHT_PROGBITS31 Size: 0x8032 - Name: .debug_line33 Type: SHT_PROGBITS34 Content: '000000000000'35 - Name: .rel.debug_line36 Type: SHT_REL37 Info: .debug_line38 Relocations:39 - Offset: 040 Symbol: f41 Type: R_386_3242 - Offset: 443 Symbol: f44 Type: R_386_3245Symbols:46 - Name: f47 Type: STT_SECTION48 Section: .text49 Value: 0x4250)";51 SmallString<0> Storage;52 std::unique_ptr<object::ObjectFile> Obj = yaml::yaml2ObjectFile(53 Storage, Yaml, [](const Twine &Err) { errs() << Err; });54 ASSERT_TRUE(Obj);55 std::unique_ptr<DWARFContext> Ctx = DWARFContext::create(*Obj);56 const DWARFObject &DObj = Ctx->getDWARFObj();57 ASSERT_EQ(6u, DObj.getLineSection().Data.size());58 59 DWARFDataExtractor Data(DObj, DObj.getLineSection(), Obj->isLittleEndian(),60 Obj->getBytesInAddress());61 DataExtractor::Cursor C(0);62 EXPECT_EQ(0x42u, Data.getRelocatedAddress(C));63 EXPECT_EQ(0u, Data.getRelocatedAddress(C));64 EXPECT_THAT_ERROR(65 C.takeError(),66 FailedWithMessage(67 "unexpected end of data at offset 0x6 while reading [0x4, 0x8)"));68}69 70TEST(DWARFDataExtractorTest, getInitialLength) {71 auto GetWithError = [](ArrayRef<uint8_t> Bytes)72 -> Expected<std::tuple<uint64_t, dwarf::DwarfFormat, uint64_t>> {73 DWARFDataExtractor Data(Bytes, /*IsLittleEndian=*/false, /*AddressSize=*/8);74 DWARFDataExtractor::Cursor C(0);75 uint64_t Length;76 dwarf::DwarfFormat Format;77 std::tie(Length, Format) = Data.getInitialLength(C);78 if (C)79 return std::make_tuple(Length, Format, C.tell());80 81 EXPECT_EQ(Length, 0u);82 EXPECT_EQ(Format, dwarf::DWARF32);83 EXPECT_EQ(C.tell(), 0u);84 return C.takeError();85 };86 auto GetWithoutError = [](ArrayRef<uint8_t> Bytes) {87 DWARFDataExtractor Data(Bytes, /*IsLittleEndian=*/false, /*AddressSize=*/8);88 uint64_t Offset = 0;89 uint64_t Length;90 dwarf::DwarfFormat Format;91 std::tie(Length, Format) = Data.getInitialLength(&Offset);92 return std::make_tuple(Length, Format, Offset);93 };94 auto ErrorResult = std::make_tuple(0, dwarf::DWARF32, 0);95 96 // Empty data.97 EXPECT_THAT_EXPECTED(98 GetWithError({}),99 FailedWithMessage(100 "unexpected end of data at offset 0x0 while reading [0x0, 0x4)"));101 EXPECT_EQ(GetWithoutError({}), ErrorResult);102 103 // Not long enough for the U32 field.104 EXPECT_THAT_EXPECTED(105 GetWithError({0x00, 0x01, 0x02}),106 FailedWithMessage(107 "unexpected end of data at offset 0x3 while reading [0x0, 0x4)"));108 EXPECT_EQ(GetWithoutError({0x00, 0x01, 0x02}), ErrorResult);109 110 EXPECT_THAT_EXPECTED(111 GetWithError({0x00, 0x01, 0x02, 0x03}),112 HasValue(std::make_tuple(0x00010203, dwarf::DWARF32, 4)));113 EXPECT_EQ(GetWithoutError({0x00, 0x01, 0x02, 0x03}),114 std::make_tuple(0x00010203, dwarf::DWARF32, 4));115 116 // Zeroes are not an error, but without the Error object it is hard to tell117 // them apart from a failed read.118 EXPECT_THAT_EXPECTED(119 GetWithError({0x00, 0x00, 0x00, 0x00}),120 HasValue(std::make_tuple(0x00000000, dwarf::DWARF32, 4)));121 EXPECT_EQ(GetWithoutError({0x00, 0x00, 0x00, 0x00}),122 std::make_tuple(0x00000000, dwarf::DWARF32, 4));123 124 // Smallest invalid value.125 EXPECT_THAT_EXPECTED(126 GetWithError({0xff, 0xff, 0xff, 0xf0}),127 FailedWithMessage(128 "unsupported reserved unit length of value 0xfffffff0"));129 EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xf0}), ErrorResult);130 131 // DWARF64 marker without the subsequent length field.132 EXPECT_THAT_EXPECTED(133 GetWithError({0xff, 0xff, 0xff, 0xff}),134 FailedWithMessage(135 "unexpected end of data at offset 0x4 while reading [0x4, 0xc)"));136 EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff}), ErrorResult);137 138 // Not enough data for the U64 length.139 EXPECT_THAT_EXPECTED(140 GetWithError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03}),141 FailedWithMessage(142 "unexpected end of data at offset 0x8 while reading [0x4, 0xc)"));143 EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03}),144 ErrorResult);145 146 EXPECT_THAT_EXPECTED(147 GetWithError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,148 0x06, 0x07}),149 HasValue(std::make_tuple(0x0001020304050607, dwarf::DWARF64, 12)));150 EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03,151 0x04, 0x05, 0x06, 0x07}),152 std::make_tuple(0x0001020304050607, dwarf::DWARF64, 12));153}154 155TEST(DWARFDataExtractorTest, Truncation) {156 StringRef Yaml = R"(157!ELF158FileHeader:159 Class: ELFCLASS32160 Data: ELFDATA2LSB161 Type: ET_REL162 Machine: EM_386163Sections:164 - Name: .text165 Type: SHT_PROGBITS166 Size: 0x80167 - Name: .debug_line168 Type: SHT_PROGBITS169 Content: '616263640000000065666768'170 - Name: .rel.debug_line171 Type: SHT_REL172 Info: .debug_line173 Relocations:174 - Offset: 4175 Symbol: f176 Type: R_386_32177Symbols:178 - Name: f179 Type: STT_SECTION180 Section: .text181 Value: 0x42182)";183 SmallString<0> Storage;184 std::unique_ptr<object::ObjectFile> Obj = yaml::yaml2ObjectFile(185 Storage, Yaml, [](const Twine &Err) { errs() << Err; });186 ASSERT_TRUE(Obj);187 std::unique_ptr<DWARFContext> Ctx = DWARFContext::create(*Obj);188 const DWARFObject &DObj = Ctx->getDWARFObj();189 ASSERT_EQ(12u, DObj.getLineSection().Data.size());190 191 DWARFDataExtractor Data(DObj, DObj.getLineSection(), Obj->isLittleEndian(),192 Obj->getBytesInAddress());193 DataExtractor::Cursor C(0);194 EXPECT_EQ(0x64636261u, Data.getRelocatedAddress(C));195 EXPECT_EQ(0x42u, Data.getRelocatedAddress(C));196 EXPECT_EQ(0x68676665u, Data.getRelocatedAddress(C));197 EXPECT_THAT_ERROR(C.takeError(), Succeeded());198 199 C = DataExtractor::Cursor{0};200 DWARFDataExtractor Truncated8(Data, 8);201 EXPECT_EQ(0x64636261u, Truncated8.getRelocatedAddress(C));202 EXPECT_EQ(0x42u, Truncated8.getRelocatedAddress(C));203 EXPECT_EQ(0x0u, Truncated8.getRelocatedAddress(C));204 EXPECT_THAT_ERROR(205 C.takeError(),206 FailedWithMessage(207 "unexpected end of data at offset 0x8 while reading [0x8, 0xc)"));208 209 C = DataExtractor::Cursor{0};210 DWARFDataExtractor Truncated6(Data, 6);211 EXPECT_EQ(0x64636261u, Truncated6.getRelocatedAddress(C));212 EXPECT_EQ(0x0u, Truncated6.getRelocatedAddress(C));213 EXPECT_THAT_ERROR(214 C.takeError(),215 FailedWithMessage(216 "unexpected end of data at offset 0x6 while reading [0x4, 0x8)"));217 218 C = DataExtractor::Cursor{0};219 DWARFDataExtractor Truncated2(Data, 2);220 EXPECT_EQ(0x0u, Truncated2.getRelocatedAddress(C));221 EXPECT_THAT_ERROR(222 C.takeError(),223 FailedWithMessage(224 "unexpected end of data at offset 0x2 while reading [0x0, 0x4)"));225}226 227} // namespace228