DYNAMIC_DEBUG has extra weight/memory in its data table/section; its (module,filename,function) columns have ordered, repeating data (90%,55%,45%), and is highly compressible (~110/300) with simple RLE. On my i7 laptop, the compressible chunk is ~70kb, This patchset prepares for compression, but doesn't try it; RFC. Using that RLE compression estimate, we could save ~45kb; Id hope for better with ZSTD. Series Overview: 1st, split the struct _ddebug & __dyndbg elf section into 2, moving compressible fields into their own section/array/block. A temporary site pointer connects the 2 halves of the composite callsite, it will be obsoleted later, after we verify our replacement against it, we can drop the .site pointer. table change: from: [ key,mod,func,filenm,fmt,ln,flg ] into: [ key,fmt,ln,flg,site-> ] [ mod,func,filenm ] 2nd, make the 'site' data optional. The "module:function:line" log-message prefix is fundamentally an optional decoration, if we can do without it, we simplify codepath, and we could drop the storage in those cases, possibly reducing memory footprint. into: [ key,fmt,ln,flg,site->? ] 0 Then things get more interesting: 3rd, make kernel/module handle "__dyndbg_sites" ELF section (which was added in 1) as is already done for "__dyndbg". Hide/replace ->site with site_get/_put api this will let us retrieve site info from compressed storage. Add _index. gives us the fixed offset from __dyndbg[N] to __dyndbg[0]. into: [ key,fmt,ln,flg,_index,site->? ] 0 Add table/header record-pair. These 2 records are created into ".gnu.linkonce.dyndbg*" sections. The linker script places these 2 sections in front of their respective "__dyndbg*" sections. So this header-pair becomes __dyndbg[0], __dyndbg_sites[0]. we can use __dyndbg[0]->site[N] to get the site info. module.lds.h - insert ".gnu.linkonce.dyndbg*" sections into "__dyndbg*". Without this, headers arent part of the sections that kernel/module loads. validate ddebug_site_get() invariants. prove that our indirection to ->site[N] is correct. BUG_ON uses survived 0-day tests. they go away with !SITE_CHK into: 0: [ ...,_index,site-> ] ---> 0:[ ... ] ^ ..N: [ key,fmt,ln,flg,_index ] N:[ ... ] specialize header from _ddebug, keep header.site, drop _ddebug.site RFC: needs refinement, better type choices? Status: recent revs passed 0day compile grind, including BUG_ONs I got one KASAN report, quick reproduction failed, none more recently memory footprint is same as master. Whats Next ? Compression: RFC !!! POC: could compress during __init, decompress on-demand. Doing this would give something to decompress, to build out that code. ISTM Compression during build is best, but targets are unclear: initrd, initramfs, cpio, FW-blob all seem suitable at some level, but so does (ro) zram & zswap. How should I think about this ? Also, I understand that support exists for compressed elf sections, I dunno if/how kernel uses it currently, which would considerably ease this. Builtin __dyndbg_site data is in .data, probably needs to be moved to a separate elf section to get generic tool support for compressed sections. It would be nice if a compressed "__dyndbg_sites" elf section could be loaded by unchanged kernel/module.c. A magic number in the attached memory block could distinguish it from the current elf block. There is room in the 2 header records for new private data; we could store decompression contexts there while iterating thru a block. Decompression - a few use-cases: = for builtins, each loadable module: 1- stream, for `cat control` etc. these are 1 visit and forget 2- `module foo +mfp > control` - enable contiguous blocks w decorations 3- pr_debug - semi-random access - by (ptr - _index) [0-5k] for builtin pr-debugs, [0-20] for most loadable modules _index is 16 bit currently Simplest, minimum-memory strategy is late-fetch; to wait until a pr_debug is actually called, then check flags before fetching the site-rec, and save it to a hash on modname+_index (and delete on -p). Without the save, it works for (1) too. The only downside with late-fetch is that during pr_debug, a 1st fetch of site-info maybe cant come from io/zswap without locking/latency concerns. A forced-prefetch ala (2) with a new flag '!' could work around this, but might look like a wart. So thats it. I hope its clear and concise. Jim Cromie (28): trivial cleanup: dyndbg: avoid calling dyndbg_emit_prefix when it has no work dyndbg: drop uninformative vpr_info split to 2 vectors of callsite: dyndbg: split struct _ddebug's display fields to new _ddebug_site dyndbg: __init iterate over __dyndbg & __dyndbg_site in parallel make site info optional: dyndbg: refactor part of ddebug_change to ddebug_match_site dyndbg: accept null site in ddebug_match_site dyndbg: hoist ->site out of ddebug_match_site dyndbg: accept null site in ddebug_change dyndbg: accept null site in dynamic_emit_prefix dyndbg: accept null site in ddebug_proc_show dyndbg: refactor ddebug_alter_site out of ddebug_change dyndbg: allow deleting site info via control interface interesting: dyndbg+module: expose ddebug_sites to modules dyndbg: add ddebug_site(_get|_put) abstraction dyndbg: ddebug_add_module avoid adding empty modules dyndbg: add _index to struct _ddebug dyndbg: prevent build bugs via -DNO_DYNAMIC_DEBUG_TABLE dyndbg: RFC - DEFINE_DYNAMIC_DEBUG_TABLE dyndbg: RFC handle __dyndbg* sections in module.lds.h dyndbg: ddebug_add_module() handle headers. dyndbg: validate ddebug_site_get invariants dyndbg: fix NULL deref after deleting sites dyndbg: dont show header records in control dyndbg: make site pointer and checks on it optional (not quite) dyndbg: swap WARN_ON for BUG_ON see what 0-day says dyndbg: fixup protect header when deleting site dyndbg: unionize _ddebug*_headers with struct _ddebug* dyndbg: drop _ddebug.site pointer arch/arm/boot/compressed/Makefile | 2 + arch/sparc/vdso/Makefile | 2 + arch/x86/boot/compressed/Makefile | 1 + arch/x86/entry/vdso/Makefile | 3 + arch/x86/purgatory/Makefile | 1 + drivers/firmware/efi/libstub/Makefile | 3 +- include/asm-generic/module.lds.h | 12 +- include/asm-generic/vmlinux.lds.h | 24 +- include/linux/dynamic_debug.h | 135 ++++++++-- kernel/module-internal.h | 1 + kernel/module.c | 9 +- lib/dynamic_debug.c | 363 +++++++++++++++++++------- 12 files changed, 437 insertions(+), 119 deletions(-) -- 2.31.1