From 646ab89f0a2758ee8e3123616fdcc9a1310b1c3e Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 4 Jan 2005 12:04:06 +0000 Subject: [PATCH] Support mapping non page-aligned binaries for SEC_IMAGE mappings. --- dlls/ntdll/virtual.c | 47 +++++++++++++++++++++++++++++++++++++++----- server/mapping.c | 9 ++++++--- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index dbbef38029f..c71456485fa 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -882,6 +882,41 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, DWORD total_size goto error; } + /* check for non page-aligned binary */ + + if (nt->OptionalHeader.SectionAlignment <= page_mask) + { + /* unaligned sections, this happens for native subsystem binaries */ + /* in that case Windows simply maps in the whole file */ + + if (map_file_into_view( view, fd, 0, total_size, 0, VPROT_COMMITTED | VPROT_READ, + removable ) != STATUS_SUCCESS) goto error; + + /* check that all sections are loaded at the right offset */ + for (i = 0; i < nt->FileHeader.NumberOfSections; i++) + { + if (sec[i].VirtualAddress != sec[i].PointerToRawData) + goto error; /* Windows refuses to load in that case too */ + } + + /* set the image protections */ + VIRTUAL_SetProt( view, ptr, total_size, + VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY | VPROT_EXEC ); + + /* perform relocations if necessary */ + /* FIXME: not 100% compatible, Windows doesn't do this for non page-aligned binaries */ + if (ptr != base) + { + const IMAGE_DATA_DIRECTORY *relocs; + relocs = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; + if (relocs->VirtualAddress && relocs->Size) + do_relocations( ptr, relocs, ptr - base, total_size ); + } + + goto done; + } + + /* map all the sections */ for (i = pos = 0; i < nt->FileHeader.NumberOfSections; i++, sec++) @@ -994,11 +1029,6 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, DWORD total_size } } - if (!removable) /* don't keep handle open on removable media */ - NtDuplicateObject( GetCurrentProcess(), hmapping, - GetCurrentProcess(), &view->mapping, - 0, 0, DUPLICATE_SAME_ACCESS ); - /* set the image protections */ sec = (IMAGE_SECTION_HEADER*)((char *)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader); @@ -1011,6 +1041,13 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, DWORD total_size if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE) vprot |= VPROT_EXEC; VIRTUAL_SetProt( view, ptr + sec->VirtualAddress, size, vprot ); } + + done: + if (!removable) /* don't keep handle open on removable media */ + NtDuplicateObject( GetCurrentProcess(), hmapping, + GetCurrentProcess(), &view->mapping, + 0, 0, DUPLICATE_SAME_ACCESS ); + RtlLeaveCriticalSection( &csVirtual ); *addr_ptr = ptr; diff --git a/server/mapping.c b/server/mapping.c index 44bc33158ab..0af9c9e2c3d 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -103,8 +103,10 @@ static void init_page_size(void) #define ROUND_ADDR(addr) \ ((int)(addr) & ~page_mask) -#define ROUND_SIZE(addr,size) \ - (((int)(size) + ((int)(addr) & page_mask) + page_mask) & ~page_mask) +#define ROUND_SIZE_MASK(addr,size,mask) \ + (((int)(size) + ((int)(addr) & (mask)) + (mask)) & ~(mask)) + +#define ROUND_SIZE(addr,size) ROUND_SIZE_MASK( addr, size, page_mask ) /* find the shared PE mapping for a given mapping */ @@ -236,7 +238,8 @@ static int get_image_params( struct mapping *mapping ) mapping->size_low = ROUND_SIZE( 0, nt.OptionalHeader.SizeOfImage ); mapping->size_high = 0; mapping->base = (void *)nt.OptionalHeader.ImageBase; - mapping->header_size = ROUND_SIZE( mapping->base, nt.OptionalHeader.SizeOfHeaders ); + mapping->header_size = ROUND_SIZE_MASK( mapping->base, nt.OptionalHeader.SizeOfHeaders, + nt.OptionalHeader.SectionAlignment - 1 ); mapping->protect = VPROT_IMAGE; /* sanity check */