From 21149e63313797a1603ca496a4c876418605d495 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 18 Dec 2017 11:16:13 +0100 Subject: [PATCH] kernel32: Properly detect ELF binaries that are position independent executables. Based on a patch by Sebastian Lackner. Signed-off-by: Alexandre Julliard --- dlls/kernel32/module.c | 64 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/dlls/kernel32/module.c b/dlls/kernel32/module.c index c0d9918dc58..d068f2a996f 100644 --- a/dlls/kernel32/module.c +++ b/dlls/kernel32/module.c @@ -310,12 +310,28 @@ void MODULE_get_binary_info( HANDLE hfile, struct binary_info *info ) unsigned char magic[4]; unsigned char class; unsigned char data; - unsigned char version; - unsigned char ignored[9]; + unsigned char ignored1[10]; unsigned short type; unsigned short machine; + unsigned char ignored2[8]; + unsigned int phoff; + unsigned char ignored3[12]; + unsigned short phnum; } elf; struct + { + unsigned char magic[4]; + unsigned char class; + unsigned char data; + unsigned char ignored1[10]; + unsigned short type; + unsigned short machine; + unsigned char ignored2[12]; + unsigned __int64 phoff; + unsigned char ignored3[16]; + unsigned short phnum; + } elf64; + struct { unsigned int magic; unsigned int cputype; @@ -335,20 +351,54 @@ void MODULE_get_binary_info( HANDLE hfile, struct binary_info *info ) if (!memcmp( header.elf.magic, "\177ELF", 4 )) { - if (header.elf.class == 2) info->flags |= BINARY_FLAG_64BIT; #ifdef WORDS_BIGENDIAN - if (header.elf.data == 1) + BOOL byteswap = (header.elf.data == 1); #else - if (header.elf.data == 2) + BOOL byteswap = (header.elf.data == 2); #endif + if (header.elf.class == 2) info->flags |= BINARY_FLAG_64BIT; + if (byteswap) { header.elf.type = RtlUshortByteSwap( header.elf.type ); header.elf.machine = RtlUshortByteSwap( header.elf.machine ); } switch(header.elf.type) { - case 2: info->type = BINARY_UNIX_EXE; break; - case 3: info->type = BINARY_UNIX_LIB; break; + case 2: + info->type = BINARY_UNIX_EXE; + break; + case 3: + { + LARGE_INTEGER phoff; + unsigned short phnum; + unsigned int type; + if (header.elf.class == 2) + { + phoff.QuadPart = byteswap ? RtlUlonglongByteSwap( header.elf64.phoff ) : header.elf64.phoff; + phnum = byteswap ? RtlUshortByteSwap( header.elf64.phnum ) : header.elf64.phnum; + } + else + { + phoff.QuadPart = byteswap ? RtlUlongByteSwap( header.elf.phoff ) : header.elf.phoff; + phnum = byteswap ? RtlUshortByteSwap( header.elf.phnum ) : header.elf.phnum; + } + while (phnum--) + { + if (SetFilePointerEx( hfile, phoff, NULL, FILE_BEGIN ) == -1) return; + if (!ReadFile( hfile, &type, sizeof(type), &len, NULL ) || len < sizeof(type)) return; + if (byteswap) type = RtlUlongByteSwap( type ); + if (type == 3) + { + info->type = BINARY_UNIX_EXE; + break; + } + phoff.QuadPart += (header.elf.class == 2) ? 56 : 32; + } + if (!info->type) info->type = BINARY_UNIX_LIB; + break; + } + default: + return; } switch(header.elf.machine) {