Up until now, to create our header record (pair), we reused struct _ddebug(|_sites), initializing the pair with "impossible" field values (for a pr_debug() site), which makes it recognizable as a header not a pr-debug callsite. Now we want to specialize the header; differentiate it from its model, then we can drop _ddebug.site, and use header.site indirectly. This commit has several elements combining: Update DEFINE_DYNAMIC_DEBUG_TABLE by replacing "struct _ddebug*" with "union _ddebug*_header". This change places the new object types into our 2 elf sections. our 2 new union types have 2 jobs: a.fit properly in the section/array. We do this by putting the struct inside the union, making the unions the same size as their contained structs. This was sufficient to fix a data-misalignment crash on 2nd loop (ie 1st record after header) in _init. b.unions need the same field defns as their models, as refd in: DEFINE_DYNAMIC_DEBUG_TABLE() - inits is_dyndbg_header_pair(i,s) - validates that init use anonymous struct. RFC: My "anonymous union/struct fu" feels incomplete. The struct in b must contain all the fields of its outer union's own contained struct, maybe even in the same order (tho not obvious yet). Signed-off-by: Jim Cromie <jim.cromie@xxxxxxxxx> --- include/linux/dynamic_debug.h | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index 46901b5348ee..9ca413985fb2 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -36,6 +36,16 @@ struct _ddebug_site { const char *function; } __aligned(8); +/* verbatim copy of struct _ddebug_site. nothing to save here. */ +union _ddebug_site_header { + struct _ddebug_site __; /* inherit footprint */ + struct { /* header validation */ + const char *modname; + const char *filename; + const char *function; + }; +}; + struct _ddebug { SITE_CHK_(struct _ddebug_site *site;) /* format is always needed, lineno shares word with flags */ @@ -74,6 +84,21 @@ struct _ddebug { #endif } __aligned(8); +/* + * specialized version of struct _ddebug. The only field we NEED is + * .site, since keeping it here allows dropping from struct _ddebug + * itself. format, lineno are used to validate header records. + */ +union _ddebug_header { + struct _ddebug __; /* inherit footprint */ + struct { /* header validation */ + union _ddebug_site_header *site; + const char *format; + const unsigned lineno:18; + unsigned _index:14; + unsigned int flags:8; + }; +}; #if defined(CONFIG_DYNAMIC_DEBUG_CORE) @@ -136,10 +161,10 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor, */ #define DEFINE_DYNAMIC_DEBUG_TABLE() \ /* forward decl, allowing loopback pointer */ \ - __weak struct _ddebug __used __aligned(8) \ + __weak union _ddebug_header __used __aligned(8) \ __section(".gnu.linkonce.dyndbg") \ _LINKONCE_dyndbg_header; \ - __weak struct _ddebug_site __used __aligned(8) \ + __weak union _ddebug_site_header __used __aligned(8) \ __section(".gnu.linkonce.dyndbg_site") \ _LINKONCE_dyndbg_site_header = { \ .modname = KBUILD_MODNAME, \ @@ -147,7 +172,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor, /* forced pointer loopback, for distinction */ \ .filename = (void *) &_LINKONCE_dyndbg_header \ }; \ - __weak struct _ddebug __used __aligned(8) \ + __weak union _ddebug_header __used __aligned(8) \ __section(".gnu.linkonce.dyndbg") \ _LINKONCE_dyndbg_header = { \ SITE_INIT_(_LINKONCE_dyndbg_site_header) \ -- 2.31.1