import copy
import traceback
import os
import sys
import time
import subprocess
import logging


logger = logging.getLogger("QEMU")

count = 0

subproc = None
stats = None
_arch = None

def get_lines(n=1):
    lines = []
    str_buffer = ''
    received_lines = 0
    while received_lines < n:
        c = subproc.stdout.read(1)
        str_buffer += c
        if c == '\n':
            lines.append(str_buffer)
            str_buffer = ''
            received_lines += 1

    return lines

def parse_mmu_debug_output(s):
    d = {}

    # Get guest address space
    d['reserved'] = int(s.pop(0).split()[1], 0)
    d['host_mmap_min_addr'] = int(s.pop(0).split('=')[1], 0)
    d['guest_base'] = int(s.pop(0).split()[1], 0)

    # get rid of mapping heading
    s.pop(0)
    d['maps'] = []
    
    while '-' in s[0]:
        line = s.pop(0)
        range, size, protections = line.split()
        start, end = range.split('-')
        d['maps'].append((int(start, 16),
                          int(end, 16),
                          int(size, 16),
                          protections))

    while s:
        line = s.pop(0)
        if not line:
            continue
        var, addr = line.split()
        d[var] = int(addr, 0)

    return d


def start(arch, argv, port=1234, va_size=0xc0000000, stack_size=0x20000):
    global subproc, stats
    aslr_file = '/proc/sys/kernel/randomize_va_space'
    try:
        with open(aslr_file, 'r') as f:
            if f.read().strip() != '0':
                logger.warning("Disable ASLR before running qemu-user")
                logger.warning("  sudo sh -c 'echo 0 > %s'", aslr_file)
    finally:
        pass
                    
    args = ['qemu-%s'%(arch,), '-g', port, '-d', 'mmu', '-R', va_size, '-s', stack_size] + argv
    args = map(str, args)
    print("Running: %s"%(' '.join(args),))
    subproc = subprocess.Popen(args, stdin=subprocess.PIPE,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.STDOUT)
    mmu_debug_output = get_lines(16)

    stats = parse_mmu_debug_output(mmu_debug_output)
    for m in stats['maps']:
        start,  end, size, perms = m
        print '{:x}-{:x}, {}, {}'.format(*m)

def correspond(text):
    """Communicate with the child process without closing stdin."""
    if text:
        subproc.stdin.write(text)
    subproc.stdin.flush()
    return get_lines()
