diff --git a/common.py b/common.py index 730ff16..635556c 100644 --- a/common.py +++ b/common.py @@ -939,19 +939,18 @@ Incompatible archs are skipped. env['qcow2_file'] = env['buildroot_qcow2_file'] # Image - if env['_args_given']['baremetal']: + if env['baremetal'] is not None: env['disk_image'] = env['gem5_fake_iso'] - path = self.resolve_baremetal_executable(env['baremetal']) + env['image'] = self.resolve_baremetal_executable(env['baremetal']) source_path_noext = os.path.splitext(join( env['root_dir'], - os.path.relpath(path, env['baremetal_build_dir']) + os.path.relpath(env['image'], env['baremetal_build_dir']) ))[0] - for ext in [env['c_ext'], env['asm_ext']]: + for ext in env['baremetal_build_in_exts']: source_path = source_path_noext + ext if os.path.exists(source_path): env['source_path'] = source_path break - env['image'] = path elif env['userland'] is not None: env['image'] = self.resolve_userland_executable(env['userland']) else: @@ -1688,6 +1687,15 @@ class TestCliFunction(LkmcCliFunction): Automates test reporting boilerplate for those commands. ''' + base_run_args = { + 'background': True, + 'ctrl_c_host': True, + 'print_cmd_oneline': True, + 'show_cmds': False, + 'show_stdout': False, + 'show_time': False, + } + def __init__(self, *args, **kwargs): defaults = { 'quit_on_fail': False, @@ -1739,14 +1747,9 @@ class TestCliFunction(LkmcCliFunction): ''' if run_obj.is_arch_supported(run_args['archs'][0]): cur_run_args = { - 'background': True, - 'ctrl_c_host': True, - 'print_cmd_oneline': True, 'run_id': thread_id, - 'show_cmds': False, - 'show_stdout': False, - 'show_time': False, } + cur_run_args.update(self.base_run_args) if run_args is not None: cur_run_args.update(run_args) test_id_string = self.test_setup(run_args, test_id) diff --git a/run-gdb b/run-gdb index ce424d5..e7d601e 100755 --- a/run-gdb +++ b/run-gdb @@ -5,9 +5,10 @@ import signal import subprocess import sys +from shell_helpers import LF import common import lkmc.import_path -from shell_helpers import LF +import thread_pool class GdbTestcase: def __init__( @@ -38,12 +39,11 @@ class GdbTestcase: exception = None try: test.test(self) - except AssertionError as e: + except Exception as e: exception = e self.child.sendcontrol('d') self.child.close() - if exception is not None: - raise exception + self.exception = exception def before(self): return self.child.before.rstrip() @@ -83,48 +83,53 @@ class Main(common.LkmcCliFunction): Connect with GDB to an emulator to debug Linux itself ''') self.add_argument( - '--after', default='', + '--after', + default='', help='Pass extra arguments to GDB, to be appended after all other arguments' ) self.add_argument( - '--before', default='', + '--before', + default='', help='Pass extra arguments to GDB to be prepended before any of the arguments passed by this script' ) self.add_argument( - 'break_at', nargs='?', - help='Extra options to append at the end of the emulator command line' - ) - self.add_argument( - '-k', '--kgdb', default=False, - ) - self.add_argument( - '-C', '--no-continue', default=False, + '--continue', + default=True, help="Don't run continue after connecting" ) self.add_argument( - '-X', '--no-lxsymbols', default=False, + '--kgdb', + default=False, ) self.add_argument( - '--test', default=False, + '--lxsymbols', + default=True, + ) + self.add_argument( + '--sim', + default=False, + help='''Use the built-in GDB CPU simulator +See: https://github.com/cirosantilli/linux-kernel-module-cheat#gdb-builtin-cpu-simulator +''' + ) + self.add_argument( + '--test', + default=False, help='''\ Run an expect test case instead of interactive usage. For baremetal and userland, the script is a .py file next to the source code. ''' ) self.add_argument( - '--sim', default=False, - help='''Use the built-in GDB CPU simulator -See: https://github.com/cirosantilli/linux-kernel-module-cheat#gdb-builtin-cpu-simulator -''' - ) - self.add_argument( - '-u', '--userland', + 'break_at', + nargs='?', + help='Extra options to append at the end of the emulator command line' ) def timed_main(self): after = self.sh.shlex_split(self.env['after']) before = self.sh.shlex_split(self.env['before']) - no_continue = self.env['no_continue'] + no_continue = not self.env['continue'] if self.env['test']: no_continue = True before.extend([ @@ -149,7 +154,6 @@ See: https://github.com/cirosantilli/linux-kernel-module-cheat#gdb-builtin-cpu-s image = self.env['image'] elif self.env['baremetal']: image = self.env['image'] - test_script_path = os.path.splitext(self.env['source_path'])[0] + '.py' else: image = self.env['vmlinux'] cmd = ( @@ -193,18 +197,24 @@ See: https://github.com/cirosantilli/linux-kernel-module-cheat#gdb-builtin-cpu-s # The lx-symbols commands gets loaded through the file vmlinux-gdb.py # which gets put on the kernel build root when python debugging scripts are enabled. cmd.extend(['-ex', 'continue', LF]) - if not self.env['no_lxsymbols'] and linux_full_system: + if self.env['lxsymbols'] and linux_full_system: cmd.extend(['-ex', 'lx-symbols {}'.format(self.env['kernel_modules_build_subdir']), LF]) cmd.extend(after) if self.env['test']: self.sh.print_cmd(cmd) if not self.env['dry_run']: - GdbTestcase( + exception = GdbTestcase( self.env['source_path'], - test_script_path, + os.path.splitext(self.env['source_path'])[0] + '.py', self.sh.strip_newlines(cmd), verbose=self.env['verbose'], - ) + ).exception + if exception is None: + exit_status = 0 + else: + exit_status = 1 + self.log_info(thread_pool.ThreadPool.exception_traceback_string(exception)) + return exit_status else: # I would rather have cwd be out_rootfs_overlay_dir, # but then lx-symbols cannot fine the vmlinux and fails with: diff --git a/test-gdb b/test-gdb index 75b4470..eb9dabc 100755 --- a/test-gdb +++ b/test-gdb @@ -34,8 +34,6 @@ found by searching for the Python test files. ) def timed_main(self): - run = lkmc.import_path.import_path_main('run') - run_gdb = lkmc.import_path.import_path_main('run-gdb') rootdir_abs_len = len(self.env['root_dir']) for test in self.env['tests']: for path, in_dirnames, in_filenames in self.sh.walk(test): @@ -48,19 +46,21 @@ found by searching for the Python test files. if ext in self.env['baremetal_build_in_exts'] and os.path.exists(path_relative_root_base + '.py'): my_path_properties = path_properties.get(path_relative_root) if my_path_properties.should_be_tested(self.env, is_baremetal=True): + run = lkmc.import_path.import_path_main('run') + run_gdb = lkmc.import_path.import_path_main('run-gdb') common_args = self.get_common_args() common_args['baremetal'] = path_relative_root run_args = common_args.copy() run_args['gdb_wait'] = True - run_args['background'] = True + run_args.update(self.base_run_args) test_id_string = self.test_setup(run_args, path_relative_root) run_thread = threading.Thread(target=lambda: run(**run_args)) run_thread.start() gdb_args = common_args.copy() gdb_args['test'] = True - run_gdb(**gdb_args) + exit_status = run_gdb(**gdb_args) run_thread.join() - self.test_teardown(run, 0, test_id_string) + self.test_teardown(run, exit_status, test_id_string) if __name__ == '__main__': Main().cli()