/* * Copyright (C) 2017-2019 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "writer.h" #include // 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(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(curString - stringTable); curSectionHeader = reinterpret_cast(reinterpret_cast(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(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(E_EH_CLASS::EH_CLASS_64); binary.Identity[ELFConstants::idIdxVersion] = static_cast(E_EHT_VERSION::EH_VERSION_CURRENT); // Add other non-zero info binary.Type = type; binary.Machine = machine; binary.Flags = static_cast(flag); binary.ElfHeaderSize = static_cast(sizeof(SElf64Header)); binary.SectionHeaderEntrySize = static_cast(sizeof(SElf64SectionHeader)); binary.NumSectionHeaderEntries = numSections; binary.SectionHeadersOffset = static_cast(sizeof(SElf64Header)); binary.SectionNameTableIndex = numSections - 1; // last index } } // namespace CLElfLib