#!/usr/bin/python
#
# Test remote kernel debugging using qemu built-in gdb stub.
# Requires a build with kernel debug symbols.
#

from __future__ import print_function

import os
import anita
import pexpect
import socket # gethostname

from bracket import *

name = 'kgdb_remote'

def test_func(ts):
    target_slogfn = os.path.join(results_dir(ts), name + "_target.slog")
    gdb_slogfn = os.path.join(results_dir(ts), name + "_gdb.slog")

    dist = anita.distribution(anita_dist_url(ts))
    # vmm_args = ['--no-kvm']
    vmm_args = []

    print("booting target VM")
    # Note that we need to increase memory from the default of 32M,
    # or the system will run out of swap while running the RC scripts
    anita_target = anita.Anita(dist,
                               memory_size = '128M',
                               vmm_args = vmm_args + ['-gdb', 'tcp::1234'],
                               workdir = anita_workdir(ts),
                               structured_log_file = target_slogfn)
    child_target = anita_target.boot()

    print("booting gdb VM")
    # Note that we need to increase memory from the default of 32M, or gdb will
    # take ages reading the symbols from /netbsd.
    anita_gdb = anita.Anita(dist,
                            memory_size = '256M',
                            vmm_args = vmm_args,
                            workdir = anita_workdir(ts),
                            structured_log_file = gdb_slogfn)
    anita_gdb.boot()
    anita_gdb.shell_cmd('dhcpcd -w')
    # To debug dhcpcd issue
    anita_gdb.shell_cmd('cat /etc/resolv.conf')
    anita_gdb.shell_cmd('sleep 30')
    anita_gdb.shell_cmd('cat /etc/resolv.conf')

    # If there is a /netbsd.gdb, use it instead of /netbsd
    kernel =  ['/netbsd', '/netbsd.gdb'] \
        [anita_gdb.shell_cmd('test -f /netbsd.gdb') == 0]
    print("using kernel", kernel)

    anita_gdb.child.send("gdb %s\r" % kernel)
    anita_gdb.child.expect("\(gdb\)")
    anita_gdb.child.send("target remote %s:1234\r" % socket.gethostname())
    anita_gdb.child.expect("\(gdb\)")
    anita_gdb.child.send("bt\r")
    try:
        anita_gdb.child.expect(" in ") # e.g., "#0  0xc010d1c0 in mutex_spin_exit ()"
        # Collect the rest of the backtrace for display
        anita.gather_input(anita_gdb.child, 10)
    except pexpect.TIMEOUT:
        return False
    return True

def op():
    return TestOp(test_func, [install_op], name = name)
