Support mapping non page-aligned binaries for SEC_IMAGE mappings.
This commit is contained in:
parent
2835633789
commit
646ab89f0a
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue