diff --git a/AGENTS.md b/AGENTS.md index 4d9b646..aaabc4a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -89,6 +89,7 @@ docs/ AsciiDoc documentation, file format spec, diagrams. - Meta entries are ordinary `static const` objects; each call site emits a pointer pair `{meta, file-offset cache}` into the custom ELF section `_clltk__metaptr` via an inline-asm `.pushsection` data directive. The constructor registers every meta at startup and writes the resolved file offset into the cache, so the first tracepoint execution needs no lookup (NOT via `__attribute__((section(...)))` -- the attribute would join the enclosing function's COMDAT group inside inline functions and templates, and GCC >= 15.2 rejects mixing grouped and ungrouped sections of the same name). Buffer names MUST be valid C identifiers. - Constructor/destructor priority is 101 (very early). User code with priority < 101 cannot use tracing; at priority exactly 101 the order against clltk's own constructor/destructor is emission-order dependent (LTO flips it), so tracing there is undefined -- it may or may not be recorded. - `_CLLTK_INTERNAL` define gates macro expansion. The library itself compiles with `-D_CLLTK_INTERNAL`; consumer code must NOT define it. +- Kernel modules register at load through TWO paths, both idempotent: the per-module constructor (needs `CONFIG_CONSTRUCTORS`, off in most production kernels) AND a module notifier registered by the clltk kernel module (`register_module_notifier`, works on any kernel). Do not remove the notifier assuming the constructor suffices -- without `CONFIG_CONSTRUCTORS` the constructor never runs and tracing would silently do nothing. ### API Typo -- Do NOT Fix - `clltk_unrecoverbale_error_callback` has a typo ("unrecoverbale"). This IS the public API. Fixing the spelling would be a breaking change. diff --git a/VERSION.md b/VERSION.md index ddce9a0..24d20f4 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1,6 +1,13 @@ -1.7.3 +1.7.4 # Change log +## 1.7.4 +- fix: kernel tracing registers via a module notifier, so it works on kernels built + without CONFIG_CONSTRUCTORS (the default for most production kernels). Registration + previously ran only from a module constructor, which such kernels never call - the + module loaded but tracing silently did nothing. The constructor path is kept for + CONFIG_CONSTRUCTORS kernels; both are idempotent. + ## 1.7.3 - docs: README fixes and additions - remove the (now lifted) in-class-member-function tracing limitation, correct the minimal-build feature flags and the decoder output diff --git a/kernel_tracing_library/src/module.c b/kernel_tracing_library/src/module.c index 8eb6575..cc1a8a8 100644 --- a/kernel_tracing_library/src/module.c +++ b/kernel_tracing_library/src/module.c @@ -2,6 +2,7 @@ // SPDX-License-Identifier: BSD-2-Clause-Patent #include +#include #include "CommonLowLevelTracingKit/tracing/tracing.h" @@ -10,12 +11,49 @@ char *tracing_path = "/tmp/"; module_param(tracing_path, charp, 0000); MODULE_PARM_DESC(tracing_path, "path where to write the traces"); +// Registration of a traced module's tracebuffers/tracepoints runs from a C +// constructor injected into that module (see _kernel_tracing.h). The kernel +// only calls module constructors when CONFIG_CONSTRUCTORS is enabled, which is +// off in most production kernels - so on those the constructor never fires and +// tracing silently does nothing. +// +// A module notifier does the same work on any kernel and needs no cooperation +// from the traced module: the kernel calls it as each module is (un)loaded. +// Both paths are idempotent, so on a CONFIG_CONSTRUCTORS kernel the constructor +// and the notifier simply agree. +void _clltk_init_tracing_for_this_module(const struct mod_kallsyms *); +void _clltk_deinit_tracing_for_this_module(const struct mod_kallsyms *); + +static int clltk_module_notify(struct notifier_block *nb, unsigned long action, void *data) +{ + struct module *const mod = data; + (void)nb; + switch (action) { + case MODULE_STATE_COMING: // linked, before the module runs its own init + _clltk_init_tracing_for_this_module(mod->kallsyms); + break; + case MODULE_STATE_GOING: // being removed + _clltk_deinit_tracing_for_this_module(mod->kallsyms); + break; + default: + break; + } + return NOTIFY_OK; +} + +static struct notifier_block clltk_module_nb = { + .notifier_call = clltk_module_notify, +}; + static int __init init_clltk_kf(void) { - return 0; + return register_module_notifier(&clltk_module_nb); } -static void __exit exit_clltk_kf(void) {} +static void __exit exit_clltk_kf(void) +{ + unregister_module_notifier(&clltk_module_nb); +} module_init(init_clltk_kf); module_exit(exit_clltk_kf); diff --git a/scripts/ci-cd/step_static_analysis.sh b/scripts/ci-cd/step_static_analysis.sh index d56744e..5d76c0f 100755 --- a/scripts/ci-cd/step_static_analysis.sh +++ b/scripts/ci-cd/step_static_analysis.sh @@ -173,16 +173,18 @@ run_clang_tidy_diff() { # root; tell git the mount is trusted so `git diff` works git config --global --add safe.directory "$ROOT_PATH" 2>/dev/null || true - # Only source files: headers are not translation units (not in - # compile_commands.json), and some intentionally #error when compiled - # standalone. Header changes are still covered by the full builds and by - # clang-tidy of the sources that include them. + # Only source files that cmake actually compiles: headers are not + # translation units (not in compile_commands.json), and some intentionally + # #error when compiled standalone. Kernel-module sources are built by Kbuild, + # not cmake, so they are absent from compile_commands.json too - clang-tidy + # would fall back to defaults and fail on the kernel headers. Exclude both; + # they are covered by the full builds and the kernel-module build job. # # -U0: no context lines, so only changed lines are analyzed. -p1 strips the # a/ b/ diff prefix. clang-tidy-diff exits non-zero on findings, so guard the # assignment (set -e) and decide pass/fail from the output itself. local out - out=$(git diff -U0 "${DIFF_BASE}" -- '*.c' '*.cpp' \ + out=$(git diff -U0 "${DIFF_BASE}" -- '*.c' '*.cpp' ':(exclude)kernel_tracing_library/*' \ | python3 "$diff_tool" -p1 -path "$BUILD_DIR" -clang-tidy-binary clang-tidy \ -extra-arg=-Wno-unknown-warning-option 2>&1) || true echo "$out"