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

📄 imagesection.c

📁 该项目主要是将wingdows程序直接运行在linux上
💻 C
字号:
/* * imagesection.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. *//* * imagesection.c: * Reference to Linux Kernel code */#include "section.h"#include "pefile.h"#include "objwait.h"#include <linux/file.h>#include <linux/mm.h>#include <linux/mman.h>#include <linux/swap.h>#include <linux/highmem.h>#include <linux/smp_lock.h>#include <linux/pagemap.h>#include <linux/mount.h>#include <linux/hugetlb.h>#include <linux/personality.h>#include <asm/uaccess.h>#include <asm/pgalloc.h>#ifdef CONFIG_UNIFIED_KERNELextern unsigned long win32_do_mmap_pgoff(struct task_struct *, char, struct file *,		unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);static int image_section_map(struct task_struct *tsk, struct win32_section *ws,		unsigned long *addr, unsigned long len, unsigned long flags, unsigned long offset);static int image_section_munmap(struct win32_section *ws);static struct page *filemap_pe_nopage(struct vm_area_struct *area,				unsigned long address, int *type);static unsigned long character2prot[] = {	PROT_NONE,	PROT_EXEC,			/* IMAGE_SCN_MEM_EXECUTE */	PROT_READ,			/* IMAGE_SCN_MEM_READ */	PROT_READ | PROT_EXEC,	PROT_WRITE,			/* IMAGE_SCN_MEM_WRITE */	PROT_WRITE | PROT_EXEC,	PROT_WRITE | PROT_READ,	PROT_WRITE | PROT_READ | PROT_WRITE};static struct vm_operations_struct file_pe_shared_mmap = {	.nopage = filemap_pe_nopage,};static struct vm_operations_struct file_pe_private_mmap = {	.nopage = filemap_pe_nopage,};/* origin in kernel-win32 */static int is_power_of2(unsigned long addr){	if (!addr)		return 0;	while (!(addr % 2))		addr /= 2;	return addr == 1;}/* * parse a PE image and build a set of VM areas and a relocation table index * - performs a cursory check of the image's validity * - ignores the fact that file sections may _not_ be page aligned! */#define	ALIGN_UP(addr, align)	(((addr) + (align) - 1) & ~((align) - 1))int image_section_setup(struct win32_section *ws){	IMAGE_DOS_HEADER	*dos_hdr;	IMAGE_NT_HEADERS	*nt_hdr;	IMAGE_OPTIONAL_HEADER	*opt_hdr;	IMAGE_SECTION_HEADER	*sec_hdr, *ps;	struct win32_image_section	*wis;	struct file	*file;	size_t	hdr_len, nt_hdr_size, sec_hdr_size, total_hdr_size;	void	*hdr_buf;	DWORD	rva;	int	sec_align, file_align, sec_mask, file_mask;	int	tmp, err;	ktrace("image_section_setup(%p)\n",ws);	ws->ws_mmap = image_section_map;	ws->ws_munmap = image_section_munmap ;	/* check that we can map the file into the VM */	if (!ws->ws_file && ws->ws_wfile)		ws->ws_file = ws->ws_wfile->wf_file;	file = ws->ws_file;	if (!file->f_op || !file->f_op->mmap)		return -ENODEV;	/* check we can read the file */	if (!(file->f_mode & FMODE_READ))		return -EACCES;	/* get the image header and find the offset of the extended header */	/* alloc 2 pages to store file header */	hdr_buf = (void *)__get_free_pages(GFP_KERNEL, 1);	if (!hdr_buf)		return -ENOMEM;	/* read 2 pages to hdr_buf */	hdr_len = kernel_read(file, 0, hdr_buf, PAGE_SIZE << 1);	if (hdr_len < 0) {		err = hdr_len;		goto free_hdr;	}	err = -ENOEXEC;	if (hdr_len < sizeof(IMAGE_DOS_HEADER))		goto free_hdr;	/* check the DOS header */	dos_hdr = (IMAGE_DOS_HEADER *)hdr_buf;	if (dos_hdr->e_magic != IMAGE_DOS_SIGNATURE || dos_hdr->e_lfanew <= 0)		goto free_hdr;	/* get the NT header and OPTIONAL header */	nt_hdr = (IMAGE_NT_HEADERS *)(hdr_buf + dos_hdr->e_lfanew);	opt_hdr = (IMAGE_OPTIONAL_HEADER *)&nt_hdr->OptionalHeader;	if (hdr_len < dos_hdr->e_lfanew + sizeof(IMAGE_NT_HEADERS)			|| nt_hdr->Signature != IMAGE_NT_SIGNATURE			|| nt_hdr->FileHeader.Machine != IMAGE_FILE_MACHINE_I386			|| !(nt_hdr->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)			|| opt_hdr->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC			|| opt_hdr->ImageBase & 0xffff	/* ImageBase need aligned to 64KB */			|| !is_power_of2(opt_hdr->SectionAlignment)			|| !is_power_of2(opt_hdr->FileAlignment)			|| opt_hdr->SectionAlignment < opt_hdr->FileAlignment			|| opt_hdr->SectionAlignment < PAGE_SIZE)		goto free_hdr;	/* section alignment and file alignment */	sec_align = opt_hdr->SectionAlignment;	sec_mask = sec_align - 1;	file_align = opt_hdr->FileAlignment;	file_mask = file_align - 1;	/* fill section for global */	ws->ws_imagebase = opt_hdr->ImageBase;	ws->ws_nsecs = nt_hdr->FileHeader.NumberOfSections + 1;	ws->ws_stackresv = opt_hdr->SizeOfStackReserve;	ws->ws_stackcommit = opt_hdr->SizeOfStackCommit;	ws->ws_subsystem = opt_hdr->Subsystem;	ws->ws_majorver = opt_hdr->MajorSubsystemVersion;	ws->ws_minorver = opt_hdr->MinorSubsystemVersion;	ws->ws_entrypoint = opt_hdr->AddressOfEntryPoint;	ws->ws_executable = opt_hdr->SizeOfCode != 0;	ws->ws_imagecharacter = nt_hdr->FileHeader.Characteristics;	ws->ws_machine = nt_hdr->FileHeader.Machine;	/* locate section header */	nt_hdr_size = sizeof(*nt_hdr) - sizeof(*opt_hdr) + nt_hdr->FileHeader.SizeOfOptionalHeader;	sec_hdr = (IMAGE_SECTION_HEADER *)((char *)nt_hdr + nt_hdr_size);	sec_hdr_size = nt_hdr->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);	total_hdr_size = dos_hdr->e_lfanew + nt_hdr_size + sec_hdr_size;	if (total_hdr_size > hdr_len)		goto free_hdr;	ws->ws_secoff = (char *)sec_hdr - (char *)hdr_buf;	/* allocate my section table (with a dummy section on the end) */	err = -ENOMEM;	tmp = sizeof(struct win32_image_section) * ws->ws_nsecs;	ws->ws_sections = (struct win32_image_section *)kmalloc(tmp, GFP_KERNEL);	if (!ws->ws_sections)		goto free_hdr;	/* create a virtual section to map the image header */	wis = ws->ws_sections;	ps = sec_hdr;	wis->wis_rva	= 0;	wis->wis_fpos	= 0;	wis->wis_size	= ALIGN_UP(total_hdr_size, sec_align);	wis->wis_rawsize = ALIGN_UP(total_hdr_size, file_align);	wis->wis_flags = MAP_DENYWRITE | MAP_PRIVATE;	wis->wis_protect = PROT_READ;	wis->wis_character = 0;	/* validate the section table */	err = -ENOEXEC;	rva = wis->wis_size;	for (wis++; wis < ws->ws_sections + ws->ws_nsecs; ps++, wis++) {		unsigned long	characteristics;		/* not alignment */		if (ps->VirtualAddress & sec_mask)			goto free_section;		wis->wis_rva = ps->VirtualAddress;	/* relate virtual address */		if (wis->wis_rva < rva)		/* rva = relate virtual address of previous section end */			goto free_section;		characteristics = ps->Characteristics;		/* check the IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE */		if (!(characteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE))) {			/* no explicit protection */			if (characteristics & IMAGE_SCN_CNT_CODE)				characteristics |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ;			if (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)				characteristics |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;			if (characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)				characteristics |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;		}		wis->wis_character = characteristics;		/* get segement size, aligned to SectionAlignment */		if (!ps->Misc.VirtualSize || ps->Misc.VirtualSize < ps->SizeOfRawData)			wis->wis_size = ALIGN_UP(ps->SizeOfRawData, sec_align);		else			wis->wis_size = ALIGN_UP(ps->Misc.VirtualSize, sec_align);		if (wis->wis_size > TASK_SIZE)			goto free_section;		wis->wis_fpos = ps->PointerToRawData;	/* file postion */		wis->wis_rawsize = ALIGN_UP(ps->SizeOfRawData, file_align);		if (wis->wis_size < wis->wis_rawsize)			goto free_section;		/* calc this section end */		rva = wis->wis_rva + wis->wis_size;		/* determine the specific VM flags for this section */		wis->wis_flags = MAP_DENYWRITE | MAP_EXECUTABLE;		if (characteristics & IMAGE_SCN_MEM_SHARED)			wis->wis_flags |= MAP_SHARED;		else			wis->wis_flags |= MAP_PRIVATE;		/* section protect, get highest 3 bits */		wis->wis_protect = character2prot[characteristics >> 29];		if ((wis->wis_flags & MAP_SHARED)				&& (wis->wis_protect & (PROT_WRITE | PROT_EXEC)))			goto free_section;	}	/* total segements len */	ws->ws_len = rva;	ws->ws_pagelen = PAGE_ALIGN(rva);	err = 0;	goto free_hdr;free_section:	ws->ws_nsecs = 0;	kfree(ws->ws_sections);	ws->ws_sections = NULL;free_hdr:	free_pages((unsigned long)hdr_buf, 1);	ktrace("image_section_setup end %p\n", ws);	return err;} /* end image_section_setup *//* * map the PE image into the process's VM space */static int image_section_map(struct task_struct *tsk, struct win32_section *ws,		unsigned long *addr, unsigned long len, unsigned long flags, unsigned long offset){	int			load_addr_set = 0;	unsigned long		ret, base;	struct file		*file = ws->ws_file;	struct vm_area_struct	*vma;	struct win32_image_section	*wis;	struct vm_operations_struct	*vmops;	ktrace("image_section_map (%p)\n",ws);	base = *addr;	if (!base)		base = ws->ws_imagebase;	/* iterate through all the chunks */	for (wis = ws->ws_sections; wis < ws->ws_sections + ws->ws_nsecs; wis++) {		if (wis->wis_character & IMAGE_SCN_TYPE_NOLOAD)			continue;		/* set vmops */		flags = 0;		if ((wis->wis_flags & MAP_SHARED) && (wis->wis_protect & PROT_WRITE))			vmops = &file_pe_shared_mmap;		else			vmops = &file_pe_private_mmap;		if (ws->ws_imagecharacter & IMAGE_FILE_EXECUTABLE_IMAGE || load_addr_set)			flags = MAP_FIXED;		/* map a section */		ret = tsk == current			? do_mmap_pgoff(file, base + wis->wis_rva, wis->wis_size,				wis->wis_protect, wis->wis_flags | flags, wis->wis_rva >> PAGE_SHIFT)			: win32_do_mmap_pgoff(tsk, 0, file, base + wis->wis_rva, wis->wis_size,				wis->wis_protect, wis->wis_flags | flags, wis->wis_rva >> PAGE_SHIFT);		/* fixup vma */		vma = find_vma(tsk->mm, ret);		if (vma) {			vma->vm_private_data = (void *)ws;			vma->vm_ops = vmops;		}		if (IS_ERR((void *)ret))			goto failed;		if (!load_addr_set) {			load_addr_set = 1;			if (ws->ws_imagecharacter & IMAGE_FILE_DLL)				ws->ws_realbase = ret - wis->wis_rva;			else				ws->ws_realbase = base;			base = ws->ws_realbase;		}	}	*addr = base;	ktrace("image_section_map (%p): okay\n",ws);	return 0;	/* clean up on error */failed:	ktrace("image_section_map (%p): failed %lu\n", ws, ret);	return PTR_ERR((void *)ret);} /* end image_section_map () */static int image_section_munmap(struct win32_section *ws){	int	err, ret = 0;	struct win32_image_section	*wis;	struct mm_struct	*mm = current->mm;	ktrace("enter image_section_munmap %p\n", ws);	/* grab the process's memory mapping semaphore */	down_write(&mm->mmap_sem);	for (wis = ws->ws_sections; wis < ws->ws_sections + ws->ws_nsecs; wis++) {		if (wis->wis_character & IMAGE_SCN_TYPE_NOLOAD)			continue;		err = do_munmap(mm, ws->ws_realbase + wis->wis_rva, wis->wis_size);		if (err) {			kdebug("do_munmap addr 0x%lx len 0x%x, error %d\n",					ws->ws_realbase + wis->wis_rva, wis->wis_size, err);			ret = err;		}	}	/* release the process's memory mapping semaphore */	up_write(&mm->mmap_sem);	kfree(ws);	ktrace("image_section_munmap end %p\n", ws);	return ret;} /* image_section_munmap */static struct page *filemap_pe_nopage(struct vm_area_struct *area,				unsigned long address, int *type){	int	error;	void	*pgbuf;	unsigned long	pgoff, floff, voff, size;	struct page	*page;	struct file	*file = area->vm_file;	struct win32_section	*ws;	struct win32_image_section	*wis;	ktrace("enter filemap_pe_nopage, area 0x%p\n", area);	if (!(ws = (struct win32_section *)area->vm_private_data))		return NULL;	for (wis = ws->ws_sections; wis < ws->ws_sections + ws->ws_nsecs; wis++)		if ((address < ws->ws_realbase + wis->wis_rva + wis->wis_size)				&& (address >= ws->ws_realbase + wis->wis_rva))			break;	/* get page offset and virtual offset */	voff = address - area->vm_start;	pgoff = (voff >> PAGE_CACHE_SHIFT) + area->vm_pgoff;	voff += area->vm_start - ws->ws_realbase - wis->wis_rva;	if (pgoff >= ((wis->wis_rva + wis->wis_size) >> PAGE_CACHE_SHIFT))		if (area->vm_mm == current->mm)			return NULL;	page = alloc_pages(GFP_ATOMIC, 0);	if (!page)		return NOPAGE_OOM;	pgbuf = kmap(page);	if (pgbuf) {		if (voff > wis->wis_rawsize)			memset(pgbuf, 0, PAGE_SIZE);		else {			floff = voff + wis->wis_fpos;			size = wis->wis_rawsize - voff;			size = size < PAGE_SIZE ? size : PAGE_SIZE;			error = kernel_read(file, floff, pgbuf, size);			if (size < PAGE_SIZE)				memset(pgbuf + size, 0, PAGE_SIZE - size);			if (error < 0)				goto cleanup;			grab_swap_token();		}		kunmap(page);		return page;	}cleanup:	kunmap(page);	__free_pages(page, 0);	return NULL;} /* end filemap_pe_nopage */#endif

⌨️ 快捷键说明

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