mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
bbfbcfbfb2
Summary: This is a result of the discussion at D78113. Previously we would be only giving the current offset at which the error was detected. However, this was phrased somewhat ambiguously (as it could also mean that end of data was at that offset). The new error message includes the current offset as well as the extent of the data being read. I've changed a couple of file-level static functions into private member functions in order to avoid passing a bunch of new arguments everywhere. Reviewers: dblaikie, jhenderson Subscribers: hiraditya, MaskRay, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D78558
228 lines
7.6 KiB
C++
228 lines
7.6 KiB
C++
//===- DWARFDataExtractorTest.cpp -----------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
|
|
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
|
#include "llvm/Object/ObjectFile.h"
|
|
#include "llvm/ObjectYAML/yaml2obj.h"
|
|
#include "llvm/Testing/Support/Error.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
|
|
TEST(DWARFDataExtractorTest, getRelocatedValue) {
|
|
StringRef Yaml = R"(
|
|
!ELF
|
|
FileHeader:
|
|
Class: ELFCLASS32
|
|
Data: ELFDATA2LSB
|
|
Type: ET_REL
|
|
Machine: EM_386
|
|
Sections:
|
|
- Name: .text
|
|
Type: SHT_PROGBITS
|
|
Size: 0x80
|
|
- Name: .debug_line
|
|
Type: SHT_PROGBITS
|
|
Content: '000000000000'
|
|
- Name: .rel.debug_line
|
|
Type: SHT_REL
|
|
Info: .debug_line
|
|
Relocations:
|
|
- Offset: 0
|
|
Symbol: f
|
|
Type: R_386_32
|
|
- Offset: 4
|
|
Symbol: f
|
|
Type: R_386_32
|
|
Symbols:
|
|
- Name: f
|
|
Type: STT_SECTION
|
|
Section: .text
|
|
Value: 0x42
|
|
)";
|
|
SmallString<0> Storage;
|
|
std::unique_ptr<object::ObjectFile> Obj = yaml::yaml2ObjectFile(
|
|
Storage, Yaml, [](const Twine &Err) { errs() << Err; });
|
|
ASSERT_TRUE(Obj);
|
|
std::unique_ptr<DWARFContext> Ctx = DWARFContext::create(*Obj);
|
|
const DWARFObject &DObj = Ctx->getDWARFObj();
|
|
ASSERT_EQ(6u, DObj.getLineSection().Data.size());
|
|
|
|
DWARFDataExtractor Data(DObj, DObj.getLineSection(), Obj->isLittleEndian(),
|
|
Obj->getBytesInAddress());
|
|
DataExtractor::Cursor C(0);
|
|
EXPECT_EQ(0x42u, Data.getRelocatedAddress(C));
|
|
EXPECT_EQ(0u, Data.getRelocatedAddress(C));
|
|
EXPECT_THAT_ERROR(
|
|
C.takeError(),
|
|
FailedWithMessage(
|
|
"unexpected end of data at offset 0x6 while reading [0x4, 0x8)"));
|
|
}
|
|
|
|
TEST(DWARFDataExtractorTest, getInitialLength) {
|
|
auto GetWithError = [](ArrayRef<uint8_t> Bytes)
|
|
-> Expected<std::tuple<uint64_t, dwarf::DwarfFormat, uint64_t>> {
|
|
DWARFDataExtractor Data(Bytes, /*IsLittleEndian=*/false, /*AddressSize=*/8);
|
|
DWARFDataExtractor::Cursor C(0);
|
|
uint64_t Length;
|
|
dwarf::DwarfFormat Format;
|
|
std::tie(Length, Format) = Data.getInitialLength(C);
|
|
if (C)
|
|
return std::make_tuple(Length, Format, C.tell());
|
|
|
|
EXPECT_EQ(Length, 0u);
|
|
EXPECT_EQ(Format, dwarf::DWARF32);
|
|
EXPECT_EQ(C.tell(), 0u);
|
|
return C.takeError();
|
|
};
|
|
auto GetWithoutError = [](ArrayRef<uint8_t> Bytes) {
|
|
DWARFDataExtractor Data(Bytes, /*IsLittleEndian=*/false, /*AddressSize=*/8);
|
|
uint64_t Offset = 0;
|
|
uint64_t Length;
|
|
dwarf::DwarfFormat Format;
|
|
std::tie(Length, Format) = Data.getInitialLength(&Offset);
|
|
return std::make_tuple(Length, Format, Offset);
|
|
};
|
|
auto ErrorResult = std::make_tuple(0, dwarf::DWARF32, 0);
|
|
|
|
// Empty data.
|
|
EXPECT_THAT_EXPECTED(
|
|
GetWithError({}),
|
|
FailedWithMessage(
|
|
"unexpected end of data at offset 0x0 while reading [0x0, 0x4)"));
|
|
EXPECT_EQ(GetWithoutError({}), ErrorResult);
|
|
|
|
// Not long enough for the U32 field.
|
|
EXPECT_THAT_EXPECTED(
|
|
GetWithError({0x00, 0x01, 0x02}),
|
|
FailedWithMessage(
|
|
"unexpected end of data at offset 0x3 while reading [0x0, 0x4)"));
|
|
EXPECT_EQ(GetWithoutError({0x00, 0x01, 0x02}), ErrorResult);
|
|
|
|
EXPECT_THAT_EXPECTED(
|
|
GetWithError({0x00, 0x01, 0x02, 0x03}),
|
|
HasValue(std::make_tuple(0x00010203, dwarf::DWARF32, 4)));
|
|
EXPECT_EQ(GetWithoutError({0x00, 0x01, 0x02, 0x03}),
|
|
std::make_tuple(0x00010203, dwarf::DWARF32, 4));
|
|
|
|
// Zeroes are not an error, but without the Error object it is hard to tell
|
|
// them apart from a failed read.
|
|
EXPECT_THAT_EXPECTED(
|
|
GetWithError({0x00, 0x00, 0x00, 0x00}),
|
|
HasValue(std::make_tuple(0x00000000, dwarf::DWARF32, 4)));
|
|
EXPECT_EQ(GetWithoutError({0x00, 0x00, 0x00, 0x00}),
|
|
std::make_tuple(0x00000000, dwarf::DWARF32, 4));
|
|
|
|
// Smallest invalid value.
|
|
EXPECT_THAT_EXPECTED(
|
|
GetWithError({0xff, 0xff, 0xff, 0xf0}),
|
|
FailedWithMessage(
|
|
"unsupported reserved unit length of value 0xfffffff0"));
|
|
EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xf0}), ErrorResult);
|
|
|
|
// DWARF64 marker without the subsequent length field.
|
|
EXPECT_THAT_EXPECTED(
|
|
GetWithError({0xff, 0xff, 0xff, 0xff}),
|
|
FailedWithMessage(
|
|
"unexpected end of data at offset 0x4 while reading [0x4, 0xc)"));
|
|
EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff}), ErrorResult);
|
|
|
|
// Not enough data for the U64 length.
|
|
EXPECT_THAT_EXPECTED(
|
|
GetWithError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03}),
|
|
FailedWithMessage(
|
|
"unexpected end of data at offset 0x8 while reading [0x4, 0xc)"));
|
|
EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03}),
|
|
ErrorResult);
|
|
|
|
EXPECT_THAT_EXPECTED(
|
|
GetWithError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
|
|
0x06, 0x07}),
|
|
HasValue(std::make_tuple(0x0001020304050607, dwarf::DWARF64, 12)));
|
|
EXPECT_EQ(GetWithoutError({0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03,
|
|
0x04, 0x05, 0x06, 0x07}),
|
|
std::make_tuple(0x0001020304050607, dwarf::DWARF64, 12));
|
|
}
|
|
|
|
TEST(DWARFDataExtractorTest, Truncation) {
|
|
StringRef Yaml = R"(
|
|
!ELF
|
|
FileHeader:
|
|
Class: ELFCLASS32
|
|
Data: ELFDATA2LSB
|
|
Type: ET_REL
|
|
Machine: EM_386
|
|
Sections:
|
|
- Name: .text
|
|
Type: SHT_PROGBITS
|
|
Size: 0x80
|
|
- Name: .debug_line
|
|
Type: SHT_PROGBITS
|
|
Content: '616263640000000065666768'
|
|
- Name: .rel.debug_line
|
|
Type: SHT_REL
|
|
Info: .debug_line
|
|
Relocations:
|
|
- Offset: 4
|
|
Symbol: f
|
|
Type: R_386_32
|
|
Symbols:
|
|
- Name: f
|
|
Type: STT_SECTION
|
|
Section: .text
|
|
Value: 0x42
|
|
)";
|
|
SmallString<0> Storage;
|
|
std::unique_ptr<object::ObjectFile> Obj = yaml::yaml2ObjectFile(
|
|
Storage, Yaml, [](const Twine &Err) { errs() << Err; });
|
|
ASSERT_TRUE(Obj);
|
|
std::unique_ptr<DWARFContext> Ctx = DWARFContext::create(*Obj);
|
|
const DWARFObject &DObj = Ctx->getDWARFObj();
|
|
ASSERT_EQ(12u, DObj.getLineSection().Data.size());
|
|
|
|
DWARFDataExtractor Data(DObj, DObj.getLineSection(), Obj->isLittleEndian(),
|
|
Obj->getBytesInAddress());
|
|
DataExtractor::Cursor C(0);
|
|
EXPECT_EQ(0x64636261u, Data.getRelocatedAddress(C));
|
|
EXPECT_EQ(0x42u, Data.getRelocatedAddress(C));
|
|
EXPECT_EQ(0x68676665u, Data.getRelocatedAddress(C));
|
|
EXPECT_THAT_ERROR(C.takeError(), Succeeded());
|
|
|
|
C = DataExtractor::Cursor{0};
|
|
DWARFDataExtractor Truncated8(Data, 8);
|
|
EXPECT_EQ(0x64636261u, Truncated8.getRelocatedAddress(C));
|
|
EXPECT_EQ(0x42u, Truncated8.getRelocatedAddress(C));
|
|
EXPECT_EQ(0x0u, Truncated8.getRelocatedAddress(C));
|
|
EXPECT_THAT_ERROR(
|
|
C.takeError(),
|
|
FailedWithMessage(
|
|
"unexpected end of data at offset 0x8 while reading [0x8, 0xc)"));
|
|
|
|
C = DataExtractor::Cursor{0};
|
|
DWARFDataExtractor Truncated6(Data, 6);
|
|
EXPECT_EQ(0x64636261u, Truncated6.getRelocatedAddress(C));
|
|
EXPECT_EQ(0x0u, Truncated6.getRelocatedAddress(C));
|
|
EXPECT_THAT_ERROR(
|
|
C.takeError(),
|
|
FailedWithMessage(
|
|
"unexpected end of data at offset 0x6 while reading [0x4, 0x8)"));
|
|
|
|
C = DataExtractor::Cursor{0};
|
|
DWARFDataExtractor Truncated2(Data, 2);
|
|
EXPECT_EQ(0x0u, Truncated2.getRelocatedAddress(C));
|
|
EXPECT_THAT_ERROR(
|
|
C.takeError(),
|
|
FailedWithMessage(
|
|
"unexpected end of data at offset 0x2 while reading [0x0, 0x4)"));
|
|
}
|
|
|
|
} // namespace
|