Beispiel #1
0
def target_tests_run(tests_queue, port_queue, res_queue, is_finish, reuse,
                     verbose):
    qemu = None
    session = None
    qmp_port = None
    qmp = None
    while True:
        try:
            test_src, test_elf = tests_queue.get(timeout=0.1)
        except Empty:
            if is_finish.value:
                if reuse and qemu and session:
                    session.kill()
                    qemu.join()
                    session.port_close()
                res_queue.put(("target", None, "TEST_EXIT"))
                break
            continue
        else:
            if reuse and session and qmp:
                qmp("stop")
                qmp("system_reset")
                session.reset(test_src, test_elf)
            else:
                qemu_port = port_queue.get(block=True)
                if (not c2t_cfg.rsp_target.user
                        and (reuse or c2t_cfg.rsp_target.qemu_reset)):
                    qmp_port = port_queue.get(block=True)

                qemu = run_qemu(test_elf, qemu_port, qmp_port, verbose)

                if not wait_for_tcp_port(qemu_port):
                    c2t_exit("qemu malfunction")

                if qmp_port and wait_for_tcp_port(qmp_port):
                    qmp = QMP(qmp_port)

                session = TargetSession(c2t_cfg.rsp_target.rsp, test_src,
                                        str(qemu_port), test_elf, res_queue,
                                        verbose)

            if qmp and c2t_cfg.rsp_target.qemu_reset:
                # TODO: use future 'entry' feature
                session.rt.target[4] = pack(
                    "<I",
                    session.rt.dic.symtab.get_symbol_by_name("main")
                    [0].entry.st_value)
                qmp("system_reset")

            res_queue.put((session.session_type, test_src, "TEST_RUN"))

            session.run()

            res_queue.put((session.session_type, test_src, "TEST_END"))

            if not reuse:
                session.kill()
                qemu.join()
                session.port_close()
Beispiel #2
0
    def setUp(self):
        try:
            rsp = archmap[machine()]
        except KeyError:
            self.skipTest("No RSP target for " + machine())
            return

        # Passing function arguments through registers
        self._arg2reg = {
            "i386": ("ecx", "edx")  # fastcall calling convention is assumed
            ,
            "x86_64": ("rdi", "rsi"),
            "arm": ("r0", "r1")
        }.get(machine(), None)

        LDFLAGS = " ".join(("-l" + l) for l in self.LIBS)
        CFLAGS = " ".join("-D%s=%s" % (D, V) for D, V in self.DEFS.items())
        self.assertEqual(
            run("gcc", "-no-pie", "-o", self.EXE, "-g", "-O0", CFLAGS,
                self.SRC, LDFLAGS), 0)
        rsp_port = find_free_port()
        if rsp_port is None:
            raise RuntimeError("Cannot find free port!")
        self._port = port = str(rsp_port)
        self._gdb = gdb = Popen(["gdbserver", "localhost:" + port, self.EXE])

        # Wait for gdb to start listening.
        if not wait_for_tcp_port(rsp_port) or gdb.returncode is not None:
            raise RuntimeError("gdbserver malfunction")

        self._target = rsp(self._port,
                           elffile=self.EXE,
                           verbose=True,
                           noack=self.noack,
                           noshell=True)
Beispiel #3
0
def co_update_device_tree(qemu_exec, src_path, arch_name, root):
    dic = create_dwarf_cache(qemu_exec)

    gvl_adptr = GitLineVersionAdapter(src_path)

    qomtr = QOMTreeReverser(dic,
                            interrupt=True,
                            verbose=True,
                            line_adapter=gvl_adptr)

    port = find_free_port(4321)
    qemu_debug_addr = "localhost:%u" % port
    Popen(["gdbserver", qemu_debug_addr, qemu_exec])

    if not wait_for_tcp_port(port):
        raise RuntimeError("gdbserver does not listen %u" % port)

    yield True

    qemu_debugger = AMD64(str(port), noack=True)
    rt = Runtime(qemu_debugger, dic)

    qomtr.init_runtime(rt)

    yield rt.co_run_target()

    device_subtree = qomtr.tree.name2type.get("device", None)

    if device_subtree is None:
        raise RuntimeError(
            'No "device" QOM subtree. Did you forget to pass ' +
            '"--extra-cflags=-no-pie" and/or "--disable-pie" to `configure`?')

    yield co_fill_children(device_subtree, root, arch_name)
