Files
UnrealEngineUWP/Engine/Source/Programs/UnrealBuildAccelerator/Common/Private/UbaObjectFile.cpp
henrik karlsson a698ad4a9c [UBA]
* Added exclusions for exports in UbObjTool and added D3D12SDKVersion and friends to exclusion list
* Fixed so UbaObjTool works for linux (or builds at least)
* Added version to importexport files

[CL 33840177 by henrik karlsson in ue5-main branch]
2024-05-22 15:22:17 -04:00

216 lines
5.1 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "UbaObjectFile.h"
#include "UbaBinaryReaderWriter.h"
#include "UbaFileAccessor.h"
#include "UbaObjectFileCoff.h"
#include "UbaObjectFileElf.h"
namespace uba
{
u8 SymbolFileVersion = 1;
ObjectFile* ObjectFile::OpenAndParse(Logger& logger, const tchar* filename)
{
auto file = new FileAccessor(logger, filename);
auto fileGuard = MakeGuard([&]() { delete file; });
if (!file->OpenMemoryRead())
return nullptr;
ObjectFile* objectFile = Parse(logger, file->GetData(), file->GetSize(), filename);
if (!objectFile)
return nullptr;
fileGuard.Cancel();
objectFile->m_file = file;
return objectFile;
}
ObjectFile* ObjectFile::Parse(Logger& logger, u8* data, u64 dataSize, const tchar* hint)
{
if (dataSize < 4)
return nullptr;
ObjectFile* objectFile = nullptr;
constexpr u8 elfMagic[] = { 0x7f, 'E', 'L', 'F' };
if (memcmp(data, elfMagic, sizeof(elfMagic)) == 0)
objectFile = new ObjectFileElf();
else
objectFile = new ObjectFileCoff();
objectFile->m_data = data;
objectFile->m_dataSize = dataSize;
if (objectFile->Parse(logger, hint))
return objectFile;
delete objectFile;
return nullptr;
}
bool ObjectFile::CopyMemoryAndClose()
{
u8* data = (u8*)malloc(m_dataSize);
memcpy(data, m_data, m_dataSize);
m_data = data;
m_ownsData = true;
delete m_file;
m_file = nullptr;
return true;
}
bool ObjectFile::StripExports(Logger& logger)
{
u32 keptExportCount = 0;
return StripExports(logger, m_data, {}, keptExportCount);
return true;
}
bool ObjectFile::WriteImportsAndExports(Logger& logger, MemoryBlock& memoryBlock)
{
auto write = [&](const void* data, u64 dataSize) { memcpy(memoryBlock.Allocate(dataSize, 1, TC("")), data, dataSize); };
write(&SymbolFileVersion, 1);
write(&m_type, 1);
// Write all imports
for (auto& symbol : m_imports)
{
write(symbol.c_str(), symbol.size());
write("", 1);
}
write("", 1);
// Write all exports
for (auto& kv : m_exports)
{
write(kv.first.c_str(), kv.first.size());
write(kv.second.c_str(), kv.second.size());
write("", 1);
}
write("", 1);
return true;
}
bool ObjectFile::WriteImportsAndExports(Logger& logger, const tchar* exportsFilename)
{
FileAccessor exportsFile(logger, exportsFilename);
if (!exportsFile.CreateWrite())
return false;
char buffer[256*1024];
u64 bufferPos = 0;
auto flush = [&]() { exportsFile.Write(buffer, bufferPos); bufferPos = 0; };
auto write = [&](const void* data, u64 dataSize) { if (bufferPos + dataSize > sizeof(buffer)) flush(); memcpy(buffer + bufferPos, data, dataSize); bufferPos += dataSize; };
// Write all imports
for (auto& symbol : m_imports)
{
write(symbol.c_str(), symbol.size());
write("", 1);
}
write("", 1);
// Write all exports
for (auto& kv : m_exports)
{
write(kv.first.c_str(), kv.first.size());
write(kv.second.c_str(), kv.second.size());
write("", 1);
}
write("", 1);
flush();
return exportsFile.Close();
}
ObjectFile::~ObjectFile()
{
if (m_ownsData)
free(m_data);
delete m_file;
}
const tchar* ObjectFile::GetFileName() const
{
return m_file->GetFileName();
}
const UnorderedSymbols& ObjectFile::GetImports() const
{
return m_imports;
}
const UnorderedExports& ObjectFile::GetExports() const
{
return m_exports;
}
const UnorderedSymbols& ObjectFile::GetPotentialDuplicates() const
{
return m_potentialDuplicates;
}
bool ObjectFile::CreateExtraFile(Logger& logger, const tchar* extraObjFilename, ObjectFileType type, const UnorderedSymbols& allNeededImports, const UnorderedSymbols& allSharedImports, const UnorderedExports& allSharedExports, bool includeExportsInFile)
{
ObjectFileCoff objectFileCoff;
ObjectFileElf objectFileElf;
ObjectFile& objectFile = type == ObjectFileType_Coff ? (ObjectFile&)objectFileCoff : (ObjectFile&)objectFileElf;
MemoryBlock memoryBlock(16*1024*1024);
if (!objectFile.CreateExtraFile(logger, memoryBlock, allNeededImports, allSharedImports, allSharedExports, includeExportsInFile))
return false;
FileAccessor extraFile(logger, extraObjFilename);
if (!extraFile.CreateWrite())
return false;
if (!extraFile.Write(memoryBlock.memory, memoryBlock.writtenSize))
return false;
return extraFile.Close();
}
bool SymbolFile::ParseFile(Logger& logger, const tchar* filename)
{
FileAccessor symFile(logger, filename);
if (!symFile.OpenMemoryRead())
return false;
auto readPos = (const char*)symFile.GetData();
u8 version = *(u8*)readPos++;
if (SymbolFileVersion != version)
return logger.Error(TC("%s - Import/export file version mismatch"), filename);
type = *(const ObjectFileType*)readPos++;
while (*readPos)
{
auto strEnd = strlen(readPos);
imports.insert(std::string(readPos, readPos + strEnd));
readPos = readPos + strEnd + 1;
}
++readPos;
while (*readPos)
{
auto strEnd = strlen(readPos);
std::string extra;
if (const char* comma = strchr(readPos, ','))
{
strEnd = comma - readPos;
extra = comma;
}
exports.emplace(std::string(readPos, readPos + strEnd), extra);
readPos = readPos + strEnd + 1;
}
return true;
}
}