Files
UnrealEngine/Engine/Source/Developer/Windows/LiveCodingServer/Private/External/LC_CoffDetail.cpp
2025-05-18 13:04:45 +08:00

116 lines
3.8 KiB
C++

// Copyright 2011-2020 Molecular Matters GmbH, all rights reserved.
#if LC_VERSION == 1
// BEGIN EPIC MOD
//#include PCH_INCLUDE
// END EPIC MOD
#include "LC_CoffDetail.h"
// BEGIN EPIC MOD
#include "LC_Logging.h"
// END EPIC MOD
namespace
{
#if LC_64_BIT
static const WORD EXPECTED_MACHINE = IMAGE_FILE_MACHINE_AMD64;
#else
static const WORD EXPECTED_MACHINE = IMAGE_FILE_MACHINE_I386;
#endif
static const uint8_t BIGOBJ_MAGIC_UUID[16] = { 0xC7, 0xA1, 0xBA, 0xD1, 0xEE, 0xBA, 0xA9, 0x4B, 0xAF, 0x20, 0xFA, 0xF6, 0x6A, 0xA4, 0xDC, 0xB8 };
}
namespace coffDetail
{
CoffType::Enum GetCoffType(const void* imageBase)
{
// check object file header first
// check for DOS header
const IMAGE_DOS_HEADER* dosHeader = pointer::As<const IMAGE_DOS_HEADER*>(imageBase);
if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE)
{
LC_ERROR_DEV("Unhandled DOS image in COFF file");
return CoffType::UNKNOWN;
}
// check for import headers, which are part of .lib import libraries that belong to a .dll.
// there is no meaningful information to extract from them, so ignore them.
// see COFF Spec "8. Import Library Format"
const IMPORT_OBJECT_HEADER* importHeader = pointer::As<const IMPORT_OBJECT_HEADER*>(imageBase);
if ((importHeader->Sig1 == IMAGE_FILE_MACHINE_UNKNOWN) && (importHeader->Sig2 == IMPORT_OBJECT_HDR_SIG2))
{
// note that COFF files compiled with /bigobj have the same signature as import headers, so we also
// need to distinguish between bigobjs and import headers.
const ANON_OBJECT_HEADER_BIGOBJ* bigobjHeader = pointer::As<const ANON_OBJECT_HEADER_BIGOBJ*>(imageBase);
if ((bigobjHeader->Version >= 2u) && memcmp(&bigobjHeader->ClassID, BIGOBJ_MAGIC_UUID, sizeof(BIGOBJ_MAGIC_UUID)) == 0)
{
// avoid machine mismatches, e.g. loading .obj files from a wrong directory or similar
if (bigobjHeader->Machine != EXPECTED_MACHINE)
{
LC_ERROR_DEV("Unknown machine in COFF file");
return CoffType::UNKNOWN;
}
return CoffType::BIGOBJ;
}
else
{
// avoid machine mismatches, e.g. loading .obj files from a wrong directory or similar
if (importHeader->Machine != EXPECTED_MACHINE)
{
LC_ERROR_DEV("Unknown machine in COFF file");
return CoffType::UNKNOWN;
}
return CoffType::IMPORT_LIBRARY;
}
}
// we should be dealing with an ordinary COFF file now, but check to make sure
const IMAGE_FILE_HEADER* imageHeader = pointer::As<const IMAGE_FILE_HEADER*>(imageBase);
if (imageHeader->SizeOfOptionalHeader != 0u)
{
LC_ERROR_DEV("Unknown COFF file format");
return CoffType::UNKNOWN;
}
// avoid machine mismatches, e.g. loading .obj files from a wrong directory or similar
if (imageHeader->Machine != EXPECTED_MACHINE)
{
LC_ERROR_DEV("Unknown machine in COFF file");
return CoffType::UNKNOWN;
}
return CoffType::COFF;
}
unsigned int GetRelocationCount(const void* imageBase, const IMAGE_SECTION_HEADER* section)
{
const DWORD relocationCount = section->NumberOfRelocations;
/*
From the COFF spec:
IMAGE_SCN_LNK_NRELOC_OVFL indicates that the count of relocations for the
section exceeds the 16 bits that are reserved for it in the section header. If the bit is
set and the NumberOfRelocations field in the section header is 0xffff, the actual
relocation count is stored in the 32-bit VirtualAddress field of the first relocation. It is
an error if IMAGE_SCN_LNK_NRELOC_OVFL is set and there are fewer than 0xffff
relocations in the section.
*/
const bool hasOverflow = ((section->Characteristics & IMAGE_SCN_LNK_NRELOC_OVFL) != 0u);
if ((relocationCount == 0xFFFF) && hasOverflow)
{
const IMAGE_RELOCATION* firstRelocation = pointer::Offset<const IMAGE_RELOCATION*>(imageBase, section->PointerToRelocations);
return firstRelocation->RelocCount;
}
return relocationCount;
}
}
#endif