All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jim Cromie <jim.cromie@gmail.com>
To: Arnd Bergmann <arnd@arndb.de>, Jason Baron <jbaron@akamai.com>,
	linux-arch@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: linux-mm@kvack.org, Jim Cromie <jim.cromie@gmail.com>
Subject: [RFC PATCH v5 18/28] dyndbg: RFC - DEFINE_DYNAMIC_DEBUG_TABLE
Date: Tue, 11 May 2021 12:50:47 -0600	[thread overview]
Message-ID: <20210511185057.3815777-19-jim.cromie@gmail.com> (raw)
In-Reply-To: <20210511185057.3815777-1-jim.cromie@gmail.com>

DEFINE_DYNAMIC_DEBUG_TABLE is based on DEFINE_DYNAMIC_DEBUG_METADATA.
Like its model, it creates/allocates a pair of structs: _ddebug &
_ddebug_site.  It inits them distinctively, so is_dyndbg_header_pair()
macro can verify them.

Its purpose is to reserve a single pair of header records in the front
of the "__dyndbg" & "__dyndbg_sites" sections.  This has several parts;

- the pair of structs are placed into 2 .gnu.linkonce.dyndbg* sections
  corresponding to the 2 dyndbg* sections populated by _METADATA

- vmlinux.lds.h places these 2 new sections into the dyndbg* sections,
  at the start___dyndbg*s.

- the pair has "__used __weak" to qualm compiler concerns.
  explicit externs were problematic with initialization, static decls too.

With this, the header record is now really __dyndbg[0].

Notes:

DYNAMIC_DEBUG is a 'transparent' facility, in that pr_debug() users
get extra features without additional api.  Because of this,
DEFINE_DYNAMIC_DEBUG_TABLE is invoked by dynamic_debug.h on behalf of
all its (indirect) users, including printk.h.

IOW this has wide effects; it results in multiple redundant
declarations of header records, even single object files may get
multiple copies.  Placing these records into .gnu.linkonce. sections
with "__used __weak " seems to resolve the redundancies.  This may
well be the cause of the need for HEAD~1.

In vmlinux-lds.h, I added 2 more KEEPs to place the .gnu.linkonce.*
headers at the front of their respective __dyndbg* sections.  I moved
the __dyndbg lines into a new macro, which maybe should be done as a
separate commit, or in the earlier commit that touched it. RFC.

The headers are really just struct _ddebug*s, they are initialized
distinctively so that they're recogizable by code, using macro
is_dyndbg_header_pair(dbg, dbgsite).

DECLARE_DYNAMIC_DEBUG_TABLE() initializes the header record pairs with
values which are "impossible" for pr_debug()s:

- lineno == 0
- site == iter->site
- modname == function		not possible in proper linkage
- modname == format		not possible in normal linkage
- filename = (void*) iter	forced loopback

Next:

Get __dyndbg[0] from any *dp within __dyndbg[N].  Then with
__dyndbg[0].site, we can get __dyndbg_sites[N].  This is a little
slower than a direct pointer, but this is an unlikely debug path, so
this 'up-N-over-down-N' access is ok.

Eventually we can adapt the header (as a new struct/union) to keep its
pointer to the __dyndbg_sites[] section/block, while allowing us to
drop it from struct _ddebug, regaining memory parity with master.  But
for now, we keep .site, and will soon use it to validate the
'up-N-over-down-N' computation.

For clarity, N is _ddebug._index.  For both builtins & loadable
modules, it is init'd to remember the fixed offset from the beginning
of the section/block/memory-allocation (actual elf sections for *ko's,
and a __start/__stop delineated part of .data for builtins).

N/_index will be used solely to get to __debugs[0] and over to
__debug_sites[N].  It is distinct from a module's numdbgs, which is
used mainly when walking control, and is kept in struct _ddeug_table.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/asm-generic/vmlinux.lds.h | 27 ++++++++++++-------
 include/linux/dynamic_debug.h     | 45 +++++++++++++++++++++++++++++++
 lib/dynamic_debug.c               | 18 ++++++-------
 3 files changed, 72 insertions(+), 18 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 4f2af9de2f03..189286405b40 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -335,6 +335,22 @@
 	KEEP(*(.dtb.init.rodata))					\
 	__dtb_end = .;
 
