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
|
/*
* Copyright (C) 2022-2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/offline_compiler/source/ocloc_concat.h"
#include "shared/offline_compiler/source/ocloc_api.h"
#include "shared/offline_compiler/source/ocloc_arg_helper.h"
#include "shared/source/device_binary_format/ar/ar_decoder.h"
#include "shared/source/device_binary_format/ar/ar_encoder.h"
#include "shared/source/device_binary_format/elf/elf_decoder.h"
#include "shared/source/device_binary_format/zebin/zebin_decoder.h"
#include "shared/source/helpers/product_config_helper.h"
namespace NEO {
OclocConcat::ErrorCode OclocConcat::initialize(const std::vector<std::string> &args) {
auto error = parseArguments(args);
if (error) {
return error;
}
error = checkIfFatBinariesExist();
return error;
}
Ar::Ar OclocConcat::decodeAr(ArrayRef<const uint8_t> arFile, std::string &outErrors, std::string &outWarnings) {
return NEO::Ar::decodeAr(arFile, outErrors, outWarnings);
}
OclocConcat::ErrorCode OclocConcat::parseArguments(const std::vector<std::string> &args) {
for (size_t i = 2; i < args.size(); i++) {
if (NEO::ConstStringRef("-out") == args[i]) {
if (i + 1 >= args.size()) {
argHelper->printf("Missing out file name after \"-out\" argument\n");
return OCLOC_INVALID_COMMAND_LINE;
}
fatBinaryName = args[++i];
} else {
fileNamesToConcat.push_back(args[i]);
}
}
if (fileNamesToConcat.empty()) {
argHelper->printf("No files to concatenate were provided.\n");
return OCLOC_INVALID_COMMAND_LINE;
}
return OCLOC_SUCCESS;
}
OclocConcat::ErrorCode OclocConcat::checkIfFatBinariesExist() {
bool filesExist = true;
for (auto &fileName : fileNamesToConcat) {
if (false == argHelper->fileExists(fileName)) {
filesExist = false;
auto errorMsg = fileName + " doesn't exist!\n";
argHelper->printf(errorMsg.c_str());
}
}
return filesExist ? OCLOC_SUCCESS : OCLOC_INVALID_COMMAND_LINE;
}
void OclocConcat::printMsg(ConstStringRef fileName, const std::string &message) {
if (false == message.empty()) {
argHelper->printf(fileName.data());
argHelper->printf(" : ");
argHelper->printf(message.c_str());
}
}
AOT::PRODUCT_CONFIG OclocConcat::getAOTProductConfigFromBinary(ArrayRef<const uint8_t> binary, std::string &outErrors) {
std::vector<Zebin::Elf::IntelGTNote> intelGTNotes;
if (Zebin::isZebin<Elf::EI_CLASS_64>(binary)) {
std::string warnings;
auto elf = NEO::Elf::decodeElf(binary, outErrors, warnings);
Zebin::getIntelGTNotes<Elf::EI_CLASS_64>(elf, intelGTNotes, outErrors, warnings);
} else if (Zebin::isZebin<Elf::EI_CLASS_32>(binary)) {
std::string warnings;
auto elf = NEO::Elf::decodeElf<Elf::EI_CLASS_32>(binary, outErrors, warnings);
Zebin::getIntelGTNotes<Elf::EI_CLASS_32>(elf, intelGTNotes, outErrors, warnings);
} else {
outErrors.append("Not a zebin file\n");
return {};
}
AOT::PRODUCT_CONFIG productConfig{};
bool productConfigFound = false;
for (auto ¬e : intelGTNotes) {
if (note.type == Zebin::Elf::IntelGTSectionType::productConfig) {
productConfig = *reinterpret_cast<const AOT::PRODUCT_CONFIG *>(note.data.begin());
productConfigFound = true;
break;
}
}
if (false == productConfigFound) {
outErrors.append("Couldn't find AOT product configuration in intelGTNotes section.\n");
}
return productConfig;
}
OclocConcat::ErrorCode OclocConcat::concatenate() {
NEO::Ar::ArEncoder arEncoder(true);
for (auto &fileName : fileNamesToConcat) {
auto file = argHelper->readBinaryFile(fileName);
auto fileRef = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(file.data()), file.size());
if (NEO::Ar::isAr(fileRef)) {
std::string warnings;
std::string errors;
auto ar = decodeAr(fileRef, errors, warnings);
if (false == errors.empty()) {
printMsg(fileName, errors);
return OCLOC_INVALID_FILE;
}
printMsg(fileName, warnings);
for (auto &fileEntry : ar.files) {
if (NEO::ConstStringRef(fileEntry.fileName).startsWith("pad_")) {
continue;
}
arEncoder.appendFileEntry(fileEntry.fileName, fileEntry.fileData);
}
} else {
std::string errors;
auto productConfig = getAOTProductConfigFromBinary(fileRef, errors);
if (false == errors.empty()) {
printMsg(fileName, errors);
return OCLOC_INVALID_FILE;
}
auto entryName = ProductConfigHelper::parseMajorMinorRevisionValue(productConfig);
arEncoder.appendFileEntry(entryName, fileRef);
}
}
auto arFile = arEncoder.encode();
argHelper->saveOutput(fatBinaryName, arFile.data(), arFile.size());
return OCLOC_SUCCESS;
}
void OclocConcat::printHelp() {
argHelper->printf(helpMessage.data());
}
} // namespace NEO
|