Skip to content

Commit

Permalink
dynamic debug: combine dprintk and dynamic printk
Browse files Browse the repository at this point in the history
This patch combines Greg Bank's dprintk() work with the existing dynamic
printk patchset, we are now calling it 'dynamic debug'.

The new feature of this patchset is a richer /debugfs control file interface,
(an example output from my system is at the bottom), which allows fined grained
control over the the debug output. The output can be controlled by function,
file, module, format string, and line number.

for example, enabled all debug messages in module 'nf_conntrack':

echo -n 'module nf_conntrack +p' > /mnt/debugfs/dynamic_debug/control

to disable them:

echo -n 'module nf_conntrack -p' > /mnt/debugfs/dynamic_debug/control

A further explanation can be found in the documentation patch.

Signed-off-by: Greg Banks <gnb@sgi.com>
Signed-off-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
jibaron authored and gregkh committed Mar 24, 2009
1 parent 095160a commit e9d376f
Show file tree
Hide file tree
Showing 13 changed files with 867 additions and 543 deletions.
5 changes: 0 additions & 5 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1816,11 +1816,6 @@ and is between 256 and 4096 characters. It is defined in the file
autoconfiguration.
Ranges are in pairs (memory base and size).

dynamic_printk Enables pr_debug()/dev_dbg() calls if
CONFIG_DYNAMIC_PRINTK_DEBUG has been enabled.
These can also be switched on/off via
<debugfs>/dynamic_printk/modules

print-fatal-signals=
[KNL] debug: print fatal signals
print-fatal-signals=1: print segfault info to
Expand Down
15 changes: 6 additions & 9 deletions include/asm-generic/vmlinux.lds.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@
VMLINUX_SYMBOL(__start___tracepoints) = .; \
*(__tracepoints) \
VMLINUX_SYMBOL(__stop___tracepoints) = .; \
/* implement dynamic printk debug */ \
. = ALIGN(8); \
VMLINUX_SYMBOL(__start___verbose) = .; \
*(__verbose) \
VMLINUX_SYMBOL(__stop___verbose) = .; \
LIKELY_PROFILE() \
BRANCH_PROFILE()

Expand Down Expand Up @@ -309,15 +314,7 @@
CPU_DISCARD(init.data) \
CPU_DISCARD(init.rodata) \
MEM_DISCARD(init.data) \
MEM_DISCARD(init.rodata) \
/* implement dynamic printk debug */ \
VMLINUX_SYMBOL(__start___verbose_strings) = .; \
*(__verbose_strings) \
VMLINUX_SYMBOL(__stop___verbose_strings) = .; \
. = ALIGN(8); \
VMLINUX_SYMBOL(__start___verbose) = .; \
*(__verbose) \
VMLINUX_SYMBOL(__stop___verbose) = .;
MEM_DISCARD(init.rodata)

#define INIT_TEXT \
*(.init.text) \
Expand Down
2 changes: 1 addition & 1 deletion include/linux/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ extern const char *dev_driver_string(const struct device *dev);
#if defined(DEBUG)
#define dev_dbg(dev, format, arg...) \
dev_printk(KERN_DEBUG , dev , format , ## arg)
#elif defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
#elif defined(CONFIG_DYNAMIC_DEBUG)
#define dev_dbg(dev, format, ...) do { \
dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \
} while (0)
Expand Down
88 changes: 88 additions & 0 deletions include/linux/dynamic_debug.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#ifndef _DYNAMIC_DEBUG_H
#define _DYNAMIC_DEBUG_H

/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which
* bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
* use independent hash functions, to reduce the chance of false positives.
*/
extern long long dynamic_debug_enabled;
extern long long dynamic_debug_enabled2;

/*
* An instance of this structure is created in a special
* ELF section at every dynamic debug callsite. At runtime,
* the special section is treated as an array of these.
*/
struct _ddebug {
/*
* These fields are used to drive the user interface
* for selecting and displaying debug callsites.
*/
const char *modname;
const char *function;
const char *filename;
const char *format;
char primary_hash;
char secondary_hash;
unsigned int lineno:24;
/*
* The flags field controls the behaviour at the callsite.
* The bits here are changed dynamically when the user
* writes commands to <debugfs>/dynamic_debug/ddebug
*/
#define _DPRINTK_FLAGS_PRINT (1<<0) /* printk() a message using the format */
#define _DPRINTK_FLAGS_DEFAULT 0
unsigned int flags:8;
} __attribute__((aligned(8)));


int ddebug_add_module(struct _ddebug *tab, unsigned int n,
const char *modname);

#if defined(CONFIG_DYNAMIC_DEBUG)
extern int ddebug_remove_module(char *mod_name);

#define __dynamic_dbg_enabled(dd) ({ \
int __ret = 0; \
if (unlikely((dynamic_debug_enabled & (1LL << DEBUG_HASH)) && \
(dynamic_debug_enabled2 & (1LL << DEBUG_HASH2)))) \
if (unlikely(dd.flags)) \
__ret = 1; \
__ret; })

#define dynamic_pr_debug(fmt, ...) do { \
static struct _ddebug descriptor \
__used \
__attribute__((section("__verbose"), aligned(8))) = \
{ KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH, \
DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT }; \
if (__dynamic_dbg_enabled(descriptor)) \
printk(KERN_DEBUG KBUILD_MODNAME ":" fmt, \
##__VA_ARGS__); \
} while (0)


#define dynamic_dev_dbg(dev, fmt, ...) do { \
static struct _ddebug descriptor \
__used \
__attribute__((section("__verbose"), aligned(8))) = \
{ KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH, \
DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT }; \
if (__dynamic_dbg_enabled(descriptor)) \
dev_printk(KERN_DEBUG, dev, \
KBUILD_MODNAME ": " fmt, \
##__VA_ARGS__); \
} while (0)

#else

static inline int ddebug_remove_module(char *mod)
{
return 0;
}

#define dynamic_pr_debug(fmt, ...) do { } while (0)
#define dynamic_dev_dbg(dev, format, ...) do { } while (0)
#endif

#endif
93 changes: 0 additions & 93 deletions include/linux/dynamic_printk.h

This file was deleted.

4 changes: 2 additions & 2 deletions include/linux/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include <linux/log2.h>
#include <linux/typecheck.h>
#include <linux/ratelimit.h>
#include <linux/dynamic_printk.h>
#include <linux/dynamic_debug.h>
#include <asm/byteorder.h>
#include <asm/bug.h>

Expand Down Expand Up @@ -358,7 +358,7 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
#if defined(DEBUG)
#define pr_debug(fmt, ...) \
printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#elif defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
#elif defined(CONFIG_DYNAMIC_DEBUG)
#define pr_debug(fmt, ...) do { \
dynamic_pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \
} while (0)
Expand Down
25 changes: 10 additions & 15 deletions kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -822,7 +822,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
mutex_lock(&module_mutex);
/* Store the name of the last unloaded module for diagnostic purposes */
strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
unregister_dynamic_debug_module(mod->name);
ddebug_remove_module(mod->name);
free_module(mod);

out:
Expand Down Expand Up @@ -1827,19 +1827,13 @@ static inline void add_kallsyms(struct module *mod,
}
#endif /* CONFIG_KALLSYMS */

static void dynamic_printk_setup(struct mod_debug *debug, unsigned int num)
static void dynamic_debug_setup(struct _ddebug *debug, unsigned int num)
{
#ifdef CONFIG_DYNAMIC_PRINTK_DEBUG
unsigned int i;

for (i = 0; i < num; i++) {
register_dynamic_debug_module(debug[i].modname,
debug[i].type,
debug[i].logical_modname,
debug[i].flag_names,
debug[i].hash, debug[i].hash2);
}
#endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */
#ifdef CONFIG_DYNAMIC_DEBUG
if (ddebug_add_module(debug, num, debug->modname))
printk(KERN_ERR "dynamic debug error adding module: %s\n",
debug->modname);
#endif
}

static void *module_alloc_update_bounds(unsigned long size)
Expand Down Expand Up @@ -2213,12 +2207,13 @@ static noinline struct module *load_module(void __user *umod,
add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);

if (!mod->taints) {
struct mod_debug *debug;
struct _ddebug *debug;
unsigned int num_debug;

debug = section_objs(hdr, sechdrs, secstrings, "__verbose",
sizeof(*debug), &num_debug);
dynamic_printk_setup(debug, num_debug);
if (debug)
dynamic_debug_setup(debug, num_debug);
}

/* sechdrs[0].sh_size is always zero */
Expand Down
2 changes: 1 addition & 1 deletion lib/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,7 @@ config BUILD_DOCSRC

Say N if you are unsure.

config DYNAMIC_PRINTK_DEBUG
config DYNAMIC_DEBUG
bool "Enable dynamic printk() call support"
default n
depends on PRINTK
Expand Down
2 changes: 1 addition & 1 deletion lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ obj-$(CONFIG_HAVE_LMB) += lmb.o

obj-$(CONFIG_HAVE_ARCH_TRACEHOOK) += syscall.o

obj-$(CONFIG_DYNAMIC_PRINTK_DEBUG) += dynamic_printk.o
obj-$(CONFIG_DYNAMIC_DEBUG) += dynamic_debug.o

hostprogs-y := gen_crc32table
clean-files := crc32table.h
Expand Down
Loading

0 comments on commit e9d376f

Please sign in to comment.