[PATCH v6 53/57] dyndbg: add/use is_dyndbg_header then set _uplink

From: Jim Cromie
Date: Sun Sep 04 2022 - 17:46:40 EST


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