compute-runtime/elf/writer.cpp

106 lines
4.0 KiB
C++

/*
* Copyright (C) 2017-2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "writer.h"
#include <cstring>
// Need for linux compatibility with memcpy_s
#include "runtime/helpers/string.h"
namespace CLElfLib {
void CElfWriter::resolveBinary(ElfBinaryStorage &binary) {
SElf64SectionHeader *curSectionHeader = nullptr;
char *data = nullptr;
char *stringTable = nullptr;
char *curString = nullptr;
if (binary.size() < getTotalBinarySize()) {
binary.resize(getTotalBinarySize());
}
// get a pointer to the first section header
curSectionHeader = reinterpret_cast<SElf64SectionHeader *>(binary.data() + sizeof(SElf64Header));
// get a pointer to the data
data = binary.data() +
sizeof(SElf64Header) +
((numSections + 1) * sizeof(SElf64SectionHeader)); // +1 to account for string table entry
// get a pointer to the string table
stringTable = binary.data() + sizeof(SElf64Header) +
((numSections + 1) * sizeof(SElf64SectionHeader)) + // +1 to account for string table entry
dataSize;
curString = stringTable;
// Walk through the section nodes
while (nodeQueue.empty() == false) {
// Copy data into the section header
const auto &queueFront = nodeQueue.front();
curSectionHeader->Type = queueFront.type;
curSectionHeader->Flags = queueFront.flag;
curSectionHeader->DataSize = queueFront.dataSize;
curSectionHeader->DataOffset = data - binary.data();
curSectionHeader->Name = static_cast<Elf64_Word>(curString - stringTable);
curSectionHeader = reinterpret_cast<SElf64SectionHeader *>(reinterpret_cast<unsigned char *>(curSectionHeader) + sizeof(SElf64SectionHeader));
// copy the data, move the data pointer
memcpy_s(data, queueFront.dataSize, queueFront.data.c_str(), queueFront.dataSize);
data += queueFront.dataSize;
// copy the name into the string table, move the string pointer
if (queueFront.name.size() > 0) {
memcpy_s(curString, queueFront.name.size(), queueFront.name.c_str(), queueFront.name.size());
curString += queueFront.name.size();
}
*(curString++) = '\0'; // NOLINT
nodeQueue.pop();
}
// add the string table section header
SElf64SectionHeader stringSectionHeader = {0};
stringSectionHeader.Type = E_SH_TYPE::SH_TYPE_STR_TBL;
stringSectionHeader.Flags = E_SH_FLAG::SH_FLAG_NONE;
stringSectionHeader.DataOffset = stringTable - &binary[0];
stringSectionHeader.DataSize = stringTableSize;
stringSectionHeader.Name = 0;
// Copy into the last section header
memcpy_s(curSectionHeader, sizeof(SElf64SectionHeader),
&stringSectionHeader, sizeof(SElf64SectionHeader));
// Add to our section number
numSections++;
// patch up the ELF header
patchElfHeader(*reinterpret_cast<SElf64Header *>(binary.data()));
}
void CElfWriter::patchElfHeader(SElf64Header &binary) {
// Setup the identity
binary.Identity[ELFConstants::idIdxMagic0] = ELFConstants::elfMag0;
binary.Identity[ELFConstants::idIdxMagic1] = ELFConstants::elfMag1;
binary.Identity[ELFConstants::idIdxMagic2] = ELFConstants::elfMag2;
binary.Identity[ELFConstants::idIdxMagic3] = ELFConstants::elfMag3;
binary.Identity[ELFConstants::idIdxClass] = static_cast<uint32_t>(E_EH_CLASS::EH_CLASS_64);
binary.Identity[ELFConstants::idIdxVersion] = static_cast<uint32_t>(E_EHT_VERSION::EH_VERSION_CURRENT);
// Add other non-zero info
binary.Type = type;
binary.Machine = machine;
binary.Flags = static_cast<uint32_t>(flag);
binary.ElfHeaderSize = static_cast<uint32_t>(sizeof(SElf64Header));
binary.SectionHeaderEntrySize = static_cast<uint32_t>(sizeof(SElf64SectionHeader));
binary.NumSectionHeaderEntries = numSections;
binary.SectionHeadersOffset = static_cast<uint32_t>(sizeof(SElf64Header));
binary.SectionNameTableIndex = numSections - 1; // last index
}
} // namespace CLElfLib