+/* implement dynamic printk debug */
+#if defined(CONFIG_DYNAMIC_DEBUG) || defined(CONFIG_DYNAMIC_DEBUG_CORE)
+#define DYNAMIC_DEBUG_DATA()						\
+	. = ALIGN(8);							\
+	__start___dyndbg_sites = .;					\
+	KEEP(*(.gnu.linkonce.dyndbg_site))				\
+	KEEP(*(__dyndbg_sites))						\
+	__stop___dyndbg_sites = .;					\
+	__start___dyndbg = .;						\
+	KEEP(*(.gnu.linkonce.dyndbg))					\
+	KEEP(*(__dyndbg))						\
+	__stop___dyndbg = .;
+#else
+#define DYNAMIC_DEBUG_DATA()
+#endif
+
 /*
  * .data section
  */
@@ -351,15 +367,8 @@
 	__end_once = .;							\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	/* implement dynamic printk debug */				\
-	. = ALIGN(8);							\
-	__start___dyndbg_sites = .;					\
-	KEEP(*(__dyndbg_sites))					\
-	__stop___dyndbg_sites = .;					\
-	__start___dyndbg = .;						\
-	KEEP(*(__dyndbg))						\
-	__stop___dyndbg = .;						\
-	LIKELY_PROFILE()		       				\
+	DYNAMIC_DEBUG_DATA()						\
+	LIKELY_PROFILE()						\
 	BRANCH_PROFILE()						\
 	TRACE_PRINTKS()							\
 	BPF_RAW_TP()							\
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index a15e417cbba8..06ae1d8d8c10 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -113,6 +113,43 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 		_DPRINTK_KEY_INIT				\
 	}
 
+/*
+ * DEFINE_DYNAMIC_DEBUG_TABLE(): This is a special version of
+ * DEFINE_DYNAMIC_DEBUG_METADATA().  It creates a single pair of
+ * header records, which linker scripts place into __dyndbg[0] &
+ * __dyndbg_sites[0].
+ * To allow a robust runtime test for is_dyndbg_header_pair(I,S),
+ * force-initialize S->filename to point back to I, an otherwize
+ * pathological condition.
+ */
+#define DEFINE_DYNAMIC_DEBUG_TABLE()				\
+	/* forward decl, allowing loopback pointer */		\
+	__weak struct _ddebug __used __aligned(8)		\
+		__section(".gnu.linkonce.dyndbg")		\
+		_LINKONCE_dyndbg_header;			\
+	__weak struct _ddebug_site __used __aligned(8)		\
+		__section(".gnu.linkonce.dyndbg_site")		\
+	_LINKONCE_dyndbg_site_header = {			\
+		.modname = KBUILD_MODNAME,			\
+		.function = KBUILD_MODNAME,			\
+		/* forced pointer loopback, for distinction */	\
+		.filename = (void *) &_LINKONCE_dyndbg_header	\
+	};							\
+	__weak struct _ddebug __used __aligned(8)		\
+		__section(".gnu.linkonce.dyndbg")		\
+	_LINKONCE_dyndbg_header = {				\
+		.site = &_LINKONCE_dyndbg_site_header,		\
+		.format = KBUILD_MODNAME			\
+	}
+
+/* The header initializations as a distinguishing predicate */
+#define is_dyndbg_header_pair(iter, sitep)			\
+	(sitep == iter->site					\
+	 && (!iter->lineno)					\
+	 && (iter->format == sitep->modname)			\
+	 && (sitep->modname == sitep->function)			\
+	 && ((void *)sitep->filename == (void *)iter))
+
 #ifdef CONFIG_JUMP_LABEL
 
 #ifdef DEBUG
@@ -243,4 +280,12 @@ static inline int dynamic_debug_exec_queries(const char *query, const char *modn
 
 #endif /* !CONFIG_DYNAMIC_DEBUG_CORE */
 
+#if ((defined(CONFIG_DYNAMIC_DEBUG) ||						\
+      (defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE)))	\
+     && defined(KBUILD_MODNAME) && !defined(NO_DYNAMIC_DEBUG_TABLE))
+
+/* transparently invoked, except when -DNO_DYNAMIC_DEBUG_TABLE */
+DEFINE_DYNAMIC_DEBUG_TABLE();
+#endif
+
 #endif
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index c5927b6c1c0c..9d9cb36f40a6 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1190,8 +1190,7 @@ static int __init dynamic_debug_init(void)
 	const char *modname = NULL;
 	char *cmdline;
 	int ret = 0;
