⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 binfmt_pe.c

📁 该项目主要是将wingdows程序直接运行在linux上
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * binfmt_pe.c * * Copyright (C) 2006  Insigme Co., Ltd * * Authors:  * - Chenzhan Hu * * This software has been developed while working on the Linux Unified Kernel * project (http://linux.insigma.com.cn) in the Insigma Reaserch Institute,   * which is a subdivision of Insigma Co., Ltd (http://www.insigma.com.cn). *  * The project is sponsored by Insigma Co., Ltd. * * The authors can be reached at linux@insigma.com.cn. * * This program is free software; you can redistribute it and/or modify it * under the terms of  the GNU General  Public License as published by the * Free Software Foundation; either version 2 of the  License, or (at your * option) any later version. * * Revision History: *   Jan 2006 - Created. */ /* * binfmt_pe.c: * Reference to Linux Kernel code */#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/stat.h>#include <linux/time.h>#include <linux/mm.h>#include <linux/mman.h>#include <linux/a.out.h>#include <linux/errno.h>#include <linux/signal.h>#include <linux/binfmts.h>#include <linux/string.h>#include <linux/file.h>#include <linux/fcntl.h>#include <linux/ptrace.h>#include <linux/slab.h>#include <linux/shm.h>#include <linux/personality.h>#include <linux/elfcore.h>#include <linux/init.h>#include <linux/highuid.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/compiler.h>#include <linux/highmem.h>#include <linux/pagemap.h>#include <linux/security.h>#include <linux/syscalls.h>#include <linux/random.h>#include <asm/uaccess.h>#include <asm/param.h>#include <asm/page.h>#include <linux/elf.h>#include <linux/win32_process.h>#include <linux/win32_thread.h>#include "win32.h"#include "pefile.h"#include "section.h"#include "process.h"#include "thread.h"#include "apc.h"#ifdef CONFIG_UNIFIED_KERNELunsigned long	extra_page = 0;extern asmlinkage void w32syscall_exit(void);#define	NTDLL_SO#define ELF_PLATFORM	(system_utsname.machine)#define ELF_HWCAP	(boot_cpu_data.x86_capability[0])#define ELF_EXEC_PAGESIZE	4096#ifdef NTDLL_SO#ifndef elf_addr_t#define elf_addr_t unsigned long#endif#if ELF_EXEC_PAGESIZE > PAGE_SIZE# define ELF_MIN_ALIGN	ELF_EXEC_PAGESIZE#else# define ELF_MIN_ALIGN	PAGE_SIZE#endif#ifndef ELF_CORE_EFLAGS#define ELF_CORE_EFLAGS	0#endif#define ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ELF_MIN_ALIGN-1))#define ELF_PAGEOFFSET(_v) ((_v) & (ELF_MIN_ALIGN-1))#define ELF_PAGEALIGN(_v) (((_v) + ELF_MIN_ALIGN - 1) & ~(ELF_MIN_ALIGN - 1))#ifdef CONFIG_STACK_GROWSUP#define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) + (items))#define STACK_ROUND(sp, items) \	((15 + (unsigned long) ((sp) + (items))) &~ 15UL)#define STACK_ALLOC(sp, len) ({ elf_addr_t __user *old_sp = (elf_addr_t __user *)sp; sp += len; old_sp; })#else#define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) - (items))#define STACK_ROUND(sp, items) \	(((unsigned long) (sp - items)) &~ 15UL)#define STACK_ALLOC(sp, len) ({ sp -= len ; sp; })#endif#if ELF_CLASS == ELFCLASS32#define	elf_off_t		Elf32_Off#define	elf_half_t		Elf32_Half#else#define	elf_off_t		Elf64_Off#define	elf_half_t		Elf64_Half#endif#endifextern unsigned long get_ntdll_entry(void);extern unsigned long get_apc_dispatcher(void);extern unsigned long get_pe_entry(void);extern unsigned long get_interp_entry(void);extern unsigned long get_start_thunk(void);extern NTSTATUS STDCALL LdrpMapSystemDll(struct task_struct *tsk, char *name,		unsigned long *ntdll_load_addr, unsigned long *interp_load_addr);voidSTDCALLPspThreadSpecialApc(PKAPC Apc,		PKNORMAL_ROUTINE* NormalRoutine,		PVOID* NormalContext,		PVOID* SystemArgument1,		PVOID* SystemArgument2);static int load_pe_binary(struct linux_binprm * bprm, struct pt_regs * regs);static struct linux_binfmt pe_format = {		.module		= THIS_MODULE,		.load_binary	= load_pe_binary,		.load_shlib	= NULL,		.core_dump	= NULL,		.min_coredump	= ELF_EXEC_PAGESIZE};#define BAD_ADDR(x)	((unsigned long)(x) > TASK_SIZE)#ifdef NTDLL_SOextern elf_off_t ntdll_phoff;extern elf_half_t ntdll_phnum;/*  * create_elf_tables */static intcreate_elf_tables(struct linux_binprm *bprm, unsigned long load_addr,		elf_off_t phoff, elf_half_t phnum, unsigned long entry){	unsigned long p = bprm->p;	int argc = bprm->argc;	int envc = bprm->envc;	elf_addr_t __user *argv;	elf_addr_t __user *envp;	elf_addr_t __user *sp;	elf_addr_t __user *u_platform;	const char *k_platform = ELF_PLATFORM;	int items;	elf_addr_t *elf_info;	int ei_index = 0;	struct task_struct *tsk = current;	/*	 * If this architecture has a platform capability string, copy it	 * to userspace.  In some cases (Sparc), this info is impossible	 * for userspace to get any other way, in others (i386) it is	 * merely difficult.	 */	u_platform = NULL;	if (k_platform) {		size_t len = strlen(k_platform) + 1;		/*		 * In some cases (e.g. Hyper-Threading), we want to avoid L1		 * evictions by the processes running on the same package. One		 * thing we can do is to shuffle the initial stack for them.		 */	 		p = arch_align_stack(p);		u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);		if (__copy_to_user(u_platform, k_platform, len))			return -EFAULT;	}	/* Create the ELF interpreter info */	elf_info = (elf_addr_t *) current->mm->saved_auxv;#define NEW_AUX_ENT(id, val) \	do { elf_info[ei_index++] = id; elf_info[ei_index++] = val; } while (0)#ifdef ARCH_DLINFO11	/* 	 * ARCH_DLINFO must come first so PPC can do its special alignment of	 * AUXV.	 */	ARCH_DLINFO;#endif	NEW_AUX_ENT(AT_HWCAP, ELF_HWCAP);	NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE);	NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC);	NEW_AUX_ENT(AT_PHDR, load_addr + phoff);	NEW_AUX_ENT(AT_PHENT, sizeof(struct elf_phdr));	NEW_AUX_ENT(AT_PHNUM, phnum);	NEW_AUX_ENT(AT_BASE, 0);	NEW_AUX_ENT(AT_FLAGS, 0);	NEW_AUX_ENT(AT_ENTRY, entry);	NEW_AUX_ENT(AT_UID, (elf_addr_t) tsk->uid);	NEW_AUX_ENT(AT_EUID, (elf_addr_t) tsk->euid);	NEW_AUX_ENT(AT_GID, (elf_addr_t) tsk->gid);	NEW_AUX_ENT(AT_EGID, (elf_addr_t) tsk->egid); 	NEW_AUX_ENT(AT_SECURE, (elf_addr_t) security_bprm_secureexec(bprm));	if (k_platform) {//		NEW_AUX_ENT(AT_PLATFORM, (elf_addr_t)(unsigned long)u_platform);	}	if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) {		NEW_AUX_ENT(AT_EXECFD, (elf_addr_t) bprm->interp_data);	}#undef NEW_AUX_ENT	/* AT_NULL is zero; clear the rest too */	memset(&elf_info[ei_index], 0,	       sizeof current->mm->saved_auxv - ei_index * sizeof elf_info[0]);	/* And advance past the AT_NULL entry.  */	ei_index += 2;	sp = STACK_ADD(p, ei_index);	items = (argc + 1) + (envc + 1);	items += 1; /* ELF interpreters only put argc on the stack */	bprm->p = STACK_ROUND(sp, items);	/* Point sp at the lowest address on the stack */#ifdef CONFIG_STACK_GROWSUP	sp = (elf_addr_t __user *)bprm->p - items - ei_index;	bprm->exec = (unsigned long) sp; /* XXX: PARISC HACK */#else	sp = (elf_addr_t __user *)bprm->p;#endif	/* Now, let's put argc (and argv, envp if appropriate) on the stack */	if (__put_user(argc, sp++))		return -EFAULT;	argv = sp;	envp = argv + argc + 1;	/* Populate argv and envp */	p = current->mm->arg_end = current->mm->arg_start;	while (argc-- > 0) {		size_t len;		__put_user((elf_addr_t)p, argv++);		len = strnlen_user((void __user *)p, PAGE_SIZE*MAX_ARG_PAGES);		if (!len || len > PAGE_SIZE*MAX_ARG_PAGES)			return 0;		p += len;	}	if (__put_user(0, argv))		return -EFAULT;	current->mm->arg_end = current->mm->env_start = p;	while (envc-- > 0) {		size_t len;		__put_user((elf_addr_t)p, envp++);		len = strnlen_user((void __user *)p, PAGE_SIZE*MAX_ARG_PAGES);		if (!len || len > PAGE_SIZE*MAX_ARG_PAGES)			return 0;		p += len;	}	if (__put_user(0, envp))		return -EFAULT;	current->mm->env_end = p;	/* Put the elf_info on the stack in the right place.  */	sp = (elf_addr_t __user *)envp + 1;	if (copy_to_user(sp, elf_info, ei_index * sizeof(elf_addr_t)))		return -EFAULT;	return 0;} /* end create_elf_tables *//* * search_ntdll */static char *search_ntdll(struct linux_binprm *bprm){	unsigned long	pos = bprm->p;	unsigned long	kaddr;	char	*buf, *bp = NULL;	char	*filename = NULL;	struct page	*page;	int	len;	int	offset = 0;	int	i = MAX_ARG_PAGES;	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);	while (pos < MAX_ARG_PAGES * PAGE_SIZE - sizeof(void *)) {		i = pos >> PAGE_SHIFT;		offset = pos & (PAGE_SIZE - 1);		page = bprm->page[i];		if (!page)			break;		kaddr = (unsigned long)kmap(page);		len = strnlen((char *)kaddr + offset, PAGE_SIZE - offset);		if (len == PAGE_SIZE - offset) {			memcpy(buf, (char *)kaddr + offset, PAGE_SIZE - offset);			bp = buf + PAGE_SIZE - offset;			pos += len;		}		else {			if (bp)				memcpy(bp, (char *)kaddr + offset, len + 1);			else				bp = (char *)kaddr + offset;			if (!strncmp(bp, "WINE_DLL_PATH", strlen("WINE_DLL_PATH"))) {				char *p = &bp[strlen("WINE_DLL_PATH")];				if (*p == '=') {					filename = kmalloc(strlen(++p) + sizeof("/ntdll.dll.so"), GFP_KERNEL);					strcpy(filename, p);					strcat(filename + strlen(p), "/ntdll.dll.so");				}			}			bp = NULL;			pos += len + 1;		}		kunmap(page);		if (filename)			break;	}	kfree(buf);	return filename ? : kstrdup("/usr/local/lib/wine/ntdll.dll.so", GFP_KERNEL);} /* end search_ntdll */#else /* NTDLL_SO *//* * create_pe_tables */static intcreate_pe_tables(struct linux_binprm *bprm, struct win32_section *ws,		unsigned long load_addr, unsigned long interp_load_addr){	return 0;} /* end create_pe_tables *//* * load_pe_interp */static unsigned long load_pe_interp(void *interp_hdr,		struct file *interpreter,		unsigned long *interp_load_addr){	return 0;} /* end load_pe_interp */#endif/* * pe_map */static unsigned long pe_map(struct win32_section *ws, unsigned long base_addr){	int	ret = -ENOSYS;	unsigned long	addr = base_addr;	if (!ws)		return -EINVAL;	if (ws->ws_mmap) {		/* grab the process's memory mapping semaphore */		down_write(&current->mm->mmap_sem);		/* do the mmap operation */		addr = base_addr;		ret = ws->ws_mmap(current, ws, &addr, 0, 0, 0);		/* release the process's memory mapping semaphore */		up_write(&current->mm->mmap_sem);	}	return ret;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -