From 1a0d15ca8624af4942e2afb209ffd50c999ac638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciro=20Santilli=20=E5=85=AD=E5=9B=9B=E4=BA=8B=E4=BB=B6=20?= =?UTF-8?q?=E6=B3=95=E8=BD=AE=E5=8A=9F?= Date: Mon, 11 Mar 2019 00:00:00 +0000 Subject: [PATCH] userland: convert make to python --- README.adoc | 28 ++- build-baremetal | 9 +- build-m5 | 6 +- build-userland | 230 ++++++++++++++++++++----- common.py | 5 +- userland/README.adoc | 2 +- userland/count.c | 1 + userland/cpp/README.adoc | 1 + userland/gcc/README.adoc | 1 + userland/kernel_modules/README.adoc | 1 + userland/linux/README.adoc | 3 + userland/m5ops.c | 52 +++--- userland/m5ops.h | 80 ++++----- userland/netlink.c | 57 +++---- userland/params.mk | 1 - userland/posix/README.adoc | 1 + userland/proc_events.c | 255 ++++++++++++++-------------- userland/sleep_forever.c | 1 + userland/time_boot.c | 1 + 19 files changed, 445 insertions(+), 290 deletions(-) create mode 100644 userland/cpp/README.adoc create mode 100644 userland/gcc/README.adoc create mode 100644 userland/kernel_modules/README.adoc create mode 100644 userland/linux/README.adoc delete mode 100644 userland/params.mk create mode 100644 userland/posix/README.adoc diff --git a/README.adoc b/README.adoc index 651d3e6..0a73786 100644 --- a/README.adoc +++ b/README.adoc @@ -502,8 +502,8 @@ Now rebuild GCC, the program and re-run it: and the new ouptut is now: .... -j = 0 i = 2 +j = 0 .... We need to use the ugly `-final` thing because GCC has to packages in Buildroot, `-initial` and `-final`: https://stackoverflow.com/questions/54992977/how-to-select-an-override-srcdir-source-for-gcc-when-building-buildroot No one is able to example precisely with a minimal example why this is required: @@ -5992,7 +5992,7 @@ Bibliography: https://stackoverflow.com/questions/8516021/proc-create-example-fo ===== /proc/version -Its data is shared with `uname()`, which is a POSIX C function and has a Linux syscall to back it up. +Its data is shared with `uname()`, which is a <> function and has a Linux syscall to back it up. Where the data comes from and how to modify it: @@ -8195,7 +8195,7 @@ TODO a large chunk of tests, the Open POSIX test suite, is disabled with a comme ==== stress -POSIX userland stress. Two versions: +<> userland stress. Two versions: .... ./build-buildroot \ @@ -13117,6 +13117,28 @@ TODO: OpenMP does not like `-static`: See: https://stackoverflow.com/questions/23869981/linking-openmp-statically-with-gcc +===== userland cheats + +We have accumulated considerable material in the following userland subjects. + +====== C + +Programs under link:userland/c/[] are examples of link:https://en.wikipedia.org/wiki/ANSI_C[ANSI C] programming. + +[[cpp]] +====== C++ + +Programs under link:userland/cpp/[] are examples of link:https://en.wikipedia.org/wiki/C%2B%2B#Standardization[ISO C] programming. + +====== POSIX + +Programs under link:userland/posix/[] are examples of POSIX C programming. + +What is POSIX: + +* https://stackoverflow.com/questions/1780599/what-is-the-meaning-of-posix/31865755#31865755 +* https://unix.stackexchange.com/questions/11983/what-exactly-is-posix/220877#220877 + ==== buildroot_packages directory Source: link:buildroot_packages/[] diff --git a/build-baremetal b/build-baremetal index 6273518..de0efcc 100755 --- a/build-baremetal +++ b/build-baremetal @@ -45,7 +45,6 @@ Build the baremetal examples with crosstool-NG. '-nostartfiles', LF, ] cflags_after = ['-lm'] - gcc = self.get_toolchain_tool('gcc') if self.env['emulator'] == 'gem5': if self.env['machine'] == 'VExpress_GEM5_V1': entry_address = 0x80000000 @@ -70,7 +69,7 @@ Build the baremetal examples with crosstool-NG. ) if self.need_rebuild([src], bootloader_obj): self.sh.run_cmd( - [gcc, LF] + + [self.env['gcc'], LF] + cflags + [ '-c', LF, @@ -85,7 +84,7 @@ Build the baremetal examples with crosstool-NG. ]: if self.need_rebuild([src, self.env['common_h']], obj): self.sh.run_cmd( - [gcc, LF] + + [self.env['gcc'], LF] + cflags + [ '-c', LF, @@ -125,7 +124,7 @@ Build the baremetal examples with crosstool-NG. src = os.path.join(self.env['baremetal_source_dir'], in_path) if self.need_rebuild([src, self.env['common_h']], main_obj): self.sh.run_cmd( - [gcc, LF] + + [self.env['gcc'], LF] + cflags + [ '-c', LF, @@ -138,7 +137,7 @@ Build the baremetal examples with crosstool-NG. out = os.path.join(out_dir, in_name + self.env['baremetal_build_ext']) if self.need_rebuild(objs + [self.env['baremetal_link_script']], out): self.sh.run_cmd( - [gcc, LF] + + [self.env['gcc'], LF] + cflags + [ '-Wl,--section-start=.text={:#x}'.format(entry_address), LF, diff --git a/build-m5 b/build-m5 index a62830b..dba3f0f 100755 --- a/build-m5 +++ b/build-m5 @@ -8,8 +8,6 @@ from shell_helpers import LF class Main(common.BuildCliFunction): def _get_make_cmd(self): allowed_toolchains = ['buildroot'] - cc = self.get_toolchain_tool('gcc') - ld = self.get_toolchain_tool('ld') if self.env['arch'] == 'x86_64': arch = 'x86' else: @@ -18,8 +16,8 @@ class Main(common.BuildCliFunction): 'make', LF, '-j', str(self.env['nproc']), LF, '-f', 'Makefile.{}'.format(arch), LF, - 'CC={}'.format(cc), LF, - 'LD={}'.format(ld), LF, + 'CC={}'.format(self.env['gcc']), LF, + 'LD={}'.format(self.env['ld']), LF, 'PWD={}'.format(self.env['gem5_m5_source_dir']), LF, ] diff --git a/build-userland b/build-userland index cbc700f..7412c0b 100755 --- a/build-userland +++ b/build-userland @@ -4,6 +4,7 @@ import os import shlex import common +import subprocess from shell_helpers import LF class Main(common.BuildCliFunction): @@ -22,18 +23,6 @@ Indicate that a given package is present in the root filesystem, which allows us to build examples that rely on it. ''', ) - self.add_argument( - '--host', - default=False, - help='''\ -Build the userland programs for the host instead of guest. -Use the host packaged cross toolchain. -''', - ) - self.add_argument( - '--make-args', - default='', - ) self.add_argument( 'targets', default=[], @@ -46,43 +35,196 @@ has the OpenBLAS libraries and headers installed. nargs='*', ) + def _build_one( + self, + in_path, + out_path, + ccflags, + extra_deps=None, + link=True, + extra_objs=None, + std=None, + ccflags_after=None, + ): + if extra_deps is None: + extra_deps = [] + if extra_objs is None: + extra_objs = [] + if ccflags_after is None: + ccflags_after = [] + if self.need_rebuild([in_path] + extra_objs + extra_deps, out_path): + ccflags = ccflags.copy() + if not link: + ccflags.extend(['-c', LF]) + in_ext = os.path.splitext(in_path)[1] + if in_ext == self.env['c_ext']: + cc = self.env['gcc'] + if std is None: + std = 'c11' + ccflags.extend([ + '-fopenmp', LF, + ]) + elif in_ext == self.env['cxx_ext']: + cc = self.env['gxx'] + if std is None: + std = 'c++17' + else: + return + self.sh.run_cmd( + [ + cc, LF, + ] + + ccflags + + [ + '-std={}'.format(std), LF, + '-o', out_path, LF, + in_path, LF, + ] + + extra_objs + + [ + '-lm', LF, + '-pthread', LF, + ] + + ccflags_after + ) + def build(self): build_dir = self.get_build_dir() os.makedirs(build_dir, exist_ok=True) - make_args = shlex.split(self.env['make_args']) + has_packages = set(self.env['has_package']) + ccflags = [ + '-I', self.env['root_dir'], LF, + '-I', self.env['userland_source_dir'], LF, + '-O0', LF, + '-Wall', LF, + '-Werror', LF, + '-Wextra', LF, + '-Wno-unused-function', LF, + '-pedantic', LF, + '-ggdb3', LF, + ] if self.env['static']: - make_args.extend(['CCFLAGS_EXTRA=-static', LF]) - self.sh.run_cmd( - ( - [ - 'make', LF, - '-j', str(self.env['nproc']), LF, - 'ARCH={}'.format(self.env['arch']), LF, - 'CCFLAGS_SCRIPT={} {}'.format('-I', self.env['userland_source_dir']), LF, - 'COMMON_DIR={}'.format(self.env['root_dir']), LF, - 'CC={}'.format(self.get_toolchain_tool('gcc')), LF, - 'CXX={}'.format(self.get_toolchain_tool('g++')), LF, - 'PKG_CONFIG={}'.format(self.env['buildroot_pkg_config']), LF, - 'STAGING_DIR={}'.format(self.env['buildroot_staging_dir']), LF, - 'OUT_DIR={}'.format(build_dir), LF, - ] + - self.sh.add_newlines([ - 'HAS_{}=y'.format(package.upper()) - for package in - self.env['has_package'] - ]) + - make_args + - self.sh.add_newlines([ - os.path.join( - build_dir, - os.path.splitext(os.path.split(target)[1])[0] - ) + self.env['userland_build_ext'] - for target in self.env['targets'] - ]) - ), - cwd=self.env['userland_source_dir'], - extra_paths=[self.env['ccache_dir']], + ccflags.extend(['-static', LF]) + common_obj = os.path.join( + build_dir, + self.env['common_basename_noext'] + self.env['obj_ext'] ) + self._build_one( + in_path=self.env['common_c'], + out_path=common_obj, + ccflags=ccflags, + extra_deps=[self.env['common_h']], + link=False, + ) + pkgs = { + 'eigen': { + # TODO: was failing with: + # fatal error: Eigen/Dense: No such file or directory as of + # 975ce0723ee3fa1fea1766e6683e2f3acb8558d6 + # http://lists.busybox.net/pipermail/buildroot/2018-June/222914.html + 'ccflags': [ + '-I', + os.path.join( + self.env['buildroot_staging_dir'], + 'usr', + 'include', + 'eigen3' + ), + LF + ], + # Header only. + 'ccflags_after': [], + }, + 'libdrm': {}, + 'openblas': {}, + } + rootdir_abs_len = len(self.env['userland_source_dir']) + for path, in_dirnames, in_filenames in os.walk(self.env['userland_source_dir']): + in_dirnames.sort() + dirpath_relative_root = path[rootdir_abs_len + 1:] + dirpath_relative_root_components = dirpath_relative_root.split(os.sep) + if ( + len(dirpath_relative_root_components) < 2 or + dirpath_relative_root_components[0] != 'arch' or + dirpath_relative_root_components[1] == self.env['arch'] + ): + out_dir = os.path.join( + self.env['userland_build_dir'], + dirpath_relative_root + ) + os.makedirs(out_dir, exist_ok=True) + for in_filename in in_filenames: + in_path = os.path.join(path, in_filename) + in_name, in_ext = os.path.splitext(in_filename) + out_path = os.path.join( + out_dir, + in_name + self.env['userland_build_ext'] + ) + pkg_key = in_name.split('_')[0] + ccflags_file = ccflags.copy() + ccflags_after = [] + if pkg_key in pkgs: + if pkg_key not in has_packages: + continue + pkg = pkgs[pkg_key] + if 'ccflags' in pkg: + ccflags_file.extend(pkg['ccflags']) + else: + pkg_config_output = subprocess.check_output([ + self.env['buildroot_pkg_config'], + '--cflags', + pkg_key + ]).decode() + ccflags_file.extend(self.sh.shlex_split(pkg_config_output)) + if 'ccflags_after' in pkg: + ccflags_file.extend(pkg['ccflags_after']) + else: + pkg_config_output = subprocess.check_output([ + self.env['buildroot_pkg_config'], + '--libs', + pkg_key + ]).decode() + ccflags_after.extend(self.sh.shlex_split(pkg_config_output)) + self._build_one( + in_path=in_path, + out_path=out_path, + ccflags=ccflags_file, + extra_objs=[common_obj], + ccflags_after=ccflags_after, + ) + + #self.sh.run_cmd( + # ( + # [ + # 'make', LF, + # '-j', str(self.env['nproc']), LF, + # 'ARCH={}'.format(self.env['arch']), LF, + # 'CCFLAGS_SCRIPT={} {}'.format('-I', self.env['userland_source_dir']), LF, + # 'COMMON_DIR={}'.format(self.env['root_dir']), LF, + # 'CC={}'.format(self.env['gcc']), LF, + # 'CXX={}'.format(self.env['gxx']), LF, + # 'PKG_CONFIG={}'.format(self.env['buildroot_pkg_config']), LF, + # 'STAGING_DIR={}'.format(self.env['buildroot_staging_dir']), LF, + # 'OUT_DIR={}'.format(build_dir), LF, + # ] + + # self.sh.add_newlines([ + # 'HAS_{}=y'.format(package.upper()) + # for package in + # self.env['has_package'] + # ]) + + # make_args + + # self.sh.add_newlines([ + # os.path.join( + # build_dir, + # os.path.splitext(os.path.split(target)[1])[0] + # ) + self.env['userland_build_ext'] + # for target in self.env['targets'] + # ]) + # ), + # cwd=self.env['userland_source_dir'], + # extra_paths=[self.env['ccache_dir']], + #) + self.sh.copy_dir_if_update( srcdir=build_dir, destdir=self.env['out_rootfs_overlay_dir'], diff --git a/common.py b/common.py index e725218..dbd3173 100644 --- a/common.py +++ b/common.py @@ -94,6 +94,7 @@ consts['release_zip_file'] = os.path.join(consts['release_dir'], 'lkmc-{}.zip'.f consts['github_repo_id'] = 'cirosantilli/linux-kernel-module-cheat' consts['asm_ext'] = '.S' consts['c_ext'] = '.c' +consts['cxx_ext'] = '.cpp' consts['header_ext'] = '.h' consts['kernel_module_ext'] = '.ko' consts['obj_ext'] = '.o' @@ -796,7 +797,7 @@ Valid emulators: {} lunch aosp_{}-eng '''.format(self.env['android_arch']) - # Toolchain choice. + # Toolchain. if not env['_args_given']['gcc_which']: if env['baremetal']: env['gcc_which'] = 'crosstool-ng' @@ -826,6 +827,8 @@ lunch aosp_{}-eng raise Exception('There is no host baremetal chain for arch: ' + env['arch']) else: raise Exception('Unknown toolchain: ' + env['gcc_which']) + env['gcc'] = self.get_toolchain_tool('gcc') + env['gxx'] = self.get_toolchain_tool('g++') def add_argument(self, *args, **kwargs): ''' diff --git a/userland/README.adoc b/userland/README.adoc index 8f1808c..78fdc90 100644 --- a/userland/README.adoc +++ b/userland/README.adoc @@ -1 +1 @@ -https://github.com/cirosantilli/linux-kernel-module-cheat#userland-directory +https://github.com/cirosantilli/linux-kernel-module-cheat#ansi-c diff --git a/userland/count.c b/userland/count.c index 9a29b32..9b625ca 100644 --- a/userland/count.c +++ b/userland/count.c @@ -1,3 +1,4 @@ +#define _XOPEN_SOURCE 700 #include #include #include diff --git a/userland/cpp/README.adoc b/userland/cpp/README.adoc new file mode 100644 index 0000000..bb60001 --- /dev/null +++ b/userland/cpp/README.adoc @@ -0,0 +1 @@ +https://github.com/cirosantilli/linux-kernel-module-cheat#ansi-cpp diff --git a/userland/gcc/README.adoc b/userland/gcc/README.adoc new file mode 100644 index 0000000..3b0eb34 --- /dev/null +++ b/userland/gcc/README.adoc @@ -0,0 +1 @@ +Programs in this directory use GCC extensions. diff --git a/userland/kernel_modules/README.adoc b/userland/kernel_modules/README.adoc new file mode 100644 index 0000000..50868f9 --- /dev/null +++ b/userland/kernel_modules/README.adoc @@ -0,0 +1 @@ +Programs in this directory rely on / test functionality provided by kernel modules. diff --git a/userland/linux/README.adoc b/userland/linux/README.adoc new file mode 100644 index 0000000..fd45463 --- /dev/null +++ b/userland/linux/README.adoc @@ -0,0 +1,3 @@ +Programs in this directory rely on Linux kernel specific functionality such as `/proc`. + +These programs may also conform to ANSI C or POSIX, but we put them here because you can only observe them at work under Linux. diff --git a/userland/m5ops.c b/userland/m5ops.c index f49735a..16b73ab 100644 --- a/userland/m5ops.c +++ b/userland/m5ops.c @@ -6,31 +6,29 @@ #include "m5ops.h" -int main(int argc, char **argv) -{ - char action; - if (argc > 1) { - action = argv[1][0]; - } else { - action = 'e'; - } - switch (action) - { - case 'c': - m5_checkpoint(); - break; - case 'd': - m5_dumpstats(); - break; - case 'e': - m5_exit(); - break; - case 'f': - m5_fail_1(); - break; - case 'r': - m5_resetstats(); - break; - } - return EXIT_SUCCESS; +int main(int argc, char **argv) { + char action; + if (argc > 1) { + action = argv[1][0]; + } else { + action = 'e'; + } + switch (action) { + case 'c': + m5_checkpoint(); + break; + case 'd': + m5_dumpstats(); + break; + case 'e': + m5_exit(); + break; + case 'f': + m5_fail_1(); + break; + case 'r': + m5_resetstats(); + break; + } + return EXIT_SUCCESS; } diff --git a/userland/m5ops.h b/userland/m5ops.h index 9d4679c..82dce5c 100644 --- a/userland/m5ops.h +++ b/userland/m5ops.h @@ -2,53 +2,43 @@ #define M5OPS_H #if defined(__arm__) -static void m5_checkpoint(void) -{ - __asm__ __volatile__ ("mov r0, #0; mov r1, #0; mov r2, #0; mov r3, #0; .inst 0xEE000110 | (0x43 << 16);" : : : "r0", "r1", "r2", "r3"); -}; -static void m5_dumpstats(void) -{ - __asm__ __volatile__ ("mov r0, #0; mov r1, #0; mov r2, #0; mov r3, #0; .inst 0xEE000110 | (0x41 << 16);" : : : "r0", "r1", "r2", "r3"); -}; -static void m5_exit() -{ - __asm__ __volatile__ ("mov r0, #0; mov r1, #0; .inst 0xEE000110 | (0x21 << 16);" : : : "r0", "r1"); -}; -static void m5_fail_1(void) -{ - __asm__ __volatile__ ("mov r0, #0; mov r1, #0; mov r2, #1; mov r3, #0; .inst 0xEE000110 | (0x22 << 16);" : : : "r0", "r1", "r2", "r3"); -}; -static void m5_resetstats(void) -{ - __asm__ __volatile__ ("mov r0, #0; mov r1, #0; mov r2, #0; mov r3, #0; .inst 0xEE000110 | (0x40 << 16);" : : : "r0", "r1", "r2", "r3"); -}; +static void m5_checkpoint(void) { + __asm__ __volatile__ ("mov r0, #0; mov r1, #0; mov r2, #0; mov r3, #0; .inst 0xEE000110 | (0x43 << 16);" : : : "r0", "r1", "r2", "r3"); +} +static void m5_dumpstats(void) { + __asm__ __volatile__ ("mov r0, #0; mov r1, #0; mov r2, #0; mov r3, #0; .inst 0xEE000110 | (0x41 << 16);" : : : "r0", "r1", "r2", "r3"); +} +static void m5_exit() { + __asm__ __volatile__ ("mov r0, #0; mov r1, #0; .inst 0xEE000110 | (0x21 << 16);" : : : "r0", "r1"); +} +static void m5_fail_1(void) { + __asm__ __volatile__ ("mov r0, #0; mov r1, #0; mov r2, #1; mov r3, #0; .inst 0xEE000110 | (0x22 << 16);" : : : "r0", "r1", "r2", "r3"); +} +static void m5_resetstats(void) { + __asm__ __volatile__ ("mov r0, #0; mov r1, #0; mov r2, #0; mov r3, #0; .inst 0xEE000110 | (0x40 << 16);" : : : "r0", "r1", "r2", "r3"); +} #elif defined(__aarch64__) -static void m5_checkpoint(void) -{ - __asm__ __volatile__ ("mov x0, #0; mov x1, #0; .inst 0xFF000110 | (0x43 << 16);" : : : "x0", "x1"); -}; -static void m5_dumpstats(void) -{ - __asm__ __volatile__ ("mov x0, #0; mov x1, #0; .inst 0xFF000110 | (0x41 << 16);" : : : "x0", "x1"); -}; -static void m5_exit(void) -{ - __asm__ __volatile__ ("mov x0, #0; .inst 0XFF000110 | (0x21 << 16);" : : : "x0"); -}; -static void m5_fail_1(void) -{ - __asm__ __volatile__ ("mov x0, #0; mov x1, #1; .inst 0xFF000110 | (0x22 << 16);" : : : "x0", "x1"); -}; -static void m5_resetstats(void) -{ - __asm__ __volatile__ ("mov x0, #0; mov x1, #0; .inst 0XFF000110 | (0x40 << 16);" : : : "x0", "x1"); -}; +static void m5_checkpoint(void) { + __asm__ __volatile__ ("mov x0, #0; mov x1, #0; .inst 0xFF000110 | (0x43 << 16);" : : : "x0", "x1"); +} +static void m5_dumpstats(void) { + __asm__ __volatile__ ("mov x0, #0; mov x1, #0; .inst 0xFF000110 | (0x41 << 16);" : : : "x0", "x1"); +} +static void m5_exit(void) { + __asm__ __volatile__ ("mov x0, #0; .inst 0XFF000110 | (0x21 << 16);" : : : "x0"); +} +static void m5_fail_1(void) { + __asm__ __volatile__ ("mov x0, #0; mov x1, #1; .inst 0xFF000110 | (0x22 << 16);" : : : "x0", "x1"); +} +static void m5_resetstats(void) { + __asm__ __volatile__ ("mov x0, #0; mov x1, #0; .inst 0XFF000110 | (0x40 << 16);" : : : "x0", "x1"); +} #else -static void m5_checkpoint(void) {}; -static void m5_dumpstats(void) {}; -static void m5_exit(void) {}; -static void m5_fail_1(void) {}; -static void m5_resetstats(void) {}; +static void m5_checkpoint(void) {} +static void m5_dumpstats(void) {} +static void m5_exit(void) {} +static void m5_fail_1(void) {} +static void m5_resetstats(void) {} #endif #endif diff --git a/userland/netlink.c b/userland/netlink.c index a5caebc..fa37cfb 100644 --- a/userland/netlink.c +++ b/userland/netlink.c @@ -20,33 +20,32 @@ struct msghdr msg; struct nlmsghdr *nlh; struct sockaddr_nl src_addr, dest_addr; -int main(void) -{ - sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER); - if (sock_fd < 0) { - perror("socket"); - return EXIT_FAILURE; - } - src_addr.nl_family = AF_NETLINK; - src_addr.nl_pid = getpid(); - bind(sock_fd, (struct sockaddr *)&src_addr, sizeof(src_addr)); - dest_addr.nl_family = AF_NETLINK; - nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD)); - memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD)); - nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD); - nlh->nlmsg_pid = getpid(); - nlh->nlmsg_flags = 0; - strcpy(NLMSG_DATA(nlh), "user request"); - iov.iov_base = (void *)nlh; - iov.iov_len = nlh->nlmsg_len; - msg.msg_name = (void *)&dest_addr; - msg.msg_namelen = sizeof(dest_addr); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - fprintf(stderr, "before sendmsg\n"); - sendmsg(sock_fd, &msg, 0); - fprintf(stderr, "after sendmsg\n"); - recvmsg(sock_fd, &msg, 0); - printf("%s\n", (char *)NLMSG_DATA(nlh)); - close(sock_fd); +int main(void) { + sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER); + if (sock_fd < 0) { + perror("socket"); + return EXIT_FAILURE; + } + src_addr.nl_family = AF_NETLINK; + src_addr.nl_pid = getpid(); + bind(sock_fd, (struct sockaddr *)&src_addr, sizeof(src_addr)); + dest_addr.nl_family = AF_NETLINK; + nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD)); + memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD)); + nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD); + nlh->nlmsg_pid = getpid(); + nlh->nlmsg_flags = 0; + strcpy(NLMSG_DATA(nlh), "user request"); + iov.iov_base = (void *)nlh; + iov.iov_len = nlh->nlmsg_len; + msg.msg_name = (void *)&dest_addr; + msg.msg_namelen = sizeof(dest_addr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + fprintf(stderr, "before sendmsg\n"); + sendmsg(sock_fd, &msg, 0); + fprintf(stderr, "after sendmsg\n"); + recvmsg(sock_fd, &msg, 0); + printf("%s\n", (char *)NLMSG_DATA(nlh)); + close(sock_fd); } diff --git a/userland/params.mk b/userland/params.mk deleted file mode 100644 index eb2a8ce..0000000 --- a/userland/params.mk +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS := interactive arch/$(ARCH)/ diff --git a/userland/posix/README.adoc b/userland/posix/README.adoc new file mode 100644 index 0000000..9489bb2 --- /dev/null +++ b/userland/posix/README.adoc @@ -0,0 +1 @@ +https://github.com/cirosantilli/linux-kernel-module-cheat#posix diff --git a/userland/proc_events.c b/userland/proc_events.c index fefe6c4..9879b3f 100644 --- a/userland/proc_events.c +++ b/userland/proc_events.c @@ -24,153 +24,148 @@ int main(void) {} static volatile bool need_exit = false; -static int nl_connect() -{ - int rc; - int nl_sock; - struct sockaddr_nl sa_nl; +static int nl_connect() { + int rc; + int nl_sock; + struct sockaddr_nl sa_nl; - nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); - if (nl_sock == -1) { - perror("socket"); - return -1; - } - sa_nl.nl_family = AF_NETLINK; - sa_nl.nl_groups = CN_IDX_PROC; - sa_nl.nl_pid = getpid(); - rc = bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl)); - if (rc == -1) { - perror("bind"); - close(nl_sock); - return -1; - } - return nl_sock; + nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); + if (nl_sock == -1) { + perror("socket"); + return -1; + } + sa_nl.nl_family = AF_NETLINK; + sa_nl.nl_groups = CN_IDX_PROC; + sa_nl.nl_pid = getpid(); + rc = bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl)); + if (rc == -1) { + perror("bind"); + close(nl_sock); + return -1; + } + return nl_sock; } -static int set_proc_ev_listen(int nl_sock, bool enable) -{ - int rc; - struct __attribute__ ((aligned(NLMSG_ALIGNTO))) { - struct nlmsghdr nl_hdr; - struct __attribute__ ((__packed__)) { - struct cn_msg cn_msg; - enum proc_cn_mcast_op cn_mcast; - }; - } nlcn_msg; +static int set_proc_ev_listen(int nl_sock, bool enable) { + int rc; + struct __attribute__ ((aligned(NLMSG_ALIGNTO))) { + struct nlmsghdr nl_hdr; + struct __attribute__ ((__packed__)) { + struct cn_msg cn_msg; + enum proc_cn_mcast_op cn_mcast; + }; + } nlcn_msg; - memset(&nlcn_msg, 0, sizeof(nlcn_msg)); - nlcn_msg.nl_hdr.nlmsg_len = sizeof(nlcn_msg); - nlcn_msg.nl_hdr.nlmsg_pid = getpid(); - nlcn_msg.nl_hdr.nlmsg_type = NLMSG_DONE; + memset(&nlcn_msg, 0, sizeof(nlcn_msg)); + nlcn_msg.nl_hdr.nlmsg_len = sizeof(nlcn_msg); + nlcn_msg.nl_hdr.nlmsg_pid = getpid(); + nlcn_msg.nl_hdr.nlmsg_type = NLMSG_DONE; - nlcn_msg.cn_msg.id.idx = CN_IDX_PROC; - nlcn_msg.cn_msg.id.val = CN_VAL_PROC; - nlcn_msg.cn_msg.len = sizeof(enum proc_cn_mcast_op); + nlcn_msg.cn_msg.id.idx = CN_IDX_PROC; + nlcn_msg.cn_msg.id.val = CN_VAL_PROC; + nlcn_msg.cn_msg.len = sizeof(enum proc_cn_mcast_op); - nlcn_msg.cn_mcast = enable ? PROC_CN_MCAST_LISTEN : PROC_CN_MCAST_IGNORE; + nlcn_msg.cn_mcast = enable ? PROC_CN_MCAST_LISTEN : PROC_CN_MCAST_IGNORE; - rc = send(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0); - if (rc == -1) { - perror("netlink send"); - return -1; - } + rc = send(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0); + if (rc == -1) { + perror("netlink send"); + return -1; + } - return 0; + return 0; } -static int handle_proc_ev(int nl_sock) -{ - int rc; - struct __attribute__ ((aligned(NLMSG_ALIGNTO))) { - struct nlmsghdr nl_hdr; - struct __attribute__ ((__packed__)) { - struct cn_msg cn_msg; - struct proc_event proc_ev; - }; - } nlcn_msg; - while (!need_exit) { - rc = recv(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0); - if (rc == 0) { - return 0; - } else if (rc == -1) { - if (errno == EINTR) continue; - perror("netlink recv"); - return -1; - } - switch (nlcn_msg.proc_ev.what) { - case PROC_EVENT_NONE: - printf("set mcast listen ok\n"); - break; - case PROC_EVENT_FORK: - printf("fork: parent tid=%d pid=%d -> child tid=%d pid=%d\n", - nlcn_msg.proc_ev.event_data.fork.parent_pid, - nlcn_msg.proc_ev.event_data.fork.parent_tgid, - nlcn_msg.proc_ev.event_data.fork.child_pid, - nlcn_msg.proc_ev.event_data.fork.child_tgid); - break; - case PROC_EVENT_EXEC: - printf("exec: tid=%d pid=%d\n", - nlcn_msg.proc_ev.event_data.exec.process_pid, - nlcn_msg.proc_ev.event_data.exec.process_tgid); - break; - case PROC_EVENT_UID: - printf("uid change: tid=%d pid=%d from %d to %d\n", - nlcn_msg.proc_ev.event_data.id.process_pid, - nlcn_msg.proc_ev.event_data.id.process_tgid, - nlcn_msg.proc_ev.event_data.id.r.ruid, - nlcn_msg.proc_ev.event_data.id.e.euid); - break; - case PROC_EVENT_GID: - printf("gid change: tid=%d pid=%d from %d to %d\n", - nlcn_msg.proc_ev.event_data.id.process_pid, - nlcn_msg.proc_ev.event_data.id.process_tgid, - nlcn_msg.proc_ev.event_data.id.r.rgid, - nlcn_msg.proc_ev.event_data.id.e.egid); - break; - case PROC_EVENT_EXIT: - printf("exit: tid=%d pid=%d exit_code=%d\n", - nlcn_msg.proc_ev.event_data.exit.process_pid, - nlcn_msg.proc_ev.event_data.exit.process_tgid, - nlcn_msg.proc_ev.event_data.exit.exit_code); - break; - default: - printf("unhandled proc event\n"); - break; - } - } +static int handle_proc_ev(int nl_sock) { + int rc; + struct __attribute__ ((aligned(NLMSG_ALIGNTO))) { + struct nlmsghdr nl_hdr; + struct __attribute__ ((__packed__)) { + struct cn_msg cn_msg; + struct proc_event proc_ev; + }; + } nlcn_msg; + while (!need_exit) { + rc = recv(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0); + if (rc == 0) { + return 0; + } else if (rc == -1) { + if (errno == EINTR) continue; + perror("netlink recv"); + return -1; + } + switch (nlcn_msg.proc_ev.what) { + case PROC_EVENT_NONE: + printf("set mcast listen ok\n"); + break; + case PROC_EVENT_FORK: + printf("fork: parent tid=%d pid=%d -> child tid=%d pid=%d\n", + nlcn_msg.proc_ev.event_data.fork.parent_pid, + nlcn_msg.proc_ev.event_data.fork.parent_tgid, + nlcn_msg.proc_ev.event_data.fork.child_pid, + nlcn_msg.proc_ev.event_data.fork.child_tgid); + break; + case PROC_EVENT_EXEC: + printf("exec: tid=%d pid=%d\n", + nlcn_msg.proc_ev.event_data.exec.process_pid, + nlcn_msg.proc_ev.event_data.exec.process_tgid); + break; + case PROC_EVENT_UID: + printf("uid change: tid=%d pid=%d from %d to %d\n", + nlcn_msg.proc_ev.event_data.id.process_pid, + nlcn_msg.proc_ev.event_data.id.process_tgid, + nlcn_msg.proc_ev.event_data.id.r.ruid, + nlcn_msg.proc_ev.event_data.id.e.euid); + break; + case PROC_EVENT_GID: + printf("gid change: tid=%d pid=%d from %d to %d\n", + nlcn_msg.proc_ev.event_data.id.process_pid, + nlcn_msg.proc_ev.event_data.id.process_tgid, + nlcn_msg.proc_ev.event_data.id.r.rgid, + nlcn_msg.proc_ev.event_data.id.e.egid); + break; + case PROC_EVENT_EXIT: + printf("exit: tid=%d pid=%d exit_code=%d\n", + nlcn_msg.proc_ev.event_data.exit.process_pid, + nlcn_msg.proc_ev.event_data.exit.process_tgid, + nlcn_msg.proc_ev.event_data.exit.exit_code); + break; + default: + printf("unhandled proc event\n"); + break; + } + } - return 0; + return 0; } -static void on_sigint(__attribute__ ((unused)) int unused) -{ - need_exit = true; +static void on_sigint(__attribute__ ((unused)) int unused) { + need_exit = true; } -int main(void) -{ - int nl_sock; - int rc = EXIT_SUCCESS; +int main(void) { + int nl_sock; + int rc = EXIT_SUCCESS; - signal(SIGINT, &on_sigint); - siginterrupt(SIGINT, true); - nl_sock = nl_connect(); - if (nl_sock == -1) - exit(EXIT_FAILURE); - rc = set_proc_ev_listen(nl_sock, true); - if (rc == -1) { - rc = EXIT_FAILURE; - goto out; - } - rc = handle_proc_ev(nl_sock); - if (rc == -1) { - rc = EXIT_FAILURE; - goto out; - } - set_proc_ev_listen(nl_sock, false); + signal(SIGINT, &on_sigint); + siginterrupt(SIGINT, true); + nl_sock = nl_connect(); + if (nl_sock == -1) + exit(EXIT_FAILURE); + rc = set_proc_ev_listen(nl_sock, true); + if (rc == -1) { + rc = EXIT_FAILURE; + goto out; + } + rc = handle_proc_ev(nl_sock); + if (rc == -1) { + rc = EXIT_FAILURE; + goto out; + } + set_proc_ev_listen(nl_sock, false); out: - close(nl_sock); - exit(rc); + close(nl_sock); + exit(rc); } #endif diff --git a/userland/sleep_forever.c b/userland/sleep_forever.c index 4676458..cba5228 100644 --- a/userland/sleep_forever.c +++ b/userland/sleep_forever.c @@ -1,5 +1,6 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#sleep_forever-out */ +#define _XOPEN_SOURCE 700 #include #include diff --git a/userland/time_boot.c b/userland/time_boot.c index babec6e..5b38929 100644 --- a/userland/time_boot.c +++ b/userland/time_boot.c @@ -1,5 +1,6 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#time_boot-out */ +#define _XOPEN_SOURCE 700 #include #include