/* * i386 emulator main execution loop * * Copyright (c) 2003-2005 Fabrice Bellard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include "exec.h" #include "disas.h" #if !defined(CONFIG_SOFTMMU) #undef EAX #undef ECX #undef EDX #undef EBX #undef ESP #undef EBP #undef ESI #undef EDI #undef EIP #include #include #endif int tb_invalidated_flag; //#define DEBUG_EXEC //#define DEBUG_SIGNAL #if defined(TARGET_ARM) || defined(TARGET_SPARC) /* XXX: unify with i386 target */ void cpu_loop_exit(void) { longjmp(env->jmp_env, 1); } #endif #if !(defined(TARGET_SPARC) || defined(TARGET_SH4)) #define reg_T2 #endif /* exit the current TB from a signal handler. The host registers are restored in a state compatible with the CPU emulator */ void cpu_resume_from_signal(CPUState *env1, void *puc) { #if !defined(CONFIG_SOFTMMU) struct ucontext *uc = puc; #endif env = env1; /* XXX: restore cpu registers saved in host registers */ #if !defined(CONFIG_SOFTMMU) if (puc) { /* XXX: use siglongjmp ? */ sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL); } #endif longjmp(env->jmp_env, 1); } static TranslationBlock *tb_find_slow(target_ulong pc, target_ulong cs_base, unsigned int flags) { TranslationBlock *tb, **ptb1; int code_gen_size; unsigned int h; target_ulong phys_pc, phys_page1, phys_page2, virt_page2; uint8_t *tc_ptr; spin_lock(&tb_lock); tb_invalidated_flag = 0; regs_to_env(); /* XXX: do it just before cpu_gen_code() */ /* find translated block using physical mappings */ phys_pc = get_phys_addr_code(env, pc); phys_page1 = phys_pc & TARGET_PAGE_MASK; phys_page2 = -1; h = tb_phys_hash_func(phys_pc); ptb1 = &tb_phys_hash[h]; for(;;) { tb = *ptb1; if (!tb) goto not_found; if (tb->pc == pc && tb->page_addr[0] == phys_page1 && tb->cs_base == cs_base && tb->flags == flags) { /* check next page if needed */ if (tb->page_addr[1] != -1) { virt_page2 = (pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; phys_page2 = get_phys_addr_code(env, virt_page2); if (tb->page_addr[1] == phys_page2) goto found; } else { goto found; } } ptb1 = &tb->phys_hash_next; } not_found: /* if no translated code available, then translate it now */ tb = tb_alloc(pc); if (!tb) { /* flush must be done */ tb_flush(env); /* cannot fail at this point */ tb = tb_alloc(pc); /* don't forget to invalidate previous TB info */ tb_invalidated_flag = 1; } tc_ptr = code_gen_ptr; tb->tc_ptr = tc_ptr; tb->cs_base = cs_base; tb->flags = flags; cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size); code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); /* check next page if needed */ virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK; phys_page2 = -1; if ((pc & TARGET_PAGE_MASK) != virt_page2) { phys_page2 = get_phys_addr_code(env, virt_page2); } tb_link_phys(tb, phys_pc, phys_page2); found: /* we add the TB in the virtual pc hash table */ env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb; spin_unlock(&tb_lock); return tb; } static inline TranslationBlock *tb_find_fast(void) { TranslationBlock *tb; target_ulong cs_base, pc; unsigned int flags; /* we record a subset of the CPU state. It will always be the same before a given translated block is executed. */ #if defined(TARGET_I386) flags = env->hflags; flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK)); cs_base = env->segs[R_CS].base; pc = cs_base + env->eip; #elif defined(TARGET_ARM) flags = env->thumb | (env->vfp.vec_len << 1) | (env->vfp.vec_stride << 4); if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) flags |= (1 << 6); if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) flags |= (1 << 7); cs_base = 0; pc = env->regs[15]; #elif defined(TARGET_SPARC) #ifdef TARGET_SPARC64 // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2)) | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2); #else // FPU enable . MMU enabled . MMU no-fault . Supervisor flags = (env->psref << 3) | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1) | env->psrs; #endif cs_base = env->npc; pc = env->pc; #elif defined(TARGET_PPC) flags = (msr_pr << MSR_PR) | (msr_fp << MSR_FP) | (msr_se << MSR_SE) | (msr_le << MSR_LE); cs_base = 0; pc = env->nip; #elif defined(TARGET_MIPS) flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK); cs_base = 0; pc = env->PC; #elif defined(TARGET_SH4) flags = env->sr & (SR_MD | SR_RB); cs_base = 0; /* XXXXX */ pc = env->pc; #else #error unsupported CPU #endif tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)]; if (__builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base || tb->flags != flags, 0)) { tb = tb_find_slow(pc, cs_base, flags); /* Note: we do it here to avoid a gcc bug on Mac OS X when doing it in tb_find_slow */ if (tb_invalidated_flag) { /* as some TB could have been invalidated because of memory exceptions while generating the code, we must recompute the hash index here */ T0 = 0; } } return tb; } /* main execution loop */ int cpu_exec(CPUState *env1) { int saved_T0, saved_T1; #if defined(reg_T2) int saved_T2; #endif CPUState *saved_env; #if defined(TARGET_I386) #ifdef reg_EAX int saved_EAX; #endif #ifdef reg_ECX int saved_ECX; #endif #ifdef reg_EDX int saved_EDX; #endif #ifdef reg_EBX int saved_EBX; #endif #ifdef reg_ESP int saved_ESP; #endif #ifdef reg_EBP int saved_EBP; #endif #ifdef reg_ESI int saved_ESI; #endif #ifdef reg_EDI int saved_EDI; #endif #elif defined(TARGET_SPARC) #if defined(reg_REGWPTR) uint32_t *saved_regwptr; #endif #endif #if defined(__sparc__) && !defined(HOST_SOLARIS) int saved_i7, tmp_T0; #endif int ret, interrupt_request; void (*gen_func)(void); TranslationBlock *tb; uint8_t *tc_ptr; #if defined(TARGET_I386) /* handle exit of HALTED state */ if (env1->hflags & HF_HALTED_MASK) { /* disable halt condition */ if ((env1->interrupt_request & CPU_INTERRUPT_HARD) && (env1->eflags & IF_MASK)) { env1->hflags &= ~HF_HALTED_MASK; } else { return EXCP_HALTED; } } #elif defined(TARGET_PPC) if (env1->halted) { if (env1->msr[MSR_EE] && (env1->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER))) { env1->halted = 0; } else { return EXCP_HALTED; } } #elif defined(TARGET_SPARC) if (env1->halted) { if ((env1->interrupt_request & CPU_INTERRUPT_HARD) && (env1->psret != 0)) { env1->halted = 0; } else { return EXCP_HALTED; } } #elif defined(TARGET_ARM) if (env1->halted) { /* An interrupt wakes the CPU even if the I and F CPSR bits are set. */ if (env1->interrupt_request & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD)) { env1->halted = 0; } else { return EXCP_HALTED; } } #elif defi
#!/usr/bin/env python
#
# Helper tool to enable/disable OS X proxy and wrap mitmproxy
#
# Get usage information with:
#
# mitmproxywrapper.py -h
#

