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

📄 elfload.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* This is the Linux kernel elf-loading code, ported into user space */#include <stdio.h>#include <sys/types.h>#include <fcntl.h>#include <sys/stat.h>#include <errno.h>#include <unistd.h>#include <sys/mman.h>#include <stdlib.h>#include <string.h>#include "qemu.h"#include "disas.h"/* this flag is uneffective under linux too, should be deleted */#ifndef MAP_DENYWRITE#define MAP_DENYWRITE 0#endif/* should probably go in elf.h */#ifndef ELIBBAD#define ELIBBAD 80#endif#ifdef TARGET_I386#define ELF_PLATFORM get_elf_platform()static const char *get_elf_platform(void){    static char elf_platform[] = "i386";    int family = (global_env->cpuid_version >> 8) & 0xff;    if (family > 6)        family = 6;    if (family >= 3)        elf_platform[1] = '0' + family;    return elf_platform;}#define ELF_HWCAP get_elf_hwcap()static uint32_t get_elf_hwcap(void){  return global_env->cpuid_features;}#define ELF_START_MMAP 0x80000000/* * This is used to ensure we don't load something for the wrong architecture. */#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )/* * These are used to set parameters in the core dumps. */#define ELF_CLASS	ELFCLASS32#define ELF_DATA	ELFDATA2LSB#define ELF_ARCH	EM_386	/* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program	   starts %edx contains a pointer to a function which might be	   registered using `atexit'.  This provides a mean for the	   dynamic linker to call DT_FINI functions for shared libraries	   that have been loaded before the code runs.	   A value of 0 tells we have no such handler.  */#define ELF_PLAT_INIT(_r)	_r->edx = 0static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop){    regs->esp = infop->start_stack;    regs->eip = infop->entry;}#define USE_ELF_CORE_DUMP#define ELF_EXEC_PAGESIZE	4096#endif#ifdef TARGET_ARM#define ELF_START_MMAP 0x80000000#define elf_check_arch(x) ( (x) == EM_ARM )#define ELF_CLASS	ELFCLASS32#ifdef TARGET_WORDS_BIGENDIAN#define ELF_DATA	ELFDATA2MSB#else#define ELF_DATA	ELFDATA2LSB#endif#define ELF_ARCH	EM_ARM#define ELF_PLAT_INIT(_r)	_r->ARM_r0 = 0static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop){    target_long stack = infop->start_stack;    memset(regs, 0, sizeof(*regs));    regs->ARM_cpsr = 0x10;    if (infop->entry & 1)      regs->ARM_cpsr |= CPSR_T;    regs->ARM_pc = infop->entry & 0xfffffffe;    regs->ARM_sp = infop->start_stack;    regs->ARM_r2 = tgetl(stack + 8); /* envp */    regs->ARM_r1 = tgetl(stack + 4); /* envp */    /* XXX: it seems that r0 is zeroed after ! */    //    regs->ARM_r0 = tgetl(stack); /* argc */}#define USE_ELF_CORE_DUMP#define ELF_EXEC_PAGESIZE	4096enum{  ARM_HWCAP_ARM_SWP       = 1 << 0,  ARM_HWCAP_ARM_HALF      = 1 << 1,  ARM_HWCAP_ARM_THUMB     = 1 << 2,  ARM_HWCAP_ARM_26BIT     = 1 << 3,  ARM_HWCAP_ARM_FAST_MULT = 1 << 4,  ARM_HWCAP_ARM_FPA       = 1 << 5,  ARM_HWCAP_ARM_VFP       = 1 << 6,  ARM_HWCAP_ARM_EDSP      = 1 << 7,};#define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF              \                    | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT     \                    | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP)#endif#ifdef TARGET_SPARC#ifdef TARGET_SPARC64#define ELF_START_MMAP 0x80000000#define elf_check_arch(x) ( (x) == EM_SPARC )#define ELF_CLASS   ELFCLASS64#define ELF_DATA    ELFDATA2MSB#define ELF_ARCH    EM_SPARC/*XXX*/#define ELF_PLAT_INIT(_r)static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop){    regs->tstate = 0;    regs->pc = infop->entry;    regs->npc = regs->pc + 4;    regs->y = 0;    regs->u_regs[14] = infop->start_stack - 16 * 4;}#else#define ELF_START_MMAP 0x80000000#define elf_check_arch(x) ( (x) == EM_SPARC )#define ELF_CLASS   ELFCLASS32#define ELF_DATA    ELFDATA2MSB#define ELF_ARCH    EM_SPARC/*XXX*/#define ELF_PLAT_INIT(_r)static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop){    regs->psr = 0;    regs->pc = infop->entry;    regs->npc = regs->pc + 4;    regs->y = 0;    regs->u_regs[14] = infop->start_stack - 16 * 4;}#endif#endif#ifdef TARGET_PPC#define ELF_START_MMAP 0x80000000#define elf_check_arch(x) ( (x) == EM_PPC )#define ELF_CLASS	ELFCLASS32#ifdef TARGET_WORDS_BIGENDIAN#define ELF_DATA	ELFDATA2MSB#else#define ELF_DATA	ELFDATA2LSB#endif#define ELF_ARCH	EM_PPC/* Note that isn't exactly what regular kernel does * but this is what the ABI wants and is needed to allow * execution of PPC BSD programs. */#define ELF_PLAT_INIT(_r)                                  \do {                                                       \    target_ulong *pos = (target_ulong *)bprm->p, tmp = 1;  \    _r->gpr[3] = bprm->argc;                               \    _r->gpr[4] = (unsigned long)++pos;                     \    for (; tmp != 0; pos++)                                \        tmp = ldl(pos);                                    \    _r->gpr[5] = (unsigned long)pos;                       \} while (0)/* * We need to put in some extra aux table entries to tell glibc what * the cache block size is, so it can use the dcbz instruction safely. */#define AT_DCACHEBSIZE          19#define AT_ICACHEBSIZE          20#define AT_UCACHEBSIZE          21/* A special ignored type value for PPC, for glibc compatibility.  */#define AT_IGNOREPPC            22/* * The requirements here are: * - keep the final alignment of sp (sp & 0xf) * - make sure the 32-bit value at the first 16 byte aligned position of *   AUXV is greater than 16 for glibc compatibility. *   AT_IGNOREPPC is used for that. * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC, *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined. */#define DLINFO_ARCH_ITEMS       5#define ARCH_DLINFO                                                     \do {                                                                    \        NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20);                              \        NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20);                              \        NEW_AUX_ENT(AT_UCACHEBSIZE, 0);                                 \        /*                                                              \         * Now handle glibc compatibility.                              \         */                                                             \	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\ } while (0)static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop){    _regs->msr = 1 << MSR_PR; /* Set user mode */    _regs->gpr[1] = infop->start_stack;    _regs->nip = infop->entry;}#define USE_ELF_CORE_DUMP#define ELF_EXEC_PAGESIZE	4096#endif#ifdef TARGET_MIPS#define ELF_START_MMAP 0x80000000#define elf_check_arch(x) ( (x) == EM_MIPS )#define ELF_CLASS   ELFCLASS32#ifdef TARGET_WORDS_BIGENDIAN#define ELF_DATA	ELFDATA2MSB#else#define ELF_DATA	ELFDATA2LSB#endif#define ELF_ARCH    EM_MIPS#define ELF_PLAT_INIT(_r) static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop){    regs->cp0_status = CP0St_UM;    regs->cp0_epc = infop->entry;    regs->regs[29] = infop->start_stack;}#endif /* TARGET_MIPS */#ifdef TARGET_SH4#define ELF_START_MMAP 0x80000000#define elf_check_arch(x) ( (x) == EM_SH )#define ELF_CLASS ELFCLASS32#define ELF_DATA  ELFDATA2LSB#define ELF_ARCH  EM_SH#define ELF_PLAT_INIT(_r) /* XXXXX */static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop){  /* Check other registers XXXXX */  regs->pc = infop->entry;  regs->regs[15] = infop->start_stack - 16 * 4;}#define USE_ELF_CORE_DUMP#define ELF_EXEC_PAGESIZE        4096#endif#ifndef ELF_PLATFORM#define ELF_PLATFORM (NULL)#endif#ifndef ELF_HWCAP#define ELF_HWCAP 0#endif#include "elf.h"/* * MAX_ARG_PAGES defines the number of pages allocated for arguments * and envelope for the new program. 32 should suffice, this gives * a maximum env+arg of 128kB w/4KB pages! */#define MAX_ARG_PAGES 32/* * This structure is used to hold the arguments that are  * used when loading binaries. */struct linux_binprm {        char buf[128];        void *page[MAX_ARG_PAGES];        unsigned long p;        int sh_bang;	int fd;        int e_uid, e_gid;        int argc, envc;        char * filename;        /* Name of binary */        unsigned long loader, exec;        int dont_iput;          /* binfmt handler has put inode */};struct exec{  unsigned int a_info;   /* Use macros N_MAGIC, etc for access */  unsigned int a_text;   /* length of text, in bytes */  unsigned int a_data;   /* length of data, in bytes */  unsigned int a_bss;    /* length of uninitialized data area, in bytes */  unsigned int a_syms;   /* length of symbol table data in file, in bytes */  unsigned int a_entry;  /* start address */  unsigned int a_trsize; /* length of relocation info for text, in bytes */  unsigned int a_drsize; /* length of relocation info for data, in bytes */};#define N_MAGIC(exec) ((exec).a_info & 0xffff)#define OMAGIC 0407#define NMAGIC 0410#define ZMAGIC 0413#define QMAGIC 0314/* max code+data+bss space allocated to elf interpreter */#define INTERP_MAP_SIZE (32 * 1024 * 1024)/* max code+data+bss+brk space allocated to ET_DYN executables */#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)/* from personality.h *//* Flags for bug emulation. These occupy the top three bytes. */#define STICKY_TIMEOUTS		0x4000000#define WHOLE_SECONDS		0x2000000/* Personality types. These go in the low byte. Avoid using the top bit, * it will conflict with error returns. */#define PER_MASK		(0x00ff)#define PER_LINUX		(0x0000)#define PER_SVR4		(0x0001 | STICKY_TIMEOUTS)#define PER_SVR3		(0x0002 | STICKY_TIMEOUTS)#define PER_SCOSVR3		(0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS)#define PER_WYSEV386		(0x0004 | STICKY_TIMEOUTS)#define PER_ISCR4		(0x0005 | STICKY_TIMEOUTS)#define PER_BSD			(0x0006)#define PER_XENIX		(0x0007 | STICKY_TIMEOUTS)/* Necessary parameters */#define NGROUPS 32#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))#define INTERPRETER_NONE 0#define INTERPRETER_AOUT 1#define INTERPRETER_ELF 2#define DLINFO_ITEMS 12static inline void memcpy_fromfs(void * to, const void * from, unsigned long n){	memcpy(to, from, n);}extern unsigned long x86_stack_size;static int load_aout_interp(void * exptr, int interp_fd);#ifdef BSWAP_NEEDEDstatic void bswap_ehdr(struct elfhdr *ehdr){    bswap16s(&ehdr->e_type);			/* Object file type */    bswap16s(&ehdr->e_machine);		/* Architecture */    bswap32s(&ehdr->e_version);		/* Object file version */    bswaptls(&ehdr->e_entry);		/* Entry point virtual address */    bswaptls(&ehdr->e_phoff);		/* Program header table file offset */    bswaptls(&ehdr->e_shoff);		/* Section header table file offset */    bswap32s(&ehdr->e_flags);		/* Processor-specific flags */    bswap16s(&ehdr->e_ehsize);		/* ELF header size in bytes */    bswap16s(&ehdr->e_phentsize);		/* Program header table entry size */    bswap16s(&ehdr->e_phnum);		/* Program header table entry count */    bswap16s(&ehdr->e_shentsize);		/* Section header table entry size */    bswap16s(&ehdr->e_shnum);		/* Section header table entry count */    bswap16s(&ehdr->e_shstrndx);		/* Section header string table index */}static void bswap_phdr(struct elf_phdr *phdr){    bswap32s(&phdr->p_type);			/* Segment type */    bswaptls(&phdr->p_offset);		/* Segment file offset */    bswaptls(&phdr->p_vaddr);		/* Segment virtual address */    bswaptls(&phdr->p_paddr);		/* Segment physical address */    bswaptls(&phdr->p_filesz);		/* Segment size in file */    bswaptls(&phdr->p_memsz);		/* Segment size in memory */    bswap32s(&phdr->p_flags);		/* Segment flags */    bswaptls(&phdr->p_align);		/* Segment alignment */}static void bswap_shdr(struct elf_shdr *shdr){    bswap32s(&shdr->sh_name);    bswap32s(&shdr->sh_type);    bswaptls(&shdr->sh_flags);    bswaptls(&shdr->sh_addr);    bswaptls(&shdr->sh_offset);    bswaptls(&shdr->sh_size);    bswap32s(&shdr->sh_link);    bswap32s(&shdr->sh_info);    bswaptls(&shdr->sh_addralign);    bswaptls(&shdr->sh_entsize);}static void bswap_sym(Elf32_Sym *sym){    bswap32s(&sym->st_name);    bswap32s(&sym->st_value);    bswap32s(&sym->st_size);    bswap16s(&sym->st_shndx);}#endif/* * 'copy_string()' copies argument/envelope strings from user * memory to free pages in kernel mem. These are in a format ready * to be put directly into the top of new user memory. * */static unsigned long copy_strings(int argc,char ** argv, void **page,                unsigned long p){    char *tmp, *tmp1, *pag = NULL;    int len, offset = 0;    if (!p) {	return 0;       /* bullet-proofing */    }    while (argc-- > 0) {        tmp = argv[argc];        if (!tmp) {	    fprintf(stderr, "VFS: argc is wrong");	    exit(-1);	}        tmp1 = tmp;	while (*tmp++);	len = tmp - tmp1;	if (p < len) {  /* this shouldn't happen - 128kB */		return 0;	}	while (len) {	    --p; --tmp; --len;	    if (--offset < 0) {		offset = p % TARGET_PAGE_SIZE;                pag = (char *)page[p/TARGET_PAGE_SIZE];                if (!pag) {                    pag = (char *)malloc(TARGET_PAGE_SIZE);

⌨️ 快捷键说明

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