Beispiel #4
0
def oracle_tests_run(tests_queue, port_queue, res_queue, verbose):
    while True:
        test_src, test_elf = tests_queue.get(block=True)

        gdbserver_port = port_queue.get(block=True)

        gdbserver = ProcessWithErrCatching(
            c2t_cfg.gdbserver.run_script.format(port=gdbserver_port,
                                                bin=test_elf,
                                                c2t_dir=C2T_DIR,
                                                test_dir=C2T_TEST_DIR))
        gdbserver.daemon = True
        gdbserver.start()

        if not wait_for_tcp_port(gdbserver_port):
            c2t_exit("gdbserver malfunction")

        session = OracleSession(archmap[ORACLE_CPU], test_src,
                                str(gdbserver_port), test_elf, res_queue,
                                verbose)
        session.run()

        res_queue.put((session.session_type, test_src, "TEST_END"))

        session.kill()
        gdbserver.join()
        session.port_close()

        if tests_queue.empty():
            break

    res_queue.put((session.session_type, None, "TEST_EXIT"))
Beispiel #5
0
    def __start_gdb__(self, rsp_port):
        qmp_port = find_free_port(rsp_port + 1)
        if qmp_port is None:
            raise RuntimeError("Cannot find free port for Qemu QMP!")

        qargs = [
            "qemu-system-arm",
            "-machine",
            "netduino2",
            "-kernel",
            self.EXE,
            "-S",  # guest is initially stopped
            "-gdb",
            "tcp:localhost:%u" % rsp_port,
            # QEMU monitor protocol for VM management
            "-qmp",
            "tcp:localhost:%u,server,nowait" % qmp_port,
            # do not create a window
            "-nographic"
        ]
        print(" ".join(qargs))
        self._gdb = qemu = Popen(qargs)

        if not wait_for_tcp_port(qmp_port) or qemu.returncode is not None:
            raise RuntimeError("QEMU malfunction")

        self.qmp = QMP(qmp_port)
Beispiel #6
0
def target_tests_run_nonkill(tests_queue, port_queue, res_queue, verbose):
    test_src, test_elf = tests_queue.get(block=True)

    qemu_port = port_queue.get(block=True)
    qmp_port = port_queue.get(block=True)

    qemu = run_qemu(test_elf, qemu_port, qmp_port, verbose)

    if (not wait_for_tcp_port(qemu_port) and not wait_for_tcp_port(qmp_port)):
        c2t_exit("qemu malfunction")

    qmp = QMP(qmp_port)

    session = TargetSession(c2t_cfg.rsp_target.rsp, test_src, str(qemu_port),
                            test_elf, res_queue, verbose)

    while True:
        if c2t_cfg.rsp_target.qemu_reset:
            # TODO: use future 'entry' feature
            session.rt.target[4] = pack(
                "<I",
                session.rt.dic.symtab.get_symbol_by_name("main")
                [0].entry.st_value)
            qmp("system_reset")

        session.run()

        res_queue.put((session.session_type, test_src, "TEST_END"))

        if tests_queue.empty():
            break

        test_src, test_elf = tests_queue.get(block=True)

        qmp("stop")
        qmp("system_reset")

        session.reset(test_src, test_elf)

    session.kill()
    qemu.join()
    session.port_close()
    res_queue.put((session.session_type, None, "TEST_EXIT"))