import subprocess
import re
import argparse
import contextlib
import os
import sys


class Wrapper(object):

    def __init__(self, port, extra_arguments=None):
        self.port = port
        self.extra_arguments = extra_arguments

    def run_networksetup_command(self, *arguments):
        return subprocess.check_output(
            ['sudo', 'networksetup'] + list(arguments))

    def proxy_state_for_service(self, service):
        state = self.run_networksetup_command(
            '-getwebproxy',
            service).splitlines()
        return dict([re.findall(r'([^:]+): (.*)', line)[0] for line in state])

    def enable_proxy_for_service(self, service):
        print('Enabling proxy on {}...'.format(service))
        for subcommand in ['-setwebproxy', '-setsecurewebproxy']:
            self.run_networksetup_command(
                subcommand, service, '127.0.0.1', str(
                    self.port))

    def disable_proxy_for_service(self, service):
        print('Disabling proxy on {}...'.format(service))
        for subcommand in ['-setwebproxystate', '-setsecurewebproxystate']:
            self.run_networksetup_command(subcommand, service, 'Off')

    def interface_name_to_service_name_map(self):
        order = self.run_networksetup_command('-listnetworkserviceorder')
        mapping = re.findall(
            r'\(\d+\)\s(.*)$\n\(.*Device: (.+)\)$',
            order,
            re.MULTILINE)
        return dict([(b, a) for (a, b) in mapping])

    def run_command_with_input(self, command, input):
        popen = subprocess.Popen(
            command,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE)
        (stdout, stderr) = popen.communicate(input)
        return stdout

    def primary_interace_name(self):
        scutil_script = 'get State:/Network/Global/IPv4\nd.show\n'
        stdout = self.run_command_with_input('/usr/sbin/scutil', scutil_script)
        interface, = re.findall(r'PrimaryInterface\s*:\s*(.+)', stdout)
        return interface

    def primary_service_name(self):
        return self.interface_name_to_service_name_map()[
            self.primary_interace_name()]

    def proxy_enabled_for_service(self, service):
        return self.proxy_state_for_service(service)['Enabled'] == 'Yes'

    def toggle_proxy(self):
        new_state = not self.proxy_enabled_for_service(
            self.primary_service_name())
        for service_name in self.connected_service_names():
            if self.proxy_enabled_for_service(service_name) and not new_state:
                self.disable_proxy_for_service(service_name)
            elif not self.proxy_enabled_for_service(service_name) and new_state:
                self.enable_proxy_for_service(service_name)

    def connected_service_names(self):
        scutil_script = 'list\n'
        stdout = self.run_command_with_input('/usr/sbin/scutil', scutil_script)
        service_ids = re.findall(r'State:/Network/Service/(.+)/IPv4', stdout)

        service_names = []
        for service_id in service_ids:
            scutil_script = 'show Setup:/Network/Service/{}\n'.format(
                service_id)
            stdout = self.run_command_with_input(
                '/usr/sbin/scutil',
                scutil_script)
            service_name, = re.findall(r'UserDefinedName\s*:\s*(.+)', stdout)
            service_names.append(service_name)

        return service_names

    def wrap_mitmproxy(self):
        with self.wrap_proxy():
            cmd = ['mitmproxy', '-p', str(self.port)]
            if self.extra_arguments:
                cmd.extend(self.extra_arguments)
            subprocess.check_call(cmd)

    def wrap_honeyproxy(self):
        with self.wrap_proxy():
            popen = subprocess.Popen('honeyproxy.sh')
            try:
                popen.wait()
            except KeyboardInterrupt:
                popen.terminate()

    @contextlib.contextmanager
    def wrap_proxy(self):
        connected_service_names = self.connected_service_names()
        for service_name in connected_service_names:
            if not self.proxy_enabled_for_service(service_name):
                self.enable_proxy_for_service(service_name)

        yield

        for service_name in connected_service_names:
            if self.proxy_enabled_for_service(service_name):
                self.disable_proxy_for_service(service_name)

    @classmethod
    def ensure_superuser(cls):
        if os.getuid() != 0:
            print('Relaunching with sudo...')
            os.execv('/usr/bin/sudo', ['/usr/bin/sudo'] + sys.argv)

    @classmethod
    def main(cls):
        parser = argparse.ArgumentParser(
            description='Helper tool for OS X proxy configuration and mitmproxy.',
            epilog='Any additional arguments will be passed on unchanged to mitmproxy.')
        parser.add_argument(
            '-t',
            '--toggle',
            action='store_true',
            help='just toggle the proxy configuration')
