Sort program headers by virt addr

When encoding ELF binary sort program headers by
virtual addresses incrementally.
This change is needed for compatibility with GDB.

Signed-off-by: Krystian Chmielewski <krystian.chmielewski@intel.com>
This commit is contained in:
Krystian Chmielewski
2022-01-10 14:45:23 +00:00
committed by Compute-Runtime-Automation
parent 34856747b4
commit 325ae63d05
3 changed files with 58 additions and 22 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2021 Intel Corporation
* Copyright (C) 2020-2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -455,3 +455,38 @@ TEST(ElfEncoder, WhenAppendingSectionNameThenEmplacedStringIsAlwaysNullterminate
EXPECT_STREQ("de", reinterpret_cast<const char *>(elfData.data() + sectionNamesSection->offset + strOffset2));
EXPECT_STREQ("g", reinterpret_cast<const char *>(elfData.data() + sectionNamesSection->offset + strOffset3));
}
TEST(ElfEncoder, WhenProgramHeadersArePresentThenTheyAreSortedByVirtualAddresses) {
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
const uint8_t data[] = "123412";
elfEncoder64.appendSection(SHT_PROGBITS, "", data);
elfEncoder64.appendSection(SHT_PROGBITS, "", data);
elfEncoder64.appendSection(SHT_PROGBITS, "", data);
elfEncoder64.appendSection(SHT_PROGBITS, "", data);
std::vector<std::pair<size_t, uint64_t>> sectionIdAndAddr = {{0, 0x1000},
{1, 0x2000},
{2, 0x500},
{3, 0x700}};
for (auto [secId, virtAddr] : sectionIdAndAddr) {
elfEncoder64.appendProgramHeaderLoad(secId, virtAddr, sizeof(data));
}
std::sort(sectionIdAndAddr.begin(), sectionIdAndAddr.end(), [](auto a, auto b) { return a.second < b.second; });
auto elfData = elfEncoder64.encode();
auto header = reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData.data());
ArrayRef<ElfSectionHeader<EI_CLASS_64>> sectionHeaders = {reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData.data() + header->shOff),
static_cast<size_t>(header->shNum)};
ArrayRef<ElfProgramHeader<EI_CLASS_64>> programHeaders = {reinterpret_cast<ElfProgramHeader<EI_CLASS_64> *>(elfData.data() + header->phOff),
static_cast<size_t>(header->phNum)};
EXPECT_EQ(4U, programHeaders.size());
for (size_t i = 0; i < 4U; i++) {
auto [secId, virtAddr] = sectionIdAndAddr[i];
EXPECT_EQ(virtAddr, programHeaders[i].vAddr);
EXPECT_EQ(sectionHeaders[secId].offset, programHeaders[i].offset);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021 Intel Corporation
* Copyright (C) 2021-2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -24,6 +24,8 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) {
uint8_t debugInfo[0x20] = {0x0};
uint8_t debugAbbrev[8] = {0x0};
using Segment = NEO::Debug::Segments::Segment;
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "kernel", ArrayRef<const uint8_t>(kernelISA, sizeof(kernelISA)));
auto kernelSectionIndex = elfEncoder.getLastSectionHeaderIndex();
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::dataConst, ArrayRef<const uint8_t>(constData, sizeof(constData)));
@@ -98,6 +100,7 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) {
segments.varData = {reinterpret_cast<uintptr_t>(varData), {varData, sizeof(varData)}};
segments.stringData = {reinterpret_cast<uintptr_t>(stringData), {stringData, sizeof(stringData)}};
segments.nameToSegMap["kernel"] = {reinterpret_cast<uintptr_t>(kernelISA), {kernelISA, sizeof(kernelISA)}};
auto zebinBin = elfEncoder.encode();
std::string warning, error;
@@ -119,7 +122,7 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) {
EXPECT_EQ(zebin.sectionHeaders.size(), debugZebin.sectionHeaders.size());
uint64_t offsetKernel, offsetConstData, offsetVarData, offsetStringData;
offsetKernel = offsetConstData = offsetVarData = std::numeric_limits<uint64_t>::max();
offsetKernel = offsetConstData = offsetVarData = offsetStringData = std::numeric_limits<uint64_t>::max();
for (uint32_t i = 0; i < zebin.sectionHeaders.size(); ++i) {
EXPECT_EQ(zebin.sectionHeaders[i].header->type, debugZebin.sectionHeaders[i].header->type);
EXPECT_EQ(zebin.sectionHeaders[i].header->link, debugZebin.sectionHeaders[i].header->link);
@@ -177,26 +180,23 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) {
}
}
std::vector<std::pair<Segment, uint64_t>> segmentsSortedByAddr = {{segments.constData, offsetConstData},
{segments.varData, offsetVarData},
{segments.stringData, offsetStringData},
{segments.nameToSegMap["kernel"], offsetKernel}};
std::sort(segmentsSortedByAddr.begin(), segmentsSortedByAddr.end(), [](auto seg1, auto seg2) { return seg1.first.address < seg2.first.address; });
EXPECT_EQ(4U, debugZebin.programHeaders.size());
EXPECT_EQ(segments.nameToSegMap["kernel"].address, static_cast<uintptr_t>(debugZebin.programHeaders[0].header->vAddr));
EXPECT_EQ(segments.nameToSegMap["kernel"].data.size(), static_cast<uintptr_t>(debugZebin.programHeaders[0].header->fileSz));
EXPECT_EQ(segments.nameToSegMap["kernel"].data.size(), static_cast<uintptr_t>(debugZebin.programHeaders[0].header->memSz));
EXPECT_EQ(offsetKernel, static_cast<uintptr_t>(debugZebin.programHeaders[0].header->offset));
for (size_t i = 0; i < 4U; i++) {
auto &segment = segmentsSortedByAddr[i].first;
auto &offset = segmentsSortedByAddr[i].second;
auto &ph = debugZebin.programHeaders[i].header;
EXPECT_EQ(segments.constData.address, static_cast<uintptr_t>(debugZebin.programHeaders[1].header->vAddr));
EXPECT_EQ(segments.constData.data.size(), static_cast<uintptr_t>(debugZebin.programHeaders[1].header->fileSz));
EXPECT_EQ(segments.constData.data.size(), static_cast<uintptr_t>(debugZebin.programHeaders[1].header->memSz));
EXPECT_EQ(offsetConstData, static_cast<uintptr_t>(debugZebin.programHeaders[1].header->offset));
EXPECT_EQ(segments.varData.address, static_cast<uintptr_t>(debugZebin.programHeaders[2].header->vAddr));
EXPECT_EQ(segments.varData.data.size(), static_cast<uintptr_t>(debugZebin.programHeaders[2].header->fileSz));
EXPECT_EQ(segments.varData.data.size(), static_cast<uintptr_t>(debugZebin.programHeaders[2].header->memSz));
EXPECT_EQ(offsetVarData, static_cast<uintptr_t>(debugZebin.programHeaders[2].header->offset));
EXPECT_EQ(segments.stringData.address, static_cast<uintptr_t>(debugZebin.programHeaders[3].header->vAddr));
EXPECT_EQ(segments.stringData.data.size(), static_cast<uintptr_t>(debugZebin.programHeaders[3].header->fileSz));
EXPECT_EQ(segments.stringData.data.size(), static_cast<uintptr_t>(debugZebin.programHeaders[3].header->memSz));
EXPECT_EQ(offsetStringData, static_cast<uintptr_t>(debugZebin.programHeaders[3].header->offset));
EXPECT_EQ(segment.address, static_cast<uintptr_t>(ph->vAddr));
EXPECT_EQ(segment.data.size(), static_cast<size_t>(ph->fileSz));
EXPECT_EQ(segment.data.size(), static_cast<size_t>(ph->memSz));
EXPECT_EQ(offset, static_cast<uintptr_t>(ph->offset));
}
}
TEST(DebugZebinTest, givenInvalidZebinThenDebugZebinIsNotGenerated) {