Beispiel #7
0
    def setUp(self):
        self.example_dir = join(parent_dir, "example")
        self.elf_path = join(self.example_dir, "test.elf")

        self.assertEqual(run("make", cwd=self.example_dir), 0)
        rsp_port = find_free_port()
        qmp_port = find_free_port(rsp_port + 1)
        if (rsp_port or qmp_port) is None:
            raise RuntimeError("Cannot find free port!")
        self._port = str(rsp_port)
        qargs = [
            "qemu-system-arm",
            "-machine",
            "netduino2",
            "-kernel",
            self.elf_path,
            "-S",  # guest is initially stopped
            "-gdb",
            "tcp:localhost:" + self._port,
            # QEMU monitor protocol for VM management
            "-qmp",
            "tcp:localhost:%u,server,nowait" % qmp_port,
            # do not create a window
            "-nographic"
        ]
        print(" ".join(qargs))
        self._qemu = qemu = Popen(qargs)

        if (not wait_for_tcp_port(qmp_port) or not wait_for_tcp_port(rsp_port)
                or qemu.returncode is not None):
            raise RuntimeError("QEMU malfunction")

        self.qmp = QMP(qmp_port)

        self._target = CortexM3(self._port,
                                elffile=self.elf_path,
                                verbose=True,
                                noack=self.noack)
Beispiel #8
0
    def setUp(self):
        self.example_dir = join(parent_dir, "example")
        self.elf_path = join(self.example_dir, "test.elf")

        self.assertEqual(run("make", cwd = self.example_dir), 0)
        rsp_port = find_free_port()
        qmp_port = find_free_port(rsp_port + 1)
        if (rsp_port or qmp_port) is None:
            raise RuntimeError("Cannot find free port!")
        self._port = str(rsp_port)
        qargs = [
            "qemu-system-arm",
            "-machine", "netduino2",
            "-kernel", self.elf_path,
            "-S", # guest is initially stopped
            "-gdb", "tcp:localhost:" + self._port,
            # QEMU monitor protocol for VM management
            "-qmp", "tcp:localhost:%u,server,nowait" % qmp_port,
            # do not create a window
            "-nographic"
        ]
        print(" ".join(qargs))
        self._qemu = qemu = Popen(qargs)

        if (not wait_for_tcp_port(qmp_port)
            or not wait_for_tcp_port(rsp_port)
            or qemu.returncode is not None
        ):
            raise RuntimeError("QEMU malfunction")

        self.qmp = QMP(qmp_port)

        self._target = CortexM3(self._port,
            elffile = self.elf_path,
            verbose = True,
            noack = self.noack
        )
Beispiel #9
0
    def setUp(self):
        try:
            rsp = archmap[self.arch]
        except KeyError:
            self.skipTest("No RSP target for " + machine())
            return

        rsp_port = find_free_port()
        if rsp_port is None:
            raise RuntimeError("Cannot find free port!")

        self.__build__()
        self.__start_gdb__(rsp_port)

        # Wait for server to start listening.
        if not wait_for_tcp_port(rsp_port) or self._gdb.returncode is not None:
            raise RuntimeError("server malfunction")

        self._target = rsp(str(rsp_port),
                           elffile=self.EXE,
                           verbose=True,
                           noack=self.noack,
                           noshell=True)
Beispiel #10
0
    def setUp(self):
        try:
            rsp = archmap[machine()]
        except KeyError:
            self.skipTest("No RSP target for " + machine())
            return

        # Passing function arguments through registers
        self._arg2reg = {
            "i386" : ("ecx", "edx") # fastcall calling convention is assumed
          , "x86_64" : ("rdi", "rsi")
          , "arm" : ("r0", "r1")
        }.get(machine(), None)

        LDFLAGS = " ".join(("-l" + l) for l in self.LIBS)
        CFLAGS = " ".join("-D%s=%s" % (D, V) for D, V in self.DEFS.items())
        self.assertEqual(
            run("gcc", "-no-pie", "-o", self.EXE, "-g", "-O0", CFLAGS, self.SRC, LDFLAGS),
            0
        )
        rsp_port = find_free_port()
        if rsp_port is None:
            raise RuntimeError("Cannot find free port!")
        self._port = port = str(rsp_port)
        self._gdb = gdb = Popen(["gdbserver", "localhost:" + port, self.EXE])

        # Wait for gdb to start listening.
        if not wait_for_tcp_port(rsp_port) or gdb.returncode is not None:
            raise RuntimeError("gdbserver malfunction")

        self._target = rsp(self._port,
            elffile = self.EXE,
            verbose = True,
            noack = self.noack,
            noshell = True
        )
Beispiel #11
0
def main():
    ap = QArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter,
                         description="QEMU runtime introspection tool")
    ap.add_argument("-q", dest="qsrc", help="QEMU src directory.")
    ap.add_argument(
        "-c",
        "--connect",
        nargs="?",
        metavar="HOST",
        const="127.0.0.1",  # default if `-c` is given without a value
        # Suppress reasons:
        # 1. do not print incorrect default in help by
        #    `ArgumentDefaultsHelpFormatter` (correct is `const`)
        # 2. do not add the attribute to parsed args if the arg is missed
        default=SUPPRESS,
        help="connect to existing gdbstub (default: %(const)s)")
    ap.add_argument("-p",
                    "--port",
                    type=int,
                    metavar="PORT",
                    default=4321,
                    help="start search for unused port from this number")
    ap.add_argument(
        "qarg",
        nargs="+",
        help="QEMU executable and arguments to it. Prefix them with `--`.")
    args = ap.parse_args()

    # executable
    qemu_cmd_args = args.qarg

    # src directory
    qemu_src_dir = args.qsrc

    # debug info
    qemu_debug = qemu_cmd_args[0]

    elf = InMemoryELFFile(qemu_debug)
    if not elf.has_dwarf_info():
        stderr("%s does not have DWARF info. Provide a debug QEMU build\n" %
               (qemu_debug))
        return -1

    di = elf.get_dwarf_info()

    if not di.debug_pubnames_sec:
        print("%s does not contain .debug_pubtypes section. Provide"
              " -gpubnames flag to the compiler" % qemu_debug)

    dic = DWARFInfoCache(di, symtab=elf.get_section_by_name(".symtab"))

    if qemu_src_dir:
        gvl_adptr = GitLineVersionAdapter(qemu_src_dir)
    else:
        gvl_adptr = None

    qomtr = QOMTreeReverser(dic,
                            interrupt=False,
                            verbose=True,
                            line_adapter=gvl_adptr)

    if "-i386" in qemu_debug or "-x86_64" in qemu_debug:
        MWClass = PCMachineWatcher
    else:
        MWClass = MachineWatcher

    mw = MWClass(dic, qomtr.tree, interrupt=True, line_adapter=gvl_adptr)

    proj = GUIProject()
    pht = GUIProjectHistoryTracker(proj, proj.history)

    MachineReverser(mw, pht)

    try:
        qemu_debug_addr_fmt = args.connect + ":%u"
    except AttributeError:  # no -c/--connect option
        # auto select free port for gdb-server
        port = find_free_port(args.port)

        qemu_debug_addr = "localhost:%u" % port

        qemu_proc = Popen(["gdbserver", qemu_debug_addr] + qemu_cmd_args)
    else:
        port = args.port
        qemu_debug_addr = qemu_debug_addr_fmt % port
        qemu_proc = None

    if not wait_for_tcp_port(port):
        raise RuntimeError("gdbserver does not listen %u" % port)

    qemu_debugger = AMD64(str(port), noack=True)

    rt = Runtime(qemu_debugger, dic)

    qomtr.init_runtime(rt)
    mw.init_runtime(rt)

    # Because pyrsp (with machine reconstruction suite) works in a separate
    # thread, tracker's "changed" notifications are racing with GUI. So, GUI
    # must not watch those notifications. To maintain GUI consistency
    # other project and tracker are created with same history. The GUI is
    # watching this second tracker. A special coroutine working in GUI thread
    # will poll first (master) tracker position and adjust second (slave)
    # tracker updating the GUI without races.
    proj2 = GUIProject()
    # different context (project) but same history
    slave_pht = GUIProjectHistoryTracker(proj2, proj.history)

    def co_syncronizer():
        while True:
            if slave_pht.pos != pht.pos:
                yield True
                slave_pht.do()
            else:
                yield False

    tk = QEmuWatcherGUI(slave_pht, rt)

    tk.task_manager.enqueue(co_syncronizer())

    tk.geometry("1024x1024")
    tk.mainloop()

    qomtr.to_file("qom-by-q.i.dot")

    if qemu_proc is not None:
        qemu_proc.wait()

    if gvl_adptr is not None:
        gvl_adptr.cm.store_cache()