mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-19 06:24:51 +08:00
feature: Adding elf rewriter utility
It will aid in various elf patching tasks both in ocloc and UMD Related-To: NEO-10190 Signed-off-by: Chodor, Jaroslaw <jaroslaw.chodor@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
bfc3e8fcf0
commit
90927135f9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2023 Intel Corporation
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -227,11 +227,11 @@ TEST_F(ClLinkProgramTests, GivenProgramsWithSpecConstantsThenSpecConstantsAreEmb
|
||||
ASSERT_EQ(sizeof(ir2), elf.sectionHeaders[6].data.size());
|
||||
ASSERT_EQ(sizeof(ir3), elf.sectionHeaders[7].data.size());
|
||||
|
||||
auto readSpecConstId = [](NEO::Elf::Elf<NEO::Elf::EI_CLASS_64>::SectionHeaderAndData §ion, uint32_t offset) {
|
||||
auto readSpecConstId = [](NEO::Elf::SectionHeaderAndData<NEO::Elf::EI_CLASS_64> §ion, uint32_t offset) {
|
||||
return *(reinterpret_cast<const uint32_t *>(section.data.begin()) + offset);
|
||||
};
|
||||
|
||||
auto readSpecConstValue = [](NEO::Elf::Elf<NEO::Elf::EI_CLASS_64>::SectionHeaderAndData §ion, uint32_t offset) {
|
||||
auto readSpecConstValue = [](NEO::Elf::SectionHeaderAndData<NEO::Elf::EI_CLASS_64> §ion, uint32_t offset) {
|
||||
return *(reinterpret_cast<const uint64_t *>(section.data.begin()) + offset);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2023 Intel Corporation
|
||||
* Copyright (C) 2020-2024 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "shared/source/device_binary_format/elf/elf_decoder.h"
|
||||
|
||||
#include "shared/source/device_binary_format/elf/elf.h"
|
||||
#include "shared/source/helpers/aligned_memory.h"
|
||||
#include "shared/source/helpers/ptr_math.h"
|
||||
|
||||
#include <string.h>
|
||||
@@ -16,6 +17,30 @@ namespace NEO {
|
||||
|
||||
namespace Elf {
|
||||
|
||||
template <ElfIdentifierClass numBits>
|
||||
bool decodeNoteSection(ArrayRef<const uint8_t> sectionData, std::vector<DecodedNote> &out, std::string &outErrReason, std::string &outWarning) {
|
||||
uint64_t pos = 0;
|
||||
auto sectionSize = sectionData.size();
|
||||
auto base = sectionData.begin();
|
||||
while (pos < sectionSize) {
|
||||
auto note = reinterpret_cast<const ElfNoteSection *>(base + pos);
|
||||
auto alignedEntrySize = alignUp(sizeof(ElfNoteSection) + note->nameSize + note->descSize, 4);
|
||||
if (pos + alignedEntrySize > sectionSize) {
|
||||
outErrReason.append("Invalid elf note section - not enough data\n");
|
||||
return false;
|
||||
}
|
||||
ConstStringRef name{reinterpret_cast<const char *>(note + 1), note->nameSize};
|
||||
ConstStringRef desc{reinterpret_cast<const char *>(note + 1) + note->nameSize, note->descSize};
|
||||
pos += alignedEntrySize;
|
||||
|
||||
out.push_back(DecodedNote{name, desc, note->type});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool decodeNoteSection<EI_CLASS_32>(ArrayRef<const uint8_t> sectionData, std::vector<DecodedNote> &out, std::string &outErrReason, std::string &outWarning);
|
||||
template bool decodeNoteSection<EI_CLASS_64>(ArrayRef<const uint8_t> sectionData, std::vector<DecodedNote> &out, std::string &outErrReason, std::string &outWarning);
|
||||
|
||||
template <ElfIdentifierClass numBits>
|
||||
const ElfFileHeader<numBits> *decodeElfFileHeader(const ArrayRef<const uint8_t> binary) {
|
||||
if (binary.size() < sizeof(ElfFileHeader<numBits>)) {
|
||||
@@ -87,7 +112,7 @@ Elf<numBits> decodeElf(const ArrayRef<const uint8_t> binary, std::string &outErr
|
||||
}
|
||||
|
||||
template <ElfIdentifierClass numBits>
|
||||
bool Elf<numBits>::decodeSymTab(SectionHeaderAndData §ionHeaderData, std::string &outError) {
|
||||
bool Elf<numBits>::decodeSymTab(SectionHeaderAndData<numBits> §ionHeaderData, std::string &outError) {
|
||||
if (sectionHeaderData.header->type == SectionHeaderType::SHT_SYMTAB) {
|
||||
auto symSize = sizeof(ElfSymbolEntry<numBits>);
|
||||
if (symSize != sectionHeaderData.header->entsize) {
|
||||
@@ -107,7 +132,7 @@ bool Elf<numBits>::decodeSymTab(SectionHeaderAndData §ionHeaderData, std::st
|
||||
}
|
||||
|
||||
template <ElfIdentifierClass numBits>
|
||||
bool Elf<numBits>::decodeRelocations(SectionHeaderAndData §ionHeaderData, std::string &outError) {
|
||||
bool Elf<numBits>::decodeRelocations(SectionHeaderAndData<numBits> §ionHeaderData, std::string &outError) {
|
||||
if (sectionHeaderData.header->type == SectionHeaderType::SHT_RELA) {
|
||||
auto relaSize = sizeof(ElfRela<numBits>);
|
||||
if (relaSize != sectionHeaderData.header->entsize) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2023 Intel Corporation
|
||||
* Copyright (C) 2020-2024 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -22,18 +22,20 @@ enum class RelocationX8664Type : uint32_t {
|
||||
relocation32 = 0xa
|
||||
};
|
||||
|
||||
template <ElfIdentifierClass numBits = EI_CLASS_64>
|
||||
struct ProgramHeaderAndData {
|
||||
const ElfProgramHeader<numBits> *header = nullptr;
|
||||
ArrayRef<const uint8_t> data;
|
||||
};
|
||||
|
||||
template <ElfIdentifierClass numBits = EI_CLASS_64>
|
||||
struct SectionHeaderAndData {
|
||||
const ElfSectionHeader<numBits> *header;
|
||||
ArrayRef<const uint8_t> data;
|
||||
};
|
||||
|
||||
template <ElfIdentifierClass numBits = EI_CLASS_64>
|
||||
struct Elf {
|
||||
struct ProgramHeaderAndData {
|
||||
const ElfProgramHeader<numBits> *header = nullptr;
|
||||
ArrayRef<const uint8_t> data;
|
||||
};
|
||||
|
||||
struct SectionHeaderAndData {
|
||||
const ElfSectionHeader<numBits> *header;
|
||||
ArrayRef<const uint8_t> data;
|
||||
};
|
||||
|
||||
struct RelocationInfo {
|
||||
int symbolSectionIndex;
|
||||
int symbolTableIndex;
|
||||
@@ -72,11 +74,15 @@ struct Elf {
|
||||
}
|
||||
}
|
||||
|
||||
MOCKABLE_VIRTUAL std::string getSymbolName(uint32_t nameOffset) const {
|
||||
std::string getName(uint32_t nameOffset) const {
|
||||
auto sectionHeaderNamesData = sectionHeaders[elfFileHeader->shStrNdx].data;
|
||||
return std::string(reinterpret_cast<const char *>(sectionHeaderNamesData.begin()) + nameOffset);
|
||||
}
|
||||
|
||||
MOCKABLE_VIRTUAL std::string getSymbolName(uint32_t nameOffset) const {
|
||||
return getName(nameOffset);
|
||||
}
|
||||
|
||||
decltype(ElfSymbolEntry<numBits>::value) getSymbolValue(uint32_t idx) const {
|
||||
return symbolTable[idx].value;
|
||||
}
|
||||
@@ -98,12 +104,12 @@ struct Elf {
|
||||
}
|
||||
|
||||
const ElfFileHeader<numBits> *elfFileHeader = nullptr;
|
||||
StackVec<ProgramHeaderAndData, 32> programHeaders;
|
||||
StackVec<SectionHeaderAndData, 32> sectionHeaders;
|
||||
StackVec<ProgramHeaderAndData<numBits>, 32> programHeaders;
|
||||
StackVec<SectionHeaderAndData<numBits>, 32> sectionHeaders;
|
||||
|
||||
protected:
|
||||
bool decodeSymTab(SectionHeaderAndData §ionHeaderData, std::string &outError);
|
||||
bool decodeRelocations(SectionHeaderAndData §ionHeaderData, std::string &outError);
|
||||
bool decodeSymTab(SectionHeaderAndData<numBits> §ionHeaderData, std::string &outError);
|
||||
bool decodeRelocations(SectionHeaderAndData<numBits> §ionHeaderData, std::string &outError);
|
||||
bool isDebugDataRelocation(ConstStringRef sectionName);
|
||||
|
||||
SymbolsTable symbolTable;
|
||||
@@ -111,6 +117,17 @@ struct Elf {
|
||||
Relocations debugInfoRelocations;
|
||||
};
|
||||
|
||||
struct DecodedNote {
|
||||
ConstStringRef name;
|
||||
ConstStringRef desc;
|
||||
uint32_t type;
|
||||
};
|
||||
|
||||
template <ElfIdentifierClass numBits = EI_CLASS_64>
|
||||
bool decodeNoteSection(ArrayRef<const uint8_t> sectionData, std::vector<DecodedNote> &out, std::string &outErrReason, std::string &outWarning);
|
||||
extern template bool decodeNoteSection<EI_CLASS_32>(ArrayRef<const uint8_t> sectionData, std::vector<DecodedNote> &out, std::string &outErrReason, std::string &outWarning);
|
||||
extern template bool decodeNoteSection<EI_CLASS_64>(ArrayRef<const uint8_t> sectionData, std::vector<DecodedNote> &out, std::string &outErrReason, std::string &outWarning);
|
||||
|
||||
template <ElfIdentifierClass numBits = EI_CLASS_64>
|
||||
const ElfFileHeader<numBits> *decodeElfFileHeader(const ArrayRef<const uint8_t> binary);
|
||||
extern template const ElfFileHeader<EI_CLASS_32> *decodeElfFileHeader<EI_CLASS_32>(const ArrayRef<const uint8_t>);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2023 Intel Corporation
|
||||
* Copyright (C) 2020-2024 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -29,7 +29,7 @@ ElfEncoder<numBits>::ElfEncoder(bool addUndefSectionHeader, bool addHeaderSectio
|
||||
}
|
||||
|
||||
template <ElfIdentifierClass numBits>
|
||||
void ElfEncoder<numBits>::appendSection(const ElfSectionHeader<numBits> §ionHeader, const ArrayRef<const uint8_t> sectionData) {
|
||||
ElfSectionHeader<numBits> &ElfEncoder<numBits>::appendSection(const ElfSectionHeader<numBits> §ionHeader, const ArrayRef<const uint8_t> sectionData) {
|
||||
sectionHeaders.push_back(sectionHeader);
|
||||
if ((SHT_NOBITS != sectionHeader.type) && (false == sectionData.empty())) {
|
||||
auto sectionDataAlignment = std::min<uint64_t>(defaultDataAlignment, 8U);
|
||||
@@ -42,10 +42,11 @@ void ElfEncoder<numBits>::appendSection(const ElfSectionHeader<numBits> §ion
|
||||
sectionHeaders.rbegin()->offset = static_cast<decltype(sectionHeaders.rbegin()->offset)>(alignedOffset);
|
||||
sectionHeaders.rbegin()->size = static_cast<decltype(sectionHeaders.rbegin()->size)>(sectionData.size());
|
||||
}
|
||||
return *sectionHeaders.rbegin();
|
||||
}
|
||||
|
||||
template <ElfIdentifierClass numBits>
|
||||
void ElfEncoder<numBits>::appendSegment(const ElfProgramHeader<numBits> &programHeader, const ArrayRef<const uint8_t> segmentData) {
|
||||
ElfProgramHeader<numBits> &ElfEncoder<numBits>::appendSegment(const ElfProgramHeader<numBits> &programHeader, const ArrayRef<const uint8_t> segmentData) {
|
||||
maxDataAlignmentNeeded = std::max<uint64_t>(maxDataAlignmentNeeded, static_cast<uint64_t>(programHeader.align));
|
||||
programHeaders.push_back(programHeader);
|
||||
if (false == segmentData.empty()) {
|
||||
@@ -59,6 +60,7 @@ void ElfEncoder<numBits>::appendSegment(const ElfProgramHeader<numBits> &program
|
||||
programHeaders.rbegin()->offset = static_cast<decltype(programHeaders.rbegin()->offset)>(alignedOffset);
|
||||
programHeaders.rbegin()->fileSz = static_cast<decltype(programHeaders.rbegin()->fileSz)>(segmentData.size());
|
||||
}
|
||||
return *programHeaders.rbegin();
|
||||
}
|
||||
|
||||
template <ElfIdentifierClass numBits>
|
||||
@@ -89,8 +91,7 @@ ElfSectionHeader<numBits> &ElfEncoder<numBits>::appendSection(SectionHeaderType
|
||||
default:
|
||||
break;
|
||||
}
|
||||
appendSection(section, sectionData);
|
||||
return *sectionHeaders.rbegin();
|
||||
return appendSection(section, sectionData);
|
||||
}
|
||||
|
||||
template <ElfIdentifierClass numBits>
|
||||
@@ -100,8 +101,7 @@ ElfProgramHeader<numBits> &ElfEncoder<numBits>::appendSegment(ProgramHeaderType
|
||||
segment.flags = static_cast<decltype(segment.flags)>(PF_NONE);
|
||||
segment.offset = 0U;
|
||||
segment.align = static_cast<decltype(segment.align)>(defaultDataAlignment);
|
||||
appendSegment(segment, segmentData);
|
||||
return *programHeaders.rbegin();
|
||||
return appendSegment(segment, segmentData);
|
||||
}
|
||||
|
||||
template <ElfIdentifierClass numBits>
|
||||
@@ -200,6 +200,37 @@ std::vector<uint8_t> ElfEncoder<numBits>::encode() const {
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <ElfIdentifierClass numBits>
|
||||
std::vector<uint8_t> encodeNoteSectionData(ArrayRef<const NoteToEncode> notes) {
|
||||
std::vector<uint8_t> ret;
|
||||
{
|
||||
size_t dataSize = 0U;
|
||||
for (auto ¬e : notes) {
|
||||
dataSize += sizeof(ElfNoteSection);
|
||||
dataSize += note.name.size();
|
||||
dataSize += note.desc.size();
|
||||
dataSize = alignUp(dataSize, 4);
|
||||
}
|
||||
ret.reserve(dataSize);
|
||||
}
|
||||
|
||||
for (auto ¬e : notes) {
|
||||
ElfNoteSection entry;
|
||||
entry.nameSize = static_cast<uint32_t>(note.name.size());
|
||||
entry.descSize = static_cast<uint32_t>(note.desc.size());
|
||||
entry.type = note.type;
|
||||
ret.insert(ret.end(), reinterpret_cast<uint8_t *>(&entry), reinterpret_cast<uint8_t *>((&entry) + 1));
|
||||
ret.insert(ret.end(), reinterpret_cast<const uint8_t *>(note.name.c_str()), reinterpret_cast<const uint8_t *>(note.name.c_str() + note.name.size()));
|
||||
ret.insert(ret.end(), reinterpret_cast<const uint8_t *>(note.desc.c_str()), reinterpret_cast<const uint8_t *>(note.desc.c_str() + note.desc.size()));
|
||||
ret.resize(alignUp(ret.size(), 4), 0U);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template std::vector<uint8_t> encodeNoteSectionData<EI_CLASS_64>(ArrayRef<const NoteToEncode> notes);
|
||||
template std::vector<uint8_t> encodeNoteSectionData<EI_CLASS_32>(ArrayRef<const NoteToEncode> notes);
|
||||
|
||||
template struct ElfEncoder<EI_CLASS_32>;
|
||||
template struct ElfEncoder<EI_CLASS_64>;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2023 Intel Corporation
|
||||
* Copyright (C) 2020-2024 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
@@ -54,8 +55,8 @@ struct ElfEncoder {
|
||||
ElfEncoder(bool addUndefSectionHeader = true, bool addHeaderSectionNamesSection = true,
|
||||
typename ElfSectionHeaderTypes<numBits>::AddrAlign defaultDataAlignment = 8U);
|
||||
|
||||
void appendSection(const ElfSectionHeader<numBits> §ionHeader, const ArrayRef<const uint8_t> sectionData);
|
||||
void appendSegment(const ElfProgramHeader<numBits> &programHeader, const ArrayRef<const uint8_t> segmentData);
|
||||
ElfSectionHeader<numBits> &appendSection(const ElfSectionHeader<numBits> §ionHeader, const ArrayRef<const uint8_t> sectionData);
|
||||
ElfProgramHeader<numBits> &appendSegment(const ElfProgramHeader<numBits> &programHeader, const ArrayRef<const uint8_t> segmentData);
|
||||
|
||||
ElfSectionHeader<numBits> &appendSection(SectionHeaderType sectionType, ConstStringRef sectionLabel, const ArrayRef<const uint8_t> sectionData);
|
||||
ElfProgramHeader<numBits> &appendSegment(ProgramHeaderType segmentType, const ArrayRef<const uint8_t> segmentData);
|
||||
@@ -99,6 +100,17 @@ struct ElfEncoder {
|
||||
uint32_t shStrTabNameOffset = 0;
|
||||
};
|
||||
|
||||
struct NoteToEncode {
|
||||
std::string name;
|
||||
std::string desc;
|
||||
uint32_t type;
|
||||
};
|
||||
|
||||
template <ElfIdentifierClass numBits = EI_CLASS_64>
|
||||
std::vector<uint8_t> encodeNoteSectionData(ArrayRef<const NoteToEncode> notes);
|
||||
extern template std::vector<uint8_t> encodeNoteSectionData<EI_CLASS_64>(ArrayRef<const NoteToEncode> notes);
|
||||
extern template std::vector<uint8_t> encodeNoteSectionData<EI_CLASS_32>(ArrayRef<const NoteToEncode> notes);
|
||||
|
||||
extern template struct ElfEncoder<EI_CLASS_32>;
|
||||
extern template struct ElfEncoder<EI_CLASS_64>;
|
||||
|
||||
|
||||
126
shared/source/device_binary_format/elf/elf_rewriter.h
Normal file
126
shared/source/device_binary_format/elf/elf_rewriter.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "shared/source/device_binary_format/elf/elf.h"
|
||||
#include "shared/source/device_binary_format/elf/elf_decoder.h"
|
||||
#include "shared/source/device_binary_format/elf/elf_encoder.h"
|
||||
#include "shared/source/utilities/arrayref.h"
|
||||
#include "shared/source/utilities/stackvec.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
namespace Elf {
|
||||
|
||||
template <ElfIdentifierClass NumBits = NEO::Elf::EI_CLASS_64>
|
||||
struct MutableSectionHeader {
|
||||
MutableSectionHeader(const std::string &name, const NEO::Elf::ElfSectionHeader<NumBits> &header, const std::vector<uint8_t> &data)
|
||||
: name(name), header(header), data(data) {
|
||||
}
|
||||
std::string name;
|
||||
NEO::Elf::ElfSectionHeader<NumBits> header{};
|
||||
std::vector<uint8_t> data;
|
||||
};
|
||||
|
||||
template <ElfIdentifierClass NumBits = NEO::Elf::EI_CLASS_64>
|
||||
struct MutableProgramHeader {
|
||||
MutableProgramHeader(const NEO::Elf::ElfProgramHeader<NumBits> &header, const std::vector<uint8_t> &data)
|
||||
: header(header), data(data) {
|
||||
}
|
||||
NEO::Elf::ElfProgramHeader<NumBits> header = {};
|
||||
std::vector<uint8_t> data;
|
||||
MutableSectionHeader<NumBits> *referencedSectionData = nullptr;
|
||||
};
|
||||
|
||||
template <ElfIdentifierClass NumBits = NEO::Elf::EI_CLASS_64>
|
||||
struct ElfRewriter {
|
||||
using SectionId = uint32_t;
|
||||
|
||||
ElfRewriter(NEO::Elf::Elf<NumBits> &src) {
|
||||
elfFileHeader = *src.elfFileHeader;
|
||||
for (const auto &sh : src.sectionHeaders) {
|
||||
this->sectionHeaders.push_back(std::make_unique<MutableSectionHeader<NumBits>>(src.getName(sh.header->name), *sh.header, std::vector<uint8_t>{sh.data.begin(), sh.data.end()}));
|
||||
}
|
||||
for (const auto &ph : src.programHeaders) {
|
||||
this->programHeaders.push_back(std::make_unique<MutableProgramHeader<NumBits>>(*ph.header, std::vector<uint8_t>{ph.data.begin(), ph.data.end()}));
|
||||
for (const auto &sh : this->sectionHeaders) {
|
||||
if ((sh->header.offset == ph.header->offset) && (sh->header.size == ph.header->fileSz)) {
|
||||
(*this->programHeaders.rbegin())->referencedSectionData = sh.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> encode() const {
|
||||
NEO::Elf::ElfEncoder<NumBits> encoder;
|
||||
encoder.getElfFileHeader() = elfFileHeader;
|
||||
std::unordered_map<MutableSectionHeader<NumBits> *, decltype(NEO::Elf::ElfSectionHeader<NumBits>::offset)> encodedSectionsOffsets;
|
||||
for (const auto &sh : this->sectionHeaders) {
|
||||
if ((sh->header.type == SHT_NULL) || (sh->header.type == SHT_STRTAB)) {
|
||||
continue;
|
||||
}
|
||||
auto nameIdx = encoder.appendSectionName(sh->name);
|
||||
NEO::Elf::ElfSectionHeader<NumBits> header = sh->header;
|
||||
header.name = nameIdx;
|
||||
encodedSectionsOffsets[sh.get()] = encoder.appendSection(header, sh->data).offset;
|
||||
}
|
||||
for (const auto &ph : this->programHeaders) {
|
||||
if (ph->referencedSectionData) {
|
||||
auto &header = ph->header;
|
||||
header.offset = encodedSectionsOffsets[ph->referencedSectionData];
|
||||
encoder.appendSegment(ph->header, {});
|
||||
} else {
|
||||
encoder.appendSegment(ph->header, ph->data);
|
||||
}
|
||||
}
|
||||
return encoder.encode();
|
||||
}
|
||||
|
||||
StackVec<SectionId, 16> findSections(typename ElfSectionHeaderTypes<NumBits>::Type type, ConstStringRef name) {
|
||||
StackVec<SectionId, 16> ret;
|
||||
for (size_t i = 0; i < this->sectionHeaders.size(); i++) {
|
||||
auto §ion = this->sectionHeaders[i];
|
||||
if ((type == section->header.type) && (name == section->name)) {
|
||||
ret.push_back(static_cast<SectionId>(i));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MutableSectionHeader<NumBits> &getSection(SectionId idx) {
|
||||
return *sectionHeaders[idx];
|
||||
}
|
||||
|
||||
void removeSection(SectionId idx) {
|
||||
auto sectionHeaderToRemove = std::move(sectionHeaders[idx]);
|
||||
for (auto it = idx + 1; it < sectionHeaders.size(); ++it) { // preserve order
|
||||
sectionHeaders[it - 1] = std::move(sectionHeaders[it]);
|
||||
}
|
||||
sectionHeaders.pop_back();
|
||||
for (auto &programHeader : programHeaders) {
|
||||
if (sectionHeaderToRemove.get() == programHeader->referencedSectionData) {
|
||||
programHeader->referencedSectionData = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ElfFileHeader<NumBits> elfFileHeader = {};
|
||||
|
||||
protected:
|
||||
StackVec<std::unique_ptr<MutableSectionHeader<NumBits>>, 32> sectionHeaders;
|
||||
StackVec<std::unique_ptr<MutableProgramHeader<NumBits>>, 32> programHeaders;
|
||||
};
|
||||
|
||||
} // namespace Elf
|
||||
|
||||
} // namespace NEO
|
||||
@@ -8,6 +8,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "shared/source/device_binary_format/device_binary_formats.h"
|
||||
#include "shared/source/device_binary_format/elf/elf_decoder.h"
|
||||
#include "shared/source/device_binary_format/zebin/zebin_elf.h"
|
||||
#include "shared/source/utilities/stackvec.h"
|
||||
|
||||
@@ -29,7 +30,7 @@ namespace Zebin {
|
||||
|
||||
template <Elf::ElfIdentifierClass numBits = Elf::EI_CLASS_64>
|
||||
struct ZebinSections {
|
||||
using SectionHeaderData = typename NEO::Elf::Elf<numBits>::SectionHeaderAndData;
|
||||
using SectionHeaderData = NEO::Elf::SectionHeaderAndData<numBits>;
|
||||
StackVec<SectionHeaderData *, 32> textKernelSections;
|
||||
StackVec<SectionHeaderData *, 32> gtpinInfoSections;
|
||||
StackVec<SectionHeaderData *, 1> zeInfoSections;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (C) 2020-2022 Intel Corporation
|
||||
# Copyright (C) 2020-2024 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
@@ -15,6 +15,7 @@ target_sources(neo_shared_tests PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_formats_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_decoder_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_encoder_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_rewriter_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_decoder_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_dumper_tests.cpp
|
||||
@@ -22,4 +23,4 @@ target_sources(neo_shared_tests PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/yaml/yaml_parser_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zebin_debug_binary_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zebin_decoder_tests.cpp
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2023 Intel Corporation
|
||||
* Copyright (C) 2020-2024 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -309,7 +309,7 @@ TEST(PackDeviceBinaryOclElf, WhenPackingBinaryWitIntermediateRepresentationThenC
|
||||
EXPECT_EQ(3U, elf.elfFileHeader->shNum);
|
||||
|
||||
auto spirVSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_SPIRV; });
|
||||
[](const SectionHeaderAndData<> §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_SPIRV; });
|
||||
ASSERT_NE(nullptr, spirVSection);
|
||||
ASSERT_EQ(spirV.size(), spirVSection->data.size());
|
||||
EXPECT_EQ(0, memcmp(spirV.begin(), spirVSection->data.begin(), spirV.size()));
|
||||
@@ -338,7 +338,7 @@ TEST(PackDeviceBinaryOclElf, WhenPackingBinaryWitIntermediateRepresentationThenC
|
||||
EXPECT_EQ(3U, elf.elfFileHeader->shNum);
|
||||
|
||||
auto llvmSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_LLVM_BINARY; });
|
||||
[](const SectionHeaderAndData<> §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_LLVM_BINARY; });
|
||||
ASSERT_NE(nullptr, llvmSection);
|
||||
ASSERT_EQ(llvmBc.size(), llvmSection->data.size());
|
||||
EXPECT_EQ(0, memcmp(llvmBc.begin(), llvmSection->data.begin(), llvmBc.size()));
|
||||
@@ -372,16 +372,16 @@ TEST(PackDeviceBinaryOclElf, WhenPackingBinaryThenSectionsAreProperlyPopulated)
|
||||
ASSERT_NE(nullptr, elf.elfFileHeader);
|
||||
|
||||
auto spirvSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_SPIRV; });
|
||||
[](const SectionHeaderAndData<> §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_SPIRV; });
|
||||
|
||||
auto deviceBinarySection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_DEV_BINARY; });
|
||||
[](const SectionHeaderAndData<> §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_DEV_BINARY; });
|
||||
|
||||
auto deviceDebugSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_DEV_DEBUG; });
|
||||
[](const SectionHeaderAndData<> §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_DEV_DEBUG; });
|
||||
|
||||
auto buildOptionsSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_OPTIONS; });
|
||||
[](const SectionHeaderAndData<> §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_OPTIONS; });
|
||||
|
||||
ASSERT_NE(nullptr, spirvSection);
|
||||
ASSERT_EQ(spirV.size(), spirvSection->data.size());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2023 Intel Corporation
|
||||
* Copyright (C) 2020-2024 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "shared/source/device_binary_format/elf/elf.h"
|
||||
#include "shared/source/device_binary_format/elf/elf_decoder.h"
|
||||
#include "shared/source/device_binary_format/elf/elf_encoder.h"
|
||||
#include "shared/source/helpers/aligned_memory.h"
|
||||
#include "shared/source/helpers/array_count.h"
|
||||
#include "shared/source/helpers/file_io.h"
|
||||
#include "shared/test/common/helpers/gtest_helpers.h"
|
||||
@@ -16,6 +17,9 @@
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace NEO::Elf;
|
||||
|
||||
using ELF_CLASS = NEO::Elf::ElfIdentifierClass;
|
||||
@@ -812,3 +816,77 @@ TEST(ElfDecoder, GivenElfWithRelocationsWhenDecodedThenCorrectRelocationsAndSymo
|
||||
EXPECT_EQ(SymbolTableType::STT_OBJECT, elf64.extractSymbolType(symbolTable[3]));
|
||||
EXPECT_EQ(SymbolTableBind::STB_GLOBAL, elf64.extractSymbolBind(symbolTable[3]));
|
||||
}
|
||||
|
||||
TEST(DecodeElfNoteSection, GivenEmptyDataSectionThenDecodeAsZeroEntries) {
|
||||
std::vector<NEO::Elf::DecodedNote> decodedNotes;
|
||||
std::string err, warn;
|
||||
auto ret = NEO::Elf::decodeNoteSection(ArrayRef<const uint8_t>{}, decodedNotes, err, warn);
|
||||
EXPECT_TRUE(ret);
|
||||
EXPECT_TRUE(err.empty()) << err;
|
||||
EXPECT_TRUE(warn.empty()) << warn;
|
||||
EXPECT_TRUE(decodedNotes.empty());
|
||||
}
|
||||
|
||||
TEST(DecodeElfNoteSection, GivenDataSectionWithInvalidSizeThenReturnError) {
|
||||
std::vector<NEO::Elf::DecodedNote> decodedNotes;
|
||||
std::string err, warn;
|
||||
NEO::Elf::ElfNoteSection note;
|
||||
note.nameSize = 5;
|
||||
note.descSize = 7;
|
||||
auto ret = NEO::Elf::decodeNoteSection(ArrayRef<const uint8_t>::fromAny(¬e, 1), decodedNotes, err, warn);
|
||||
EXPECT_FALSE(ret);
|
||||
EXPECT_FALSE(err.empty());
|
||||
EXPECT_TRUE(warn.empty()) << warn;
|
||||
EXPECT_TRUE(decodedNotes.empty());
|
||||
}
|
||||
|
||||
TEST(DecodeElfNoteSection, GivenValidNotesThenDecodeThem) {
|
||||
std::string unalignedDescName = "note"
|
||||
"Type";
|
||||
std::string unalignedDesc = "some"
|
||||
" Des"
|
||||
"c ";
|
||||
uint32_t unalignedDescNoteType = 3;
|
||||
|
||||
std::string unalignedNameName = "note"
|
||||
"Ty";
|
||||
std::string unalignedNameDesc = "so"
|
||||
"me";
|
||||
uint32_t unalignedNameNoteType = 5;
|
||||
|
||||
std::string alignedDescName = "some"
|
||||
"Note";
|
||||
std::string alignedDesc = "some"
|
||||
"Desc";
|
||||
uint32_t alignedDescNoteType = 7;
|
||||
|
||||
NEO::Elf::DecodedNote notes[] = {{unalignedDescName, unalignedDesc, unalignedDescNoteType},
|
||||
{unalignedNameName, unalignedNameDesc, unalignedNameNoteType},
|
||||
{alignedDescName, alignedDesc, alignedDescNoteType}};
|
||||
std::vector<uint8_t> data;
|
||||
for (const auto ¬e : notes) {
|
||||
NEO::Elf::ElfNoteSection section;
|
||||
section.nameSize = static_cast<uint32_t>(note.name.size());
|
||||
section.descSize = static_cast<uint32_t>(note.desc.size());
|
||||
section.type = note.type;
|
||||
data.insert(data.end(), reinterpret_cast<const uint8_t *>(§ion), reinterpret_cast<const uint8_t *>(§ion + 1));
|
||||
data.insert(data.end(), reinterpret_cast<const uint8_t *>(note.name.begin()), reinterpret_cast<const uint8_t *>(note.name.end()));
|
||||
data.insert(data.end(), reinterpret_cast<const uint8_t *>(note.desc.begin()), reinterpret_cast<const uint8_t *>(note.desc.end()));
|
||||
data.resize(alignUp(data.size(), 4));
|
||||
}
|
||||
|
||||
std::vector<NEO::Elf::DecodedNote> decodedNotes;
|
||||
std::string err, warn;
|
||||
auto ret = NEO::Elf::decodeNoteSection(data, decodedNotes, err, warn);
|
||||
EXPECT_TRUE(ret);
|
||||
EXPECT_TRUE(err.empty()) << err;
|
||||
EXPECT_TRUE(warn.empty()) << warn;
|
||||
EXPECT_FALSE(decodedNotes.empty());
|
||||
|
||||
ASSERT_EQ(3U, decodedNotes.size());
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
EXPECT_EQ(notes[i].type, decodedNotes[i].type);
|
||||
EXPECT_EQ(notes[i].name, decodedNotes[i].name);
|
||||
EXPECT_EQ(notes[i].desc, decodedNotes[i].desc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Intel Corporation
|
||||
* Copyright (C) 2020-2024 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -500,3 +500,55 @@ TEST(ElfEncoder, WhenGetSectionHeaderIndexIsCalledThenCorrectSectionIdxIsReturne
|
||||
auto &sec1 = elfEncoder64.appendSection(SHT_PROGBITS, "", {});
|
||||
EXPECT_EQ(1U, elfEncoder64.getSectionHeaderIndex(sec1));
|
||||
}
|
||||
|
||||
TEST(DecodeElfNoteSection, givenZeroNotesToEncodeThenReturnsEmptyDataVector) {
|
||||
auto encoded = NEO::Elf::encodeNoteSectionData({});
|
||||
EXPECT_TRUE(encoded.empty());
|
||||
}
|
||||
|
||||
TEST(DecodeElfNoteSection, givenValidNotesToEncodeThenReturnsProperlyEncodedData) {
|
||||
std::string unalignedDescName = "note"
|
||||
"Type";
|
||||
std::string unalignedDesc = "some"
|
||||
" Des"
|
||||
"c ";
|
||||
uint32_t unalignedDescNoteType = 3;
|
||||
|
||||
std::string unalignedNameName = "note"
|
||||
"Ty";
|
||||
std::string unalignedNameDesc = "so"
|
||||
"me";
|
||||
uint32_t unalignedNameNoteType = 5;
|
||||
|
||||
std::string alignedDescName = "some"
|
||||
"Note";
|
||||
std::string alignedDesc = "some"
|
||||
"Desc";
|
||||
uint32_t alignedDescNoteType = 7;
|
||||
|
||||
NEO::Elf::NoteToEncode notes[] = {{unalignedDescName, unalignedDesc, unalignedDescNoteType},
|
||||
{unalignedNameName, unalignedNameDesc, unalignedNameNoteType},
|
||||
{alignedDescName, alignedDesc, alignedDescNoteType}};
|
||||
|
||||
size_t expectedSize = 0;
|
||||
for (const auto ¬e : notes) {
|
||||
expectedSize += sizeof(NEO::Elf::ElfNoteSection);
|
||||
expectedSize += note.name.size();
|
||||
expectedSize += note.desc.size();
|
||||
expectedSize = alignUp(expectedSize, 4);
|
||||
}
|
||||
|
||||
auto encoded = NEO::Elf::encodeNoteSectionData({notes, 3});
|
||||
ASSERT_EQ(expectedSize, encoded.size());
|
||||
|
||||
uint8_t *pos = encoded.data();
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
auto header = reinterpret_cast<NEO::Elf::ElfNoteSection *>(pos);
|
||||
EXPECT_EQ(notes[i].type, header->type);
|
||||
EXPECT_EQ(notes[i].name.size(), header->nameSize);
|
||||
EXPECT_EQ(notes[i].desc.size(), header->descSize);
|
||||
EXPECT_EQ(notes[i].name, NEO::ConstStringRef(reinterpret_cast<const char *>((header + 1)), notes[i].name.size()));
|
||||
EXPECT_EQ(notes[i].desc, NEO::ConstStringRef(reinterpret_cast<const char *>((header + 1)) + notes[i].name.size(), notes[i].desc.size()));
|
||||
pos = alignUp(pos + sizeof(NEO::Elf::ElfNoteSection) + notes[i].name.size() + notes[i].desc.size(), 4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/source/device_binary_format/elf/elf.h"
|
||||
#include "shared/source/device_binary_format/elf/elf_decoder.h"
|
||||
#include "shared/source/device_binary_format/elf/elf_encoder.h"
|
||||
#include "shared/source/device_binary_format/elf/elf_rewriter.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace NEO::Elf {
|
||||
|
||||
inline bool operator==(const ElfFileHeaderIdentity &lhs, const ElfFileHeaderIdentity &rhs) {
|
||||
return (lhs.abiVersion == rhs.abiVersion) && (lhs.data == rhs.data) && (lhs.eClass == rhs.eClass) && (lhs.osAbi == rhs.osAbi) && (lhs.version == rhs.version) && (lhs.magic[0] == rhs.magic[0]) && (lhs.magic[1] == rhs.magic[1]) && (lhs.magic[2] == rhs.magic[2]) && (lhs.magic[3] == rhs.magic[3]);
|
||||
}
|
||||
|
||||
template <ElfIdentifierClass NumBits>
|
||||
inline bool operator==(const ElfFileHeader<NumBits> &lhs, const ElfFileHeader<NumBits> &rhs) {
|
||||
return (lhs.identity == rhs.identity) && (lhs.type == rhs.type) && (lhs.machine == rhs.machine) && (lhs.version == rhs.version) && (lhs.entry == rhs.entry) && (lhs.phOff == rhs.phOff) && (lhs.shOff == rhs.shOff) && (lhs.flags == rhs.flags) && (lhs.ehSize == rhs.ehSize) && (lhs.phEntSize == rhs.phEntSize) && (lhs.phNum == rhs.phNum) && (lhs.shEntSize == rhs.shEntSize) && (lhs.shNum == rhs.shNum) && (lhs.shStrNdx == rhs.shStrNdx);
|
||||
}
|
||||
|
||||
template <ElfIdentifierClass NumBits>
|
||||
inline bool operator==(const SectionHeaderAndData<NumBits> &lhs, const SectionHeaderAndData<NumBits> &rhs) {
|
||||
return (lhs.header->name == rhs.header->name) && (lhs.header->type == rhs.header->type) && (lhs.header->flags == rhs.header->flags) && (lhs.header->addr == rhs.header->addr) && (lhs.header->offset == rhs.header->offset) && (lhs.header->size == rhs.header->size) && (lhs.header->link == rhs.header->link) && (lhs.header->info == rhs.header->info) && (lhs.header->addralign == rhs.header->addralign) && (lhs.header->entsize == rhs.header->entsize) && (lhs.data.size() == rhs.data.size()) && ((lhs.data.size() == 0) || (0 == memcmp(lhs.data.begin(), rhs.data.begin(), lhs.data.size())));
|
||||
}
|
||||
|
||||
template <ElfIdentifierClass NumBits>
|
||||
inline bool operator==(const ProgramHeaderAndData<NumBits> &lhs, const ProgramHeaderAndData<NumBits> &rhs) {
|
||||
return (lhs.header->type == rhs.header->type) && (lhs.header->offset == rhs.header->offset) && (lhs.header->vAddr == rhs.header->vAddr) && (lhs.header->pAddr == rhs.header->pAddr) && (lhs.header->fileSz == rhs.header->fileSz) && (lhs.header->memSz == rhs.header->memSz) && (lhs.header->flags == rhs.header->flags) && (lhs.header->align == rhs.header->align) && (lhs.data.size() == rhs.data.size()) && ((lhs.data.size() == 0) || (0 == memcmp(lhs.data.begin(), rhs.data.begin(), lhs.data.size())));
|
||||
}
|
||||
|
||||
} // namespace NEO::Elf
|
||||
|
||||
TEST(ElfRewriter, GivenElfWhenNotModifiedThenOutputIsSameAsSource) {
|
||||
NEO::Elf::ElfEncoder<> encoder;
|
||||
std::vector<uint8_t> txtData;
|
||||
txtData.resize(4096U, 7);
|
||||
auto &txtSection = encoder.appendSection(NEO::Elf::SectionHeaderType::SHT_PROGBITS, ".txt", txtData);
|
||||
encoder.appendProgramHeaderLoad(encoder.getSectionHeaderIndex(txtSection), 4096U, 4096U);
|
||||
auto elfBinSrc = encoder.encode();
|
||||
|
||||
std::string err, warn;
|
||||
auto decodedElfSrc = NEO::Elf::decodeElf(elfBinSrc, err, warn);
|
||||
ASSERT_TRUE(err.empty()) << err;
|
||||
ASSERT_TRUE(warn.empty()) << warn;
|
||||
NEO::Elf::ElfRewriter<> rewriter{decodedElfSrc};
|
||||
auto elfBinOut = rewriter.encode();
|
||||
|
||||
ASSERT_EQ(elfBinSrc.size(), elfBinOut.size());
|
||||
auto decodedElfOut = NEO::Elf::decodeElf(elfBinOut, err, warn);
|
||||
ASSERT_TRUE(err.empty()) << err;
|
||||
ASSERT_TRUE(warn.empty()) << warn;
|
||||
EXPECT_EQ(*decodedElfSrc.elfFileHeader, *decodedElfOut.elfFileHeader);
|
||||
ASSERT_EQ(decodedElfSrc.sectionHeaders.size(), decodedElfOut.sectionHeaders.size());
|
||||
for (size_t i = 0; i < decodedElfSrc.sectionHeaders.size(); ++i) {
|
||||
EXPECT_EQ(decodedElfSrc.sectionHeaders[i], decodedElfOut.sectionHeaders[i]);
|
||||
}
|
||||
ASSERT_EQ(decodedElfSrc.programHeaders.size(), decodedElfOut.programHeaders.size());
|
||||
for (size_t i = 0; i < decodedElfSrc.programHeaders.size(); ++i) {
|
||||
EXPECT_EQ(decodedElfSrc.programHeaders[i], decodedElfOut.programHeaders[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ElfRewriterFindSections, GivenSectionTypeAndNameThenReturnsMatchedSections) {
|
||||
NEO::Elf::ElfEncoder<> encoder;
|
||||
std::vector<uint8_t> txtData;
|
||||
txtData.resize(4096U, 7);
|
||||
encoder.appendSection(NEO::Elf::SectionHeaderType::SHT_PROGBITS, ".txt", txtData);
|
||||
encoder.appendSection(NEO::Elf::SectionHeaderType::SHT_PROGBITS, ".txtX", txtData);
|
||||
encoder.appendSection(NEO::Elf::SectionHeaderType::SHT_PROGBITS, ".txt", txtData);
|
||||
encoder.appendSection(NEO::Elf::SectionHeaderType::SHT_STRTAB, ".txt", txtData);
|
||||
auto elfBinSrc = encoder.encode();
|
||||
std::string err, warn;
|
||||
auto decodedElfSrc = NEO::Elf::decodeElf(elfBinSrc, err, warn);
|
||||
ASSERT_TRUE(err.empty()) << err;
|
||||
ASSERT_TRUE(warn.empty()) << warn;
|
||||
NEO::Elf::ElfRewriter<> rewriter{decodedElfSrc};
|
||||
|
||||
auto foundSections = rewriter.findSections(NEO::Elf::SectionHeaderType::SHT_PROGBITS, ".txt");
|
||||
ASSERT_EQ(2U, foundSections.size());
|
||||
EXPECT_EQ(NEO::Elf::SectionHeaderType::SHT_PROGBITS, rewriter.getSection(foundSections[0]).header.type);
|
||||
EXPECT_EQ(NEO::Elf::SectionHeaderType::SHT_PROGBITS, rewriter.getSection(foundSections[1]).header.type);
|
||||
EXPECT_EQ(".txt", rewriter.getSection(foundSections[0]).name);
|
||||
EXPECT_EQ(".txt", rewriter.getSection(foundSections[1]).name);
|
||||
}
|
||||
|
||||
TEST(ElfRewriterRemoveSection, GivenSectionIndexThenRemovesThatSection) {
|
||||
NEO::Elf::ElfEncoder<> encoder;
|
||||
std::vector<uint8_t> txtData;
|
||||
txtData.resize(4096U, 7);
|
||||
auto §ionWithLoad = encoder.appendSection(NEO::Elf::SectionHeaderType::SHT_PROGBITS, ".txt.0", txtData);
|
||||
encoder.appendSection(NEO::Elf::SectionHeaderType::SHT_PROGBITS, ".txt.1", txtData);
|
||||
encoder.appendProgramHeaderLoad(encoder.getSectionHeaderIndex(sectionWithLoad), 4096U, 4096U);
|
||||
auto elfBinSrc = encoder.encode();
|
||||
std::string err, warn;
|
||||
auto decodedElfSrc = NEO::Elf::decodeElf(elfBinSrc, err, warn);
|
||||
ASSERT_TRUE(err.empty()) << err;
|
||||
ASSERT_TRUE(warn.empty()) << warn;
|
||||
NEO::Elf::ElfRewriter<> rewriter{decodedElfSrc};
|
||||
|
||||
auto foundSections = rewriter.findSections(NEO::Elf::SectionHeaderType::SHT_PROGBITS, ".txt.0");
|
||||
ASSERT_EQ(1U, foundSections.size());
|
||||
EXPECT_EQ(NEO::Elf::SectionHeaderType::SHT_PROGBITS, rewriter.getSection(foundSections[0]).header.type);
|
||||
EXPECT_EQ(".txt.0", rewriter.getSection(foundSections[0]).name);
|
||||
rewriter.removeSection(foundSections[0]);
|
||||
EXPECT_EQ(0U, rewriter.findSections(NEO::Elf::SectionHeaderType::SHT_PROGBITS, ".txt.0").size());
|
||||
NEO::Elf::decodeElf(rewriter.encode(), err, warn);
|
||||
EXPECT_TRUE(err.empty()) << err;
|
||||
EXPECT_TRUE(warn.empty()) << warn;
|
||||
|
||||
foundSections = rewriter.findSections(NEO::Elf::SectionHeaderType::SHT_PROGBITS, ".txt.1");
|
||||
ASSERT_EQ(1U, foundSections.size());
|
||||
EXPECT_EQ(NEO::Elf::SectionHeaderType::SHT_PROGBITS, rewriter.getSection(foundSections[0]).header.type);
|
||||
EXPECT_EQ(".txt.1", rewriter.getSection(foundSections[0]).name);
|
||||
rewriter.removeSection(foundSections[0]);
|
||||
EXPECT_EQ(0U, rewriter.findSections(NEO::Elf::SectionHeaderType::SHT_PROGBITS, ".txt.1").size());
|
||||
NEO::Elf::decodeElf(rewriter.encode(), err, warn);
|
||||
EXPECT_TRUE(err.empty()) << err;
|
||||
EXPECT_TRUE(warn.empty()) << warn;
|
||||
}
|
||||
Reference in New Issue
Block a user