Skip to content

Commit 359dfc3

Browse files
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 <krystian.chmielewski@intel.com>
1 parent 7463e19 commit 359dfc3

File tree

7 files changed

+438
-61
lines changed

7 files changed

+438
-61
lines changed

shared/source/device_binary_format/elf/elf.h

Lines changed: 151 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2020-2021 Intel Corporation
2+
* Copyright (C) 2020-2022 Intel Corporation
33
*
44
* SPDX-License-Identifier: MIT
55
*
@@ -347,67 +347,177 @@ struct ElfSymbolEntryTypes<EI_CLASS_64> {
347347
};
348348

349349
template <ELF_IDENTIFIER_CLASS NumBits>
350-
struct ElfSymbolEntry;
350+
struct ElfSymbolEntry {
351+
using Name = typename ElfSymbolEntryTypes<NumBits>::Name;
352+
using Value = typename ElfSymbolEntryTypes<NumBits>::Value;
353+
using Size = typename ElfSymbolEntryTypes<NumBits>::Size;
354+
using Info = typename ElfSymbolEntryTypes<NumBits>::Info;
355+
using Other = typename ElfSymbolEntryTypes<NumBits>::Other;
356+
using Shndx = typename ElfSymbolEntryTypes<NumBits>::Shndx;
357+
Name name = 0U;
358+
Info info = 0U;
359+
Other other = 0U;
360+
Shndx shndx = SHN_UNDEF;
361+
Value value = 0U;
362+
Size size = 0U;
363+
364+
Info getBinding() const {
365+
return info >> 4;
366+
}
351367

352-
template <>
353-
struct ElfSymbolEntry<EI_CLASS_32> {
354-
ElfSymbolEntryTypes<EI_CLASS_32>::Name name;
355-
ElfSymbolEntryTypes<EI_CLASS_32>::Value value;
356-
ElfSymbolEntryTypes<EI_CLASS_32>::Size size;
357-
ElfSymbolEntryTypes<EI_CLASS_32>::Info info;
358-
ElfSymbolEntryTypes<EI_CLASS_32>::Other other;
359-
ElfSymbolEntryTypes<EI_CLASS_32>::Shndx shndx;
360-
};
368+
Info getType() const {
369+
return info & 0xF;
370+
}
361371

362-
template <>
363-
struct ElfSymbolEntry<EI_CLASS_64> {
364-
ElfSymbolEntryTypes<EI_CLASS_64>::Name name;
365-
ElfSymbolEntryTypes<EI_CLASS_64>::Info info;
366-
ElfSymbolEntryTypes<EI_CLASS_64>::Other other;
367-
ElfSymbolEntryTypes<EI_CLASS_64>::Shndx shndx;
368-
ElfSymbolEntryTypes<EI_CLASS_64>::Value value;
369-
ElfSymbolEntryTypes<EI_CLASS_64>::Size size;
372+
Other getVisibility() const {
373+
return other & 0x3;
374+
}
375+
376+
void setBinding(Info binding) {
377+
info = (info & 0xF) | (binding << 4);
378+
}
379+
380+
void setType(Info type) {
381+
info = (info & (~0xF)) | (type & 0xF);
382+
}
383+
384+
void setVisibility(Other visibility) {
385+
other = (other & (~0x3)) | (visibility & 0x3);
386+
}
370387
};
371388

372389
static_assert(sizeof(ElfSymbolEntry<EI_CLASS_32>) == 0x10, "");
373390
static_assert(sizeof(ElfSymbolEntry<EI_CLASS_64>) == 0x18, "");
374391

375-
template <ELF_IDENTIFIER_CLASS NumBits>
376-
struct ElfRel;
392+
template <int NumBits>
393+
struct ElfRelocationEntryTypes;
377394

378395
template <>
379-
struct ElfRel<EI_CLASS_32> {
380-
uint32_t offset;
381-
uint32_t info;
396+
struct ElfRelocationEntryTypes<EI_CLASS_32> {
397+
using Offset = uint32_t;
398+
using Info = uint32_t;
399+
using Addend = int32_t;
382400
};
383401

384402
template <>
385-
struct ElfRel<EI_CLASS_64> {
386-
uint64_t offset;
387-
uint64_t info;
403+
struct ElfRelocationEntryTypes<EI_CLASS_64> {
404+
using Offset = uint64_t;
405+
using Info = uint64_t;
406+
using Addend = int64_t;
388407
};
389408

390-
static_assert(sizeof(ElfRel<EI_CLASS_32>) == 0x8, "");
391-
static_assert(sizeof(ElfRel<EI_CLASS_64>) == 0x10, "");
409+
namespace RelocationFuncs {
410+
template <typename T>
411+
constexpr T getSymbolTableIndex(T info);
392412

393-
template <ELF_IDENTIFIER_CLASS NumBits>
394-
struct ElfRela;
413+
template <>
414+
constexpr ElfRelocationEntryTypes<EI_CLASS_32>::Info getSymbolTableIndex(ElfRelocationEntryTypes<EI_CLASS_32>::Info info) {
415+
return info >> 8;
416+
}
395417

396418
template <>
397-
struct ElfRela<EI_CLASS_32> {
398-
uint32_t offset;
399-
uint32_t info;
400-
int32_t addend;
401-
};
419+
constexpr ElfRelocationEntryTypes<EI_CLASS_64>::Info getSymbolTableIndex(ElfRelocationEntryTypes<EI_CLASS_64>::Info info) {
420+
return info >> 32;
421+
}
422+
423+
template <typename T>
424+
constexpr T getRelocationType(T info);
425+
426+
template <>
427+
constexpr ElfRelocationEntryTypes<EI_CLASS_32>::Info getRelocationType(ElfRelocationEntryTypes<EI_CLASS_32>::Info info) {
428+
return static_cast<uint8_t>(info);
429+
}
402430

403431
template <>
404-
struct ElfRela<EI_CLASS_64> {
405-
uint64_t offset;
406-
uint64_t info;
407-
int64_t addend;
432+
constexpr ElfRelocationEntryTypes<EI_CLASS_64>::Info getRelocationType(ElfRelocationEntryTypes<EI_CLASS_64>::Info info) {
433+
return static_cast<uint32_t>(info);
434+
}
435+
436+
template <typename T>
437+
constexpr T setSymbolTableIndex(T info, T index);
438+
439+
template <>
440+
constexpr ElfRelocationEntryTypes<EI_CLASS_32>::Info setSymbolTableIndex(ElfRelocationEntryTypes<EI_CLASS_32>::Info info,
441+
ElfRelocationEntryTypes<EI_CLASS_32>::Info index) {
442+
return (info & 0x000000FF) | (index << 8);
443+
}
444+
445+
template <>
446+
constexpr ElfRelocationEntryTypes<EI_CLASS_64>::Info setSymbolTableIndex(ElfRelocationEntryTypes<EI_CLASS_64>::Info info,
447+
ElfRelocationEntryTypes<EI_CLASS_64>::Info index) {
448+
return (info & 0x00000000FFFFFFFF) | (index << 32);
449+
}
450+
451+
template <typename T>
452+
constexpr T setRelocationType(T info, T type);
453+
454+
template <>
455+
constexpr ElfRelocationEntryTypes<EI_CLASS_32>::Info setRelocationType(ElfRelocationEntryTypes<EI_CLASS_32>::Info info,
456+
ElfRelocationEntryTypes<EI_CLASS_32>::Info type) {
457+
return (info & 0xFFFFFF00) | static_cast<uint8_t>(type);
458+
}
459+
460+
template <>
461+
constexpr ElfRelocationEntryTypes<EI_CLASS_64>::Info setRelocationType(ElfRelocationEntryTypes<EI_CLASS_64>::Info info,
462+
ElfRelocationEntryTypes<EI_CLASS_64>::Info type) {
463+
return (info & 0xFFFFFFFF00000000) | static_cast<uint32_t>(type);
464+
}
465+
} // namespace RelocationFuncs
466+
467+
template <ELF_IDENTIFIER_CLASS NumBits>
468+
struct ElfRel {
469+
using Offset = typename ElfRelocationEntryTypes<NumBits>::Offset;
470+
using Info = typename ElfRelocationEntryTypes<NumBits>::Info;
471+
Offset offset = 0U;
472+
Info info = 0U;
473+
474+
constexpr Info getSymbolTableIndex() const {
475+
return RelocationFuncs::getSymbolTableIndex(info);
476+
}
477+
478+
constexpr Info getRelocationType() const {
479+
return RelocationFuncs::getRelocationType(info);
480+
}
481+
482+
constexpr void setSymbolTableIndex(Info index) {
483+
info = RelocationFuncs::setSymbolTableIndex(info, index);
484+
}
485+
486+
constexpr void setRelocationType(Info type) {
487+
info = RelocationFuncs::setRelocationType(info, type);
488+
}
489+
};
490+
491+
static_assert(sizeof(ElfRel<EI_CLASS_32>) == 0x8, "");
492+
static_assert(sizeof(ElfRel<EI_CLASS_64>) == 0x10, "");
493+
494+
template <int NumBits>
495+
struct ElfRela {
496+
using Offset = typename ElfRelocationEntryTypes<NumBits>::Offset;
497+
using Info = typename ElfRelocationEntryTypes<NumBits>::Info;
498+
using Addend = typename ElfRelocationEntryTypes<NumBits>::Addend;
499+
Offset offset = 0U;
500+
Info info = 0U;
501+
Addend addend = 0U;
502+
503+
constexpr Info getSymbolTableIndex() const {
504+
return RelocationFuncs::getSymbolTableIndex(info);
505+
}
506+
507+
constexpr Info getRelocationType() const {
508+
return RelocationFuncs::getRelocationType(info);
509+
}
510+
511+
constexpr void setSymbolTableIndex(Info index) {
512+
info = RelocationFuncs::setSymbolTableIndex(info, index);
513+
}
514+
515+
constexpr void setRelocationType(Info type) {
516+
info = RelocationFuncs::setRelocationType(info, type);
517+
}
408518
};
409519

410-
static_assert(sizeof(ElfRela<EI_CLASS_32>) == 0xc, "");
520+
static_assert(sizeof(ElfRela<EI_CLASS_32>) == 0xC, "");
411521
static_assert(sizeof(ElfRela<EI_CLASS_64>) == 0x18, "");
412522

413523
namespace SpecialSectionNames {

shared/source/device_binary_format/elf/elf_encoder.cpp

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ ElfEncoder<NumBits>::ElfEncoder(bool addUndefSectionHeader, bool addHeaderSectio
2020
: addUndefSectionHeader(addUndefSectionHeader), addHeaderSectionNamesSection(addHeaderSectionNamesSection), defaultDataAlignment(defaultDataAlignemnt) {
2121
// add special strings
2222
UNRECOVERABLE_IF(defaultDataAlignment == 0);
23-
stringTable.push_back('\0');
24-
specialStringsOffsets.undef = 0U;
25-
specialStringsOffsets.shStrTab = this->appendSectionName(SpecialSectionNames::shStrTab);
23+
shStrTabNameOffset = this->appendSectionName(SpecialSectionNames::shStrTab);
2624

2725
if (addUndefSectionHeader) {
2826
ElfSectionHeader<NumBits> undefSection;
@@ -63,6 +61,13 @@ void ElfEncoder<NumBits>::appendSegment(const ElfProgramHeader<NumBits> &program
6361
}
6462
}
6563

64+
template <ELF_IDENTIFIER_CLASS NumBits>
65+
uint32_t ElfEncoder<NumBits>::getSectionHeaderIndex(const ElfSectionHeader<NumBits> &sectionHeader) {
66+
UNRECOVERABLE_IF(&sectionHeader < sectionHeaders.begin());
67+
UNRECOVERABLE_IF(&sectionHeader >= sectionHeaders.begin() + sectionHeaders.size());
68+
return static_cast<uint32_t>(&sectionHeader - &*sectionHeaders.begin());
69+
}
70+
6671
template <ELF_IDENTIFIER_CLASS NumBits>
6772
ElfSectionHeader<NumBits> &ElfEncoder<NumBits>::appendSection(SECTION_HEADER_TYPE sectionType, ConstStringRef sectionLabel, const ArrayRef<const uint8_t> sectionData) {
6873
ElfSectionHeader<NumBits> section = {};
@@ -109,15 +114,10 @@ void ElfEncoder<NumBits>::appendProgramHeaderLoad(size_t sectionId, uint64_t vAd
109114

110115
template <ELF_IDENTIFIER_CLASS NumBits>
111116
uint32_t ElfEncoder<NumBits>::appendSectionName(ConstStringRef str) {
112-
if (str.empty() || (false == addHeaderSectionNamesSection)) {
113-
return specialStringsOffsets.undef;
117+
if (false == addHeaderSectionNamesSection) {
118+
return strSecBuilder.undef();
114119
}
115-
uint32_t offset = static_cast<uint32_t>(stringTable.size());
116-
stringTable.insert(stringTable.end(), str.begin(), str.end());
117-
if (str[str.size() - 1] != '\0') {
118-
stringTable.push_back('\0');
119-
}
120-
return offset;
120+
return strSecBuilder.appendString(str);
121121
}
122122

123123
template <ELF_IDENTIFIER_CLASS NumBits>
@@ -137,13 +137,13 @@ std::vector<uint8_t> ElfEncoder<NumBits>::encode() const {
137137
auto alignedDataSize = alignUp(data.size(), static_cast<size_t>(defaultDataAlignment));
138138
dataPaddingBeforeSectionNames = alignedDataSize - data.size();
139139
sectionHeaderNamesSection.type = SHT_STRTAB;
140-
sectionHeaderNamesSection.name = specialStringsOffsets.shStrTab;
140+
sectionHeaderNamesSection.name = shStrTabNameOffset;
141141
sectionHeaderNamesSection.offset = static_cast<decltype(sectionHeaderNamesSection.offset)>(alignedDataSize);
142-
sectionHeaderNamesSection.size = static_cast<decltype(sectionHeaderNamesSection.size)>(stringTable.size());
142+
sectionHeaderNamesSection.size = static_cast<decltype(sectionHeaderNamesSection.size)>(strSecBuilder.data().size());
143143
sectionHeaderNamesSection.addralign = static_cast<decltype(sectionHeaderNamesSection.addralign)>(defaultDataAlignment);
144144
elfFileHeader.shStrNdx = static_cast<decltype(elfFileHeader.shStrNdx)>(sectionHeaders.size());
145145
sectionHeaders.push_back(sectionHeaderNamesSection);
146-
alignedSectionNamesDataSize = alignUp(stringTable.size(), static_cast<size_t>(sectionHeaderNamesSection.addralign));
146+
alignedSectionNamesDataSize = alignUp(strSecBuilder.data().size(), static_cast<size_t>(sectionHeaderNamesSection.addralign));
147147
}
148148

149149
elfFileHeader.phNum = static_cast<decltype(elfFileHeader.phNum)>(programHeaders.size());
@@ -192,7 +192,10 @@ std::vector<uint8_t> ElfEncoder<NumBits>::encode() const {
192192
ret.resize(dataOffset, 0U);
193193
ret.insert(ret.end(), data.begin(), data.end());
194194
ret.resize(ret.size() + dataPaddingBeforeSectionNames, 0U);
195-
ret.insert(ret.end(), reinterpret_cast<const uint8_t *>(stringTable.data()), reinterpret_cast<const uint8_t *>(stringTable.data() + static_cast<size_t>(sectionHeaderNamesSection.size)));
195+
if (alignedSectionNamesDataSize > 0U) {
196+
auto sectionNames = strSecBuilder.data();
197+
ret.insert(ret.end(), sectionNames.begin(), sectionNames.end());
198+
}
196199
ret.resize(ret.size() + alignedSectionNamesDataSize - static_cast<size_t>(sectionHeaderNamesSection.size), 0U);
197200
return ret;
198201
}

shared/source/device_binary_format/elf/elf_encoder.h

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,37 @@ namespace NEO {
1919

2020
namespace Elf {
2121

22+
struct StringSectionBuilder {
23+
StringSectionBuilder() {
24+
stringTable.push_back('\0');
25+
undefStringIdx = 0U;
26+
}
27+
28+
uint32_t appendString(ConstStringRef str) {
29+
if (str.empty()) {
30+
return undefStringIdx;
31+
}
32+
uint32_t offset = static_cast<uint32_t>(stringTable.size());
33+
stringTable.insert(stringTable.end(), str.begin(), str.end());
34+
if (str[str.size() - 1] != '\0') {
35+
stringTable.push_back('\0');
36+
}
37+
return offset;
38+
}
39+
40+
ArrayRef<const uint8_t> data() const {
41+
return ArrayRef<const uint8_t>::fromAny(stringTable.data(), stringTable.size());
42+
}
43+
44+
uint32_t undef() const {
45+
return undefStringIdx;
46+
}
47+
48+
protected:
49+
std::vector<char> stringTable;
50+
uint32_t undefStringIdx;
51+
};
52+
2253
template <ELF_IDENTIFIER_CLASS NumBits = EI_CLASS_64>
2354
struct ElfEncoder {
2455
ElfEncoder(bool addUndefSectionHeader = true, bool addHeaderSectionNamesSection = true,
@@ -29,6 +60,7 @@ struct ElfEncoder {
2960

3061
ElfSectionHeader<NumBits> &appendSection(SECTION_HEADER_TYPE sectionType, ConstStringRef sectionLabel, const ArrayRef<const uint8_t> sectionData);
3162
ElfProgramHeader<NumBits> &appendSegment(PROGRAM_HEADER_TYPE segmentType, const ArrayRef<const uint8_t> segmentData);
63+
uint32_t getSectionHeaderIndex(const ElfSectionHeader<NumBits> &sectionHeader);
3264
void appendProgramHeaderLoad(size_t sectionId, uint64_t vAddr, uint64_t segSize);
3365

3466
template <typename SectionHeaderEnumT>
@@ -59,16 +91,13 @@ struct ElfEncoder {
5991
StackVec<ElfProgramHeader<NumBits>, 32> programHeaders;
6092
StackVec<ElfSectionHeader<NumBits>, 32> sectionHeaders;
6193
std::vector<uint8_t> data;
62-
std::vector<char> stringTable;
94+
StringSectionBuilder strSecBuilder;
6395
struct ProgramSectionID {
6496
size_t programId;
6597
size_t sectionId;
6698
};
6799
StackVec<ProgramSectionID, 32> programSectionLookupTable;
68-
struct {
69-
uint32_t shStrTab = 0;
70-
uint32_t undef = 0;
71-
} specialStringsOffsets;
100+
uint32_t shStrTabNameOffset = 0;
72101
};
73102

74103
extern template struct ElfEncoder<EI_CLASS_32>;

shared/source/device_binary_format/elf/zebin_elf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ enum RELOC_TYPE_ZEBIN : uint32_t {
4242

4343
namespace SectionsNamesZebin {
4444
static constexpr ConstStringRef textPrefix = ".text.";
45+
static constexpr ConstStringRef functions = ".text.Intel_Symbol_Table_Void_Program";
4546
static constexpr ConstStringRef dataConst = ".data.const";
4647
static constexpr ConstStringRef dataGlobalConst = ".data.global_const";
4748
static constexpr ConstStringRef dataGlobal = ".data.global";

shared/test/unit_test/device_binary_format/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ target_sources(${TARGET_NAME} PRIVATE
1515
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_formats_tests.cpp
1616
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_decoder_tests.cpp
1717
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_encoder_tests.cpp
18+
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_tests.cpp
1819
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_decoder_tests.cpp
1920
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_dumper_tests.cpp
2021
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_tests.h

shared/test/unit_test/device_binary_format/elf/elf_encoder_tests.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,3 +490,12 @@ TEST(ElfEncoder, WhenProgramHeadersArePresentThenTheyAreSortedByVirtualAddresses
490490
EXPECT_EQ(sectionHeaders[secId].offset, programHeaders[i].offset);
491491
}
492492
}
493+
494+
TEST(ElfEncoder, WhenGetSectionHeaderIndexIsCalledThenCorrectSectionIdxIsReturned) {
495+
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
496+
auto &sec0 = elfEncoder64.appendSection(SHT_PROGBITS, "", {});
497+
EXPECT_EQ(0U, elfEncoder64.getSectionHeaderIndex(sec0));
498+
499+
auto &sec1 = elfEncoder64.appendSection(SHT_PROGBITS, "", {});
500+
EXPECT_EQ(1U, elfEncoder64.getSectionHeaderIndex(sec1));
501+
}

0 commit comments

Comments
 (0)