Store RVAs instead of pointers wherever possible in the generated NT
header and directories.
This commit is contained in:
parent
26c86969ab
commit
80083b18f8
|
@ -198,35 +198,63 @@ static void *dlopen_dll( const char *name, char *error, int errorsize,
|
|||
|
||||
|
||||
/* adjust an array of pointers to make them into RVAs */
|
||||
static inline void fixup_rva_ptrs( void *array, void *base, unsigned int count )
|
||||
static inline void fixup_rva_ptrs( void *array, BYTE *base, unsigned int count )
|
||||
{
|
||||
void **ptr = (void **)array;
|
||||
void **src = (void **)array;
|
||||
DWORD *dst = (DWORD *)array;
|
||||
while (count--)
|
||||
{
|
||||
if (*ptr) *ptr = (void *)((char *)*ptr - (char *)base);
|
||||
*dst++ = *src ? (BYTE *)*src - base : 0;
|
||||
src++;
|
||||
}
|
||||
}
|
||||
|
||||
/* fixup an array of RVAs by adding the specified delta */
|
||||
static inline void fixup_rva_dwords( DWORD *ptr, int delta, unsigned int count )
|
||||
{
|
||||
while (count--)
|
||||
{
|
||||
if (*ptr) *ptr += delta;
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* fixup RVAs in the import directory */
|
||||
static void fixup_imports( IMAGE_IMPORT_DESCRIPTOR *dir, DWORD size, void *base )
|
||||
static void fixup_imports( IMAGE_IMPORT_DESCRIPTOR *dir, BYTE *base, int delta )
|
||||
{
|
||||
int count = size / sizeof(void *);
|
||||
void **ptr = (void **)dir;
|
||||
UINT_PTR *ptr;
|
||||
|
||||
/* everything is either a pointer or an ordinal value below 0x10000 */
|
||||
while (count--)
|
||||
while (dir->Name)
|
||||
{
|
||||
if (*ptr >= (void *)0x10000) *ptr = (void *)((char *)*ptr - (char *)base);
|
||||
else if (*ptr) *ptr = (void *)(IMAGE_ORDINAL_FLAG | (UINT_PTR)*ptr);
|
||||
ptr++;
|
||||
fixup_rva_dwords( &dir->u.OriginalFirstThunk, delta, 1 );
|
||||
fixup_rva_dwords( &dir->Name, delta, 1 );
|
||||
fixup_rva_dwords( &dir->FirstThunk, delta, 1 );
|
||||
ptr = (UINT_PTR *)(base + dir->FirstThunk);
|
||||
while (*ptr)
|
||||
{
|
||||
if (!(*ptr & IMAGE_ORDINAL_FLAG)) *ptr += delta;
|
||||
ptr++;
|
||||
}
|
||||
dir++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* fixup RVAs in the export directory */
|
||||
static void fixup_exports( IMAGE_EXPORT_DIRECTORY *dir, BYTE *base, int delta )
|
||||
{
|
||||
fixup_rva_dwords( &dir->Name, delta, 1 );
|
||||
fixup_rva_dwords( &dir->AddressOfFunctions, delta, 1 );
|
||||
fixup_rva_dwords( &dir->AddressOfNames, delta, 1 );
|
||||
fixup_rva_dwords( &dir->AddressOfNameOrdinals, delta, 1 );
|
||||
fixup_rva_dwords( (DWORD *)(base + dir->AddressOfNames), delta, dir->NumberOfNames );
|
||||
fixup_rva_ptrs( (base + dir->AddressOfFunctions), base, dir->NumberOfFunctions );
|
||||
}
|
||||
|
||||
|
||||
/* fixup RVAs in the resource directory */
|
||||
static void fixup_resources( IMAGE_RESOURCE_DIRECTORY *dir, char *root, void *base )
|
||||
static void fixup_resources( IMAGE_RESOURCE_DIRECTORY *dir, BYTE *root, int delta )
|
||||
{
|
||||
IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
|
||||
int i;
|
||||
|
@ -235,11 +263,11 @@ static void fixup_resources( IMAGE_RESOURCE_DIRECTORY *dir, char *root, void *ba
|
|||
for (i = 0; i < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; i++, entry++)
|
||||
{
|
||||
void *ptr = root + entry->u2.s3.OffsetToDirectory;
|
||||
if (entry->u2.s3.DataIsDirectory) fixup_resources( ptr, root, base );
|
||||
if (entry->u2.s3.DataIsDirectory) fixup_resources( ptr, root, delta );
|
||||
else
|
||||
{
|
||||
IMAGE_RESOURCE_DATA_ENTRY *data = ptr;
|
||||
fixup_rva_ptrs( &data->OffsetToData, base, 1 );
|
||||
fixup_rva_dwords( &data->OffsetToData, delta, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -257,7 +285,7 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
|
|||
DWORD code_start, data_start, data_end;
|
||||
const size_t page_size = getpagesize();
|
||||
const size_t page_mask = page_size - 1;
|
||||
int nb_sections = 2; /* code + data */
|
||||
int i, delta, nb_sections = 2; /* code + data */
|
||||
|
||||
size_t size = (sizeof(IMAGE_DOS_HEADER)
|
||||
+ sizeof(IMAGE_NT_HEADERS)
|
||||
|
@ -288,9 +316,12 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
|
|||
|
||||
*nt = *nt_descr;
|
||||
|
||||
delta = (BYTE *)nt_descr - addr;
|
||||
code_start = page_size;
|
||||
data_start = ((BYTE *)nt_descr - addr) & ~page_mask;
|
||||
data_end = (((BYTE *)nt->OptionalHeader.SizeOfImage - addr) + page_mask) & ~page_mask;
|
||||
data_start = delta & ~page_mask;
|
||||
data_end = (nt->OptionalHeader.SizeOfImage + delta + page_mask) & ~page_mask;
|
||||
|
||||
fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 );
|
||||
|
||||
nt->FileHeader.NumberOfSections = nb_sections;
|
||||
nt->OptionalHeader.BaseOfCode = code_start;
|
||||
|
@ -303,8 +334,6 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
|
|||
nt->OptionalHeader.SizeOfImage = data_end;
|
||||
nt->OptionalHeader.ImageBase = (ULONG_PTR)addr;
|
||||
|
||||
fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 );
|
||||
|
||||
/* Build the code section */
|
||||
|
||||
memcpy( sec->Name, ".text", sizeof(".text") );
|
||||
|
@ -326,14 +355,16 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
|
|||
IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ);
|
||||
sec++;
|
||||
|
||||
for (i = 0; i < nt->OptionalHeader.NumberOfRvaAndSizes; i++)
|
||||
fixup_rva_dwords( &nt->OptionalHeader.DataDirectory[i].VirtualAddress, delta, 1 );
|
||||
|
||||
/* Build the import directory */
|
||||
|
||||
dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY];
|
||||
if (dir->Size)
|
||||
{
|
||||
IMAGE_IMPORT_DESCRIPTOR *imports = (void *)dir->VirtualAddress;
|
||||
fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 );
|
||||
fixup_imports( imports, dir->Size, addr );
|
||||
IMAGE_IMPORT_DESCRIPTOR *imports = (void *)(addr + dir->VirtualAddress);
|
||||
fixup_imports( imports, addr, delta );
|
||||
}
|
||||
|
||||
/* Build the resource directory */
|
||||
|
@ -341,9 +372,8 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
|
|||
dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY];
|
||||
if (dir->Size)
|
||||
{
|
||||
void *ptr = (void *)dir->VirtualAddress;
|
||||
fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 );
|
||||
fixup_resources( ptr, ptr, addr );
|
||||
void *ptr = (void *)(addr + dir->VirtualAddress);
|
||||
fixup_resources( ptr, ptr, delta );
|
||||
}
|
||||
|
||||
/* Build the export directory */
|
||||
|
@ -351,14 +381,8 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
|
|||
dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
|
||||
if (dir->Size)
|
||||
{
|
||||
IMAGE_EXPORT_DIRECTORY *exports = (void *)dir->VirtualAddress;
|
||||
fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 );
|
||||
fixup_rva_ptrs( (void *)exports->AddressOfFunctions, addr, exports->NumberOfFunctions );
|
||||
fixup_rva_ptrs( (void *)exports->AddressOfNames, addr, exports->NumberOfNames );
|
||||
fixup_rva_ptrs( &exports->Name, addr, 1 );
|
||||
fixup_rva_ptrs( &exports->AddressOfFunctions, addr, 1 );
|
||||
fixup_rva_ptrs( &exports->AddressOfNames, addr, 1 );
|
||||
fixup_rva_ptrs( &exports->AddressOfNameOrdinals, addr, 1 );
|
||||
IMAGE_EXPORT_DIRECTORY *exports = (void *)(addr + dir->VirtualAddress);
|
||||
fixup_exports( exports, addr, delta );
|
||||
}
|
||||
return addr;
|
||||
#else /* HAVE_MMAP */
|
||||
|
|
|
@ -761,8 +761,9 @@ static void output_immediate_imports( FILE *outfile )
|
|||
fprintf( outfile, "\t.long 0\n" ); /* OriginalFirstThunk */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* TimeDateStamp */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* ForwarderChain */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_import_name_%s\n", dll_name ); /* Name */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_import_data_ptrs+%d\n", /* FirstThunk */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_import_name_%s-.L__wine_spec_rva_base\n", /* Name */
|
||||
dll_name );
|
||||
fprintf( outfile, "\t.long .L__wine_spec_import_data_ptrs+%d-.L__wine_spec_rva_base\n", /* FirstThunk */
|
||||
j * get_ptr_size() );
|
||||
j += dll_imports[i]->nb_imports + 1;
|
||||
}
|
||||
|
@ -782,10 +783,15 @@ static void output_immediate_imports( FILE *outfile )
|
|||
{
|
||||
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||
if (!(odp->flags & FLAG_NONAME))
|
||||
fprintf( outfile, "\t%s .L__wine_spec_import_data_%s_%s\n",
|
||||
fprintf( outfile, "\t%s .L__wine_spec_import_data_%s_%s-.L__wine_spec_rva_base\n",
|
||||
get_asm_ptr_keyword(), dll_name, odp->name );
|
||||
else
|
||||
fprintf( outfile, "\t%s %d\n", get_asm_ptr_keyword(), odp->ordinal );
|
||||
{
|
||||
if (get_ptr_size() == 8)
|
||||
fprintf( outfile, "\t.quad 0x800000000000%04x\n", odp->ordinal );
|
||||
else
|
||||
fprintf( outfile, "\t.long 0x8000%04x\n", odp->ordinal );
|
||||
}
|
||||
}
|
||||
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );
|
||||
}
|
||||
|
|
|
@ -437,7 +437,7 @@ void output_resources( FILE *outfile, DLLSPEC *spec )
|
|||
/* dump the resource data entries */
|
||||
|
||||
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
|
||||
fprintf( outfile, "\t.long .L__wine_spec_res_%d,%u,0,0\n",
|
||||
fprintf( outfile, "\t.long .L__wine_spec_res_%d-.L__wine_spec_rva_base,%u,0,0\n",
|
||||
i, res->data_size );
|
||||
|
||||
/* dump the name strings */
|
||||
|
|
|
@ -117,15 +117,15 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
|
|||
fprintf( outfile, "\t.long 0\n" ); /* Characteristics */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* TimeDateStamp */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* MajorVersion/MinorVersion */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exp_names\n" ); /* Name */
|
||||
fprintf( outfile, "\t.long %d\n", spec->base ); /* Base */
|
||||
fprintf( outfile, "\t.long %d\n", nr_exports ); /* NumberOfFunctions */
|
||||
fprintf( outfile, "\t.long %d\n", spec->nb_names ); /* NumberOfNames */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exports_funcs\n" ); /* AddressOfFunctions */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exp_names-.L__wine_spec_rva_base\n" ); /* Name */
|
||||
fprintf( outfile, "\t.long %u\n", spec->base ); /* Base */
|
||||
fprintf( outfile, "\t.long %u\n", nr_exports ); /* NumberOfFunctions */
|
||||
fprintf( outfile, "\t.long %u\n", spec->nb_names ); /* NumberOfNames */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exports_funcs-.L__wine_spec_rva_base\n" ); /* AddressOfFunctions */
|
||||
if (spec->nb_names)
|
||||
{
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exp_name_ptrs\n" ); /* AddressOfNames */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exp_ordinals\n" ); /* AddressOfNameOrdinals */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exp_name_ptrs-.L__wine_spec_rva_base\n" ); /* AddressOfNames */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exp_ordinals-.L__wine_spec_rva_base\n" ); /* AddressOfNameOrdinals */
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -174,7 +174,7 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
|
|||
fprintf( outfile, "\n.L__wine_spec_exp_name_ptrs:\n" );
|
||||
for (i = 0; i < spec->nb_names; i++)
|
||||
{
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exp_names+%d\n", namepos );
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exp_names+%u-.L__wine_spec_rva_base\n", namepos );
|
||||
namepos += strlen(spec->names[i]->name) + 1;
|
||||
}
|
||||
|
||||
|
@ -483,6 +483,7 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
|||
fprintf( outfile, "\n\t.data\n" );
|
||||
fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
|
||||
fprintf( outfile, "%s\n", asm_globl("__wine_spec_nt_header") );
|
||||
fprintf( outfile, ".L__wine_spec_rva_base:\n" );
|
||||
|
||||
fprintf( outfile, "\t.long 0x%04x\n", IMAGE_NT_SIGNATURE ); /* Signature */
|
||||
switch(target_cpu)
|
||||
|
@ -513,11 +514,14 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
|||
fprintf( outfile, "\t.long 0\n" ); /* SizeOfCode */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* SizeOfInitializedData */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* SizeOfUninitializedData */
|
||||
fprintf( outfile, "\t.long %s\n", /* AddressOfEntryPoint */
|
||||
asm_name(spec->init_func) );
|
||||
fprintf( outfile, "\t.long 0\n" ); /* BaseOfCode */
|
||||
/* note: we expand the AddressOfEntryPoint field on 64-bit by overwriting the BaseOfCode field */
|
||||
fprintf( outfile, "\t%s %s\n", /* AddressOfEntryPoint */
|
||||
get_asm_ptr_keyword(), asm_name(spec->init_func) );
|
||||
if (get_ptr_size() == 4)
|
||||
fprintf( outfile, "\t.long %s\n", asm_name("__wine_spec_nt_header") ); /* BaseOfData */
|
||||
{
|
||||
fprintf( outfile, "\t.long 0\n" ); /* BaseOfCode */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* BaseOfData */
|
||||
}
|
||||
fprintf( outfile, "\t%s __wine_spec_pe_header\n", /* ImageBase */
|
||||
get_asm_ptr_keyword() );
|
||||
fprintf( outfile, "\t.long %u\n", page_size ); /* SectionAlignment */
|
||||
|
@ -528,8 +532,8 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
|||
get_asm_short_keyword() );
|
||||
fprintf( outfile, "\t%s %u,%u\n", /* Major/MinorSubsystemVersion */
|
||||
get_asm_short_keyword(), spec->subsystem_major, spec->subsystem_minor );
|
||||
fprintf( outfile, "\t.long 0\n" ); /* Win32VersionValue */
|
||||
fprintf( outfile, "\t.long %s\n", /* SizeOfImage */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* Win32VersionValue */
|
||||
fprintf( outfile, "\t.long %s-.L__wine_spec_rva_base\n", /* SizeOfImage */
|
||||
asm_name("_end") );
|
||||
fprintf( outfile, "\t.long %u\n", page_size ); /* SizeOfHeaders */
|
||||
fprintf( outfile, "\t.long 0\n" ); /* CheckSum */
|
||||
|
@ -545,17 +549,20 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
|||
fprintf( outfile, "\t.long 16\n" ); /* NumberOfRvaAndSizes */
|
||||
|
||||
if (spec->base <= spec->limit) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exports, .L__wine_spec_exports_end-.L__wine_spec_exports\n" );
|
||||
fprintf( outfile, "\t.long .L__wine_spec_exports-.L__wine_spec_rva_base,"
|
||||
".L__wine_spec_exports_end-.L__wine_spec_exports\n" );
|
||||
else
|
||||
fprintf( outfile, "\t.long 0,0\n" );
|
||||
|
||||
if (has_imports()) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_imports, .L__wine_spec_imports_end-.L__wine_spec_imports\n" );
|
||||
fprintf( outfile, "\t.long .L__wine_spec_imports-.L__wine_spec_rva_base,"
|
||||
".L__wine_spec_imports_end-.L__wine_spec_imports\n" );
|
||||
else
|
||||
fprintf( outfile, "\t.long 0,0\n" );
|
||||
|
||||
if (spec->nb_resources) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */
|
||||
fprintf( outfile, "\t.long .L__wine_spec_resources, .L__wine_spec_resources_end-.L__wine_spec_resources\n" );
|
||||
fprintf( outfile, "\t.long .L__wine_spec_resources-.L__wine_spec_rva_base,"
|
||||
".L__wine_spec_resources_end-.L__wine_spec_resources\n" );
|
||||
else
|
||||
fprintf( outfile, "\t.long 0,0\n" );
|
||||
|
||||
|
@ -577,7 +584,7 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
|||
fprintf( outfile, "%s\n", asm_globl("__wine_spec_file_name") );
|
||||
fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
|
||||
if (target_platform == PLATFORM_APPLE)
|
||||
fprintf( outfile, "\t.comm %s,4\n", asm_name("_end") );
|
||||
fprintf( outfile, "\t.lcomm %s,4\n", asm_name("_end") );
|
||||
|
||||
output_stubs( outfile, spec );
|
||||
output_exports( outfile, spec );
|
||||
|
|
Loading…
Reference in New Issue