1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
/*
* Copyright (C) 2020-2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/source/device_binary_format/elf/elf.h"
#include "shared/source/utilities/arrayref.h"
#include "shared/source/utilities/const_stringref.h"
#include "shared/source/utilities/stackvec.h"
#include <cstdint>
namespace NEO {
namespace Elf {
enum class RelocationX8664Type : uint32_t {
relocation64 = 0x1,
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 RelocationInfo {
int symbolSectionIndex;
int symbolTableIndex;
int targetSectionIndex;
int64_t addend;
uint64_t offset;
uint32_t relocType;
std::string symbolName;
};
using Relocations = std::vector<RelocationInfo>;
using SymbolsTable = std::vector<ElfSymbolEntry<numBits>>;
bool decodeSections(std::string &outError);
template <class ElfReloc>
int extractSymbolIndex(const ElfReloc &elfReloc) const;
template <class ElfReloc>
uint32_t extractRelocType(const ElfReloc &elfReloc) const;
template <class ElfSymbol>
uint32_t extractSymbolType(const ElfSymbol &elfSymbol) const {
return elfSymbol.info & 0xf;
}
template <class ElfSymbol>
uint32_t extractSymbolBind(const ElfSymbol &elfSymbol) const {
return (elfSymbol.info >> 4) & 0xf;
}
MOCKABLE_VIRTUAL std::string getSectionName(uint32_t id) const {
if (sectionHeaders.size() > id && sectionHeaders.size() > elfFileHeader->shStrNdx) {
auto sectionHeaderNamesData = sectionHeaders[elfFileHeader->shStrNdx].data;
return std::string(reinterpret_cast<const char *>(sectionHeaderNamesData.begin()) + sectionHeaders[id].header->name);
} else {
return std::string("");
}
}
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;
}
decltype(ElfSectionHeader<numBits>::offset) getSectionOffset(uint32_t idx) const {
return sectionHeaders[idx].header->offset;
}
const Relocations &getRelocations() const {
return relocations;
}
const Relocations &getDebugInfoRelocations() const {
return debugInfoRelocations;
}
const SymbolsTable &getSymbols() const {
return symbolTable;
}
const ElfFileHeader<numBits> *elfFileHeader = nullptr;
StackVec<ProgramHeaderAndData<numBits>, 32> programHeaders;
StackVec<SectionHeaderAndData<numBits>, 32> sectionHeaders;
protected:
bool decodeSymTab(SectionHeaderAndData<numBits> §ionHeaderData, std::string &outError);
bool decodeRelocations(SectionHeaderAndData<numBits> §ionHeaderData, std::string &outError);
bool isDebugDataRelocation(ConstStringRef sectionName);
SymbolsTable symbolTable;
Relocations relocations;
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>);
extern template const ElfFileHeader<EI_CLASS_64> *decodeElfFileHeader<EI_CLASS_64>(const ArrayRef<const uint8_t>);
template <ElfIdentifierClass numBits = EI_CLASS_64>
Elf<numBits> decodeElf(const ArrayRef<const uint8_t> binary, std::string &outErrReason, std::string &outWarning);
extern template Elf<EI_CLASS_32> decodeElf<EI_CLASS_32>(const ArrayRef<const uint8_t>, std::string &, std::string &);
extern template Elf<EI_CLASS_64> decodeElf<EI_CLASS_64>(const ArrayRef<const uint8_t>, std::string &, std::string &);
template <ElfIdentifierClass numBits>
inline bool isElf(const ArrayRef<const uint8_t> binary) {
return (nullptr != decodeElfFileHeader<numBits>(binary));
}
inline bool isElf(const ArrayRef<const uint8_t> binary) {
return isElf<EI_CLASS_32>(binary) || isElf<EI_CLASS_64>(binary);
}
inline ElfIdentifierClass getElfNumBits(const ArrayRef<const uint8_t> binary) {
if (isElf<EI_CLASS_32>(binary)) {
return EI_CLASS_32;
} else if (isElf<EI_CLASS_64>(binary)) {
return EI_CLASS_64;
}
return EI_CLASS_NONE;
}
} // namespace Elf
} // namespace NEO
|