From 359dfc301f66acfaf21028449dee358795792f81 Mon Sep 17 00:00:00 2001 From: Krystian Chmielewski Date: Fri, 13 May 2022 11:42:59 +0200 Subject: [PATCH] Improve elf encoder This change: * adds functions for setting members of ElfSymbol, and ElfRela. * simplifies string section creation in ElfEncoder. * adds function to query index of section in ElfEncoder. Signed-off-by: Krystian Chmielewski --- shared/source/device_binary_format/elf/elf.h | 194 +++++++++++---- .../device_binary_format/elf/elf_encoder.cpp | 33 +-- .../device_binary_format/elf/elf_encoder.h | 39 ++- .../device_binary_format/elf/zebin_elf.h | 1 + .../device_binary_format/CMakeLists.txt | 1 + .../elf/elf_encoder_tests.cpp | 9 + .../device_binary_format/elf/elf_tests.cpp | 224 ++++++++++++++++++ 7 files changed, 439 insertions(+), 62 deletions(-) create mode 100644 shared/test/unit_test/device_binary_format/elf/elf_tests.cpp diff --git a/shared/source/device_binary_format/elf/elf.h b/shared/source/device_binary_format/elf/elf.h index b6ef78e0a4..b1b8a3d6b0 100644 --- a/shared/source/device_binary_format/elf/elf.h +++ b/shared/source/device_binary_format/elf/elf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2021 Intel Corporation + * Copyright (C) 2020-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -347,67 +347,177 @@ struct ElfSymbolEntryTypes { }; template -struct ElfSymbolEntry; +struct ElfSymbolEntry { + using Name = typename ElfSymbolEntryTypes::Name; + using Value = typename ElfSymbolEntryTypes::Value; + using Size = typename ElfSymbolEntryTypes::Size; + using Info = typename ElfSymbolEntryTypes::Info; + using Other = typename ElfSymbolEntryTypes::Other; + using Shndx = typename ElfSymbolEntryTypes::Shndx; + Name name = 0U; + Info info = 0U; + Other other = 0U; + Shndx shndx = SHN_UNDEF; + Value value = 0U; + Size size = 0U; -template <> -struct ElfSymbolEntry { - ElfSymbolEntryTypes::Name name; - ElfSymbolEntryTypes::Value value; - ElfSymbolEntryTypes::Size size; - ElfSymbolEntryTypes::Info info; - ElfSymbolEntryTypes::Other other; - ElfSymbolEntryTypes::Shndx shndx; -}; + Info getBinding() const { + return info >> 4; + } -template <> -struct ElfSymbolEntry { - ElfSymbolEntryTypes::Name name; - ElfSymbolEntryTypes::Info info; - ElfSymbolEntryTypes::Other other; - ElfSymbolEntryTypes::Shndx shndx; - ElfSymbolEntryTypes::Value value; - ElfSymbolEntryTypes::Size size; + Info getType() const { + return info & 0xF; + } + + Other getVisibility() const { + return other & 0x3; + } + + void setBinding(Info binding) { + info = (info & 0xF) | (binding << 4); + } + + void setType(Info type) { + info = (info & (~0xF)) | (type & 0xF); + } + + void setVisibility(Other visibility) { + other = (other & (~0x3)) | (visibility & 0x3); + } }; static_assert(sizeof(ElfSymbolEntry) == 0x10, ""); static_assert(sizeof(ElfSymbolEntry) == 0x18, ""); -template -struct ElfRel; +template +struct ElfRelocationEntryTypes; template <> -struct ElfRel { - uint32_t offset; - uint32_t info; +struct ElfRelocationEntryTypes { + using Offset = uint32_t; + using Info = uint32_t; + using Addend = int32_t; }; template <> -struct ElfRel { - uint64_t offset; - uint64_t info; +struct ElfRelocationEntryTypes { + using Offset = uint64_t; + using Info = uint64_t; + using Addend = int64_t; +}; + +namespace RelocationFuncs { +template +constexpr T getSymbolTableIndex(T info); + +template <> +constexpr ElfRelocationEntryTypes::Info getSymbolTableIndex(ElfRelocationEntryTypes::Info info) { + return info >> 8; +} + +template <> +constexpr ElfRelocationEntryTypes::Info getSymbolTableIndex(ElfRelocationEntryTypes::Info info) { + return info >> 32; +} + +template +constexpr T getRelocationType(T info); + +template <> +constexpr ElfRelocationEntryTypes::Info getRelocationType(ElfRelocationEntryTypes::Info info) { + return static_cast(info); +} + +template <> +constexpr ElfRelocationEntryTypes::Info getRelocationType(ElfRelocationEntryTypes::Info info) { + return static_cast(info); +} + +template +constexpr T setSymbolTableIndex(T info, T index); + +template <> +constexpr ElfRelocationEntryTypes::Info setSymbolTableIndex(ElfRelocationEntryTypes::Info info, + ElfRelocationEntryTypes::Info index) { + return (info & 0x000000FF) | (index << 8); +} + +template <> +constexpr ElfRelocationEntryTypes::Info setSymbolTableIndex(ElfRelocationEntryTypes::Info info, + ElfRelocationEntryTypes::Info index) { + return (info & 0x00000000FFFFFFFF) | (index << 32); +} + +template +constexpr T setRelocationType(T info, T type); + +template <> +constexpr ElfRelocationEntryTypes::Info setRelocationType(ElfRelocationEntryTypes::Info info, + ElfRelocationEntryTypes::Info type) { + return (info & 0xFFFFFF00) | static_cast(type); +} + +template <> +constexpr ElfRelocationEntryTypes::Info setRelocationType(ElfRelocationEntryTypes::Info info, + ElfRelocationEntryTypes::Info type) { + return (info & 0xFFFFFFFF00000000) | static_cast(type); +} +} // namespace RelocationFuncs + +template +struct ElfRel { + using Offset = typename ElfRelocationEntryTypes::Offset; + using Info = typename ElfRelocationEntryTypes::Info; + Offset offset = 0U; + Info info = 0U; + + constexpr Info getSymbolTableIndex() const { + return RelocationFuncs::getSymbolTableIndex(info); + } + + constexpr Info getRelocationType() const { + return RelocationFuncs::getRelocationType(info); + } + + constexpr void setSymbolTableIndex(Info index) { + info = RelocationFuncs::setSymbolTableIndex(info, index); + } + + constexpr void setRelocationType(Info type) { + info = RelocationFuncs::setRelocationType(info, type); + } }; static_assert(sizeof(ElfRel) == 0x8, ""); static_assert(sizeof(ElfRel) == 0x10, ""); -template -struct ElfRela; +template +struct ElfRela { + using Offset = typename ElfRelocationEntryTypes::Offset; + using Info = typename ElfRelocationEntryTypes::Info; + using Addend = typename ElfRelocationEntryTypes::Addend; + Offset offset = 0U; + Info info = 0U; + Addend addend = 0U; -template <> -struct ElfRela { - uint32_t offset; - uint32_t info; - int32_t addend; + constexpr Info getSymbolTableIndex() const { + return RelocationFuncs::getSymbolTableIndex(info); + } + + constexpr Info getRelocationType() const { + return RelocationFuncs::getRelocationType(info); + } + + constexpr void setSymbolTableIndex(Info index) { + info = RelocationFuncs::setSymbolTableIndex(info, index); + } + + constexpr void setRelocationType(Info type) { + info = RelocationFuncs::setRelocationType(info, type); + } }; -template <> -struct ElfRela { - uint64_t offset; - uint64_t info; - int64_t addend; -}; - -static_assert(sizeof(ElfRela) == 0xc, ""); +static_assert(sizeof(ElfRela) == 0xC, ""); static_assert(sizeof(ElfRela) == 0x18, ""); namespace SpecialSectionNames { diff --git a/shared/source/device_binary_format/elf/elf_encoder.cpp b/shared/source/device_binary_format/elf/elf_encoder.cpp index 5a0f5fffbb..28dab304a3 100644 --- a/shared/source/device_binary_format/elf/elf_encoder.cpp +++ b/shared/source/device_binary_format/elf/elf_encoder.cpp @@ -20,9 +20,7 @@ ElfEncoder::ElfEncoder(bool addUndefSectionHeader, bool addHeaderSectio : addUndefSectionHeader(addUndefSectionHeader), addHeaderSectionNamesSection(addHeaderSectionNamesSection), defaultDataAlignment(defaultDataAlignemnt) { // add special strings UNRECOVERABLE_IF(defaultDataAlignment == 0); - stringTable.push_back('\0'); - specialStringsOffsets.undef = 0U; - specialStringsOffsets.shStrTab = this->appendSectionName(SpecialSectionNames::shStrTab); + shStrTabNameOffset = this->appendSectionName(SpecialSectionNames::shStrTab); if (addUndefSectionHeader) { ElfSectionHeader undefSection; @@ -63,6 +61,13 @@ void ElfEncoder::appendSegment(const ElfProgramHeader &program } } +template +uint32_t ElfEncoder::getSectionHeaderIndex(const ElfSectionHeader §ionHeader) { + UNRECOVERABLE_IF(§ionHeader < sectionHeaders.begin()); + UNRECOVERABLE_IF(§ionHeader >= sectionHeaders.begin() + sectionHeaders.size()); + return static_cast(§ionHeader - &*sectionHeaders.begin()); +} + template ElfSectionHeader &ElfEncoder::appendSection(SECTION_HEADER_TYPE sectionType, ConstStringRef sectionLabel, const ArrayRef sectionData) { ElfSectionHeader section = {}; @@ -109,15 +114,10 @@ void ElfEncoder::appendProgramHeaderLoad(size_t sectionId, uint64_t vAd template uint32_t ElfEncoder::appendSectionName(ConstStringRef str) { - if (str.empty() || (false == addHeaderSectionNamesSection)) { - return specialStringsOffsets.undef; + if (false == addHeaderSectionNamesSection) { + return strSecBuilder.undef(); } - uint32_t offset = static_cast(stringTable.size()); - stringTable.insert(stringTable.end(), str.begin(), str.end()); - if (str[str.size() - 1] != '\0') { - stringTable.push_back('\0'); - } - return offset; + return strSecBuilder.appendString(str); } template @@ -137,13 +137,13 @@ std::vector ElfEncoder::encode() const { auto alignedDataSize = alignUp(data.size(), static_cast(defaultDataAlignment)); dataPaddingBeforeSectionNames = alignedDataSize - data.size(); sectionHeaderNamesSection.type = SHT_STRTAB; - sectionHeaderNamesSection.name = specialStringsOffsets.shStrTab; + sectionHeaderNamesSection.name = shStrTabNameOffset; sectionHeaderNamesSection.offset = static_cast(alignedDataSize); - sectionHeaderNamesSection.size = static_cast(stringTable.size()); + sectionHeaderNamesSection.size = static_cast(strSecBuilder.data().size()); sectionHeaderNamesSection.addralign = static_cast(defaultDataAlignment); elfFileHeader.shStrNdx = static_cast(sectionHeaders.size()); sectionHeaders.push_back(sectionHeaderNamesSection); - alignedSectionNamesDataSize = alignUp(stringTable.size(), static_cast(sectionHeaderNamesSection.addralign)); + alignedSectionNamesDataSize = alignUp(strSecBuilder.data().size(), static_cast(sectionHeaderNamesSection.addralign)); } elfFileHeader.phNum = static_cast(programHeaders.size()); @@ -192,7 +192,10 @@ std::vector ElfEncoder::encode() const { ret.resize(dataOffset, 0U); ret.insert(ret.end(), data.begin(), data.end()); ret.resize(ret.size() + dataPaddingBeforeSectionNames, 0U); - ret.insert(ret.end(), reinterpret_cast(stringTable.data()), reinterpret_cast(stringTable.data() + static_cast(sectionHeaderNamesSection.size))); + if (alignedSectionNamesDataSize > 0U) { + auto sectionNames = strSecBuilder.data(); + ret.insert(ret.end(), sectionNames.begin(), sectionNames.end()); + } ret.resize(ret.size() + alignedSectionNamesDataSize - static_cast(sectionHeaderNamesSection.size), 0U); return ret; } diff --git a/shared/source/device_binary_format/elf/elf_encoder.h b/shared/source/device_binary_format/elf/elf_encoder.h index 8174dbad97..724e189c2d 100644 --- a/shared/source/device_binary_format/elf/elf_encoder.h +++ b/shared/source/device_binary_format/elf/elf_encoder.h @@ -19,6 +19,37 @@ namespace NEO { namespace Elf { +struct StringSectionBuilder { + StringSectionBuilder() { + stringTable.push_back('\0'); + undefStringIdx = 0U; + } + + uint32_t appendString(ConstStringRef str) { + if (str.empty()) { + return undefStringIdx; + } + uint32_t offset = static_cast(stringTable.size()); + stringTable.insert(stringTable.end(), str.begin(), str.end()); + if (str[str.size() - 1] != '\0') { + stringTable.push_back('\0'); + } + return offset; + } + + ArrayRef data() const { + return ArrayRef::fromAny(stringTable.data(), stringTable.size()); + } + + uint32_t undef() const { + return undefStringIdx; + } + + protected: + std::vector stringTable; + uint32_t undefStringIdx; +}; + template struct ElfEncoder { ElfEncoder(bool addUndefSectionHeader = true, bool addHeaderSectionNamesSection = true, @@ -29,6 +60,7 @@ struct ElfEncoder { ElfSectionHeader &appendSection(SECTION_HEADER_TYPE sectionType, ConstStringRef sectionLabel, const ArrayRef sectionData); ElfProgramHeader &appendSegment(PROGRAM_HEADER_TYPE segmentType, const ArrayRef segmentData); + uint32_t getSectionHeaderIndex(const ElfSectionHeader §ionHeader); void appendProgramHeaderLoad(size_t sectionId, uint64_t vAddr, uint64_t segSize); template @@ -59,16 +91,13 @@ struct ElfEncoder { StackVec, 32> programHeaders; StackVec, 32> sectionHeaders; std::vector data; - std::vector stringTable; + StringSectionBuilder strSecBuilder; struct ProgramSectionID { size_t programId; size_t sectionId; }; StackVec programSectionLookupTable; - struct { - uint32_t shStrTab = 0; - uint32_t undef = 0; - } specialStringsOffsets; + uint32_t shStrTabNameOffset = 0; }; extern template struct ElfEncoder; diff --git a/shared/source/device_binary_format/elf/zebin_elf.h b/shared/source/device_binary_format/elf/zebin_elf.h index 11d5022e43..67b518c938 100644 --- a/shared/source/device_binary_format/elf/zebin_elf.h +++ b/shared/source/device_binary_format/elf/zebin_elf.h @@ -42,6 +42,7 @@ enum RELOC_TYPE_ZEBIN : uint32_t { namespace SectionsNamesZebin { static constexpr ConstStringRef textPrefix = ".text."; +static constexpr ConstStringRef functions = ".text.Intel_Symbol_Table_Void_Program"; static constexpr ConstStringRef dataConst = ".data.const"; static constexpr ConstStringRef dataGlobalConst = ".data.global_const"; static constexpr ConstStringRef dataGlobal = ".data.global"; diff --git a/shared/test/unit_test/device_binary_format/CMakeLists.txt b/shared/test/unit_test/device_binary_format/CMakeLists.txt index c4e491ae74..3aed07d987 100644 --- a/shared/test/unit_test/device_binary_format/CMakeLists.txt +++ b/shared/test/unit_test/device_binary_format/CMakeLists.txt @@ -15,6 +15,7 @@ target_sources(${TARGET_NAME} 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_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_decoder_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_dumper_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_tests.h diff --git a/shared/test/unit_test/device_binary_format/elf/elf_encoder_tests.cpp b/shared/test/unit_test/device_binary_format/elf/elf_encoder_tests.cpp index ad7540c0ee..4fb242bc34 100644 --- a/shared/test/unit_test/device_binary_format/elf/elf_encoder_tests.cpp +++ b/shared/test/unit_test/device_binary_format/elf/elf_encoder_tests.cpp @@ -490,3 +490,12 @@ TEST(ElfEncoder, WhenProgramHeadersArePresentThenTheyAreSortedByVirtualAddresses EXPECT_EQ(sectionHeaders[secId].offset, programHeaders[i].offset); } } + +TEST(ElfEncoder, WhenGetSectionHeaderIndexIsCalledThenCorrectSectionIdxIsReturned) { + ElfEncoder elfEncoder64(false, false); + auto &sec0 = elfEncoder64.appendSection(SHT_PROGBITS, "", {}); + EXPECT_EQ(0U, elfEncoder64.getSectionHeaderIndex(sec0)); + + auto &sec1 = elfEncoder64.appendSection(SHT_PROGBITS, "", {}); + EXPECT_EQ(1U, elfEncoder64.getSectionHeaderIndex(sec1)); +} diff --git a/shared/test/unit_test/device_binary_format/elf/elf_tests.cpp b/shared/test/unit_test/device_binary_format/elf/elf_tests.cpp new file mode 100644 index 0000000000..6d0ecd673d --- /dev/null +++ b/shared/test/unit_test/device_binary_format/elf/elf_tests.cpp @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/device_binary_format/elf/elf.h" +#include "shared/test/common/test_macros/test.h" + +using namespace NEO::Elf; + +TEST(ElfFormat, WhenAccessingFieldsFromElfSymbolEntryThenAdequateValueIsSetOrReturned) { + // fields info and other have same size in both 32bit and 64bit elf + ElfSymbolEntry elfSym{0}; + + uint8_t binding = 1U; + elfSym.info = 0U; + elfSym.info = (elfSym.info & 0xFU) | (binding << 4U); + EXPECT_EQ(binding, elfSym.getBinding()); + + elfSym.info = 0U; + elfSym.setBinding(binding); + EXPECT_EQ(binding, elfSym.info >> 4); + + uint8_t type = 2U; + elfSym.info = 0U; + elfSym.info = (elfSym.info & (~0xFU)) | type; + EXPECT_EQ(type, elfSym.getType()); + + elfSym.info = 0U; + elfSym.setType(type); + EXPECT_EQ(type, elfSym.info & 0xF); + + uint8_t visibility = 3U; + elfSym.other = 0U; + elfSym.other = (elfSym.other & (~0x3)) | visibility; + EXPECT_EQ(visibility, elfSym.getVisibility()); + + elfSym.other = 0U; + elfSym.setVisibility(visibility); + EXPECT_EQ(visibility, elfSym.other & 0x3); +} + +TEST(ElfFormat, Elf32SymbolsAreReadCorrectly) { + uint8_t elfSymbolData32b[0x10] = {0}; + auto &name = *reinterpret_cast(elfSymbolData32b); + auto &info = *reinterpret_cast(elfSymbolData32b + 4); + auto &other = *reinterpret_cast(elfSymbolData32b + 5); + auto &shndx = *reinterpret_cast(elfSymbolData32b + 6); + auto &value = *reinterpret_cast(elfSymbolData32b + 8); + auto &size = *reinterpret_cast(elfSymbolData32b + 0xC); + + uint8_t type = 1U; + uint8_t bind = 2U; + uint8_t visibility = 3U; + name = std::numeric_limits::max(); + info = (bind << 4) | (type & 0xF); + other = (visibility & 0x3); + shndx = std::numeric_limits::max(); + value = std::numeric_limits::max(); + size = std::numeric_limits::max(); + + auto elfSymbolEntry = reinterpret_cast *>(elfSymbolData32b); + EXPECT_EQ(name, elfSymbolEntry->name); + EXPECT_EQ(info, elfSymbolEntry->info); + EXPECT_EQ(type, elfSymbolEntry->getType()); + EXPECT_EQ(bind, elfSymbolEntry->getBinding()); + EXPECT_EQ(other, elfSymbolEntry->other); + EXPECT_EQ(visibility, elfSymbolEntry->getVisibility()); + EXPECT_EQ(shndx, elfSymbolEntry->shndx); + EXPECT_EQ(value, elfSymbolEntry->value); + EXPECT_EQ(size, elfSymbolEntry->size); +} + +TEST(ElfFormat, Elf64SymbolsAreReadCorrectly) { + uint8_t elfSymbolData64b[0x18] = {0}; + auto &name = *reinterpret_cast(elfSymbolData64b); + auto &info = *reinterpret_cast(elfSymbolData64b + 4); + auto &other = *reinterpret_cast(elfSymbolData64b + 5); + auto &shndx = *reinterpret_cast(elfSymbolData64b + 6); + auto &value = *reinterpret_cast(elfSymbolData64b + 8); + auto &size = *reinterpret_cast(elfSymbolData64b + 0x10); + + uint8_t type = 1U; + uint8_t bind = 2U; + uint8_t visibility = 3U; + name = std::numeric_limits::max(); + info = (bind << 4) | (type & 0xF); + other = (visibility & 0x3); + shndx = std::numeric_limits::max(); + value = std::numeric_limits::max(); + size = std::numeric_limits::max(); + + auto elfSymbolEntry = reinterpret_cast *>(elfSymbolData64b); + EXPECT_EQ(name, elfSymbolEntry->name); + EXPECT_EQ(info, elfSymbolEntry->info); + EXPECT_EQ(type, elfSymbolEntry->getType()); + EXPECT_EQ(bind, elfSymbolEntry->getBinding()); + EXPECT_EQ(other, elfSymbolEntry->other); + EXPECT_EQ(visibility, elfSymbolEntry->getVisibility()); + EXPECT_EQ(shndx, elfSymbolEntry->shndx); + EXPECT_EQ(value, elfSymbolEntry->value); + EXPECT_EQ(size, elfSymbolEntry->size); +} + +TEST(ElfFormat, WhenAccessingInfoFieldFromElf32RelThenAdequateValueIsSetOrReturned) { + ElfRel elfRel{0}; + + uint8_t relocType = 0x8; + elfRel.info = relocType; + + EXPECT_EQ(relocType, elfRel.getRelocationType()); + + elfRel.info = 0U; + elfRel.setRelocationType(relocType); + EXPECT_EQ(relocType, static_cast(elfRel.info)); + + uint32_t symTableIdx = 0x10; + elfRel.info = symTableIdx << 8; + EXPECT_EQ(symTableIdx, elfRel.getSymbolTableIndex()); + + elfRel.info = 0U; + elfRel.setSymbolTableIndex(symTableIdx); + EXPECT_EQ(symTableIdx, (elfRel.info >> 8)); +} + +TEST(ElfFormat, WhenAccessingInfoFieldFromElf64RelThenAdequateValueIsSetOrReturned) { + ElfRel elfRel{0}; + + uint64_t relocType = 0x1000; + elfRel.info = relocType; + EXPECT_EQ(relocType, elfRel.getRelocationType()); + + elfRel.info = 0U; + elfRel.setRelocationType(relocType); + EXPECT_EQ(relocType, static_cast(elfRel.info)); + + uint32_t symTableIdx = 0x2000; + elfRel.info = static_cast(symTableIdx) << 32; + EXPECT_EQ(symTableIdx, elfRel.getSymbolTableIndex()); + + elfRel.info = 0U; + elfRel.setSymbolTableIndex(symTableIdx); + EXPECT_EQ(symTableIdx, (elfRel.info >> 32)); +} + +TEST(ElfFormat, Elf32RelAreReadCorrectly) { + uint8_t elfRel32Data[0x8] = {0}; + auto &offset = *reinterpret_cast(elfRel32Data); + auto &info = *reinterpret_cast(elfRel32Data + 4); + + uint32_t relocType = 0x8; + uint32_t symTabIdx = 0x100; + + offset = 0x1000; + info = static_cast(relocType) | (symTabIdx << 8); + + auto elfRel = reinterpret_cast *>(elfRel32Data); + EXPECT_EQ(offset, elfRel->offset); + EXPECT_EQ(info, elfRel->info); + EXPECT_EQ(relocType, elfRel->getRelocationType()); + EXPECT_EQ(symTabIdx, elfRel->getSymbolTableIndex()); +} + +TEST(ElfFormat, Elf32RelaAreReadCorrectly) { + uint8_t elfRela32Data[0xC] = {0}; + auto &offset = *reinterpret_cast(elfRela32Data); + auto &info = *reinterpret_cast(elfRela32Data + 4); + auto &addend = *reinterpret_cast(elfRela32Data + 8); + + uint32_t relocType = 0x8; + uint32_t symTabIdx = 0x100; + + offset = 0x1000; + info = static_cast(relocType) | (symTabIdx << 8); + addend = 0x2000; + + auto elfRela = reinterpret_cast *>(elfRela32Data); + EXPECT_EQ(offset, elfRela->offset); + EXPECT_EQ(info, elfRela->info); + EXPECT_EQ(relocType, elfRela->getRelocationType()); + EXPECT_EQ(symTabIdx, elfRela->getSymbolTableIndex()); + EXPECT_EQ(addend, elfRela->addend); +} + +TEST(ElfFormat, Elf64RelAreReadCorrectly) { + uint8_t elfRel64Data[0x10] = {0}; + auto &offset = *reinterpret_cast(elfRel64Data); + auto &info = *reinterpret_cast(elfRel64Data + 0x8); + + uint64_t relocType = 0x800; + uint64_t symTabIdx = 0x100; + + offset = 0x1000; + info = static_cast(relocType) + (symTabIdx << 32); + + auto elfRel = reinterpret_cast *>(elfRel64Data); + EXPECT_EQ(offset, elfRel->offset); + EXPECT_EQ(info, elfRel->info); + EXPECT_EQ(relocType, elfRel->getRelocationType()); + EXPECT_EQ(symTabIdx, elfRel->getSymbolTableIndex()); +} + +TEST(ElfFormat, Elf64RelaAreReadCorrectly) { + uint8_t elfRela64Data[0x18] = {0}; + auto &offset = *reinterpret_cast(elfRela64Data); + auto &info = *reinterpret_cast(elfRela64Data + 0x8); + auto &addend = *reinterpret_cast(elfRela64Data + 0x10); + + uint64_t relocType = 0x800; + uint64_t symTabIdx = 0x100; + + offset = 0x1000; + info = static_cast(relocType) + (symTabIdx << 32); + addend = 0x2000; + + auto elfRela = reinterpret_cast *>(elfRela64Data); + EXPECT_EQ(offset, elfRela->offset); + EXPECT_EQ(info, elfRela->info); + EXPECT_EQ(relocType, elfRela->getRelocationType()); + EXPECT_EQ(symTabIdx, elfRela->getSymbolTableIndex()); + EXPECT_EQ(addend, elfRela->addend); +}