[syslinux:elflink] debug.c32: Dynamically enable/ disable debug code at runtime

syslinux-bot for Matt Fleming matt.fleming at intel.com
Fri Jul 5 05:57:07 PDT 2013


Commit-ID:  487f7581b4a4639d237a4a27a50252adabac62af
Gitweb:     http://www.syslinux.org/commit/487f7581b4a4639d237a4a27a50252adabac62af
Author:     Matt Fleming <matt.fleming at intel.com>
AuthorDate: Fri, 28 Jun 2013 20:53:30 +0100
Committer:  Matt Fleming <matt.fleming at intel.com>
CommitDate: Fri, 5 Jul 2013 13:50:03 +0100

debug.c32: Dynamically enable/disable debug code at runtime

It's useful to be able to enable (and disable) debug code at runtime,
particularly for allowing users that are unable to build their own
Syslinux releases the chance to provide useful debugging output.

For example, say a user reports trouble with their PXE stack but doesn't
have a development environment setup to turn on the debug code
themselves. With this change you can simply request that they do,

    debug.c32 -e pxe_call unload_pxe open_file

to enable the debug in those functions. By only turning on code in
specific functions we reduce the chance of disrupting the buggy
behaviour and improve the signal to noise ratio for print statements.

To disable debug code use the -d flag,

    debug.c32 -d pxe_call

To use this new feature simply do,

    if (syslinux_debug_enabled) {
        debug1();
        debug2();
        ....
    }

from within the function you wish to add debug code. Note that this
feature is not limited to print statements - you can put any code within
the conditional, such as verifying a checksum or checking for memory
leaks.

The plan is to leave the dynamic debug code built in for all prereleases
and to turn it off for final releases.

People may still want to build with all dprintf() statements enabled,
and so a new symbol, DYNAMIC_DEBUG, was introduced rather than
repurposing the old DEBUG, DEBUG_STDIO and DEBUG_PORT symbols.

Signed-off-by: Matt Fleming <matt.fleming at intel.com>

---
 NEWS                           |  4 ++
 com32/include/dprintf.h        | 10 ++++-
 com32/include/syslinux/debug.h | 15 +++++++
 com32/lib/Makefile             |  1 +
 com32/lib/syslinux/debug.c     | 95 ++++++++++++++++++++++++++++++++++++++++++
 com32/modules/Makefile         |  2 +-
 com32/modules/debug.c          | 54 ++++++++++++++++++++++++
 7 files changed, 178 insertions(+), 3 deletions(-)

diff --git a/NEWS b/NEWS
index 56f9d93..a1c5617 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@ Starting with 1.47, changes marked with SYSLINUX, PXELINUX, ISOLINUX
 or EXTLINUX apply to that specific program only; other changes apply
 to all derivatives.
 
+Changes in 5.11:
+	* Dynamic debug support: Add new module, debug.c32, that allows
+	  debug code to be dynamically enabled and disabled at runtime.
+
 Changes in 5.10:
 	* PXELINUX: An entirely new network implementation based on
 	  the lwIP embedded TCP/IP stack.  As a result, plain PXELINUX
diff --git a/com32/include/dprintf.h b/com32/include/dprintf.h
index 26ca734..51d5c61 100644
--- a/com32/include/dprintf.h
+++ b/com32/include/dprintf.h
@@ -5,6 +5,8 @@
 #ifndef _DPRINTF_H
 #define _DPRINTF_H
 
+#include <syslinux/debug.h>
+
 #if !defined(DEBUG_PORT) && !defined(DEBUG_STDIO)
 # undef DEBUG
 #endif
@@ -23,8 +25,12 @@ void vdprintf(const char *, va_list);
 
 #else
 
-# define dprintf(fmt, ...)	((void)(0))
-# define vdprintf(fmt, ap)	((void)(0))
+#define dprintf(...) \
+    if (syslinux_debug_enabled) \
+        printf(__VA_ARGS__)
+#define vdprintf(fmt, ap) \
+    if (syslinux_debug_enabled) \
+        vprintf(fmt, ap)
 
 #endif /* DEBUG */
 
diff --git a/com32/include/syslinux/debug.h b/com32/include/syslinux/debug.h
new file mode 100644
index 0000000..aee6fdb
--- /dev/null
+++ b/com32/include/syslinux/debug.h
@@ -0,0 +1,15 @@
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#include <stdbool.h>
+
+#ifdef DYNAMIC_DEBUG
+#define syslinux_debug_enabled	__syslinux_debug_enabled(__func__)
+extern bool __syslinux_debug_enabled(const char *func);
+#else
+#define syslinux_debug_enabled	(0)
+#endif /* DYNAMIC_DEBUG */
+
+extern int syslinux_debug(const char *str, bool enable);
+
+#endif /* DEBUG_H */
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index a7cfe77..d1b6bf7 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -176,6 +176,7 @@ CORELIBOBJS = \
 	libgcc/__negdi2.o libgcc/__ashrdi3.o libgcc/__lshrdi3.o		\
 	libgcc/__muldi3.o libgcc/__udivmoddi4.o libgcc/__umoddi3.o	\
 	libgcc/__divdi3.o libgcc/__moddi3.o				\
