engine: library: fix saves on 64-bit Windows, compile custom loader only on x86
This commit is contained in:
parent
21174dc9cf
commit
a0af256641
2 changed files with 43 additions and 160 deletions
|
@ -31,7 +31,7 @@ typedef struct dll_user_s
|
||||||
dword *funcs;
|
dword *funcs;
|
||||||
char *names[MAX_LIBRARY_EXPORTS]; // max 4096 exports supported
|
char *names[MAX_LIBRARY_EXPORTS]; // max 4096 exports supported
|
||||||
int num_ordinals; // actual exports count
|
int num_ordinals; // actual exports count
|
||||||
dword funcBase; // base offset
|
uintptr_t funcBase; // base offset
|
||||||
} dll_user_t;
|
} dll_user_t;
|
||||||
|
|
||||||
dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath );
|
dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath );
|
||||||
|
|
|
@ -16,7 +16,11 @@ GNU General Public License for more details.
|
||||||
#if XASH_LIB == LIB_WIN32
|
#if XASH_LIB == LIB_WIN32
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "library.h"
|
#include "library.h"
|
||||||
|
#include <winnt.h>
|
||||||
|
|
||||||
|
#define CALCULATE_ADDRESS( base, offset ) ( ( DWORD )( base ) + ( DWORD )( offset ) )
|
||||||
|
|
||||||
|
#if XASH_X86
|
||||||
/*
|
/*
|
||||||
---------------------------------------------------------------
|
---------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -25,106 +29,11 @@ GNU General Public License for more details.
|
||||||
---------------------------------------------------------------
|
---------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DOS_SIGNATURE 0x5A4D // MZ
|
|
||||||
#define NT_SIGNATURE 0x00004550 // PE00
|
|
||||||
#define NUMBER_OF_DIRECTORY_ENTRIES 16
|
#define NUMBER_OF_DIRECTORY_ENTRIES 16
|
||||||
#ifndef IMAGE_SIZEOF_BASE_RELOCATION
|
#ifndef IMAGE_SIZEOF_BASE_RELOCATION
|
||||||
#define IMAGE_SIZEOF_BASE_RELOCATION ( sizeof( IMAGE_BASE_RELOCATION ))
|
#define IMAGE_SIZEOF_BASE_RELOCATION ( sizeof( IMAGE_BASE_RELOCATION ))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
// dos .exe header
|
|
||||||
word e_magic; // magic number
|
|
||||||
word e_cblp; // bytes on last page of file
|
|
||||||
word e_cp; // pages in file
|
|
||||||
word e_crlc; // relocations
|
|
||||||
word e_cparhdr; // size of header in paragraphs
|
|
||||||
word e_minalloc; // minimum extra paragraphs needed
|
|
||||||
word e_maxalloc; // maximum extra paragraphs needed
|
|
||||||
word e_ss; // initial (relative) SS value
|
|
||||||
word e_sp; // initial SP value
|
|
||||||
word e_csum; // checksum
|
|
||||||
word e_ip; // initial IP value
|
|
||||||
word e_cs; // initial (relative) CS value
|
|
||||||
word e_lfarlc; // file address of relocation table
|
|
||||||
word e_ovno; // overlay number
|
|
||||||
word e_res[4]; // reserved words
|
|
||||||
word e_oemid; // OEM identifier (for e_oeminfo)
|
|
||||||
word e_oeminfo; // OEM information; e_oemid specific
|
|
||||||
word e_res2[10]; // reserved words
|
|
||||||
long e_lfanew; // file address of new exe header
|
|
||||||
} DOS_HEADER;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
// win .exe header
|
|
||||||
word Machine;
|
|
||||||
word NumberOfSections;
|
|
||||||
dword TimeDateStamp;
|
|
||||||
dword PointerToSymbolTable;
|
|
||||||
dword NumberOfSymbols;
|
|
||||||
word SizeOfOptionalHeader;
|
|
||||||
word Characteristics;
|
|
||||||
} PE_HEADER;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
dword VirtualAddress;
|
|
||||||
dword Size;
|
|
||||||
} DATA_DIRECTORY;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
word Magic;
|
|
||||||
byte MajorLinkerVersion;
|
|
||||||
byte MinorLinkerVersion;
|
|
||||||
dword SizeOfCode;
|
|
||||||
dword SizeOfInitializedData;
|
|
||||||
dword SizeOfUninitializedData;
|
|
||||||
dword AddressOfEntryPoint;
|
|
||||||
dword BaseOfCode;
|
|
||||||
dword BaseOfData;
|
|
||||||
dword ImageBase;
|
|
||||||
dword SectionAlignment;
|
|
||||||
dword FileAlignment;
|
|
||||||
word MajorOperatingSystemVersion;
|
|
||||||
word MinorOperatingSystemVersion;
|
|
||||||
word MajorImageVersion;
|
|
||||||
word MinorImageVersion;
|
|
||||||
word MajorSubsystemVersion;
|
|
||||||
word MinorSubsystemVersion;
|
|
||||||
dword Win32VersionValue;
|
|
||||||
dword SizeOfImage;
|
|
||||||
dword SizeOfHeaders;
|
|
||||||
dword CheckSum;
|
|
||||||
word Subsystem;
|
|
||||||
word DllCharacteristics;
|
|
||||||
dword SizeOfStackReserve;
|
|
||||||
dword SizeOfStackCommit;
|
|
||||||
dword SizeOfHeapReserve;
|
|
||||||
dword SizeOfHeapCommit;
|
|
||||||
dword LoaderFlags;
|
|
||||||
dword NumberOfRvaAndSizes;
|
|
||||||
|
|
||||||
DATA_DIRECTORY DataDirectory[NUMBER_OF_DIRECTORY_ENTRIES];
|
|
||||||
} OPTIONAL_HEADER;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
dword Characteristics;
|
|
||||||
dword TimeDateStamp;
|
|
||||||
word MajorVersion;
|
|
||||||
word MinorVersion;
|
|
||||||
dword Name;
|
|
||||||
dword Base;
|
|
||||||
dword NumberOfFunctions;
|
|
||||||
dword NumberOfNames;
|
|
||||||
dword AddressOfFunctions; // RVA from base of image
|
|
||||||
dword AddressOfNames; // RVA from base of image
|
|
||||||
dword AddressOfNameOrdinals; // RVA from base of image
|
|
||||||
} EXPORT_DIRECTORY;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
PIMAGE_NT_HEADERS headers;
|
PIMAGE_NT_HEADERS headers;
|
||||||
|
@ -134,26 +43,6 @@ typedef struct
|
||||||
int initialized;
|
int initialized;
|
||||||
} MEMORYMODULE, *PMEMORYMODULE;
|
} MEMORYMODULE, *PMEMORYMODULE;
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
byte Name[8]; // dos name length
|
|
||||||
|
|
||||||
union
|
|
||||||
{
|
|
||||||
dword PhysicalAddress;
|
|
||||||
dword VirtualSize;
|
|
||||||
} Misc;
|
|
||||||
|
|
||||||
dword VirtualAddress;
|
|
||||||
dword SizeOfRawData;
|
|
||||||
dword PointerToRawData;
|
|
||||||
dword PointerToRelocations;
|
|
||||||
dword PointerToLinenumbers;
|
|
||||||
word NumberOfRelocations;
|
|
||||||
word NumberOfLinenumbers;
|
|
||||||
dword Characteristics;
|
|
||||||
} SECTION_HEADER;
|
|
||||||
|
|
||||||
// Protection flags for memory pages (Executable, Readable, Writeable)
|
// Protection flags for memory pages (Executable, Readable, Writeable)
|
||||||
static int ProtectionFlags[2][2][2] =
|
static int ProtectionFlags[2][2][2] =
|
||||||
{
|
{
|
||||||
|
@ -170,7 +59,6 @@ static int ProtectionFlags[2][2][2] =
|
||||||
typedef BOOL (WINAPI *DllEntryProc)( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved );
|
typedef BOOL (WINAPI *DllEntryProc)( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved );
|
||||||
|
|
||||||
#define GET_HEADER_DICTIONARY( module, idx ) &(module)->headers->OptionalHeader.DataDirectory[idx]
|
#define GET_HEADER_DICTIONARY( module, idx ) &(module)->headers->OptionalHeader.DataDirectory[idx]
|
||||||
#define CALCULATE_ADDRESS( base, offset ) ((DWORD)(base) + (DWORD)(offset))
|
|
||||||
|
|
||||||
static void CopySections( const byte *data, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module )
|
static void CopySections( const byte *data, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module )
|
||||||
{
|
{
|
||||||
|
@ -598,6 +486,7 @@ library_error:
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static DWORD GetOffsetByRVA( DWORD rva, PIMAGE_NT_HEADERS nt_header )
|
static DWORD GetOffsetByRVA( DWORD rva, PIMAGE_NT_HEADERS nt_header )
|
||||||
{
|
{
|
||||||
|
@ -653,41 +542,18 @@ static void FreeNameFuncGlobals( dll_user_t *hInst )
|
||||||
hInst->funcs = NULL;
|
hInst->funcs = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *GetMSVCName( const char *in_name )
|
|
||||||
{
|
|
||||||
static string out_name;
|
|
||||||
char *pos;
|
|
||||||
|
|
||||||
if( in_name[0] == '?' ) // is this a MSVC C++ mangled name?
|
|
||||||
{
|
|
||||||
if(( pos = Q_strstr( in_name, "@@" )) != NULL )
|
|
||||||
{
|
|
||||||
int len = pos - in_name;
|
|
||||||
|
|
||||||
// strip off the leading '?'
|
|
||||||
Q_strncpy( out_name, in_name + 1, sizeof( out_name ));
|
|
||||||
out_name[len-1] = 0; // terminate string at the "@@"
|
|
||||||
return out_name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_strncpy( out_name, in_name, sizeof( out_name ));
|
|
||||||
|
|
||||||
return out_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
qboolean LibraryLoadSymbols( dll_user_t *hInst )
|
qboolean LibraryLoadSymbols( dll_user_t *hInst )
|
||||||
{
|
{
|
||||||
file_t *f;
|
file_t *f;
|
||||||
string errorstring;
|
string errorstring;
|
||||||
DOS_HEADER dos_header;
|
IMAGE_DOS_HEADER dos_header;
|
||||||
LONG nt_signature;
|
LONG nt_signature;
|
||||||
PE_HEADER pe_header;
|
IMAGE_FILE_HEADER pe_header;
|
||||||
SECTION_HEADER section_header;
|
IMAGE_SECTION_HEADER section_header;
|
||||||
qboolean rdata_found;
|
qboolean rdata_found;
|
||||||
OPTIONAL_HEADER optional_header;
|
IMAGE_OPTIONAL_HEADER optional_header;
|
||||||
long rdata_delta = 0;
|
long rdata_delta = 0;
|
||||||
EXPORT_DIRECTORY export_directory;
|
IMAGE_EXPORT_DIRECTORY export_directory;
|
||||||
long name_offset;
|
long name_offset;
|
||||||
long exports_offset;
|
long exports_offset;
|
||||||
long ordinal_offset;
|
long ordinal_offset;
|
||||||
|
@ -715,7 +581,7 @@ qboolean LibraryLoadSymbols( dll_user_t *hInst )
|
||||||
goto table_error;
|
goto table_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( dos_header.e_magic != DOS_SIGNATURE )
|
if( dos_header.e_magic != IMAGE_DOS_SIGNATURE )
|
||||||
{
|
{
|
||||||
Q_sprintf( errorstring, "%s does not have a valid dll signature", hInst->shortPath );
|
Q_sprintf( errorstring, "%s does not have a valid dll signature", hInst->shortPath );
|
||||||
goto table_error;
|
goto table_error;
|
||||||
|
@ -733,7 +599,7 @@ qboolean LibraryLoadSymbols( dll_user_t *hInst )
|
||||||
goto table_error;
|
goto table_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( nt_signature != NT_SIGNATURE )
|
if( nt_signature != IMAGE_NT_SIGNATURE )
|
||||||
{
|
{
|
||||||
Q_sprintf( errorstring, "%s does not have a valid NT signature", hInst->shortPath );
|
Q_sprintf( errorstring, "%s does not have a valid NT signature", hInst->shortPath );
|
||||||
goto table_error;
|
goto table_error;
|
||||||
|
@ -860,7 +726,7 @@ qboolean LibraryLoadSymbols( dll_user_t *hInst )
|
||||||
if( FS_Seek( f, name_offset, SEEK_SET ) != -1 )
|
if( FS_Seek( f, name_offset, SEEK_SET ) != -1 )
|
||||||
{
|
{
|
||||||
FsGetString( f, function_name );
|
FsGetString( f, function_name );
|
||||||
hInst->names[i] = copystring( GetMSVCName( function_name ));
|
hInst->names[i] = copystring( COM_GetMSVCName( function_name ));
|
||||||
}
|
}
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
|
@ -880,8 +746,8 @@ qboolean LibraryLoadSymbols( dll_user_t *hInst )
|
||||||
void *fn_offset;
|
void *fn_offset;
|
||||||
|
|
||||||
index = hInst->ordinals[i];
|
index = hInst->ordinals[i];
|
||||||
fn_offset = (void *)COM_GetProcAddress( hInst, "GiveFnptrsToDll" );
|
fn_offset = COM_GetProcAddress( hInst, "GiveFnptrsToDll" );
|
||||||
hInst->funcBase = (dword)(fn_offset) - hInst->funcs[index];
|
hInst->funcBase = (uintptr_t)(fn_offset) - hInst->funcs[index];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -938,7 +804,7 @@ qboolean COM_CheckLibraryDirectDependency( const char *name, const char *depname
|
||||||
importDir = &peHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
importDir = &peHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||||
if( importDir->Size <= 0 )
|
if( importDir->Size <= 0 )
|
||||||
{
|
{
|
||||||
Q_snprintf( errorstring, sizeof( errorstring ), "%s has no dependencies. Is this library valid?\n", name );
|
Con_Printf( S_WARN "%s: %s has no dependencies. Is this library valid?\n", __FUNCTION__, name );
|
||||||
goto libraryerror;
|
goto libraryerror;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -956,7 +822,10 @@ qboolean COM_CheckLibraryDirectDependency( const char *name, const char *depname
|
||||||
}
|
}
|
||||||
|
|
||||||
libraryerror:
|
libraryerror:
|
||||||
if( errorstring[0] ) Con_Printf( errorstring );
|
if( errorstring[0] )
|
||||||
|
{
|
||||||
|
Con_Printf( S_ERROR "%s: %s\n", __FUNCTION__, errorstring );
|
||||||
|
}
|
||||||
if( data ) Mem_Free( data ); // release memory
|
if( data ) Mem_Free( data ); // release memory
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -975,17 +844,22 @@ void *COM_LoadLibrary( const char *dllname, int build_ordinals_table, qboolean d
|
||||||
hInst = FS_FindLibrary( dllname, directpath );
|
hInst = FS_FindLibrary( dllname, directpath );
|
||||||
if( !hInst ) return NULL; // nothing to load
|
if( !hInst ) return NULL; // nothing to load
|
||||||
|
|
||||||
|
if( hInst->encrypted )
|
||||||
|
{
|
||||||
|
Con_Printf( S_ERROR "LoadLibrary: couldn't load encrypted library %s\n", dllname );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if XASH_X86
|
||||||
if( hInst->custom_loader )
|
if( hInst->custom_loader )
|
||||||
{
|
{
|
||||||
if( hInst->encrypted )
|
|
||||||
{
|
|
||||||
Con_Printf( S_ERROR "LoadLibrary: couldn't load encrypted library %s\n", dllname );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hInst->hInstance = MemoryLoadLibrary( hInst->fullPath );
|
hInst->hInstance = MemoryLoadLibrary( hInst->fullPath );
|
||||||
}
|
}
|
||||||
else hInst->hInstance = LoadLibrary( hInst->fullPath );
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
hInst->hInstance = LoadLibrary( hInst->fullPath );
|
||||||
|
}
|
||||||
|
|
||||||
if( !hInst->hInstance )
|
if( !hInst->hInstance )
|
||||||
{
|
{
|
||||||
|
@ -1017,8 +891,10 @@ void *COM_GetProcAddress( void *hInstance, const char *name )
|
||||||
if( !hInst || !hInst->hInstance )
|
if( !hInst || !hInst->hInstance )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
#if XASH_X86
|
||||||
if( hInst->custom_loader )
|
if( hInst->custom_loader )
|
||||||
return (void *)MemoryGetProcAddress( hInst->hInstance, name );
|
return (void *)MemoryGetProcAddress( hInst->hInstance, name );
|
||||||
|
#endif
|
||||||
return (void *)GetProcAddress( hInst->hInstance, name );
|
return (void *)GetProcAddress( hInst->hInstance, name );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1037,9 +913,16 @@ void COM_FreeLibrary( void *hInstance )
|
||||||
}
|
}
|
||||||
else Con_Reportf( "Sys_FreeLibrary: Unloading %s\n", hInst->dllName );
|
else Con_Reportf( "Sys_FreeLibrary: Unloading %s\n", hInst->dllName );
|
||||||
|
|
||||||
|
#if XASH_X86
|
||||||
if( hInst->custom_loader )
|
if( hInst->custom_loader )
|
||||||
|
{
|
||||||
MemoryFreeLibrary( hInst->hInstance );
|
MemoryFreeLibrary( hInst->hInstance );
|
||||||
else FreeLibrary( hInst->hInstance );
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
FreeLibrary( hInst->hInstance );
|
||||||
|
}
|
||||||
|
|
||||||
hInst->hInstance = NULL;
|
hInst->hInstance = NULL;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue