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()
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)
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)
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"))
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)
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"))
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)
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 )
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)
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 )
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()