Commit 80083b18 authored by Alexandre Julliard's avatar Alexandre Julliard

Store RVAs instead of pointers wherever possible in the generated NT

header and directories.
parent 26c86969
......@@ -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 );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment