Add static int is_dyndbg_header(d), which verifies that the arg is
initialized as expected; that it points to the _ddebug_hdr &
_ddebug_site_hdr records initialized by DYNAMIC_DEBUG_TABLE().

That init macro sets the _uplink fields in the 2 records to point at
each other.  This is an impossible situation for the regular callsite
record pairs built by *_METADATA_CLS(), so it provides a robust
verification that linkage happened as we require/depend upon.

In dynamic_debug_init(), is_dyndbg_header() validates the header, and
sets _uplink to builtin_state.

Thereafter, ddebug_map_site() can use it, and we can drop the
_ddebug.site member, and shrink the DATA footprint.
---
 include/linux/dynamic_debug.h |  1 +
 lib/dynamic_debug.c           | 38 +++++++++++++++++++++++++++++++++--
 2 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 23d3d2882882..ed3e1e1c08eb 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -149,6 +149,7 @@ struct _ddebug_site_hdr {
 /* encapsulate linker provided built-in (or module) dyndbg vectors */
 struct _ddebug_info {
        struct _ddebug_hdr *hdr;
+       struct _ddebug_site_hdr *site_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 891d70d7fed4..0a68fbfd8432 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1339,6 +1339,25 @@ static void ddebug_attach_module_classes(struct 
ddebug_table *dt,
                vpr_info("module:%s attached %d classes\n", dt->mod_name, ct);
 }
 
+/*
+ * detect the hardwired loopback initialized into the header pairs'
+ * _uplink member.  In dynamic_debug_init(), it verifies the presence
+ * of the header, before setting its _uplink to either &builtin_state
+ * or the module's embedded _ddebug_info.  __ddebug_add_module() will
+ * also use it..
+ */
+static int is_dyndbg_header(struct _ddebug_hdr *hdr)
+{
+       struct _ddebug_site_hdr *sp;
+
+       if (!hdr || !hdr->_uplink)
+               return 0;
+
+       sp = (struct _ddebug_site_hdr *) ((struct _ddebug_hdr *)hdr)->_uplink;
+       return hdr == (struct _ddebug_hdr *)
+               ((struct _ddebug_site_hdr *)sp)->_uplink;
+}
+
 /*
  * Allocate a new ddebug_table for the given module
  * and add it to the global list.
@@ -1351,6 +1370,15 @@ static int __ddebug_add_module(struct _ddebug_info *di, 
unsigned int base,
        int i, num_funcs = 0;
 
        v3pr_info("add-module: %s %d/%d sites, start: %d\n", modname, 
di->num_descs, di->num_sites, base);
+
+       if (is_dyndbg_header((struct _ddebug_hdr *)&di->descs[0])) {
+               pr_info("module header\n");
+               di->hdr = (struct _ddebug_hdr *) di->descs;
+               di->descs++;
+               di->sites++;
+               di->num_descs--;
+               di->num_sites--;
+       }
        if (!di->num_descs) {
                v3pr_info(" skip %s\n", modname);
                return 0;
@@ -1525,6 +1553,7 @@ static int __init dynamic_debug_init(void)
 
        struct _ddebug_info di = {
                .hdr = __dyndbg_header,
+               .site_hdr = __dyndbg_site_header,
                .descs = __start___dyndbg,
                .sites = __start___dyndbg_sites,
                .classes = __start___dyndbg_classes,
@@ -1548,11 +1577,16 @@ 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.hdr, __dyndbg_site_header);
        v2pr_info("%px %px \n", di.descs, di.sites);
 
+       if (is_dyndbg_header(di.hdr)) {
+               di.hdr->_uplink = &builtin_state;
+       } else {
+               pr_err("missing header records: cannot continue!\n");
+               return 1;
+       }
        iter = iter_mod_start = __start___dyndbg;
        site = site_mod_start = __start___dyndbg_sites;
        modname = site->_modname;
-- 
2.37.2

Reply via email to