-	int site_ct = 0, entries = 0, modct = 0;
-	int mod_index = 0;
+	int i, site_ct = 0, modct = 0, mod_index = 0;
 
 	if (&__start___dyndbg == &__stop___dyndbg) {
 		if (IS_ENABLED(CONFIG_DYNAMIC_DEBUG)) {
@@ -1207,10 +1206,9 @@ static int __init dynamic_debug_init(void)
 	site = site_mod_start = __start___dyndbg_sites;
 	modname = site->modname;
 
-	for (; iter < __stop___dyndbg; iter++, site++) {
+	for (i = 0; iter < __stop___dyndbg; iter++, site++, i++) {
 
-		BUG_ON(site != iter->site);
-		entries++;
+		WARN_ON(site != iter->site);
 
 		if (strcmp(modname, site->modname)) {
 			modct++;
@@ -1219,10 +1217,12 @@ static int __init dynamic_debug_init(void)
 						  site_ct, mod_index, modname);
 			if (ret)
 				goto out_err;
-			site_ct = 0;
+
 			modname = site->modname;
 			iter_mod_start = iter;
 			site_mod_start = site;
+			mod_index += site_ct;
+			site_ct = 0;
 		}
 		site_ct++;
 	}
@@ -1232,9 +1232,9 @@ static int __init dynamic_debug_init(void)
 
 	ddebug_init_success = 1;
 	vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in __dyndbg section, %d bytes in __dyndbg_sites section\n",
-		 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
-		 (int)(entries * sizeof(struct _ddebug)),
-		 (int)(entries * sizeof(struct _ddebug_site)));
+		 modct, i, (int)(modct * sizeof(struct ddebug_table)),
+		 (int)(i * sizeof(struct _ddebug)),
+		 (int)(i * sizeof(struct _ddebug_site)));
 
 	/* apply ddebug_query boot param, dont unload tables on err */
 	if (ddebug_setup_string[0] != '\0') {
-- 
2.31.1


  parent reply	other threads:[~2021-05-11 18:52 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-11 18:50 [RFC PATCH v5 00/28] dynamic debug diet plan Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 01/28] dyndbg: avoid calling dyndbg_emit_prefix when it has no work Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 02/28] dyndbg: drop uninformative vpr_info Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 03/28] dyndbg: split struct _ddebug's display fields to new _ddebug_site Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 04/28] dyndbg: __init iterate over __dyndbg & __dyndbg_site in parallel Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 05/28] dyndbg: refactor part of ddebug_change to ddebug_match_site Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 06/28] dyndbg: accept null site in ddebug_match_site Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 07/28] dyndbg: hoist ->site out of ddebug_match_site Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 08/28] dyndbg: accept null site in ddebug_change Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 09/28] dyndbg: accept null site in dynamic_emit_prefix Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 10/28] dyndbg: accept null site in ddebug_proc_show Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 11/28] dyndbg: refactor ddebug_alter_site out of ddebug_change Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 12/28] dyndbg: allow deleting site info via control interface Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 13/28] dyndbg+module: expose ddebug_sites to modules Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 14/28] dyndbg: add ddebug_site(_get|_put) abstraction Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 15/28] dyndbg: ddebug_add_module avoid adding empty modules Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 16/28] dyndbg: add _index to struct _ddebug Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 17/28] dyndbg: prevent build bugs via -DNO_DYNAMIC_DEBUG_TABLE Jim Cromie
2021-05-11 18:50   ` Jim Cromie
2021-05-12 14:55   ` Ard Biesheuvel
2021-05-12 14:55     ` Ard Biesheuvel
2021-05-12 14:55     ` Ard Biesheuvel
2021-05-12 18:03     ` jim.cromie
2021-05-12 18:03       ` jim.cromie
2021-05-12 18:03       ` jim.cromie
2021-05-11 18:50 ` Jim Cromie [this message]
2021-05-11 18:50 ` [RFC PATCH v5 19/28] dyndbg: RFC handle __dyndbg* sections in module.lds.h Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 20/28] dyndbg: ddebug_add_module() handle headers Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 21/28] dyndbg: validate ddebug_site_get invariants Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 22/28] dyndbg: fix NULL deref after deleting sites Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 23/28] dyndbg: dont show header records in control Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 24/28] dyndbg: make site pointer and checks on it optional (not quite) Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 25/28] dyndbg: swap WARN_ON for BUG_ON see what 0-day says Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 26/28] dyndbg: fixup protect header when deleting site Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 27/28] dyndbg: unionize _ddebug*_headers with struct _ddebug* Jim Cromie
2021-05-11 18:50 ` [RFC PATCH v5 28/28] dyndbg: RFC drop _ddebug.site pointer Jim Cromie
2021-05-12 22:08 ` Fwd: [RFC PATCH v5 00/28] dynamic debug diet plan jim.cromie

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210511185057.3815777-19-jim.cromie@gmail.com \
    --to=jim.cromie@gmail.com \
    --cc=arnd@arndb.de \
    --cc=jbaron@akamai.com \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.