Add new structs _ddebug_hdr and _ddebug_site_hdr, latter for symmetry. The job of the struct _ddebug_hdr is to: Contain an _uplink member, which points up to the _ddebug_info record that keeps builtin and module's dyndbg state. That record is init'd (by dynamic_debug_init for builtins, or find_module_sections for loadables). Be declared in .gnu.linkonce.dyndbg section, which places it just before the __dyndbg section; a fixed relative offset. This allows _ddebug_map_site(desc) to cheaply compute &descs[desc._index], &descs[0], then container_of() to get the header and its ._uplink, to the _ddebug_info, which gives access to ->sites[desc->_map]. Structurally, the header has a single unnamed union (which exposes its field names upward) containing an embedded struct _ddebug{,_site} (this forces the size to be compatible with the array/section its destined for), shared with our new struct _ddebug_info * _uplink member, which is also inside an unnamed struct, to allow adding other fields later to use the remaining space. In dynamic_debug.c: ref the linker symbols for the headers, print them to confirm expected linkages; things look proper. Add a header ref to struct _ddebug_info, to facilitate the validity checks. Signed-off-by: Jim Cromie <jim.cromie@xxxxxxxxx> --- include/linux/dynamic_debug.h | 23 ++++++++++++++++++++++- lib/dynamic_debug.c | 9 +++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index 268e903b7c4e..f23608c38a79 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -126,8 +126,29 @@ struct ddebug_class_map { #define NUM_TYPE_ARGS(eltype, ...) \ (sizeof((eltype[]){__VA_ARGS__}) / sizeof(eltype)) -/* encapsulate linker provided built-in (or module) dyndbg data */ +/* define header record, linker inserts it at descs[0] */ +struct _ddebug_hdr { + union { + struct _ddebug __; /* force sizeof this */ + struct { + struct _ddebug_info * _uplink; + /* space available */ + }; + }; +}; +/* here for symmetry, extra storage */ +struct _ddebug_site_hdr { + union { + struct _ddebug_site __; /* force sizeof this */ + struct { + struct _ddebug_info * _uplink; + }; + }; +}; + +/* encapsulate linker provided built-in (or module) dyndbg vectors */ struct _ddebug_info { + struct _ddebug_hdr *hdr; struct _ddebug *descs; struct _ddebug_site *sites; struct ddebug_class_map *classes; diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 65b0a1025ddf..91fe7fb5dda9 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -49,6 +49,9 @@ extern struct _ddebug_site __stop___dyndbg_sites[]; extern struct ddebug_class_map __start___dyndbg_classes[]; extern struct ddebug_class_map __stop___dyndbg_classes[]; +extern struct _ddebug_hdr __dyndbg_header[]; +extern struct _ddebug_site_hdr __dyndbg_site_header[]; + struct ddebug_table { struct list_head link, maps; const char *mod_name; @@ -1522,6 +1525,7 @@ static int __init dynamic_debug_init(void) char *cmdline; struct _ddebug_info di = { + .hdr = __dyndbg_header, .descs = __start___dyndbg, .sites = __start___dyndbg_sites, .classes = __start___dyndbg_classes, @@ -1545,6 +1549,11 @@ static int __init dynamic_debug_init(void) pr_err("unequal vectors: descs/sites %d/%d\n", di.num_descs, di.num_sites); return 1; } + + /* these 2 print the same, until _TABLE is added */ + v2pr_info("%px %px \n", __dyndbg_header, __dyndbg_site_header); + v2pr_info("%px %px \n", di.descs, di.sites); + iter = iter_mod_start = __start___dyndbg; site = site_mod_start = __start___dyndbg_sites; modname = site->_modname; -- 2.37.2