CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
315 lines
10 KiB
C++
315 lines
10 KiB
C++
//===- DWARFAcceleratorTableTest.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/DWARFAcceleratorTable.h"
|
|
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
|
#include "llvm/ObjectYAML/DWARFEmitter.h"
|
|
#include "llvm/Testing/Support/Error.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
|
|
static Error ExtractDebugNames(StringRef NamesSecData, StringRef StrSecData) {
|
|
DWARFDataExtractor NamesExtractor(NamesSecData,
|
|
/*isLittleEndian=*/true,
|
|
/*AddrSize=*/4);
|
|
DataExtractor StrExtractor(StrSecData, /*isLittleEndian=*/true);
|
|
DWARFDebugNames Table(NamesExtractor, StrExtractor);
|
|
return Table.extract();
|
|
}
|
|
|
|
namespace {
|
|
|
|
TEST(DWARFDebugNames, ReservedUnitLength) {
|
|
static const char NamesSecData[64] =
|
|
"\xf0\xff\xff\xff"; // Reserved unit length value
|
|
EXPECT_THAT_ERROR(
|
|
ExtractDebugNames(StringRef(NamesSecData, sizeof(NamesSecData)),
|
|
StringRef()),
|
|
FailedWithMessage("parsing .debug_names header at 0x0: unsupported "
|
|
"reserved unit length of value 0xfffffff0"));
|
|
}
|
|
|
|
TEST(DWARFDebugNames, TooSmallForDWARF64) {
|
|
// DWARF64 header takes at least 44 bytes.
|
|
static const char NamesSecData[43] = "\xff\xff\xff\xff"; // DWARF64 mark
|
|
EXPECT_THAT_ERROR(
|
|
ExtractDebugNames(StringRef(NamesSecData, sizeof(NamesSecData)),
|
|
StringRef()),
|
|
FailedWithMessage("parsing .debug_names header at 0x0: unexpected end of "
|
|
"data at offset 0x2b while reading [0x28, 0x2c)"));
|
|
}
|
|
|
|
TEST(DWARFDebugNames, BasicTestEntries) {
|
|
const char *Yamldata = R"(
|
|
--- !ELF
|
|
debug_str:
|
|
- 'NameType1'
|
|
- 'NameType2'
|
|
|
|
debug_names:
|
|
Abbreviations:
|
|
- Code: 0x1
|
|
Tag: DW_TAG_namespace
|
|
Indices:
|
|
- Idx: DW_IDX_compile_unit
|
|
Form: DW_FORM_data4
|
|
- Idx: DW_IDX_die_offset
|
|
Form: DW_FORM_ref4
|
|
Entries:
|
|
- Name: 0x0 # strp to NameType1
|
|
Code: 0x1
|
|
Values:
|
|
- 0x0 # Compile unit
|
|
- 0x0 # DIE Offset
|
|
- Name: 0xa # strp to NameType2
|
|
Code: 0x1
|
|
Values:
|
|
- 0x1 # Compile unit
|
|
- 0x1 # DIE Offset
|
|
- Name: 0x0 # strp to NameType1
|
|
Code: 0x1
|
|
Values:
|
|
- 0x2 # Compile unit
|
|
- 0x2 # DIE Offset
|
|
|
|
)";
|
|
|
|
Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =
|
|
DWARFYAML::emitDebugSections(Yamldata,
|
|
/*IsLittleEndian=*/true,
|
|
/*Is64BitAddrSize=*/true);
|
|
ASSERT_THAT_EXPECTED(Sections, Succeeded());
|
|
auto Ctx = DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true);
|
|
const DWARFDebugNames &DebugNames = Ctx->getDebugNames();
|
|
ASSERT_NE(DebugNames.begin(), DebugNames.end());
|
|
const DWARFDebugNames::NameIndex &NameIndex = *DebugNames.begin();
|
|
|
|
ASSERT_EQ(NameIndex.getNameCount(), 2u);
|
|
ASSERT_EQ(NameIndex.getBucketCount(), 0u);
|
|
ASSERT_EQ(NameIndex.getCUCount(), 1u);
|
|
ASSERT_EQ(NameIndex.getCUOffset(0), 0u);
|
|
ASSERT_EQ(NameIndex.getForeignTUCount(), 0u);
|
|
ASSERT_EQ(NameIndex.getLocalTUCount(), 0u);
|
|
|
|
// Check "NameEntries": there should be one per unique name.
|
|
// These are indexed starting on 1.
|
|
DWARFDebugNames::NameTableEntry FirstEntry = NameIndex.getNameTableEntry(1);
|
|
ASSERT_EQ(FirstEntry.getString(), StringRef("NameType1"));
|
|
DWARFDebugNames::NameTableEntry SecondEntry = NameIndex.getNameTableEntry(2);
|
|
ASSERT_EQ(SecondEntry.getString(), StringRef("NameType2"));
|
|
|
|
SmallVector<DWARFDebugNames::Entry> FirstNameEntries =
|
|
to_vector_of<DWARFDebugNames::Entry>(NameIndex.equal_range("NameType1"));
|
|
ASSERT_EQ(FirstNameEntries.size(), 2u);
|
|
ASSERT_EQ(FirstNameEntries[0].getCUIndex(), 0u);
|
|
ASSERT_EQ(FirstNameEntries[1].getCUIndex(), 0x2);
|
|
ASSERT_EQ(FirstNameEntries[0].getDIEUnitOffset(), 0x0);
|
|
ASSERT_EQ(FirstNameEntries[1].getDIEUnitOffset(), 0x2);
|
|
|
|
SmallVector<DWARFDebugNames::Entry> SecondNameEntries =
|
|
to_vector_of<DWARFDebugNames::Entry>(NameIndex.equal_range("NameType2"));
|
|
ASSERT_EQ(SecondNameEntries.size(), 1u);
|
|
ASSERT_EQ(SecondNameEntries[0].getCUIndex(), 0x1);
|
|
ASSERT_EQ(SecondNameEntries[0].getDIEUnitOffset(), 0x1);
|
|
}
|
|
|
|
TEST(DWARFDebugNames, ParentEntries) {
|
|
const char *Yamldata = R"(
|
|
--- !ELF
|
|
debug_str:
|
|
- 'Name1'
|
|
- 'Name2'
|
|
- 'Name3'
|
|
- 'Name4'
|
|
debug_names:
|
|
Abbreviations:
|
|
- Code: 0x11
|
|
Tag: DW_TAG_namespace
|
|
Indices:
|
|
- Idx: DW_IDX_parent
|
|
Form: DW_FORM_flag_present
|
|
- Idx: DW_IDX_die_offset
|
|
Form: DW_FORM_ref4
|
|
- Code: 0x22
|
|
Tag: DW_TAG_namespace
|
|
Indices:
|
|
- Idx: DW_IDX_parent
|
|
Form: DW_FORM_ref4
|
|
- Idx: DW_IDX_die_offset
|
|
Form: DW_FORM_ref4
|
|
- Code: 0x33
|
|
Tag: DW_TAG_namespace
|
|
Indices:
|
|
- Idx: DW_IDX_die_offset
|
|
Form: DW_FORM_ref4
|
|
Entries:
|
|
- Name: 0x0 # strp to Name1
|
|
Code: 0x11
|
|
Values:
|
|
- 0x0 # Die offset
|
|
- Name: 0x6 # strp to Name2
|
|
Code: 0x22
|
|
Values:
|
|
- 0x0 # Parent = First entry
|
|
- 0x1 # Die offset
|
|
- Name: 0xc # strp to Name3
|
|
Code: 0x22
|
|
Values:
|
|
- 0x6 # Parent = Second entry
|
|
- 0x1 # Die offset
|
|
- Name: 0x12 # strp to Name4
|
|
Code: 0x33
|
|
Values:
|
|
- 0x1 # Die offset
|
|
)";
|
|
|
|
Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =
|
|
DWARFYAML::emitDebugSections(Yamldata,
|
|
/*IsLittleEndian=*/true,
|
|
/*Is64BitAddrSize=*/true);
|
|
ASSERT_THAT_EXPECTED(Sections, Succeeded());
|
|
auto Ctx = DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true);
|
|
const DWARFDebugNames &DebugNames = Ctx->getDebugNames();
|
|
ASSERT_NE(DebugNames.begin(), DebugNames.end());
|
|
const DWARFDebugNames::NameIndex &NameIndex = *DebugNames.begin();
|
|
|
|
SmallVector<DWARFDebugNames::Entry> Name1Entries =
|
|
to_vector_of<DWARFDebugNames::Entry>(NameIndex.equal_range("Name1"));
|
|
ASSERT_EQ(Name1Entries.size(), 1u);
|
|
Expected<std::optional<DWARFDebugNames::Entry>> Name1Parent =
|
|
Name1Entries[0].getParentDIEEntry();
|
|
ASSERT_THAT_EXPECTED(Name1Parent, Succeeded());
|
|
ASSERT_EQ(*Name1Parent, std::nullopt); // Name1 has no parent
|
|
|
|
SmallVector<DWARFDebugNames::Entry> Name2Entries =
|
|
to_vector_of<DWARFDebugNames::Entry>(NameIndex.equal_range("Name2"));
|
|
ASSERT_EQ(Name2Entries.size(), 1u);
|
|
Expected<std::optional<DWARFDebugNames::Entry>> Name2Parent =
|
|
Name2Entries[0].getParentDIEEntry();
|
|
ASSERT_THAT_EXPECTED(Name2Parent, Succeeded());
|
|
ASSERT_EQ((**Name2Parent).getDIEUnitOffset(), 0x0); // Name2 parent == Name1
|
|
|
|
SmallVector<DWARFDebugNames::Entry> Name3Entries =
|
|
to_vector_of<DWARFDebugNames::Entry>(NameIndex.equal_range("Name3"));
|
|
ASSERT_EQ(Name3Entries.size(), 1u);
|
|
Expected<std::optional<DWARFDebugNames::Entry>> Name3Parent =
|
|
Name3Entries[0].getParentDIEEntry();
|
|
ASSERT_THAT_EXPECTED(Name3Parent, Succeeded());
|
|
ASSERT_EQ((**Name3Parent).getDIEUnitOffset(), 0x1); // Name3 parent == Name2
|
|
|
|
SmallVector<DWARFDebugNames::Entry> Name4Entries =
|
|
to_vector_of<DWARFDebugNames::Entry>(NameIndex.equal_range("Name4"));
|
|
ASSERT_EQ(Name4Entries.size(), 1u);
|
|
ASSERT_FALSE(Name4Entries[0].hasParentInformation());
|
|
}
|
|
|
|
TEST(DWARFDebugNames, InvalidAbbrevCode) {
|
|
const char *Yamldata = R"(
|
|
--- !ELF
|
|
debug_str:
|
|
- 'NameType1'
|
|
|
|
debug_names:
|
|
Abbreviations:
|
|
- Code: 0x1
|
|
Tag: DW_TAG_namespace
|
|
Indices:
|
|
- Idx: DW_IDX_compile_unit
|
|
Form: DW_FORM_data4
|
|
Entries:
|
|
- Name: 0x0 # strp to NameType1
|
|
Code: 0x123456
|
|
Values:
|
|
- 0x0 # Compile unit
|
|
)";
|
|
|
|
Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =
|
|
DWARFYAML::emitDebugSections(Yamldata,
|
|
/*IsLittleEndian=*/true,
|
|
/*Is64BitAddrSize=*/true);
|
|
ASSERT_THAT_EXPECTED(
|
|
Sections,
|
|
FailedWithMessage("did not find an Abbreviation for this code"));
|
|
}
|
|
|
|
TEST(DWARFDebugNames, InvalidNumOfValues) {
|
|
const char *Yamldata = R"(
|
|
--- !ELF
|
|
debug_str:
|
|
- 'NameType1'
|
|
|
|
debug_names:
|
|
Abbreviations:
|
|
- Code: 0x1
|
|
Tag: DW_TAG_namespace
|
|
Indices:
|
|
- Idx: DW_IDX_compile_unit
|
|
Form: DW_FORM_data4
|
|
Entries:
|
|
- Name: 0x0 # strp to NameType1
|
|
Code: 0x1
|
|
Values:
|
|
- 0x0 # Compile unit
|
|
- 0x0 # Compile unit
|
|
- 0x0 # Compile unit
|
|
)";
|
|
|
|
Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =
|
|
DWARFYAML::emitDebugSections(Yamldata,
|
|
/*IsLittleEndian=*/true,
|
|
/*Is64BitAddrSize=*/true);
|
|
ASSERT_THAT_EXPECTED(
|
|
Sections, FailedWithMessage(
|
|
"mismatch between provided and required number of values"));
|
|
}
|
|
|
|
TEST(DWARFDebugNames, UnsupportedForm) {
|
|
const char *Yamldata = R"(
|
|
--- !ELF
|
|
debug_str:
|
|
- 'NameType1'
|
|
|
|
debug_names:
|
|
Abbreviations:
|
|
- Code: 0x1
|
|
Tag: DW_TAG_namespace
|
|
Indices:
|
|
- Idx: DW_IDX_compile_unit
|
|
Form: DW_FORM_strx
|
|
Entries:
|
|
- Name: 0x0 # strp to NameType1
|
|
Code: 0x1
|
|
Values:
|
|
- 0x0 # Compile unit
|
|
)";
|
|
|
|
Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =
|
|
DWARFYAML::emitDebugSections(Yamldata,
|
|
/*IsLittleEndian=*/true,
|
|
/*Is64BitAddrSize=*/true);
|
|
ASSERT_THAT_EXPECTED(
|
|
Sections,
|
|
FailedWithMessage("unsupported Form for YAML debug_names emitter"));
|
|
}
|
|
|
|
TEST(DWARFDebugNames, TestStripTemplateParameters) {
|
|
|
|
std::optional<StringRef> stripped_name;
|
|
// Make sure we can extract the name "foo" from the template parameters.
|
|
stripped_name = StripTemplateParameters("foo<int>");
|
|
ASSERT_TRUE(stripped_name.has_value());
|
|
ASSERT_EQ(*stripped_name, StringRef("foo"));
|
|
// Make sure that we don't get a valid name back when the string starts with
|
|
// '<'.
|
|
stripped_name = StripTemplateParameters("<int>");
|
|
ASSERT_FALSE(stripped_name.has_value());
|
|
}
|
|
|
|
} // end anonymous namespace
|