#         parser.add_argument('--honeyproxy', action='store_true', help='run honeyproxy instead of mitmproxy')
        parser.add_argument(
            '-p',
            '--port',
            type=int,
            help='override the default port of 8080',
            default=8080)
        args, extra_arguments = parser.parse_known_args()

        wrapper = cls(port=args.port, extra_arguments=extra_arguments)

        if args.toggle:
            wrapper.toggle_proxy()
#         elif args.honeyproxy:
#             wrapper.wrap_honeyproxy()
        else:
            wrapper.wrap_mitmproxy()


if __name__ == '__main__':
    Wrapper.ensure_superuser()
    Wrapper.main()
ess, is_write, *(unsigned long *)old_set); #endif /* XXX: locking issue */ if (is_write && page_unprotect(h2g(address), pc, puc)) { return 1; } /* see if it is an MMU fault */ ret = cpu_sh4_handle_mmu_fault(env, address, is_write, 1, 0); if (ret < 0) return 0; /* not an MMU fault */ if (ret == 0) return 1; /* the MMU fault was handled without causing real CPU fault */ /* now we have a real cpu fault */ tb = tb_find_pc(pc); if (tb) { /* the PC is inside the translated code. It means that we have a virtual CPU fault */ cpu_restore_state(tb, env, pc, puc); } #if 0 printf("PF exception: NIP=0x%08x error=0x%x %p\n", env->nip, env->error_code, tb); #endif /* we restore the process signal mask as the sigreturn should do it (XXX: use sigsetjmp) */ sigprocmask(SIG_SETMASK, old_set, NULL); cpu_loop_exit(); /* never comes here */ return 1; } #else #error unsupported target CPU #endif #if defined(__i386__) #if defined(USE_CODE_COPY) static void cpu_send_trap(unsigned long pc, int trap, struct ucontext *uc) { TranslationBlock *tb; if (cpu_single_env) env = cpu_single_env; /* XXX: find a correct solution for multithread */ /* now we have a real cpu fault */ tb = tb_find_pc(pc); if (tb) { /* the PC is inside the translated code. It means that we have a virtual CPU fault */ cpu_restore_state(tb, env, pc, uc); } sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL); raise_exception_err(trap, env->error_code); } #endif int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc) { struct ucontext *uc = puc; unsigned long pc; int trapno; #ifndef REG_EIP /* for glibc 2.1 */ #define REG_EIP EIP #define REG_ERR ERR #define REG_TRAPNO TRAPNO #endif pc = uc->uc_mcontext.gregs[REG_EIP]; trapno = uc->uc_mcontext.gregs[REG_TRAPNO]; #if defined(TARGET_I386) && defined(USE_CODE_COPY) if (trapno == 0x00 || trapno == 0x05) { /* send division by zero or bound exception */ cpu_send_trap(pc, trapno, uc); return 1; } else #endif return handle_cpu_signal(pc, (unsigned long)info->si_addr, trapno == 0xe ? (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0, &uc->uc_sigmask, puc); } #elif defined(__x86_64__) int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc) { struct ucontext *uc = puc; unsigned long pc; pc = uc->uc_mcontext.gregs[REG_RIP]; return handle_cpu_signal(pc, (unsigned long)info->si_addr, uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ? (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0, &uc->uc_sigmask, puc); } #elif defined(__powerpc__) /*********************************************************************** * signal context platform-specific definitions * From Wine */ #ifdef linux /* All Registers access - only for local access */ # define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name) /* Gpr Registers access */ # define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context) # define IAR_sig(context) REG_sig(nip, context) /* Program counter */ # define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */ # define CTR_sig(context) REG_sig(ctr, context) /* Count register */ # define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */ # define LR_sig(context) REG_sig(link, context) /* Link register */ # define CR_sig(context) REG_sig(ccr, context) /* Condition register */ /* Float Registers access */ # define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num]) # define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4))) /* Exception Registers access */ # define DAR_sig(context) REG_sig(dar, context) # define DSISR_sig(context) REG_sig(dsisr, context) # define TRAP_sig(context) REG_sig(trap, context) #endif /* linux */ #ifdef __APPLE__ # include typedef struct ucontext SIGCONTEXT; /* All Registers access - only for local access */ # define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name) # define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name) # define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name) # define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name) /* Gpr Registers access */ # define GPR_sig(reg_num, context) REG_sig(r##reg_num, context) # define IAR_sig(context) REG_sig(srr0, context) /* Program counter */ # define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */ # define CTR_sig(context) REG_sig(ctr, context) # define XER_sig(context) REG_sig(xer, context) /* Link register */ # define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */ # define CR_sig(context) REG_sig(cr, context) /* Condition register */ /* Float Registers access */ # define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context) # define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context)) /* Exception Registers access */ # define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */ # define DSISR_sig(context) EXCEPREG_sig(dsisr, context) # define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */ #endif /* __APPLE__ */ int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc) { struct ucontext *uc = puc; unsigned long pc; int is_write; pc = IAR_sig(uc); is_write = 0; #if 0 /* ppc 4xx case */ if (DSISR_sig(uc) & 0x00800000) is_write = 1; #else if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000)) is_write = 1; #endif return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, &uc->uc_sigmask, puc); } #elif defined(__alpha__) int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc) { struct ucontext *uc = puc; uint32_t *pc = uc->uc_mcontext.sc_pc; uint32_t insn = *pc; int is_write = 0; /* XXX: need kernel patch to get write flag faster */ switch (insn >> 26) { case 0x0d: // stw case 0x0e: // stb case 0x0f: // stq_u case 0x24: // stf case 0x25: // stg case 0x26: // sts case 0x27: // stt case 0x2c: // stl case 0x2d: // stq case 0x2e: // stl_c case 0x2f: // stq_c is_write = 1; } return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, &uc->uc_sigmask, puc); } #elif defined(__sparc__) int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc) { uint32_t *regs = (uint32_t *)(info + 1); void *sigmask = (regs + 20); unsigned long pc; int is_write; uint32_t insn; /* XXX: is there a standard glibc define ? */ pc = regs[1]; /* XXX: need kernel patch to get write flag faster */ is_write = 0; insn = *(uint32_t *)pc; if ((insn >> 30) == 3) { switch((insn >> 19) & 0x3f) { case 0x05: // stb case 0x06: // sth case 0x04: // st case 0x07: // std case 0x24: // stf case 0x27: // stdf case 0x25: // stfsr is_write = 1; break; } } return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, sigmask, NULL); } #elif defined(__arm__) int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc) { struct ucontext *uc = puc; unsigned long pc; int is_write; pc = uc->uc_mcontext.gregs[R15]; /* XXX: compute is_write */ is_write = 0; return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, &uc->uc_sigmask); } #elif defined(__mc68000) int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc) { struct ucontext *uc = puc; unsigned long pc; int is_write; pc = uc->uc_mcontext.gregs[16]; /* XXX: compute is_write */ is_write = 0; return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, &uc->uc_sigmask, puc); } #elif defined(__ia64) #ifndef __ISR_VALID /* This ought to be in ... */ # define __ISR_VALID 1 #endif int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc) { struct ucontext *uc = puc; unsigned long ip; int is_write = 0; ip = uc->uc_mcontext.sc_ip; switch (host_signum) { case SIGILL: case SIGFPE: case SIGSEGV: case SIGBUS: case SIGTRAP: if (info->si_code && (info->si_segvflags & __ISR_VALID)) /* ISR.W (write-access) is bit 33: */ is_write = (info->si_isr >> 33) & 1; break; default: break; } return handle_cpu_signal(ip, (unsigned long)info->si_addr, is_write, &uc->uc_sigmask, puc); } #elif defined(__s390__) int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc) { struct ucontext *uc = puc; unsigned long pc; int is_write; pc = uc->uc_mcontext.psw.addr; /* XXX: compute is_write */ is_write = 0; return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, &uc->uc_sigmask, puc); } #else #error host CPU specific signal handler needed #endif #endif /* !defined(CONFIG_SOFTMMU) */