blob: bdd4ca5b019960bf5df5db2891853c2beea2dabf [file] [log] [blame]
//===- llvm/unittest/DebugInfo/DWARFDebugArangeSetTest.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/DWARFDebugArangeSet.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
struct WarningHandler {
~WarningHandler() { EXPECT_THAT_ERROR(std::move(Err), Succeeded()); }
void operator()(Error E) { Err = joinErrors(std::move(Err), std::move(E)); }
Error getWarning() { return std::move(Err); }
Error Err = Error::success();
};
template <size_t SecSize>
void ExpectExtractError(const char (&SecDataRaw)[SecSize],
const char *ErrorMessage) {
DWARFDataExtractor Extractor(StringRef(SecDataRaw, SecSize - 1),
/* IsLittleEndian = */ true,
/* AddressSize = */ 4);
DWARFDebugArangeSet Set;
uint64_t Offset = 0;
WarningHandler Warnings;
Error E = Set.extract(Extractor, &Offset, Warnings);
ASSERT_TRUE(E.operator bool());
EXPECT_STREQ(ErrorMessage, toString(std::move(E)).c_str());
}
TEST(DWARFDebugArangeSet, LengthExceedsSectionSize) {
static const char DebugArangesSecRaw[] =
"\x15\x00\x00\x00" // The length exceeds the section boundaries
"\x02\x00" // Version
"\x00\x00\x00\x00" // Debug Info Offset
"\x04" // Address Size
"\x00" // Segment Selector Size
"\x00\x00\x00\x00" // Padding
"\x00\x00\x00\x00" // Termination tuple
"\x00\x00\x00\x00";
ExpectExtractError(
DebugArangesSecRaw,
"the length of address range table at offset 0x0 exceeds section size");
}
TEST(DWARFDebugArangeSet, LengthExceedsSectionSizeDWARF64) {
static const char DebugArangesSecRaw[] =
"\xff\xff\xff\xff" // DWARF64 mark
"\x15\x00\x00\x00\x00\x00\x00\x00" // The length exceeds the section
// boundaries
"\x02\x00" // Version
"\x00\x00\x00\x00\x00\x00\x00\x00" // Debug Info Offset
"\x04" // Address Size
"\x00" // Segment Selector Size
// No padding
"\x00\x00\x00\x00" // Termination tuple
"\x00\x00\x00\x00";
ExpectExtractError(
DebugArangesSecRaw,
"the length of address range table at offset 0x0 exceeds section size");
}
TEST(DWARFDebugArangeSet, UnsupportedAddressSize) {
static const char DebugArangesSecRaw[] =
"\x0c\x00\x00\x00" // Length
"\x02\x00" // Version
"\x00\x00\x00\x00" // Debug Info Offset
"\x02" // Address Size (not supported)
"\x00" // Segment Selector Size
// No padding
"\x00\x00\x00\x00"; // Termination tuple
ExpectExtractError(
DebugArangesSecRaw,
"address range table at offset 0x0 has unsupported address size: 2 "
"(4 and 8 supported)");
}
TEST(DWARFDebugArangeSet, UnsupportedSegmentSelectorSize) {
static const char DebugArangesSecRaw[] =
"\x14\x00\x00\x00" // Length
"\x02\x00" // Version
"\x00\x00\x00\x00" // Debug Info Offset
"\x04" // Address Size
"\x04" // Segment Selector Size (not supported)
// No padding
"\x00\x00\x00\x00" // Termination tuple
"\x00\x00\x00\x00"
"\x00\x00\x00\x00";
ExpectExtractError(
DebugArangesSecRaw,
"non-zero segment selector size in address range table at offset 0x0 "
"is not supported");
}
TEST(DWARFDebugArangeSet, NoTerminationEntry) {
static const char DebugArangesSecRaw[] =
"\x14\x00\x00\x00" // Length
"\x02\x00" // Version
"\x00\x00\x00\x00" // Debug Info Offset
"\x04" // Address Size
"\x00" // Segment Selector Size
"\x00\x00\x00\x00" // Padding
"\x00\x00\x00\x00" // Entry: Address
"\x01\x00\x00\x00" // Length
; // No termination tuple
ExpectExtractError(
DebugArangesSecRaw,
"address range table at offset 0x0 is not terminated by null entry");
}
TEST(DWARFDebugArangeSet, ReservedUnitLength) {
// Note: 12 is the minimum length to pass the basic check for the size of
// the section. 1 will be automatically subtracted in ExpectExtractError().
static const char DebugArangesSecRaw[12 + 1] =
"\xf0\xff\xff\xff"; // Reserved unit length value
ExpectExtractError(DebugArangesSecRaw,
"parsing address ranges table at offset 0x0: unsupported "
"reserved unit length of value 0xfffffff0");
}
TEST(DWARFDebugArangeSet, SectionTooShort) {
// Note: 1 will be automatically subtracted in ExpectExtractError().
static const char DebugArangesSecRaw[11 + 1] = {0};
ExpectExtractError(DebugArangesSecRaw,
"parsing address ranges table at offset 0x0: unexpected "
"end of data at offset 0xb while reading [0xb, 0xc)");
}
TEST(DWARFDebugArangeSet, SectionTooShortDWARF64) {
// Note: 1 will be automatically subtracted in ExpectExtractError().
static const char DebugArangesSecRaw[23 + 1] =
"\xff\xff\xff\xff"; // DWARF64 mark
ExpectExtractError(DebugArangesSecRaw,
"parsing address ranges table at offset 0x0: unexpected "
"end of data at offset 0x17 while reading [0x17, 0x18)");
}
TEST(DWARFDebugArangeSet, NoSpaceForEntries) {
static const char DebugArangesSecRaw[] =
"\x0c\x00\x00\x00" // Length
"\x02\x00" // Version
"\x00\x00\x00\x00" // Debug Info Offset
"\x04" // Address Size
"\x00" // Segment Selector Size
"\x00\x00\x00\x00" // Padding
; // No entries
ExpectExtractError(
DebugArangesSecRaw,
"address range table at offset 0x0 has an insufficient length "
"to contain any entries");
}
TEST(DWARFDebugArangeSet, UnevenLength) {
static const char DebugArangesSecRaw[] =
"\x1b\x00\x00\x00" // Length (not a multiple of tuple size)
"\x02\x00" // Version
"\x00\x00\x00\x00" // Debug Info Offset
"\x04" // Address Size
"\x00" // Segment Selector Size
"\x00\x00\x00\x00" // Padding
"\x00\x00\x00\x00" // Entry: Address
"\x01\x00\x00\x00" // Length
"\x00\x00\x00\x00" // Termination tuple
"\x00\x00\x00\x00";
ExpectExtractError(
DebugArangesSecRaw,
"address range table at offset 0x0 has length that is not a multiple "
"of the tuple size");
}
TEST(DWARFDebugArangeSet, ZeroAddressEntry) {
static const char DebugArangesSecRaw[] =
"\x1c\x00\x00\x00" // Length
"\x02\x00" // Version
"\x00\x00\x00\x00" // Debug Info Offset
"\x04" // Address Size
"\x00" // Segment Selector Size
"\x00\x00\x00\x00" // Padding
"\x00\x00\x00\x00" // Entry1: Address
"\x01\x00\x00\x00" // Length
"\x00\x00\x00\x00" // Termination tuple
"\x00\x00\x00\x00";
DWARFDataExtractor Extractor(
StringRef(DebugArangesSecRaw, sizeof(DebugArangesSecRaw) - 1),
/*IsLittleEndian=*/true,
/*AddressSize=*/4);
DWARFDebugArangeSet Set;
uint64_t Offset = 0;
ASSERT_THAT_ERROR(Set.extract(Extractor, &Offset, WarningHandler()),
Succeeded());
auto Range = Set.descriptors();
auto Iter = Range.begin();
ASSERT_EQ(std::distance(Iter, Range.end()), 1);
EXPECT_EQ(Iter->Address, 0u);
EXPECT_EQ(Iter->Length, 1u);
}
TEST(DWARFDebugArangeSet, ZeroLengthEntry) {
static const char DebugArangesSecRaw[] =
"\x1c\x00\x00\x00" // Length
"\x02\x00" // Version
"\x00\x00\x00\x00" // Debug Info Offset
"\x04" // Address Size
"\x00" // Segment Selector Size
"\x00\x00\x00\x00" // Padding
"\x01\x00\x00\x00" // Entry1: Address
"\x00\x00\x00\x00" // Length
"\x00\x00\x00\x00" // Termination tuple
"\x00\x00\x00\x00";
DWARFDataExtractor Extractor(
StringRef(DebugArangesSecRaw, sizeof(DebugArangesSecRaw) - 1),
/*IsLittleEndian=*/true,
/*AddressSize=*/4);
DWARFDebugArangeSet Set;
uint64_t Offset = 0;
ASSERT_THAT_ERROR(Set.extract(Extractor, &Offset, WarningHandler()),
Succeeded());
auto Range = Set.descriptors();
auto Iter = Range.begin();
ASSERT_EQ(std::distance(Iter, Range.end()), 1);
EXPECT_EQ(Iter->Address, 1u);
EXPECT_EQ(Iter->Length, 0u);
}
TEST(DWARFDebugArangesSet, PrematureTerminator) {
static const char DebugArangesSecRaw[] =
"\x24\x00\x00\x00" // Length
"\x02\x00" // Version
"\x00\x00\x00\x00" // Debug Info Offset
"\x04" // Address Size
"\x00" // Segment Selector Size
"\x00\x00\x00\x00" // Padding
"\x00\x00\x00\x00" // Entry1: Premature
"\x00\x00\x00\x00" // terminator
"\x01\x00\x00\x00" // Entry2: Address
"\x01\x00\x00\x00" // Length
"\x00\x00\x00\x00" // Termination tuple
"\x00\x00\x00\x00";
DWARFDataExtractor Extractor(
StringRef(DebugArangesSecRaw, sizeof(DebugArangesSecRaw) - 1),
/*IsLittleEndian=*/true,
/*AddressSize=*/4);
DWARFDebugArangeSet Set;
uint64_t Offset = 0;
WarningHandler Warnings;
ASSERT_THAT_ERROR(Set.extract(Extractor, &Offset, Warnings), Succeeded());
auto Range = Set.descriptors();
auto Iter = Range.begin();
ASSERT_EQ(std::distance(Iter, Range.end()), 2);
EXPECT_EQ(Iter->Address, 0u);
EXPECT_EQ(Iter->Length, 0u);
++Iter;
EXPECT_EQ(Iter->Address, 1u);
EXPECT_EQ(Iter->Length, 1u);
EXPECT_THAT_ERROR(
Warnings.getWarning(),
FailedWithMessage("address range table at offset 0x0 has a premature "
"terminator entry at offset 0x10"));
}
} // end anonymous namespace