You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
* 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]
248 lines
7.4 KiB
C++
248 lines
7.4 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "UbaObjectFileElf.h"
|
|
#include "UbaFileAccessor.h"
|
|
|
|
namespace uba
|
|
{
|
|
struct Elf64Header
|
|
{
|
|
unsigned char e_ident[16]; /* Magic number and other info */
|
|
u16 e_type; /* Object file type */
|
|
u16 e_machine; /* Architecture */
|
|
u32 e_version; /* Object file version */
|
|
u64 e_entry; /* Entry point virtual address */
|
|
u64 e_phoff; /* Program header table file offset */
|
|
u64 e_shoff; /* Section header table file offset */
|
|
u32 e_flags; /* Processor-specific flags */
|
|
u16 e_ehsize; /* ELF header size in bytes */
|
|
u16 e_phentsize; /* Program header table entry size */
|
|
u16 e_phnum; /* Program header table entry count */
|
|
u16 e_shentsize; /* Section header table entry size */
|
|
u16 e_shnum; /* Section header table entry count */
|
|
u16 e_shstrndx; /* Section header string table index */
|
|
};
|
|
|
|
struct Elf64SectionHeader
|
|
{
|
|
u32 sh_name; /* Section name (string tbl index) */
|
|
u32 sh_type; /* Section type */
|
|
u64 sh_flags; /* Section flags */
|
|
u64 sh_addr; /* Section virtual addr at execution */
|
|
u64 sh_offset; /* Section file offset */
|
|
u64 sh_size; /* Section size in bytes */
|
|
u32 sh_link; /* Link to another section */
|
|
u32 sh_info; /* Additional section information */
|
|
u64 sh_addralign; /* Section alignment */
|
|
u64 sh_entsize; /* Entry size if section holds table */
|
|
};
|
|
|
|
struct Elf64Sym
|
|
{
|
|
u32 st_name; /* Symbol name (string tbl index) */
|
|
u8 st_info; /* Symbol type and binding */
|
|
u8 st_other; /* Symbol visibility */
|
|
u16 st_shndx; /* Section index */
|
|
u64 st_value; /* Symbol value */
|
|
u64 st_size; /* Symbol size */
|
|
};
|
|
|
|
#define EM_X86_64 62 /* AMD x86-64 architecture */
|
|
|
|
#define SHT_SYMTAB 2 /* Symbol table */
|
|
#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
|
|
|
|
#define STT_OBJECT 1 /* Symbol is a data object */
|
|
#define STT_FUNC 2 /* Symbol is a code object */
|
|
|
|
#define STB_WEAK 2 /* Weak symbol */
|
|
|
|
|
|
#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4)
|
|
#define ELF32_ST_TYPE(val) ((val) & 0xf)
|
|
#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
|
|
|
|
/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */
|
|
#define ELF64_ST_BIND(val) ELF32_ST_BIND (val)
|
|
#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val)
|
|
#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type))
|
|
|
|
// These are symbols that are added to all dlls through some macros.
|
|
// When merging dlls we need to remove duplicates of these
|
|
UnorderedSymbols ObjectFileElf::PotentiallyDuplicatedSymbols =
|
|
{
|
|
#if 0 // This is not needed anymore
|
|
// REPLACEMENT_OPERATOR_NEW_AND_DELETE
|
|
"_Znwm",
|
|
"_Znam",
|
|
"_ZnwmRKSt9nothrow_t",
|
|
"_ZnamRKSt9nothrow_t",
|
|
"_ZnwmSt11align_val_t",
|
|
"_ZnamSt11align_val_t",
|
|
"_ZnwmSt11align_val_tRKSt9nothrow_t",
|
|
"_ZnamSt11align_val_tRKSt9nothrow_t",
|
|
"_ZdlPv",
|
|
"_ZdaPv",
|
|
"_ZdlPvRKSt9nothrow_t",
|
|
"_ZdaPvRKSt9nothrow_t",
|
|
"_ZdlPvm",
|
|
"_ZdaPvm",
|
|
"_ZdlPvmRKSt9nothrow_t",
|
|
"_ZdaPvmRKSt9nothrow_t",
|
|
"_ZdlPvSt11align_val_t",
|
|
"_ZdaPvSt11align_val_t",
|
|
"_ZdlPvSt11align_val_tRKSt9nothrow_t",
|
|
"_ZdaPvSt11align_val_tRKSt9nothrow_t",
|
|
"_ZdlPvmSt11align_val_t",
|
|
"_ZdaPvmSt11align_val_t",
|
|
"_ZdlPvmSt11align_val_tRKSt9nothrow_t",
|
|
"_ZdaPvmSt11align_val_tRKSt9nothrow_t",
|
|
|
|
// UE_DEFINE_FMEMORY_WRAPPERS
|
|
"_Z14FMemory_Mallocmm",
|
|
"_Z15FMemory_ReallocPvmm",
|
|
"_Z12FMemory_FreePv",
|
|
|
|
// UE4_VISUALIZERS_HELPERS
|
|
"GNameBlocksDebug",
|
|
"GObjectIndexToPackedObjectRefDebug",
|
|
"GObjectArrayForDebugVisualizers",
|
|
"GComplexObjectPathDebug",
|
|
"GObjectHandlePackageDebug",
|
|
#endif
|
|
};
|
|
|
|
ObjectFileElf::ObjectFileElf()
|
|
{
|
|
m_type = ObjectFileType_Elf;
|
|
}
|
|
|
|
|
|
bool ObjectFileElf::Parse(Logger& logger, const tchar* filename)
|
|
{
|
|
auto& header = *(Elf64Header*)m_data;
|
|
if (header.e_ident[4] != 2) // 64-bit
|
|
return false;
|
|
if (header.e_ident[5] != 1) // Little endian
|
|
return false;
|
|
if (header.e_ident[6] != 1) // Version
|
|
return false;
|
|
if (header.e_type != 1) // Relocatable file
|
|
return false;
|
|
|
|
UBA_ASSERT(sizeof(Elf64SectionHeader) == header.e_shentsize);
|
|
|
|
auto sections = (Elf64SectionHeader*)(m_data + header.e_shoff);
|
|
|
|
auto& namesSection = sections[header.e_shstrndx];
|
|
u8* stringTableData = m_data + namesSection.sh_offset;
|
|
|
|
#if 0
|
|
u64 stringTableSize = namesSection.sh_size;
|
|
u32 counter = 0;
|
|
char* it = (char*)stringTableData;
|
|
char* end = it + stringTableSize;
|
|
while (it != end)
|
|
{
|
|
printf("%s\n", it);
|
|
u64 len = strlen(it);
|
|
it += len + 1;
|
|
counter++;
|
|
}
|
|
#endif
|
|
|
|
for (u16 i=0; i!=header.e_shnum; ++i)
|
|
{
|
|
auto& section = sections[i];
|
|
//auto sectionName = (char*)stringTableData + section.sh_name;
|
|
|
|
if (section.sh_type == SHT_SYMTAB || section.sh_type == SHT_DYNSYM)
|
|
{
|
|
UBA_ASSERT(section.sh_link == header.e_shstrndx);
|
|
UBA_ASSERT(section.sh_entsize == sizeof(Elf64Sym));
|
|
auto symbols = (Elf64Sym*)(m_data + section.sh_offset);
|
|
u64 symbolCount = section.sh_size / sizeof(Elf64Sym);
|
|
for (u64 j=0; j!=symbolCount; ++j)
|
|
{
|
|
auto& symbol = symbols[j];
|
|
u8 symbolType = ELF64_ST_TYPE(symbol.st_info);
|
|
if (symbolType != STT_FUNC && symbolType != STT_OBJECT)
|
|
continue;
|
|
|
|
auto name = (char*)stringTableData + symbol.st_name;
|
|
if (PotentiallyDuplicatedSymbols.find(name) == PotentiallyDuplicatedSymbols.end())
|
|
continue;
|
|
|
|
m_potentialDuplicates.emplace(name);
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
/*
|
|
bool ObjectFileElf::CreateStripped(Logger& logger, const tchar* newFilename, const UnorderedSymbols& allNeededImports, u32& outKeptExportCount)
|
|
{
|
|
FileAccessor newFile(logger, newFilename);
|
|
if (!newFile.CreateMemoryWrite(false, DefaultAttributes(), m_dataSize))
|
|
return false;
|
|
|
|
u8* newData = newFile.GetData();
|
|
memcpy(newData, m_data, m_dataSize);
|
|
|
|
auto& header = *(Elf64Header*)newData;
|
|
auto sections = (Elf64SectionHeader*)(newData + header.e_shoff);
|
|
|
|
auto& namesSection = sections[header.e_shstrndx];
|
|
u8* stringTableData = newData + namesSection.sh_offset;
|
|
|
|
for (u16 i=0; i!=header.e_shnum; ++i)
|
|
{
|
|
auto& section = sections[i];
|
|
|
|
if (section.sh_type == SHT_SYMTAB || section.sh_type == SHT_DYNSYM)
|
|
{
|
|
UBA_ASSERT(section.sh_link == header.e_shstrndx);
|
|
UBA_ASSERT(section.sh_entsize == sizeof(Elf64Sym));
|
|
auto symbols = (Elf64Sym*)(newData + section.sh_offset);
|
|
u64 symbolCount = section.sh_size / sizeof(Elf64Sym);
|
|
for (u64 j=0; j!=symbolCount; ++j)
|
|
{
|
|
auto& symbol = symbols[j];
|
|
u8 symbolType = ELF64_ST_TYPE(symbol.st_info);
|
|
if (symbolType != STT_FUNC && symbolType != STT_OBJECT)
|
|
continue;
|
|
auto name = (char*)stringTableData + symbol.st_name;
|
|
|
|
if (m_toRemove.find(name) == m_toRemove.end())
|
|
continue;
|
|
symbol.st_info = ELF64_ST_INFO(STB_WEAK, symbolType);
|
|
}
|
|
}
|
|
}
|
|
|
|
return newFile.Close();
|
|
}
|
|
*/
|
|
bool ObjectFileElf::StripExports(Logger& logger, u8* newData, const UnorderedSymbols& allNeededImports, u32& outKeptExportCount)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool ObjectFileElf::CreateExtraFile(Logger& logger, MemoryBlock& memoryBlock, const UnorderedSymbols& allNeededImports, const UnorderedSymbols& allSharedImports, const UnorderedExports& allSharedExports, bool includeExportsInFile)
|
|
{
|
|
auto& header = *(Elf64Header*)memoryBlock.Allocate(sizeof(Elf64Header), 1, TC(""));
|
|
|
|
header.e_ident[0] = 0x7f;
|
|
header.e_ident[1] = 'E';
|
|
header.e_ident[2] = 'L';
|
|
header.e_ident[3] = 'F';
|
|
header.e_ident[4] = 2;
|
|
header.e_ident[5] = 1;
|
|
header.e_ident[6] = 1;
|
|
header.e_type = 1;
|
|
header.e_machine = EM_X86_64;
|
|
header.e_ehsize = sizeof(Elf64Header);
|
|
return true;
|
|
}
|
|
}
|