mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-26 11:41:35 +01:00
run kind of runs
This commit is contained in:
15
README.adoc
15
README.adoc
@@ -960,7 +960,7 @@ This automatically clears the GDB pane, and starts a new one.
|
||||
Pass extra GDB arguments with:
|
||||
|
||||
....
|
||||
./run --wait-gdb --tmux=start_kernel
|
||||
./run --wait-gdb --tmux --tmux-args start_kernel
|
||||
....
|
||||
|
||||
See the tmux manual for further details:
|
||||
@@ -2986,7 +2986,8 @@ Or alternatively, if you are using <<tmux>>, do everything in one go with:
|
||||
./run \
|
||||
--arch aarch64 \
|
||||
--userland print_argv \
|
||||
--tmux=main \
|
||||
--tmux \
|
||||
--tmux-args main \
|
||||
--wait-gdb \
|
||||
-- \
|
||||
asdf qwer \
|
||||
@@ -5056,7 +5057,7 @@ If `CONFIG_KALLSYMS=n`, then addresses are shown on traces instead of symbol plu
|
||||
In v4.16 it does not seem possible to configure that at runtime. GDB step debugging with:
|
||||
|
||||
....
|
||||
./run --eval-after 'insmod /dump_stack.ko' --wait-gdb --tmux=dump_stack
|
||||
./run --eval-after 'insmod /dump_stack.ko' --wait-gdb --tmux --tmux-args dump_stack
|
||||
....
|
||||
|
||||
shows that traces are printed at `arch/x86/kernel/dumpstack.c`:
|
||||
@@ -8168,7 +8169,7 @@ And in QEMU:
|
||||
Or for a faster development loop:
|
||||
|
||||
....
|
||||
./run --debug-vm='-ex "break edu_mmio_read" -ex "run"'
|
||||
./run --debug-vm --debug-vm-args '-ex "break edu_mmio_read" -ex "run"'
|
||||
....
|
||||
|
||||
When in <<qemu-text-mode>>, using `--debug-vm` makes Ctrl-C not get passed to the QEMU guest anymore: it is instead captured by GDB itself, so allow breaking. So e.g. you won't be able to easily quit from a guest program like:
|
||||
@@ -10259,13 +10260,13 @@ then on the second shell:
|
||||
Or if you are a <<tmux,tmux pro>>, do everything in one go with:
|
||||
|
||||
....
|
||||
./run --arch arm --baremetal interactive/prompt --wait-gdb --tmux=main
|
||||
./run --arch arm --baremetal interactive/prompt --wait-gdb --tmux --tmux-args main
|
||||
....
|
||||
|
||||
Alternatively, to start from the very first executed instruction of our tiny <<baremetal-bootloaders>>:
|
||||
|
||||
....
|
||||
./run --arch arm --baremetal interactive/prompt --wait-gdb --tmux=--no-continue
|
||||
./run --arch arm --baremetal interactive/prompt --wait-gdb --tmux --tmux-args --no-continue
|
||||
....
|
||||
|
||||
Now you can just `stepi` to when jumping into main to go to the C code in link:baremetal/interactive/prompt.c[].
|
||||
@@ -10273,7 +10274,7 @@ Now you can just `stepi` to when jumping into main to go to the C code in link:b
|
||||
This is specially interesting for the executables that don't use the bootloader from under `baremetal/arch/<arch>/no_bootloader/*.S`, e.g.:
|
||||
|
||||
....
|
||||
./run --arch arm --baremetal arch/arm/no_bootloader/semihost_exit --wait-gdb --tmux=--no-continue
|
||||
./run --arch arm --baremetal arch/arm/no_bootloader/semihost_exit --wait-gdb --tmux --tmux-args --no-continue
|
||||
....
|
||||
|
||||
The cool thing about those examples is that you start at the very first instruction of your program, which gives more control.
|
||||
|
||||
@@ -9,7 +9,7 @@ import common
|
||||
build_linux = imp.load_source('build-linux', os.path.join(kwargs['root_dir'], 'build_linux'))
|
||||
run = imp.load_source('run', os.path.join(kwargs['root_dir'], 'run'))
|
||||
|
||||
parser = common.get_argparse(
|
||||
parser = self.get_argparse(
|
||||
argparse_args={
|
||||
'description': '''Bisect the Linux kernel on gem5 boots.
|
||||
|
||||
@@ -20,11 +20,11 @@ More information at: https://github.com/cirosantilli/linux-kernel-module-cheat#b
|
||||
'linux_build_id': 'bisect',
|
||||
},
|
||||
)
|
||||
args = common.setup(parser)
|
||||
args = self.setup(parser)
|
||||
# We need a clean rebuild because rebuilds at different revisions:
|
||||
# - may fail
|
||||
# - may not actually rebuild all files, e.g. on header changes
|
||||
common.rmrf(kwargs['linux_build_dir'])
|
||||
self.rmrf(kwargs['linux_build_dir'])
|
||||
build_linux.LinuxComponent().do_build(args)
|
||||
status = run.main(args, {
|
||||
'eval': 'm5 exit',
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
import common
|
||||
parser = common.get_argparse(
|
||||
parser = self.get_argparse(
|
||||
argparse_args={'description':'Convert a BST vs heap stat file into a gnuplot input'}
|
||||
)
|
||||
args = common.setup(parser)
|
||||
stats = common.get_stats()
|
||||
args = self.setup(parser)
|
||||
stats = self.get_stats()
|
||||
it = iter(stats)
|
||||
i = 1
|
||||
for stat in it:
|
||||
|
||||
4
build
4
build
@@ -315,9 +315,9 @@ Extra args to pass to all scripts.
|
||||
parser.add_argument('components', choices=list(name_to_component_map.keys()) + [[]], default=[], nargs='*', help='''\
|
||||
Which components to build. Default: qemu-buildroot
|
||||
'''.format(kwargs['default_arch']))
|
||||
common.add_dry_run_argument(parser)
|
||||
self.add_dry_run_argument(parser)
|
||||
args = parser.parse_args()
|
||||
common.setup_dry_run_arguments(args)
|
||||
self.setup_dry_run_arguments(args)
|
||||
|
||||
# Decide archs.
|
||||
if kwargs['arch'] == []:
|
||||
|
||||
@@ -4,9 +4,9 @@ import os
|
||||
|
||||
import common
|
||||
|
||||
class BaremetalComponent(common.Component):
|
||||
class BaremetalComponent(self.Component):
|
||||
def do_build(self, args):
|
||||
common.assert_crosstool_ng_supports_arch(kwargs['arch'])
|
||||
self.assert_crosstool_ng_supports_arch(kwargs['arch'])
|
||||
build_dir = self.get_build_dir(args)
|
||||
bootloader_obj = os.path.join(kwargs['baremetal_build_lib_dir'], 'bootloader{}'.format(kwargs['obj_ext']))
|
||||
common_basename_noext = 'common'
|
||||
@@ -28,7 +28,7 @@ class BaremetalComponent(common.Component):
|
||||
gcc = 'arm-none-eabi-gcc'
|
||||
else:
|
||||
os.environ['PATH'] = kwargs['crosstool_ng_bin_dir'] + os.environ['PATH']
|
||||
gcc = common.get_toolchain_tool('gcc', allowed_toolchains=['crosstool-ng'])
|
||||
gcc = self.get_toolchain_tool('gcc', allowed_toolchains=['crosstool-ng'])
|
||||
if kwargs['emulator'] == 'gem5':
|
||||
if kwargs['machine'] == 'VExpress_GEM5_V1':
|
||||
entry_address = 0x80000000
|
||||
@@ -45,7 +45,7 @@ class BaremetalComponent(common.Component):
|
||||
os.makedirs(build_dir, exist_ok=True)
|
||||
os.makedirs(kwargs['baremetal_build_lib_dir'], exist_ok=True)
|
||||
src = os.path.join(kwargs['baremetal_src_lib_dir'], '{}{}'.format(kwargs['arch'], kwargs['asm_ext']))
|
||||
if common.need_rebuild([src], bootloader_obj):
|
||||
if self.need_rebuild([src], bootloader_obj):
|
||||
self.sh.run_cmd(
|
||||
[gcc, LF] +
|
||||
cflags +
|
||||
@@ -59,7 +59,7 @@ class BaremetalComponent(common.Component):
|
||||
(common_src, common_obj),
|
||||
(syscalls_src, syscalls_obj),
|
||||
]:
|
||||
if common.need_rebuild([src], obj):
|
||||
if self.need_rebuild([src], obj):
|
||||
self.sh.run_cmd(
|
||||
[gcc, LF] +
|
||||
cflags +
|
||||
@@ -149,7 +149,7 @@ Build the baremetal examples with crosstool-NG.
|
||||
in_name = os.path.splitext(in_basename)[0]
|
||||
main_obj = os.path.join(kwargs['baremetal_build_dir'], subpath, '{}{}'.format(in_name, kwargs['obj_ext']))
|
||||
src = os.path.join(kwargs['baremetal_src_dir'], in_path)
|
||||
if common.need_rebuild([src], main_obj):
|
||||
if self.need_rebuild([src], main_obj):
|
||||
self.sh.run_cmd(
|
||||
[gcc, LF] +
|
||||
cflags +
|
||||
@@ -162,7 +162,7 @@ Build the baremetal examples with crosstool-NG.
|
||||
objs = common_objs + [main_obj]
|
||||
out = os.path.join(kwargs['baremetal_build_dir'], subpath, in_name + kwargs['baremetal_build_ext'])
|
||||
link_script = os.path.join(kwargs['baremetal_src_dir'], 'link.ld')
|
||||
if common.need_rebuild(objs + [link_script], out):
|
||||
if self.need_rebuild(objs + [link_script], out):
|
||||
self.sh.run_cmd(
|
||||
[gcc, LF] +
|
||||
cflags +
|
||||
|
||||
@@ -10,10 +10,10 @@ import re
|
||||
|
||||
import common
|
||||
|
||||
class BuildrootComponent(common.Component):
|
||||
class BuildrootComponent(self.Component):
|
||||
def add_parser_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'--build-linux', default=self._defaults['build_linux'], action='store_true',
|
||||
'--build-linux', default=self._defaults['build_linux'],
|
||||
help='''\
|
||||
Enable building the Linux kernel with Buildroot. This is done mostly
|
||||
to extract Buildroot's default kernel configurations when updating Buildroot.
|
||||
@@ -22,7 +22,7 @@ not currently supported, juse use ./build-linux script if you want to do that.
|
||||
'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'--baseline', default=self._defaults['baseline'], action='store_true',
|
||||
'--baseline', default=self._defaults['baseline'],
|
||||
help='''Do a default-ish Buildroot defconfig build, without any of our extra options.
|
||||
Mostly to track how much slower we are than a basic build.
|
||||
'''
|
||||
@@ -42,14 +42,14 @@ Pass multiple times to use multiple fragment files.
|
||||
'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'--no-all', default=self._defaults['no_all'], action='store_true',
|
||||
'--no-all', default=self._defaults['no_all'],
|
||||
help='''\
|
||||
Don't build the all target which normally gets build by default.
|
||||
That target builds the root filesystem and all its dependencies.
|
||||
'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'--no-overlay', default=self._defaults['no_all'], action='store_true',
|
||||
'--no-overlay', default=self._defaults['no_all'],
|
||||
help='''\
|
||||
Don't add our overlay which contains all files we build without going through Buildroot.
|
||||
This prevents us from overwriting certain Buildroot files. Remember however that you must
|
||||
@@ -140,7 +140,7 @@ usually extra Buildroot targets.
|
||||
],
|
||||
cwd=kwargs['buildroot_src_dir'],
|
||||
)
|
||||
common.make_build_dirs()
|
||||
self.make_build_dirs()
|
||||
if not kwargs['no_all']:
|
||||
extra_make_args.extend(['all', LF])
|
||||
self.sh.run_cmd(
|
||||
@@ -161,7 +161,7 @@ usually extra Buildroot targets.
|
||||
# Skip if qemu is not present, because gem5 does not need the qcow2.
|
||||
# so we don't force a QEMU build for gem5.
|
||||
if not kwargs['no_all'] and os.path.exists(kwargs['qemu_img_executable']):
|
||||
common.raw_to_qcow2()
|
||||
self.raw_to_qcow2()
|
||||
|
||||
def get_argparse_args(self):
|
||||
return {
|
||||
|
||||
@@ -4,9 +4,9 @@ import os
|
||||
|
||||
import common
|
||||
|
||||
class CrosstoolNgComponent(common.Component):
|
||||
class CrosstoolNgComponent(self.Component):
|
||||
def do_build(self, args):
|
||||
common.assert_crosstool_ng_supports_arch(kwargs['arch'])
|
||||
self.assert_crosstool_ng_supports_arch(kwargs['arch'])
|
||||
build_dir = self.get_build_dir(args)
|
||||
defconfig_dest = os.path.join(kwargs['crosstool_ng_util_dir'], 'defconfig')
|
||||
os.makedirs(kwargs['crosstool_ng_util_dir'], exist_ok=True)
|
||||
@@ -37,7 +37,7 @@ class CrosstoolNgComponent(common.Component):
|
||||
os.path.join(kwargs['root_dir'], 'crosstool_ng_config', kwargs['arch']),
|
||||
defconfig_dest
|
||||
)
|
||||
common.write_configs(
|
||||
self.write_configs(
|
||||
kwargs['crosstool_ng_defconfig'],
|
||||
[
|
||||
'CT_PREFIX_DIR="{}"'.format(kwargs['crosstool_ng_install_dir']),
|
||||
|
||||
@@ -7,7 +7,7 @@ import tarfile
|
||||
import common
|
||||
|
||||
|
||||
class DockerComponent(common.Component):
|
||||
class DockerComponent(self.Component):
|
||||
def get_argparse_args(self):
|
||||
return {
|
||||
'description': '''\
|
||||
@@ -68,7 +68,7 @@ See also:https://github.com/cirosantilli/linux-kernel-module-cheat#ubuntu-guest-
|
||||
kwargs['docker_tar_dir'],
|
||||
kwargs['docker_rootfs_raw_file'],
|
||||
])
|
||||
common.raw_to_qcow2(prebuilt=True)
|
||||
self.raw_to_qcow2(prebuilt=True)
|
||||
|
||||
def get_build_dir(self, args):
|
||||
return kwargs['docker_build_dir']
|
||||
|
||||
@@ -37,7 +37,7 @@ Still uses options explicitly passed with `--config` and
|
||||
'''
|
||||
)
|
||||
self.add_argument(
|
||||
'--config-only', default=False, action='store_true',
|
||||
'--config-only', default=False,
|
||||
help='''\
|
||||
Configure the kernel, but don't build it.
|
||||
'''
|
||||
@@ -91,7 +91,7 @@ Configure the kernel, but don't build it.
|
||||
if self.env['config'] != []:
|
||||
cli_config_fragment_path = os.path.join(build_dir, 'lkmc_cli_config_fragment')
|
||||
cli_config_str = '\n'.join(self.env['config'])
|
||||
common.write_string_to_file(cli_config_fragment_path, cli_config_str)
|
||||
self.write_string_to_file(cli_config_fragment_path, cli_config_str)
|
||||
config_fragments.append(cli_config_fragment_path)
|
||||
self.sh.cp(
|
||||
base_config_file,
|
||||
@@ -133,7 +133,7 @@ Configure the kernel, but don't build it.
|
||||
)
|
||||
# TODO: remove build and source https://stackoverflow.com/questions/13578618/what-does-build-and-source-link-do-in-lib-modules-kernel-version
|
||||
# TODO Basically all kernel modules also basically leak full host paths. Just terrible. Buildroot deals with that stuff nicely for us.
|
||||
# common.rmrf()
|
||||
# self.rmrf()
|
||||
|
||||
def get_build_dir(self):
|
||||
return self.env['linux_build_dir']
|
||||
|
||||
6
build-m5
6
build-m5
@@ -4,11 +4,11 @@ import os
|
||||
|
||||
import common
|
||||
|
||||
class M5Component(common.Component):
|
||||
class M5Component(self.Component):
|
||||
def get_make_cmd(self, args):
|
||||
allowed_toolchains = ['buildroot']
|
||||
cc = common.get_toolchain_tool('gcc', allowed_toolchains=allowed_toolchains)
|
||||
ld = common.get_toolchain_tool('ld', allowed_toolchains=allowed_toolchains)
|
||||
cc = self.get_toolchain_tool('gcc', allowed_toolchains=allowed_toolchains)
|
||||
ld = self.get_toolchain_tool('ld', allowed_toolchains=allowed_toolchains)
|
||||
if kwargs['arch'] == 'x86_64':
|
||||
arch = 'x86'
|
||||
else:
|
||||
|
||||
@@ -7,7 +7,7 @@ import shutil
|
||||
|
||||
import common
|
||||
|
||||
class ModulesComponent(common.Component):
|
||||
class ModulesComponent(self.Component):
|
||||
def add_parser_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'--make-args',
|
||||
@@ -15,7 +15,6 @@ class ModulesComponent(common.Component):
|
||||
)
|
||||
parser.add_argument(
|
||||
'--host',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='''\
|
||||
Build the Linux kernel modules for the host instead of guest.
|
||||
@@ -70,7 +69,7 @@ Use the host packaged cross toolchain.
|
||||
else:
|
||||
allowed_toolchains = None
|
||||
build_subdir = kwargs['kernel_modules_build_subdir']
|
||||
gcc = common.get_toolchain_tool(tool, allowed_toolchains=allowed_toolchains)
|
||||
gcc = self.get_toolchain_tool(tool, allowed_toolchains=allowed_toolchains)
|
||||
prefix = gcc[:-len(tool)]
|
||||
ccache = shutil.which('ccache')
|
||||
if ccache is not None:
|
||||
@@ -97,13 +96,13 @@ Use the host packaged cross toolchain.
|
||||
'M={}'.format(build_subdir), LF,
|
||||
'OBJECT_FILES={}'.format(' '.join(object_files)), LF,
|
||||
] +
|
||||
common.shlex_split(kwargs['make_args']) +
|
||||
self.sh.shlex_split(kwargs['make_args']) +
|
||||
verbose
|
||||
),
|
||||
cwd=os.path.join(kwargs['kernel_modules_build_subdir']),
|
||||
)
|
||||
if not kwargs['host']:
|
||||
common.copy_dir_if_update_non_recursive(
|
||||
self.copy_dir_if_update_non_recursive(
|
||||
srcdir=kwargs['kernel_modules_build_subdir'],
|
||||
destdir=kwargs['out_rootfs_overlay_dir'],
|
||||
filter_ext=kwargs['kernel_module_ext'],
|
||||
|
||||
@@ -4,12 +4,11 @@ import os
|
||||
|
||||
import common
|
||||
|
||||
class QemuComponent(common.Component):
|
||||
class QemuComponent(self.Component):
|
||||
def add_parser_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'--userland',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help='Build QEMU user mode instead of system.',
|
||||
)
|
||||
parser.add_argument(
|
||||
|
||||
@@ -8,7 +8,7 @@ import subprocess
|
||||
|
||||
import common
|
||||
|
||||
class UserlandComponent(common.Component):
|
||||
class UserlandComponent(self.Component):
|
||||
def add_parser_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'--has-package',
|
||||
@@ -21,7 +21,6 @@ allows us to build examples that rely on it.
|
||||
)
|
||||
parser.add_argument(
|
||||
'--host',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='''\
|
||||
Build the userland programs for the host instead of guest.
|
||||
@@ -51,8 +50,8 @@ has the OpenBLAS libraries and headers installed.
|
||||
allowed_toolchains = ['host']
|
||||
else:
|
||||
allowed_toolchains = ['buildroot']
|
||||
cc = common.get_toolchain_tool('gcc', allowed_toolchains=allowed_toolchains)
|
||||
cxx = common.get_toolchain_tool('g++', allowed_toolchains=allowed_toolchains)
|
||||
cc = self.get_toolchain_tool('gcc', allowed_toolchains=allowed_toolchains)
|
||||
cxx = self.get_toolchain_tool('g++', allowed_toolchains=allowed_toolchains)
|
||||
self.sh.run_cmd(
|
||||
(
|
||||
[
|
||||
@@ -74,7 +73,7 @@ has the OpenBLAS libraries and headers installed.
|
||||
cwd=kwargs['userland_src_dir'],
|
||||
extra_paths=[kwargs['ccache_dir']],
|
||||
)
|
||||
common.copy_dir_if_update_non_recursive(
|
||||
self.copy_dir_if_update_non_recursive(
|
||||
srcdir=build_dir,
|
||||
destdir=kwargs['out_rootfs_overlay_dir'],
|
||||
filter_ext=kwargs['userland_build_ext'],
|
||||
|
||||
73
cli_function.py
Normal file → Executable file
73
cli_function.py
Normal file → Executable file
@@ -41,15 +41,17 @@ class Argument:
|
||||
if nargs is not None:
|
||||
self.kwargs['nargs'] = nargs
|
||||
if default is True:
|
||||
self.kwargs['action'] = 'store_false'
|
||||
bool_action = 'store_false'
|
||||
self.is_bool = True
|
||||
elif default is False:
|
||||
self.kwargs['action'] = 'store_true'
|
||||
bool_action = 'store_true'
|
||||
self.is_bool = True
|
||||
else:
|
||||
self.is_bool = False
|
||||
if default is None and nargs in ('*', '+'):
|
||||
default = []
|
||||
if self.is_bool and not 'action' in kwargs:
|
||||
self.kwargs['action'] = bool_action
|
||||
if help is not None:
|
||||
if not self.is_bool and default:
|
||||
help += ' Default: {}'.format(default)
|
||||
@@ -131,6 +133,9 @@ class CliFunction:
|
||||
help='Path to the configuration file to use'
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return '\n'.join(str(arg) for arg in self._arguments)
|
||||
|
||||
def add_argument(
|
||||
self,
|
||||
*args,
|
||||
@@ -155,11 +160,10 @@ class CliFunction:
|
||||
new_longname = '--no' + argument.longname[1:]
|
||||
kwargs = argument.kwargs.copy()
|
||||
kwargs['default'] = not argument.default
|
||||
if argument.default:
|
||||
action = 'store_true'
|
||||
else:
|
||||
action = 'store_false'
|
||||
kwargs['action'] = action
|
||||
if kwargs['action'] == 'store_false':
|
||||
kwargs['action'] = 'store_true'
|
||||
elif kwargs['action'] == 'store_true':
|
||||
kwargs['action'] = 'store_false'
|
||||
if 'help' in kwargs:
|
||||
del kwargs['help']
|
||||
parser.add_argument(new_longname, dest=argument.key, **kwargs)
|
||||
@@ -188,6 +192,7 @@ amazing function!
|
||||
self.add_argument('-q', '--qwer', default='Q', help='Help for qwer'),
|
||||
self.add_argument('-b', '--bool', default=True, help='Help for bool'),
|
||||
self.add_argument('--bool-cli', default=False, help='Help for bool'),
|
||||
self.add_argument('--bool-nargs', default=False, nargs='?', action='store', const='')
|
||||
self.add_argument('--no-default', help='Help for no-bool'),
|
||||
self.add_argument('pos-mandatory', help='Help for pos-mandatory', type=int),
|
||||
self.add_argument('pos-optional', default=0, help='Help for pos-optional', type=int),
|
||||
@@ -196,32 +201,62 @@ amazing function!
|
||||
del kwargs['config_file']
|
||||
return kwargs
|
||||
|
||||
# Code calls.
|
||||
default = OneCliFunction()(pos_mandatory=1)
|
||||
assert default == {'asdf': 'A', 'qwer': 'Q', 'bool': True, 'bool_cli': True, 'no_default': None, 'pos_mandatory': 1, 'pos_optional': 0, 'args_star': []}
|
||||
one_cli_function = OneCliFunction()
|
||||
|
||||
# Default code call.
|
||||
default = one_cli_function(pos_mandatory=1)
|
||||
assert default == {
|
||||
'asdf': 'A',
|
||||
'qwer': 'Q',
|
||||
'bool': True,
|
||||
'bool_nargs': False,
|
||||
'bool_cli': True,
|
||||
'no_default': None,
|
||||
'pos_mandatory': 1,
|
||||
'pos_optional': 0,
|
||||
'args_star': []
|
||||
}
|
||||
|
||||
# Default CLI call.
|
||||
out = one_cli_function.cli(['1'])
|
||||
assert out == default
|
||||
|
||||
# asdf
|
||||
out = OneCliFunction()(pos_mandatory=1, asdf='B')
|
||||
out = one_cli_function(pos_mandatory=1, asdf='B')
|
||||
assert out['asdf'] == 'B'
|
||||
out['asdf'] = default['asdf']
|
||||
assert(out == default)
|
||||
|
||||
# asdf and qwer
|
||||
out = OneCliFunction()(pos_mandatory=1, asdf='B', qwer='R')
|
||||
out = one_cli_function(pos_mandatory=1, asdf='B', qwer='R')
|
||||
assert out['asdf'] == 'B'
|
||||
assert out['qwer'] == 'R'
|
||||
out['asdf'] = default['asdf']
|
||||
out['qwer'] = default['qwer']
|
||||
assert(out == default)
|
||||
|
||||
# bool
|
||||
out = OneCliFunction()(pos_mandatory=1, bool=False)
|
||||
assert out['bool'] == False
|
||||
out['bool'] = default['bool']
|
||||
assert(out == default)
|
||||
if '--bool':
|
||||
out = one_cli_function(pos_mandatory=1, bool=False)
|
||||
cli_out = one_cli_function.cli(['--bool', '1'])
|
||||
assert out == cli_out
|
||||
assert out['bool'] == False
|
||||
out['bool'] = default['bool']
|
||||
assert(out == default)
|
||||
|
||||
if '--bool-nargs':
|
||||
|
||||
out = one_cli_function(pos_mandatory=1, bool_nargs=True)
|
||||
assert out['bool_nargs'] == True
|
||||
out['bool_nargs'] = default['bool_nargs']
|
||||
assert(out == default)
|
||||
|
||||
out = one_cli_function(pos_mandatory=1, bool_nargs='asdf')
|
||||
assert out['bool_nargs'] == 'asdf'
|
||||
out['bool_nargs'] = default['bool_nargs']
|
||||
assert(out == default)
|
||||
|
||||
# Force a boolean value set on the config to be False on CLI.
|
||||
assert OneCliFunction().cli(['--no-bool-cli', '1'])['bool_cli'] is False
|
||||
assert one_cli_function.cli(['--no-bool-cli', '1'])['bool_cli'] is False
|
||||
|
||||
# CLI call.
|
||||
print(OneCliFunction().cli())
|
||||
print(one_cli_function.cli())
|
||||
|
||||
349
common.py
349
common.py
@@ -13,7 +13,6 @@ import os
|
||||
import re
|
||||
import shutil
|
||||
import signal
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
@@ -120,7 +119,7 @@ mkdir are generally omitted since those are obvious
|
||||
'''
|
||||
)
|
||||
self.add_argument(
|
||||
'-v', '--verbose', default=False, action='store_true',
|
||||
'-v', '--verbose', default=False,
|
||||
help='Show full compilation commands when they are not shown by default.'
|
||||
)
|
||||
|
||||
@@ -163,10 +162,10 @@ Linux build ID. Allows you to keep multiple separate Linux builds.
|
||||
'''
|
||||
)
|
||||
self.add_argument(
|
||||
'--initramfs', default=False, action='store_true',
|
||||
'--initramfs', default=False,
|
||||
)
|
||||
self.add_argument(
|
||||
'--initrd', default=False, action='store_true',
|
||||
'--initrd', default=False,
|
||||
)
|
||||
|
||||
# Baremetal.
|
||||
@@ -189,7 +188,7 @@ inside baremetal/ and then try to use corresponding executable.
|
||||
help='Buildroot build ID. Allows you to keep multiple separate gem5 builds.'
|
||||
)
|
||||
self.add_argument(
|
||||
'--buildroot-linux', default=False, action='store_true',
|
||||
'--buildroot-linux', default=False,
|
||||
help='Boot with the Buildroot Linux kernel instead of our custom built one. Mostly for sanity checks.'
|
||||
)
|
||||
|
||||
@@ -199,7 +198,7 @@ inside baremetal/ and then try to use corresponding executable.
|
||||
help='Crosstool-NG build ID. Allows you to keep multiple separate crosstool-NG builds.'
|
||||
)
|
||||
self.add_argument(
|
||||
'--docker', default=False, action='store_true',
|
||||
'--docker', default=False,
|
||||
help='''\
|
||||
Use the docker download Ubuntu root filesystem instead of the default Buildroot one.
|
||||
'''
|
||||
@@ -234,7 +233,7 @@ and then inspect separate outputs later in different output directories.
|
||||
'''
|
||||
)
|
||||
self.add_argument(
|
||||
'-P', '--prebuilt', default=False, action='store_true',
|
||||
'-P', '--prebuilt', default=False,
|
||||
help='''\
|
||||
Use prebuilt packaged host utilities as much as possible instead
|
||||
of the ones we built ourselves. Saves build time, but decreases
|
||||
@@ -251,11 +250,11 @@ instances in parallel. Default: the run ID (-n) if that is an integer, otherwise
|
||||
|
||||
# Misc.
|
||||
self.add_argument(
|
||||
'-g', '--gem5', default=False, action='store_true',
|
||||
'-g', '--gem5', default=False,
|
||||
help='Use gem5 instead of QEMU.'
|
||||
)
|
||||
self.add_argument(
|
||||
'--qemu', default=False, action='store_true',
|
||||
'--qemu', default=False,
|
||||
help='''\
|
||||
Use QEMU as the emulator. This option exists in addition to --gem5
|
||||
to allow overriding configs from the CLI.
|
||||
@@ -426,6 +425,7 @@ to allow overriding configs from the CLI.
|
||||
env['executable'] = env['qemu_executable']
|
||||
env['run_dir'] = env['qemu_run_dir']
|
||||
env['termout_file'] = env['qemu_termout_file']
|
||||
env['guest_terminal_file'] = env['qemu_termout_file']
|
||||
env['trace_txt_file'] = env['qemu_trace_txt_file']
|
||||
env['run_cmd_file'] = join(env['run_dir'], 'run.sh')
|
||||
|
||||
@@ -497,7 +497,7 @@ to allow overriding configs from the CLI.
|
||||
if env['baremetal'] == 'all':
|
||||
path = env['baremetal']
|
||||
else:
|
||||
path = resolve_executable(
|
||||
path = self.resolve_executable(
|
||||
env['baremetal'],
|
||||
env['baremetal_src_dir'],
|
||||
env['baremetal_build_dir'],
|
||||
@@ -515,6 +515,23 @@ to allow overriding configs from the CLI.
|
||||
env['image'] = path
|
||||
self.env = env
|
||||
|
||||
def assert_crosstool_ng_supports_arch(self, arch):
|
||||
if arch not in self.env['crosstool_ng_supported_archs']:
|
||||
raise Exception('arch not yet supported: ' + arch)
|
||||
|
||||
@staticmethod
|
||||
def base64_encode(string):
|
||||
return base64.b64encode(string.encode()).decode()
|
||||
|
||||
def gem_list_checkpoint_dirs(self):
|
||||
'''
|
||||
List checkpoint directory, oldest first.
|
||||
'''
|
||||
prefix_re = re.compile(self.env['gem5_cpt_prefix'])
|
||||
files = list(filter(lambda x: os.path.isdir(os.path.join(self.env['m5out_dir'], x)) and prefix_re.search(x), os.listdir(self.env['m5out_dir'])))
|
||||
files.sort(key=lambda x: os.path.getmtime(os.path.join(self.env['m5out_dir'], x)))
|
||||
return files
|
||||
|
||||
def get_elf_entry(self, elf_file_path):
|
||||
readelf_header = subprocess.check_output([
|
||||
self.get_toolchain_tool('readelf'),
|
||||
@@ -528,6 +545,21 @@ to allow overriding configs from the CLI.
|
||||
break
|
||||
return int(addr, 0)
|
||||
|
||||
def get_stats(self, stat_re=None, stats_file=None):
|
||||
if stat_re is None:
|
||||
stat_re = '^system.cpu[0-9]*.numCycles$'
|
||||
if stats_file is None:
|
||||
stats_file = self.env['stats_file']
|
||||
stat_re = re.compile(stat_re)
|
||||
ret = []
|
||||
with open(stats_file, 'r') as statfile:
|
||||
for line in statfile:
|
||||
if line[0] != '-':
|
||||
cols = line.split()
|
||||
if len(cols) > 1 and stat_re.search(cols[0]):
|
||||
ret.append(cols[1])
|
||||
return ret
|
||||
|
||||
def get_toolchain_prefix(self, tool, allowed_toolchains=None):
|
||||
buildroot_full_prefix = os.path.join(self.env['host_bin_dir'], self.env['buildroot_toolchain_prefix'])
|
||||
buildroot_exists = os.path.exists('{}-{}'.format(buildroot_full_prefix, tool))
|
||||
@@ -562,6 +594,41 @@ to allow overriding configs from the CLI.
|
||||
def get_toolchain_tool(self, tool, allowed_toolchains=None):
|
||||
return '{}-{}'.format(self.get_toolchain_prefix(tool, allowed_toolchains), tool)
|
||||
|
||||
@staticmethod
|
||||
def github_make_request(
|
||||
authenticate=False,
|
||||
data=None,
|
||||
extra_headers=None,
|
||||
path='',
|
||||
subdomain='api',
|
||||
url_params=None,
|
||||
**extra_request_args
|
||||
):
|
||||
if extra_headers is None:
|
||||
extra_headers = {}
|
||||
headers = {'Accept': 'application/vnd.github.v3+json'}
|
||||
headers.update(extra_headers)
|
||||
if authenticate:
|
||||
headers['Authorization'] = 'token ' + os.environ['LKMC_GITHUB_TOKEN']
|
||||
if url_params is not None:
|
||||
path += '?' + urllib.parse.urlencode(url_params)
|
||||
request = urllib.request.Request(
|
||||
'https://' + subdomain + '.github.com/repos/' + github_repo_id + path,
|
||||
headers=headers,
|
||||
data=data,
|
||||
**extra_request_args
|
||||
)
|
||||
response_body = urllib.request.urlopen(request).read().decode()
|
||||
if response_body:
|
||||
_json = json.loads(response_body)
|
||||
else:
|
||||
_json = {}
|
||||
return _json
|
||||
|
||||
@staticmethod
|
||||
def log_error(msg):
|
||||
print('error: {}'.format(msg), file=sys.stderr)
|
||||
|
||||
def main(self, **kwargs):
|
||||
'''
|
||||
Time the main of the derived class.
|
||||
@@ -571,13 +638,107 @@ to allow overriding configs from the CLI.
|
||||
kwargs.update(consts)
|
||||
self._init_env(kwargs)
|
||||
self.sh = shell_helpers.ShellHelpers(dry_run=self.env['dry_run'])
|
||||
self.timed_main()
|
||||
ret = self.timed_main()
|
||||
if not kwargs['dry_run']:
|
||||
end_time = time.time()
|
||||
print_time(end_time - start_time)
|
||||
self.print_time(end_time - start_time)
|
||||
return ret
|
||||
|
||||
def run_cmd(self, *args, **kwargs):
|
||||
self.sh.run_cmd(*args, **kwargs)
|
||||
def make_build_dirs(self):
|
||||
os.makedirs(self.env['buildroot_build_build_dir'], exist_ok=True)
|
||||
os.makedirs(self.env['gem5_build_dir'], exist_ok=True)
|
||||
os.makedirs(self.env['out_rootfs_overlay_dir'], exist_ok=True)
|
||||
|
||||
def make_run_dirs(self):
|
||||
'''
|
||||
Make directories required for the run.
|
||||
The user could nuke those anytime between runs to try and clean things up.
|
||||
'''
|
||||
os.makedirs(self.env['gem5_run_dir'], exist_ok=True)
|
||||
os.makedirs(self.env['p9_dir'], exist_ok=True)
|
||||
os.makedirs(self.env['qemu_run_dir'], exist_ok=True)
|
||||
|
||||
@staticmethod
|
||||
def need_rebuild(srcs, dst):
|
||||
if not os.path.exists(dst):
|
||||
return True
|
||||
for src in srcs:
|
||||
if os.path.getmtime(src) > os.path.getmtime(dst):
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def print_time(ellapsed_seconds):
|
||||
hours, rem = divmod(ellapsed_seconds, 3600)
|
||||
minutes, seconds = divmod(rem, 60)
|
||||
print("time {:02}:{:02}:{:02}".format(int(hours), int(minutes), int(seconds)))
|
||||
|
||||
def raw_to_qcow2(eslf, prebuilt=False, reverse=False):
|
||||
if prebuilt or not os.path.exists(self.env['qemu_img_executable']):
|
||||
disable_trace = []
|
||||
qemu_img_executable = self.env['qemu_img_basename']
|
||||
else:
|
||||
# Prevent qemu-img from generating trace files like QEMU. Disgusting.
|
||||
disable_trace = ['-T', 'pr_manager_run,file=/dev/null', LF,]
|
||||
qemu_img_executable = self.env['qemu_img_executable']
|
||||
infmt = 'raw'
|
||||
outfmt = 'qcow2'
|
||||
infile = self.env['rootfs_raw_file']
|
||||
outfile = self.env['qcow2_file']
|
||||
if reverse:
|
||||
tmp = infmt
|
||||
infmt = outfmt
|
||||
outfmt = tmp
|
||||
tmp = infile
|
||||
infile = outfile
|
||||
outfile = tmp
|
||||
self.sh.run_cmd(
|
||||
[
|
||||
qemu_img_executable, LF,
|
||||
] +
|
||||
disable_trace +
|
||||
[
|
||||
'convert', LF,
|
||||
'-f', infmt, LF,
|
||||
'-O', outfmt, LF,
|
||||
infile, LF,
|
||||
outfile, LF,
|
||||
]
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def resolve_args(defaults, args, extra_args):
|
||||
if extra_args is None:
|
||||
extra_args = {}
|
||||
argcopy = copy.copy(args)
|
||||
argcopy.__dict__ = dict(list(defaults.items()) + list(argcopy.__dict__.items()) + list(extra_args.items()))
|
||||
return argcopy
|
||||
|
||||
@staticmethod
|
||||
def resolve_executable(in_path, magic_in_dir, magic_out_dir, out_ext):
|
||||
if os.path.isabs(in_path):
|
||||
return in_path
|
||||
else:
|
||||
paths = [
|
||||
os.path.join(magic_out_dir, in_path),
|
||||
os.path.join(
|
||||
magic_out_dir,
|
||||
os.path.relpath(in_path, magic_in_dir),
|
||||
)
|
||||
]
|
||||
paths[:] = [os.path.splitext(path)[0] + out_ext for path in paths]
|
||||
for path in paths:
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
raise Exception('Executable file not found. Tried:\n' + '\n'.join(paths))
|
||||
|
||||
def resolve_userland(self, path):
|
||||
return self.resolve_executable(
|
||||
path,
|
||||
self.env['userland_src_dir'],
|
||||
self.env['userland_build_dir'],
|
||||
self.env['userland_build_ext'],
|
||||
)
|
||||
|
||||
def timed_main(self):
|
||||
'''
|
||||
@@ -628,162 +789,6 @@ class BuildCliFunction(LkmcCliFunction):
|
||||
The actual build work is done by do_build in implementing classes.
|
||||
'''
|
||||
if self.env['clean']:
|
||||
self.clean()
|
||||
return self.clean()
|
||||
else:
|
||||
self.build()
|
||||
|
||||
def assert_crosstool_ng_supports_arch(arch):
|
||||
if arch not in kwargs['crosstool_ng_supported_archs']:
|
||||
raise Exception('arch not yet supported: ' + arch)
|
||||
|
||||
def base64_encode(string):
|
||||
return base64.b64encode(string.encode()).decode()
|
||||
|
||||
def gem_list_checkpoint_dirs():
|
||||
'''
|
||||
List checkpoint directory, oldest first.
|
||||
'''
|
||||
prefix_re = re.compile(kwargs['gem5_cpt_prefix'])
|
||||
files = list(filter(lambda x: os.path.isdir(os.path.join(kwargs['m5out_dir'], x)) and prefix_re.search(x), os.listdir(kwargs['m5out_dir'])))
|
||||
files.sort(key=lambda x: os.path.getmtime(os.path.join(kwargs['m5out_dir'], x)))
|
||||
return files
|
||||
|
||||
def get_stats(stat_re=None, stats_file=None):
|
||||
if stat_re is None:
|
||||
stat_re = '^system.cpu[0-9]*.numCycles$'
|
||||
if stats_file is None:
|
||||
stats_file = kwargs['stats_file']
|
||||
stat_re = re.compile(stat_re)
|
||||
ret = []
|
||||
with open(stats_file, 'r') as statfile:
|
||||
for line in statfile:
|
||||
if line[0] != '-':
|
||||
cols = line.split()
|
||||
if len(cols) > 1 and stat_re.search(cols[0]):
|
||||
ret.append(cols[1])
|
||||
return ret
|
||||
|
||||
def github_make_request(
|
||||
authenticate=False,
|
||||
data=None,
|
||||
extra_headers=None,
|
||||
path='',
|
||||
subdomain='api',
|
||||
url_params=None,
|
||||
**extra_request_args
|
||||
):
|
||||
if extra_headers is None:
|
||||
extra_headers = {}
|
||||
headers = {'Accept': 'application/vnd.github.v3+json'}
|
||||
headers.update(extra_headers)
|
||||
if authenticate:
|
||||
headers['Authorization'] = 'token ' + os.environ['LKMC_GITHUB_TOKEN']
|
||||
if url_params is not None:
|
||||
path += '?' + urllib.parse.urlencode(url_params)
|
||||
request = urllib.request.Request(
|
||||
'https://' + subdomain + '.github.com/repos/' + github_repo_id + path,
|
||||
headers=headers,
|
||||
data=data,
|
||||
**extra_request_args
|
||||
)
|
||||
response_body = urllib.request.urlopen(request).read().decode()
|
||||
if response_body:
|
||||
_json = json.loads(response_body)
|
||||
else:
|
||||
_json = {}
|
||||
return _json
|
||||
|
||||
def log_error(msg):
|
||||
print('error: {}'.format(msg), file=sys.stderr)
|
||||
|
||||
def make_build_dirs():
|
||||
os.makedirs(kwargs['buildroot_build_build_dir'], exist_ok=True)
|
||||
os.makedirs(kwargs['gem5_build_dir'], exist_ok=True)
|
||||
os.makedirs(kwargs['out_rootfs_overlay_dir'], exist_ok=True)
|
||||
|
||||
def make_run_dirs():
|
||||
'''
|
||||
Make directories required for the run.
|
||||
The user could nuke those anytime between runs to try and clean things up.
|
||||
'''
|
||||
os.makedirs(kwargs['gem5_run_dir'], exist_ok=True)
|
||||
os.makedirs(kwargs['p9_dir'], exist_ok=True)
|
||||
os.makedirs(kwargs['qemu_run_dir'], exist_ok=True)
|
||||
|
||||
def need_rebuild(srcs, dst):
|
||||
if not os.path.exists(dst):
|
||||
return True
|
||||
for src in srcs:
|
||||
if os.path.getmtime(src) > os.path.getmtime(dst):
|
||||
return True
|
||||
return False
|
||||
|
||||
def print_time(ellapsed_seconds):
|
||||
hours, rem = divmod(ellapsed_seconds, 3600)
|
||||
minutes, seconds = divmod(rem, 60)
|
||||
print("time {:02}:{:02}:{:02}".format(int(hours), int(minutes), int(seconds)))
|
||||
|
||||
def raw_to_qcow2(prebuilt=False, reverse=False):
|
||||
if prebuilt or not os.path.exists(kwargs['qemu_img_executable']):
|
||||
disable_trace = []
|
||||
qemu_img_executable = kwargs['qemu_img_basename']
|
||||
else:
|
||||
# Prevent qemu-img from generating trace files like QEMU. Disgusting.
|
||||
disable_trace = ['-T', 'pr_manager_run,file=/dev/null', LF,]
|
||||
qemu_img_executable = kwargs['qemu_img_executable']
|
||||
infmt = 'raw'
|
||||
outfmt = 'qcow2'
|
||||
infile = kwargs['rootfs_raw_file']
|
||||
outfile = kwargs['qcow2_file']
|
||||
if reverse:
|
||||
tmp = infmt
|
||||
infmt = outfmt
|
||||
outfmt = tmp
|
||||
tmp = infile
|
||||
infile = outfile
|
||||
outfile = tmp
|
||||
self.sh.run_cmd(
|
||||
[
|
||||
qemu_img_executable, LF,
|
||||
] +
|
||||
disable_trace +
|
||||
[
|
||||
'convert', LF,
|
||||
'-f', infmt, LF,
|
||||
'-O', outfmt, LF,
|
||||
infile, LF,
|
||||
outfile, LF,
|
||||
]
|
||||
)
|
||||
|
||||
def resolve_args(defaults, args, extra_args):
|
||||
if extra_args is None:
|
||||
extra_args = {}
|
||||
argcopy = copy.copy(args)
|
||||
argcopy.__dict__ = dict(list(defaults.items()) + list(argcopy.__dict__.items()) + list(extra_args.items()))
|
||||
return argcopy
|
||||
|
||||
def resolve_executable(in_path, magic_in_dir, magic_out_dir, out_ext):
|
||||
if os.path.isabs(in_path):
|
||||
return in_path
|
||||
else:
|
||||
paths = [
|
||||
os.path.join(magic_out_dir, in_path),
|
||||
os.path.join(
|
||||
magic_out_dir,
|
||||
os.path.relpath(in_path, magic_in_dir),
|
||||
)
|
||||
]
|
||||
paths[:] = [os.path.splitext(path)[0] + out_ext for path in paths]
|
||||
for path in paths:
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
raise Exception('Executable file not found. Tried:\n' + '\n'.join(paths))
|
||||
|
||||
def resolve_userland(path):
|
||||
return resolve_executable(
|
||||
path,
|
||||
kwargs['userland_src_dir'],
|
||||
kwargs['userland_build_dir'],
|
||||
kwargs['userland_build_ext'],
|
||||
)
|
||||
return self.build()
|
||||
|
||||
@@ -6,7 +6,7 @@ import shutil
|
||||
|
||||
import common
|
||||
|
||||
class CopyOverlayComponent(common.Component):
|
||||
class CopyOverlayComponent(self.Component):
|
||||
def do_build(self, args):
|
||||
distutils.dir_util.copy_tree(
|
||||
kwargs['rootfs_overlay_dir'],
|
||||
|
||||
@@ -4,11 +4,11 @@ import sys
|
||||
|
||||
import common
|
||||
|
||||
parser = common.get_argparse(
|
||||
parser = self.get_argparse(
|
||||
default_args={'gem5':True},
|
||||
argparse_args={'description':'Connect a terminal to a running gem5 instance'}
|
||||
)
|
||||
args = common.setup(parser)
|
||||
args = self.setup(parser)
|
||||
sys.exit(self.sh.run_cmd([
|
||||
kwargs['gem5_m5term'], LF,
|
||||
'localhost', LF,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
import common
|
||||
parser = common.get_argparse(
|
||||
parser = self.get_argparse(
|
||||
argparse_args={'description':'Get the value of a gem5 stat from the stats.txt file.'}
|
||||
)
|
||||
parser.add_argument(
|
||||
@@ -9,6 +9,6 @@ parser.add_argument(
|
||||
help='Python regexp matching the full stat name of interest',
|
||||
nargs='?',
|
||||
)
|
||||
args = common.setup(parser)
|
||||
stats = common.get_stats(kwargs['stat'])
|
||||
args = self.setup(parser)
|
||||
stats = self.get_stats(kwargs['stat'])
|
||||
print('\n'.join(stats))
|
||||
|
||||
4
getvar
4
getvar
@@ -4,7 +4,7 @@ import types
|
||||
|
||||
import common
|
||||
|
||||
parser = common.get_argparse(argparse_args={
|
||||
parser = self.get_argparse(argparse_args={
|
||||
'description': '''Print the value of a kwargs['py'] variable.
|
||||
|
||||
This is useful to:
|
||||
@@ -27,7 +27,7 @@ List all available variables:
|
||||
'''
|
||||
})
|
||||
parser.add_argument('variable', nargs='?')
|
||||
args = common.setup(parser)
|
||||
args = self.setup(parser)
|
||||
if kwargs['variable']:
|
||||
print(getattr(common, kwargs['variable']))
|
||||
else:
|
||||
|
||||
@@ -8,7 +8,7 @@ import common
|
||||
|
||||
prompt = b'\n(qemu) '
|
||||
|
||||
parser = common.get_argparse({
|
||||
parser = self.get_argparse({
|
||||
'description': '''\
|
||||
Run a command on the QEMU monitor of a running QEMU instance
|
||||
|
||||
@@ -21,7 +21,7 @@ parser.add_argument(
|
||||
help='If given, run this command and quit',
|
||||
nargs='*',
|
||||
)
|
||||
args = common.setup(parser)
|
||||
args = self.setup(parser)
|
||||
|
||||
def write_and_read(tn, cmd, prompt):
|
||||
tn.write(cmd.encode('utf-8'))
|
||||
|
||||
@@ -19,8 +19,8 @@ def main():
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = common.get_argparse(argparse_args={
|
||||
parser = self.get_argparse(argparse_args={
|
||||
'description': 'Convert a QEMU `-trace exec_tb` to text form.'
|
||||
})
|
||||
args = common.setup(parser)
|
||||
args = self.setup(parser)
|
||||
sys.exit(main())
|
||||
|
||||
2
release
2
release
@@ -29,4 +29,4 @@ release_zip.main()
|
||||
subprocess.check_call(['git', 'push'])
|
||||
release_upload.main()
|
||||
end_time = time.time()
|
||||
common.print_time(end_time - start_time)
|
||||
self.print_time(end_time - start_time)
|
||||
|
||||
@@ -11,6 +11,6 @@ import urllib.request
|
||||
|
||||
import common
|
||||
|
||||
_json = common.github_make_request(path='/releases')
|
||||
_json = self.github_make_request(path='/releases')
|
||||
asset = _json[0]['assets'][0]
|
||||
urllib.request.urlretrieve(asset['browser_download_url'], asset['name'])
|
||||
|
||||
@@ -24,7 +24,7 @@ def main():
|
||||
|
||||
# Check the release already exists.
|
||||
try:
|
||||
_json = common.github_make_request(path='/releases/tags/' + tag)
|
||||
_json = self.github_make_request(path='/releases/tags/' + tag)
|
||||
except urllib.error.HTTPError as e:
|
||||
if e.code == 404:
|
||||
release_exists = False
|
||||
@@ -36,7 +36,7 @@ def main():
|
||||
|
||||
# Create release if not yet created.
|
||||
if not release_exists:
|
||||
_json = common.github_make_request(
|
||||
_json = self.github_make_request(
|
||||
authenticate=True,
|
||||
data=json.dumps({
|
||||
'tag_name': tag,
|
||||
@@ -50,12 +50,12 @@ def main():
|
||||
asset_name = os.path.split(upload_path)[1]
|
||||
|
||||
# Clear the prebuilts for a upload.
|
||||
_json = common.github_make_request(
|
||||
_json = self.github_make_request(
|
||||
path=('/releases/' + str(release_id) + '/assets'),
|
||||
)
|
||||
for asset in _json:
|
||||
if asset['name'] == asset_name:
|
||||
_json = common.github_make_request(
|
||||
_json = self.github_make_request(
|
||||
authenticate=True,
|
||||
path=('/releases/assets/' + str(asset['id'])),
|
||||
method='DELETE',
|
||||
@@ -65,7 +65,7 @@ def main():
|
||||
# Upload the prebuilt.
|
||||
with open(upload_path, 'br') as myfile:
|
||||
content = myfile.read()
|
||||
_json = common.github_make_request(
|
||||
_json = self.github_make_request(
|
||||
authenticate=True,
|
||||
data=content,
|
||||
extra_headers={'Content-Type': 'application/zip'},
|
||||
|
||||
@@ -16,7 +16,7 @@ def main():
|
||||
os.unlink(kwargs['release_zip_file'])
|
||||
zipf = zipfile.ZipFile(kwargs['release_zip_file'], 'w', zipfile.ZIP_DEFLATED)
|
||||
for arch in kwargs['all_archs']:
|
||||
common.setup(common.get_argparse(default_args={'arch': arch}))
|
||||
self.setup(common.get_argparse(default_args={'arch': arch}))
|
||||
zipf.write(kwargs['qcow2_file'], arcname=os.path.relpath(kwargs['qcow2_file'], kwargs['root_dir']))
|
||||
zipf.write(kwargs['linux_image'], arcname=os.path.relpath(kwargs['linux_image'], kwargs['root_dir']))
|
||||
zipf.close()
|
||||
|
||||
@@ -58,7 +58,7 @@ cmd_action_map = {
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('cmd', choices=cmd_action_map)
|
||||
parser.add_argument('args', nargs='*')
|
||||
common.add_dry_run_argument(parser)
|
||||
self.add_dry_run_argument(parser)
|
||||
args = parser.parse_args()
|
||||
common.setup_dry_run_arguments(args)
|
||||
self.setup_dry_run_arguments(args)
|
||||
cmd_action_map[kwargs['cmd']](kwargs['args'])
|
||||
|
||||
28
run-gdb
28
run-gdb
@@ -34,8 +34,8 @@ class GdbTestcase:
|
||||
'''
|
||||
self.prompt = '\(gdb\) '
|
||||
self.source_path = source_path
|
||||
common.print_cmd(cmd)
|
||||
cmd = common.strip_newlines(cmd)
|
||||
self.print_cmd(cmd)
|
||||
cmd = self.strip_newlines(cmd)
|
||||
import pexpect
|
||||
self.child = pexpect.spawn(
|
||||
cmd[0],
|
||||
@@ -97,9 +97,9 @@ def main(args, extra_args=None):
|
||||
:rtype: int
|
||||
'''
|
||||
global defaults
|
||||
args = common.resolve_args(defaults, args, extra_args)
|
||||
after = common.shlex_split(kwargs['after'])
|
||||
before = common.shlex_split(kwargs['before'])
|
||||
args = self.resolve_args(defaults, args, extra_args)
|
||||
after = self.sh.shlex_split(kwargs['after'])
|
||||
before = self.sh.shlex_split(kwargs['before'])
|
||||
no_continue = kwargs['no_continue']
|
||||
if kwargs['test']:
|
||||
no_continue = True
|
||||
@@ -122,7 +122,7 @@ def main(args, extra_args=None):
|
||||
break_at = []
|
||||
linux_full_system = (kwargs['baremetal'] is None and kwargs['userland'] is None)
|
||||
if kwargs['userland']:
|
||||
image = common.resolve_userland(kwargs['userland'])
|
||||
image = self.resolve_userland(kwargs['userland'])
|
||||
elif kwargs['baremetal']:
|
||||
image = kwargs['image']
|
||||
test_script_path = os.path.splitext(kwargs['source_path'])[0] + '.py'
|
||||
@@ -133,7 +133,7 @@ def main(args, extra_args=None):
|
||||
else:
|
||||
allowed_toolchains = ['buildroot', 'crosstool-ng', 'host']
|
||||
cmd = (
|
||||
[common.get_toolchain_tool('gdb', allowed_toolchains=allowed_toolchains), LF] +
|
||||
[self.get_toolchain_tool('gdb', allowed_toolchains=allowed_toolchains), LF] +
|
||||
before +
|
||||
['-q', LF]
|
||||
)
|
||||
@@ -195,7 +195,7 @@ def main(args, extra_args=None):
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = common.get_argparse(argparse_args={'description': 'Connect with GDB to an emulator to debug Linux itself'})
|
||||
parser = self.get_argparse(argparse_args={'description': 'Connect with GDB to an emulator to debug Linux itself'})
|
||||
parser.add_argument(
|
||||
'-A', '--after', default=defaults['after'],
|
||||
help='Pass extra arguments to GDB, to be appended after all other arguments'
|
||||
@@ -205,23 +205,23 @@ if __name__ == '__main__':
|
||||
help='Pass extra arguments to GDB to be prepended before any of the arguments passed by this script'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-C', '--no-continue', default=defaults['no_continue'], action='store_true',
|
||||
'-C', '--no-continue', default=defaults['no_continue'],
|
||||
help="Don't run continue after connecting"
|
||||
)
|
||||
parser.add_argument(
|
||||
'-k', '--kgdb', default=defaults['kgdb'], action='store_true'
|
||||
'-k', '--kgdb', default=defaults['kgdb'],
|
||||
)
|
||||
parser.add_argument(
|
||||
'--sim', default=defaults['sim'], action='store_true',
|
||||
'--sim', default=defaults['sim'],
|
||||
help='''Use the built-in GDB CPU simulator
|
||||
See: https://github.com/cirosantilli/linux-kernel-module-cheat#gdb-builtin-cpu-simulator
|
||||
'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'-X', '--no-lxsymbols', default=defaults['no_lxsymbols'], action='store_true'
|
||||
'-X', '--no-lxsymbols', default=defaults['no_lxsymbols'],
|
||||
)
|
||||
parser.add_argument(
|
||||
'--test', default=defaults['test'], action='store_true',
|
||||
'--test', default=defaults['test'],
|
||||
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.
|
||||
@@ -234,5 +234,5 @@ the script is a .py file next to the source code.
|
||||
'break_at', nargs='?',
|
||||
help='Extra options to append at the end of the emulator command line'
|
||||
)
|
||||
args = common.setup(parser)
|
||||
args = self.setup(parser)
|
||||
sys.exit(main(args))
|
||||
|
||||
@@ -7,7 +7,7 @@ import sys
|
||||
import common
|
||||
rungdb = imp.load_source('rungdb', os.path.join(kwargs['root_dir'], 'run-gdb'))
|
||||
|
||||
parser = common.get_argparse(argparse_args={
|
||||
parser = self.get_argparse(argparse_args={
|
||||
'description': '''GDB step debug guest userland processes without gdbserver.
|
||||
|
||||
More information at: https://github.com/cirosantilli/linux-kernel-module-cheat#gdb-step-debug-userland-processes
|
||||
@@ -23,9 +23,9 @@ parser.add_argument(
|
||||
help='Break at this point, e.g. main.',
|
||||
nargs='?'
|
||||
)
|
||||
args = common.setup(parser)
|
||||
executable = common.resolve_userland(kwargs['executable'])
|
||||
addr = common.get_elf_entry(os.path.join(kwargs['buildroot_build_build_dir'], executable))
|
||||
args = self.setup(parser)
|
||||
executable = self.resolve_userland(kwargs['executable'])
|
||||
addr = self.get_elf_entry(os.path.join(kwargs['buildroot_build_build_dir'], executable))
|
||||
extra_args = {}
|
||||
extra_args['before'] = '-ex \"add-symbol-file {} {}\"'.format(executable, hex(addr))
|
||||
# Or else lx-symbols throws for arm:
|
||||
|
||||
@@ -6,7 +6,7 @@ import sys
|
||||
|
||||
import common
|
||||
|
||||
parser = common.get_argparse(argparse_args={
|
||||
parser = self.get_argparse(argparse_args={
|
||||
'description':'Connect to gdbserver running on the guest.'
|
||||
})
|
||||
parser.add_argument(
|
||||
@@ -16,13 +16,13 @@ parser.add_argument(
|
||||
parser.add_argument(
|
||||
'break_at', default='main', nargs='?'
|
||||
)
|
||||
args = common.setup(parser)
|
||||
args = self.setup(parser)
|
||||
sys.exit(subprocess.Popen([
|
||||
common.get_toolchain_tool('gdb'),
|
||||
self.get_toolchain_tool('gdb'),
|
||||
'-q',
|
||||
'-ex', 'set sysroot {}'.format(kwargs['buildroot_staging_dir']),
|
||||
'-ex', 'target remote localhost:{}'.format(kwargs['qemu_hostfwd_generic_port']),
|
||||
'-ex', 'tbreak {}'.format(kwargs['break_at']),
|
||||
'-ex', 'continue',
|
||||
os.path.join(kwargs['buildroot_build_build_dir'], common.resolve_userland(kwargs['executable'])),
|
||||
os.path.join(kwargs['buildroot_build_build_dir'], self.resolve_userland(kwargs['executable'])),
|
||||
]).wait())
|
||||
|
||||
@@ -5,7 +5,7 @@ import sys
|
||||
|
||||
import common
|
||||
|
||||
parser = common.get_argparse(argparse_args={
|
||||
parser = self.get_argparse(argparse_args={
|
||||
'description': '''Run a Buildroot ToolChain tool like readelf or objdump.
|
||||
|
||||
For example, to get some information about the arm vmlinux:
|
||||
@@ -24,7 +24,6 @@ ls "$(./getvar -a arm host_bin_dir)"
|
||||
parser.add_argument(
|
||||
'--dry',
|
||||
help='Just output the tool path to stdout but actually run it',
|
||||
action='store_true',
|
||||
)
|
||||
parser.add_argument('tool', help='Which tool to run.')
|
||||
parser.add_argument(
|
||||
@@ -34,12 +33,12 @@ parser.add_argument(
|
||||
metavar='extra-args',
|
||||
nargs='*'
|
||||
)
|
||||
args = common.setup(parser)
|
||||
args = self.setup(parser)
|
||||
if kwargs['baremetal'] is None:
|
||||
image = kwargs['vmlinux']
|
||||
else:
|
||||
image = kwargs['image']
|
||||
tool= common.get_toolchain_tool(kwargs['tool'])
|
||||
tool= self.get_toolchain_tool(kwargs['tool'])
|
||||
if kwargs['dry']:
|
||||
print(tool)
|
||||
else:
|
||||
|
||||
@@ -6,7 +6,9 @@ import os
|
||||
import shlex
|
||||
import shutil
|
||||
import signal
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
class LF:
|
||||
'''
|
||||
|
||||
@@ -9,7 +9,7 @@ import common
|
||||
run = imp.load_source('run', os.path.join(kwargs['root_dir'], 'run'))
|
||||
qemu_trace2txt = imp.load_source('qemu_trace2txt', os.path.join(kwargs['root_dir'], 'qemu-trace2txt'))
|
||||
|
||||
parser = common.get_argparse(argparse_args={
|
||||
parser = self.get_argparse(argparse_args={
|
||||
'description': '''Trace the PIC addresses executed on a Linux kernel boot.
|
||||
|
||||
More information at: https://github.com/cirosantilli/linux-kernel-module-cheat#tracing
|
||||
@@ -19,7 +19,7 @@ parser.add_argument(
|
||||
'extra_emulator_args', nargs='*',
|
||||
help='Extra options to append at the end of the emulator command line'
|
||||
)
|
||||
args = common.setup(parser)
|
||||
args = self.setup(parser)
|
||||
extra_args = {
|
||||
'extra_emulator_args': kwargs['extra_emulator_args'],
|
||||
}
|
||||
@@ -39,7 +39,7 @@ else:
|
||||
# Instruction count.
|
||||
# We could put this on a separate script, but it just adds more arch boilerplate to a new script.
|
||||
# So let's just leave it here for now since it did not add a significant processing time.
|
||||
kernel_entry_addr = hex(common.get_elf_entry(kwargs['vmlinux']))
|
||||
kernel_entry_addr = hex(self.get_elf_entry(kwargs['vmlinux']))
|
||||
nlines = 0
|
||||
nlines_firmware = 0
|
||||
with open(kwargs['qemu_trace_txt_file'], 'r') as trace_file:
|
||||
|
||||
@@ -14,15 +14,15 @@ import sys
|
||||
|
||||
import common
|
||||
|
||||
parser = common.get_argparse(argparse_args={
|
||||
parser = self.get_argparse(argparse_args={
|
||||
'description': 'Convert an execution trace containing PC values into the Linux kernel linex executed'
|
||||
})
|
||||
args = common.setup(parser)
|
||||
args = self.setup(parser)
|
||||
sys.exit(subprocess.Popen([
|
||||
os.path.join(kwargs['root_dir'], 'trace2line.sh'),
|
||||
'true' if kwargs['emulator'] == 'gem5' else 'false',
|
||||
kwargs['trace_txt_file'],
|
||||
common.get_toolchain_tool('addr2line'),
|
||||
self.get_toolchain_tool('addr2line'),
|
||||
kwargs['vmlinux'],
|
||||
kwargs['run_dir'],
|
||||
]).wait())
|
||||
@@ -40,7 +40,7 @@ sys.exit(subprocess.Popen([
|
||||
# with \
|
||||
# subprocess.Popen(
|
||||
# [
|
||||
# common.get_toolchain_tool('addr2line'),
|
||||
# self.get_toolchain_tool('addr2line'),
|
||||
# '-e',
|
||||
# kwargs['vmlinux'],
|
||||
# '-f',
|
||||
|
||||
Reference in New Issue
Block a user