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

📄 main.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  qemu user main *  *  Copyright (c) 2003 Fabrice Bellard * *  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. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <string.h>#include <errno.h>#include <unistd.h>#include "qemu.h"#define DEBUG_LOGFILE "/tmp/qemu.log"#ifdef __APPLE__#include <crt_externs.h># define environ  (*_NSGetEnviron())#endifstatic const char *interp_prefix = CONFIG_QEMU_PREFIX;#if defined(__i386__) && !defined(CONFIG_STATIC)/* Force usage of an ELF interpreter even if it is an ELF shared   object ! */const char interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";#endif/* for recent libc, we add these dummy symbols which are not declared   when generating a linked object (bug in ld ?) */#if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined(CONFIG_STATIC)long __preinit_array_start[0];long __preinit_array_end[0];long __init_array_start[0];long __init_array_end[0];long __fini_array_start[0];long __fini_array_end[0];#endif/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so   we allocate a bigger stack. Need a better solution, for example   by remapping the process stack directly at the right place */unsigned long x86_stack_size = 512 * 1024;void gemu_log(const char *fmt, ...){    va_list ap;    va_start(ap, fmt);    vfprintf(stderr, fmt, ap);    va_end(ap);}void cpu_outb(CPUState *env, int addr, int val){    fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);}void cpu_outw(CPUState *env, int addr, int val){    fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);}void cpu_outl(CPUState *env, int addr, int val){    fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);}int cpu_inb(CPUState *env, int addr){    fprintf(stderr, "inb: port=0x%04x\n", addr);    return 0;}int cpu_inw(CPUState *env, int addr){    fprintf(stderr, "inw: port=0x%04x\n", addr);    return 0;}int cpu_inl(CPUState *env, int addr){    fprintf(stderr, "inl: port=0x%04x\n", addr);    return 0;}int cpu_get_pic_interrupt(CPUState *env){    return -1;}/* timers for rdtsc */#if defined(__i386__)int64_t cpu_get_real_ticks(void){    int64_t val;    asm volatile ("rdtsc" : "=A" (val));    return val;}#elif defined(__x86_64__)int64_t cpu_get_real_ticks(void){    uint32_t low,high;    int64_t val;    asm volatile("rdtsc" : "=a" (low), "=d" (high));    val = high;    val <<= 32;    val |= low;    return val;}#elsestatic uint64_t emu_time;int64_t cpu_get_real_ticks(void){    return emu_time++;}#endif#ifdef TARGET_I386/***********************************************************//* CPUX86 core interface */uint64_t cpu_get_tsc(CPUX86State *env){    return cpu_get_real_ticks();}static void write_dt(void *ptr, unsigned long addr, unsigned long limit,                      int flags){    unsigned int e1, e2;    uint32_t *p;    e1 = (addr << 16) | (limit & 0xffff);    e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);    e2 |= flags;    p = ptr;    p[0] = tswapl(e1);    p[1] = tswapl(e2);}static void set_gate(void *ptr, unsigned int type, unsigned int dpl,                      unsigned long addr, unsigned int sel){    unsigned int e1, e2;    uint32_t *p;    e1 = (addr & 0xffff) | (sel << 16);    e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);    p = ptr;    p[0] = tswapl(e1);    p[1] = tswapl(e2);}uint64_t gdt_table[6];uint64_t idt_table[256];/* only dpl matters as we do only user space emulation */static void set_idt(int n, unsigned int dpl){    set_gate(idt_table + n, 0, dpl, 0, 0);}void cpu_loop(CPUX86State *env){    int trapnr;    target_ulong pc;    target_siginfo_t info;    for(;;) {        trapnr = cpu_x86_exec(env);        switch(trapnr) {        case 0x80:            /* linux syscall */            env->regs[R_EAX] = do_syscall(env,                                           env->regs[R_EAX],                                           env->regs[R_EBX],                                          env->regs[R_ECX],                                          env->regs[R_EDX],                                          env->regs[R_ESI],                                          env->regs[R_EDI],                                          env->regs[R_EBP]);            break;        case EXCP0B_NOSEG:        case EXCP0C_STACK:            info.si_signo = SIGBUS;            info.si_errno = 0;            info.si_code = TARGET_SI_KERNEL;            info._sifields._sigfault._addr = 0;            queue_signal(info.si_signo, &info);            break;        case EXCP0D_GPF:            if (env->eflags & VM_MASK) {                handle_vm86_fault(env);            } else {                info.si_signo = SIGSEGV;                info.si_errno = 0;                info.si_code = TARGET_SI_KERNEL;                info._sifields._sigfault._addr = 0;                queue_signal(info.si_signo, &info);            }            break;        case EXCP0E_PAGE:            info.si_signo = SIGSEGV;            info.si_errno = 0;            if (!(env->error_code & 1))                info.si_code = TARGET_SEGV_MAPERR;            else                info.si_code = TARGET_SEGV_ACCERR;            info._sifields._sigfault._addr = env->cr[2];            queue_signal(info.si_signo, &info);            break;        case EXCP00_DIVZ:            if (env->eflags & VM_MASK) {                handle_vm86_trap(env, trapnr);            } else {                /* division by zero */                info.si_signo = SIGFPE;                info.si_errno = 0;                info.si_code = TARGET_FPE_INTDIV;                info._sifields._sigfault._addr = env->eip;                queue_signal(info.si_signo, &info);            }            break;        case EXCP01_SSTP:        case EXCP03_INT3:            if (env->eflags & VM_MASK) {                handle_vm86_trap(env, trapnr);            } else {                info.si_signo = SIGTRAP;                info.si_errno = 0;                if (trapnr == EXCP01_SSTP) {                    info.si_code = TARGET_TRAP_BRKPT;                    info._sifields._sigfault._addr = env->eip;                } else {                    info.si_code = TARGET_SI_KERNEL;                    info._sifields._sigfault._addr = 0;                }                queue_signal(info.si_signo, &info);            }            break;        case EXCP04_INTO:        case EXCP05_BOUND:            if (env->eflags & VM_MASK) {                handle_vm86_trap(env, trapnr);            } else {                info.si_signo = SIGSEGV;                info.si_errno = 0;                info.si_code = TARGET_SI_KERNEL;                info._sifields._sigfault._addr = 0;                queue_signal(info.si_signo, &info);            }            break;        case EXCP06_ILLOP:            info.si_signo = SIGILL;            info.si_errno = 0;            info.si_code = TARGET_ILL_ILLOPN;            info._sifields._sigfault._addr = env->eip;            queue_signal(info.si_signo, &info);            break;        case EXCP_INTERRUPT:            /* just indicate that signals should be handled asap */            break;        case EXCP_DEBUG:            {                int sig;                sig = gdb_handlesig (env, TARGET_SIGTRAP);                if (sig)                  {                    info.si_signo = sig;                    info.si_errno = 0;                    info.si_code = TARGET_TRAP_BRKPT;                    queue_signal(info.si_signo, &info);                  }            }            break;        default:            pc = env->segs[R_CS].base + env->eip;            fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",                     (long)pc, trapnr);            abort();        }        process_pending_signals(env);    }}#endif#ifdef TARGET_ARM/* XXX: find a better solution */extern void tb_invalidate_page_range(target_ulong start, target_ulong end);static void arm_cache_flush(target_ulong start, target_ulong last){    target_ulong addr, last1;    if (last < start)        return;    addr = start;    for(;;) {        last1 = ((addr + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK) - 1;        if (last1 > last)            last1 = last;        tb_invalidate_page_range(addr, last1 + 1);        if (last1 == last)            break;        addr = last1 + 1;    }}void cpu_loop(CPUARMState *env){    int trapnr;    unsigned int n, insn;    target_siginfo_t info;    uint32_t addr;        for(;;) {        trapnr = cpu_arm_exec(env);        switch(trapnr) {        case EXCP_UDEF:            {                TaskState *ts = env->opaque;                uint32_t opcode;                /* we handle the FPU emulation here, as Linux */                /* we get the opcode */                opcode = tget32(env->regs[15]);                                if (EmulateAll(opcode, &ts->fpa, env) == 0) {                    info.si_signo = SIGILL;                    info.si_errno = 0;                    info.si_code = TARGET_ILL_ILLOPN;                    info._sifields._sigfault._addr = env->regs[15];                    queue_signal(info.si_signo, &info);                } else {                    /* increment PC */                    env->regs[15] += 4;                }            }            break;        case EXCP_SWI:        case EXCP_BKPT:            {                env->eabi = 1;                /* system call */                if (trapnr == EXCP_BKPT) {                    if (env->thumb) {                        insn = tget16(env->regs[15]);                        n = insn & 0xff;                        env->regs[15] += 2;                    } else {                        insn = tget32(env->regs[15]);                        n = (insn & 0xf) | ((insn >> 4) & 0xff0);                        env->regs[15] += 4;                    }                } else {                    if (env->thumb) {                        insn = tget16(env->regs[15] - 2);                        n = insn & 0xff;                    } else {                        insn = tget32(env->regs[15] - 4);                        n = insn & 0xffffff;                    }                }                if (n == ARM_NR_cacheflush) {                    arm_cache_flush(env->regs[0], env->regs[1]);                } else if (n == ARM_NR_semihosting                           || n == ARM_NR_thumb_semihosting) {                    env->regs[0] = do_arm_semihosting (env);                } else if (n == 0 || n >= ARM_SYSCALL_BASE                           || (env->thumb && n == ARM_THUMB_SYSCALL)) {                    /* linux syscall */                    if (env->thumb || n == 0) {                        n = env->regs[7];                    } else {                        n -= ARM_SYSCALL_BASE;                        env->eabi = 0;                    }                    env->regs[0] = do_syscall(env,                                               n,                                               env->regs[0],                                              env->regs[1],                                              env->regs[2],                                              env->regs[3],                                              env->regs[4],                                              env->regs[5]);                } else {                    goto error;                }            }            break;        case EXCP_INTERRUPT:            /* just indicate that signals should be handled asap */            break;        case EXCP_PREFETCH_ABORT:            addr = env->cp15.c6_data;            goto do_segv;        case EXCP_DATA_ABORT:            addr = env->cp15.c6_insn;            goto do_segv;        do_segv:            {                info.si_signo = SIGSEGV;                info.si_errno = 0;                /* XXX: check env->error_code */                info.si_code = TARGET_SEGV_MAPERR;                info._sifields._sigfault._addr = addr;

⌨️ 快捷键说明

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