We now have 2 vectors of data: (__dyndbg, __dyndbg_sites), known to be equal-length, with _ddebug.site connecting them, like rungs on a ladder. In order to drop _ddebug.site, we need to replace the absolute ptr with a cheap relative-address computation: struct _ddebug_site *site = _ddebug_map_site(desc); 1st step: (done here) add ._index, ._map fields, and initialize them in __debug_add_module() to N (and = each other), where N is each element's position in the builtins (or loaded-module). Then _ddebug_map_site(desc) can compute &descs[0], and then use container_of() to go up 1 struct. RFC: Next steps: (outlined here, not done): 1. UPLINK: Define 2 new header structs, with _uplink fields, pointing at _ddebug_info: struct _ddebug_site_hdr { union { struct _ddebug_info _uplink*; struct _ddebug_site __; // sizeof this }; }; struct _ddebug_hdr { union { struct _ddebug_info _uplink*; struct _ddebug __; // sizeof this }; }; the union forces the allocation to be the bigger of the 2, with the expectation that the pointer will always fit. 2. Reserve a record in front of the __dyndbg* sections. can be done in {module,vmlinux}.lds.h, something like: SECTIONS { __dyndbg_sites : ALIGN(8) { *(.gnu.linkonce.dyndbg_site) *(__dyndbg_sites) } __dyndbg : ALIGN(8) { *(.gnu.linkonce.dyndbg) *(__dyndbg) } } KEEP( *(.gnu.linkonce.__dyndbg_site) *(__dyndbg_sites)) 3. specialize DYNAMIC_DEBUG_METADATA_CLS as DYNAMIC_DEBUG_TABLE. This special macro version creates header records, and puts them into .gnu.linkonce section. Unusually (uniquely?), it is tacitly invoked by dynamic_debug.h on behalf of all printk.h includers. This can result in multiple "declarations" in the same scope, so macro uses __weak and/or __unused to suppress linkage & errors. This created mumble-RELATIVE linkage errors in a few parts of the kernel, I worked around this by just suppressing the declaration if cflags includes -DDYNDBG_NO_TABLE. The up-link is init'd in 2 cases: The file static struct _ddebug_info builtins is initialized by dynamic_debug_init(), with the 3 ELF sections addresses+lengths composing the builtin dyndbg-state. It will be able to also initialize the header.UPLINK fields, as long as the storage space is available. Then rel_map() can rely upon it to provide the &site ref for a callsite's desc*, if it is enabled. Then at runtime (assuming initialization is correct): - use _index to get &descs[0] - container-of gets .UPLINK to &dyndbg_info - info->sites[_index] - replaces .sites - info->sites[_map] - allows de-duplicated vector position. M<N But thats all talk; this patch just adds and initializes the index and map fields. ._index:14 allows ~16k entries, more than enough for ~3k built-in callsites, or ~4k in amdgpu (with dyn-drm-trc commitset). It is initialized in __ddebug_add_module(), a new refactorization. ddebug_add_module() is called from kernel/module.c, that interface is preserved. It just passes 0 to inner fn when loading modules. Signed-off-by: Jim Cromie <jim.cromie@xxxxxxxxx> --- include/linux/dynamic_debug.h | 3 +++ lib/dynamic_debug.c | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index c05148dab367..268e903b7c4e 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -31,6 +31,8 @@ struct _ddebug { /* format is always needed, lineno shares word with flags */ const char *format; const unsigned lineno:16; + unsigned _index:14; + unsigned _map:14; #define CLS_BITS 6 unsigned int class_id:CLS_BITS; #define _DPRINTK_CLASS_DFLT ((1 << CLS_BITS) - 1) @@ -60,6 +62,7 @@ struct _ddebug { #define _DPRINTK_FLAGS_DEFAULT 0 #endif unsigned int flags:8; + #ifdef CONFIG_JUMP_LABEL union { struct static_key_true dd_key_true; diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index f1f354efed5a..506a7e2e59d6 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -1344,6 +1344,7 @@ static int __ddebug_add_module(struct _ddebug_info *di, unsigned int base, const char *modname) { struct ddebug_table *dt; + int i; v3pr_info("add-module: %s.%d sites\n", modname, di->num_descs); if (!di->num_descs) { @@ -1364,6 +1365,7 @@ static int __ddebug_add_module(struct _ddebug_info *di, unsigned int base, */ dt->mod_name = modname; dt->ddebugs = di->descs; + dt->sites = di->sites; dt->num_ddebugs = di->num_descs; INIT_LIST_HEAD(&dt->link); @@ -1372,6 +1374,12 @@ static int __ddebug_add_module(struct _ddebug_info *di, unsigned int base, if (di->classes && di->num_classes) ddebug_attach_module_classes(dt, di->classes, di->num_classes); + for (i = 0; i < di->num_descs; i++) { + di->descs[i]._index = base + i; + v3pr_info(" %d %d %s.%s.%d\n", i, base, modname, + di->descs[i].site->_function, di->descs[i].lineno); + } + mutex_lock(&ddebug_lock); list_add_tail(&dt->link, &ddebug_tables); mutex_unlock(&ddebug_lock); -- 2.37.2