* This file is part of the MindStudio project.
* Copyright (c) 2025 Huawei Technologies Co.,Ltd.
*
* MindStudio is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* ------------------------------------------------------------------------- */
#include "MSBit.h"
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <unordered_map>
#include "utils/Serialize.h"
#include "utils/FileSystem.h"
#include "utils/Singleton.h"
using namespace std;
namespace {
constexpr uint8_t FUNC_NAME_SEP = 12;
const string FUNC_SEP = Serialize(FUNC_NAME_SEP);
#pragma pack(4)
struct FuncNameList {
uint32_t size;
char funcLists[0];
};
struct CtrlInfo {
uint32_t size;
uint16_t version;
uint16_t splitOffset1;
uint16_t reserve[2];
uint8_t
data[0];
};
struct FuncInfo {
uint16_t instrId;
uint16_t injectFuncId;
uint16_t paraNum;
uint16_t paraMask[0];
};
#pragma pack()
struct InjectInfo {
uint16_t instrId{};
uint16_t injectFuncId{};
vector<uint16_t> paraMask;
void Serialize(stringstream &ss) const {
FuncInfo info{instrId, injectFuncId, static_cast<uint16_t>(paraMask.size())};
ss << string(reinterpret_cast<const char *>(&info), sizeof(FuncInfo));
ss << string(reinterpret_cast<const char *>(paraMask.data()), sizeof(uint16_t) * info.paraNum);
}
};
class InjectBindHelper : public Singleton<InjectBindHelper, true> {
public:
friend class Singleton<InjectBindHelper, true>;
void Reset() {
funcNames_.clear();
injectFuncIdMap_.clear();
injectInfo_.clear();
type_ = InstrForCore::MIX;
}
void Init(const string &archName) {
if (archName.find("-vec") != std::string::npos) {
type_ = InstrForCore::VEC;
} else if (archName.find("-cube") != std::string::npos) {
type_ = InstrForCore::CUBE;
}
}
void Bind(InstrType instrType, const string &injectedFuncName, const vector<uint16_t> ¶Mask,
const InstrForCore type) {
if (type_ != InstrForCore::MIX && type != InstrForCore::MIX) {
if (type_ != type) {
return;
}
}
if (injectFuncIdMap_.count(injectedFuncName) == 0) {
injectFuncIdMap_[injectedFuncName] = static_cast<uint16_t>(funcNames_.size());
funcNames_.push_back(injectedFuncName);
}
InjectInfo injectInfo;
injectInfo.instrId = static_cast<uint16_t>(instrType);
injectInfo.injectFuncId = injectFuncIdMap_[injectedFuncName];
injectInfo.paraMask = paraMask;
injectInfo_.push_back(injectInfo);
}
void Serialize(stringstream &ss) {
stringstream buffer;
for (const auto &info : injectInfo_) {
info.Serialize(buffer);
}
CtrlInfo ctrlInfo{};
ctrlInfo.splitOffset1 = buffer.str().size();
string funcLists = Join(funcNames_.begin(), funcNames_.end(), FUNC_SEP);
FuncNameList funcNameList{static_cast<uint32_t>(funcLists.size() + sizeof(FuncNameList))};
buffer << string(reinterpret_cast<const char *>(&funcNameList), sizeof(FuncNameList));
buffer << string(reinterpret_cast<const char *>(funcLists.data()), funcNameList.size);
string bufferStr = buffer.str();
ctrlInfo.size = bufferStr.size() + sizeof(CtrlInfo);
ctrlInfo.version = 0;
ctrlInfo.reserve[0] = 0;
ctrlInfo.reserve[1] = 0;
ss << string(reinterpret_cast<const char *>(&ctrlInfo), sizeof(CtrlInfo));
ss << bufferStr;
}
private:
InjectBindHelper() = default;
private:
vector<string> funcNames_;
unordered_map<string, uint16_t> injectFuncIdMap_;
vector<InjectInfo> injectInfo_;
InstrForCore type_;
};
void WriteToBin(const string &outputData, const string &filepath) {
std::string realPath = filepath;
if (!CheckWriteFilePathValid(realPath)) {
return;
}
ofstream writer(realPath, ios::binary | ios::out);
writer.write(outputData.c_str(), static_cast<std::streamsize>(outputData.size()));
writer.close();
Chmod(realPath, SAVE_DATA_FILE_AUTHORITY);
}
void GenerateCtrlBin(const string &outputPath) {
stringstream ss;
InjectBindHelper::Instance().Serialize(ss);
WriteToBin(ss.str(), outputPath);
}
}
void Bind(
InstrType instrType, const string &injectedFuncName, const vector<uint16_t> ¶Mask, const InstrForCore type) {
InjectBindHelper::Instance().Bind(instrType, injectedFuncName, paraMask, type);
}
extern "C" {
void MSBitAtInit() { return; }
void MSBitStart(const char *output, uint16_t length, const char *archName) {
InjectBindHelper::Instance().Reset();
if (archName) {
InjectBindHelper::Instance().Init(string(archName));
}
MSBitAtInit();
string outputPath(output, length);
GenerateCtrlBin(outputPath);
}
}