+	syslinux/debug.o						\
 	$(LIBENTRY_OBJS) \
 	$(LIBMODULE_OBJS)
 
diff --git a/com32/lib/syslinux/debug.c b/com32/lib/syslinux/debug.c
new file mode 100644
index 0000000..d9ab863
--- /dev/null
+++ b/com32/lib/syslinux/debug.c
@@ -0,0 +1,95 @@
+#include <linux/list.h>
+#include <string.h>
+#include <stdbool.h>
+
+#ifdef DYNAMIC_DEBUG
+
+static LIST_HEAD(debug_funcs);
+
+struct debug_func_entry {
+    const char *name;
+    struct list_head list;
+};
+
+static struct debug_func_entry *lookup_entry(const char *func)
+{
+    struct debug_func_entry *e, *entry = NULL;
+
+    list_for_each_entry(e, &debug_funcs, list) {
+	if (!strcmp(e->name, func)) {
+	    entry = e;
+	    break;
+	}
+    }
+
+    return entry;
+}
+
+bool __syslinux_debug_enabled(const char *func)
+{
+    struct debug_func_entry *entry;
+
+    entry = lookup_entry(func);
+    if (entry)
+	return true;
+
+    return false;
+}
+
+static int __enable(const char *func)
+{
+    struct debug_func_entry *entry;
+
+    entry = lookup_entry(func);
+    if (entry)
+	return 0;	/* already enabled */
+
+    entry = malloc(sizeof(*entry));
+    if (!entry)
+	return -1;
+
+    entry->name = func;
+    list_add(&entry->list, &debug_funcs);
+    return 0;
+}
+
+static int __disable(const char *func)
+{
+    struct debug_func_entry *entry;
+
+    entry = lookup_entry(func);
+    if (!entry)
+	return 0;	/* already disabled */
+
+    list_del(&entry->list);
+    free(entry);
+    return 0;
+}
+
+/*
+ * Enable or disable debug code for function 'func'.
+ */
+int syslinux_debug(const char *func, bool enable)
+{
+    int rv;
+
+    if (enable)
+	rv = __enable(func);
+    else
+	rv = __disable(func);
+
+    return rv;
+}
+
+#else
+
+int syslinux_debug(const char *func, bool enable)
+{
+    (void)func;
+    (void)enable;
+
+    printf("Dynamic debug unavailable\n");
+    return -1;
+}
+
+#endif /* DYNAMIC_DEBUG */
diff --git a/com32/modules/Makefile b/com32/modules/Makefile
index 682e1b2..d801a26 100644
--- a/com32/modules/Makefile
+++ b/com32/modules/Makefile
@@ -25,7 +25,7 @@ MODULES	  = config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \
 	    kbdmap.c32 cmd.c32 vpdtest.c32 host.c32 ls.c32 gpxecmd.c32 \
 	    ifcpu.c32 cpuid.c32 cat.c32 pwd.c32 ifplop.c32 zzjson.c32 \
 	    whichsys.c32 prdhcp.c32 pxechn.c32 kontron_wdt.c32 ifmemdsk.c32 \
-	    hexdump.c32 poweroff.c32 cptime.c32
+	    hexdump.c32 poweroff.c32 cptime.c32 debug.c32
 
 TESTFILES =
 
diff --git a/com32/modules/debug.c b/com32/modules/debug.c
new file mode 100644
index 0000000..1026ebf
--- /dev/null
+++ b/com32/modules/debug.c
@@ -0,0 +1,54 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2013 Intel Corporation; author: Matt Fleming
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ *   Boston MA 02110-1301, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <syslinux/debug.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static char *progname;
+
+static void usage(void)
+{
+    fprintf(stderr, "Usage: %s [-e|-d] <func1> [<func2>, ...]\n", progname);
+}
+
+int main(int argc, char *argv[])
+{
+    bool enable;
+    int i;
+
+    progname = argv[0];
+
+    if (argc < 3) {
+	usage();
+	return -1;
+    }
+
+    if (!strncmp(argv[1], "-e", 2))
+	enable = true;
+    else if (!strncmp(argv[1], "-d", 2))
+	enable = false;
+    else {
+	usage();
+	return -1;
+    }
+
+    for (i = 2; i < argc; i++) {
+	char *str = argv[i];
+
+	if (syslinux_debug(str, enable) < 0)
+	    fprintf(stderr, "Failed to debug symbol \"%s\"\n", str);
+    }
+
+    return 0;
+}


More information about the Syslinux-commits mailing list