diff mbox series

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

Message ID 20220904214134.408619-54-jim.cromie@gmail.com (mailing list archive)
State New, archived
Headers show
Series DYNDBG: opt-in class'd debug for modules, use in drm. | expand

Commit Message

Jim Cromie Sept. 4, 2022, 9:41 p.m. UTC
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 mbox series

Patch

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;