2007-05-02 22:31:57

by Randy Dunlap

[permalink] [raw]
Subject: [PATCH] lib/hexdump

From: Randy Dunlap <[email protected]>

Based on ace_dump_mem() from Grant Likely for the Xilinx
SystemACE CompactFlash interface.

Add hex_dumper() to lib/hexdump.c and linux/kernel.h.

This patch adds the function 'hex_dumper' which can be used to perform a
hex + ASCII dump of data to syslog, in an easily viewable format, thus
providing a common text hex dump format.

It does not provide a hexdump_to_buffer() function.
if someone needs that, we'll have to add it.

Example usage:
hex_dumper(KERN_DEBUG, data, length);

Signed-off-by: Randy Dunlap <[email protected]>
---

include/linux/kernel.h | 1
lib/Makefile | 2 -
lib/hexdump.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 53 insertions(+), 1 deletion(-)

--- linux-2.6.21-git4.orig/include/linux/kernel.h
+++ linux-2.6.21-git4/include/linux/kernel.h
@@ -201,6 +201,7 @@ extern enum system_states {
#define TAINT_USER (1<<6)

extern void dump_stack(void);
+extern void hex_dumper(const char *level, void *base, int len);

#ifdef DEBUG
/* If you are writing a driver, please use dev_dbg instead */
--- linux-2.6.21-git4.orig/lib/Makefile
+++ linux-2.6.21-git4/lib/Makefile
@@ -5,7 +5,7 @@
lib-y := ctype.o string.o vsprintf.o cmdline.o \
rbtree.o radix-tree.o dump_stack.o \
idr.o int_sqrt.o bitmap.o extable.o prio_tree.o \
- sha1.o irq_regs.o reciprocal_div.o
+ sha1.o irq_regs.o reciprocal_div.o hexdump.o

lib-$(CONFIG_MMU) += ioremap.o
lib-$(CONFIG_SMP) += cpumask.o
--- /dev/null
+++ linux-2.6.21-git4/lib/hexdump.c
@@ -0,0 +1,51 @@
+/*
+ * lib/hexdump.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+/**
+ * hex_dumper - print a text hex dump to syslog for a binary blob of data
+ * @level: kernel log level (e.g. KERN_DEBUG)
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ *
+ * Given a buffer of u8 data, hex_dumper() will print a hex + ASCII dump
+ * to the kernel log at the specified kernel log level.
+ *
+ * E.g.:
+ * hex_dumper(KERN_DEBUG, frame->data, frame->len);
+ *
+ * Prints the offsets of the block of memory, not addresses:
+ * 0009ab42: 40414243 44454647 48494a4b 4c4d4e4f-@ABCDEFG HIJKLMNO
+ */
+void hex_dumper(const char *level, void *base, int len)
+{
+ const u8 *ptr = base;
+ int i, j;
+
+ for (i = 0; i < len; i += 16) {
+ printk("%s%.8x:", level, i);
+ for (j = 0; (j < 16) && (i + j) < len; j++) {
+ if (!(j % 4))
+ printk(" ");
+ printk("%.2x", ptr[i + j]);
+ }
+ printk("-");
+ for (j = 0; (j < 16) && (i + j) < len; j++) {
+ printk("%c", isprint(ptr[i + j]) ? ptr[i + j] : '.');
+ if (j == 7)
+ printk(" ");
+ }
+ printk("\n");
+ }
+}
+EXPORT_SYMBOL(hex_dumper);


2007-05-02 22:46:11

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] lib/hexdump

On Wed, 2 May 2007 15:35:56 -0700
Randy Dunlap <[email protected]> wrote:

> From: Randy Dunlap <[email protected]>
>
> Based on ace_dump_mem() from Grant Likely for the Xilinx
> SystemACE CompactFlash interface.
>
> Add hex_dumper() to lib/hexdump.c and linux/kernel.h.
>
> This patch adds the function 'hex_dumper' which can be used to perform a
> hex + ASCII dump of data to syslog, in an easily viewable format, thus
> providing a common text hex dump format.
>
> It does not provide a hexdump_to_buffer() function.
> if someone needs that, we'll have to add it.
>
> Example usage:
> hex_dumper(KERN_DEBUG, data, length);
>

Fair enough. This is the sort of thing one could easily overdesign ;)

>
> include/linux/kernel.h | 1
> lib/Makefile | 2 -
> lib/hexdump.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 53 insertions(+), 1 deletion(-)
>
> --- linux-2.6.21-git4.orig/include/linux/kernel.h
> +++ linux-2.6.21-git4/include/linux/kernel.h
> @@ -201,6 +201,7 @@ extern enum system_states {
> #define TAINT_USER (1<<6)
>
> extern void dump_stack(void);
> +extern void hex_dumper(const char *level, void *base, int len);
>
> #ifdef DEBUG
> /* If you are writing a driver, please use dev_dbg instead */
> --- linux-2.6.21-git4.orig/lib/Makefile
> +++ linux-2.6.21-git4/lib/Makefile
> @@ -5,7 +5,7 @@
> lib-y := ctype.o string.o vsprintf.o cmdline.o \
> rbtree.o radix-tree.o dump_stack.o \
> idr.o int_sqrt.o bitmap.o extable.o prio_tree.o \
> - sha1.o irq_regs.o reciprocal_div.o
> + sha1.o irq_regs.o reciprocal_div.o hexdump.o
>
> lib-$(CONFIG_MMU) += ioremap.o
> lib-$(CONFIG_SMP) += cpumask.o
> --- /dev/null
> +++ linux-2.6.21-git4/lib/hexdump.c
> @@ -0,0 +1,51 @@
> +/*
> + * lib/hexdump.c
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation. See README and COPYING for
> + * more details.
> + */
> +
> +#include <linux/types.h>
> +#include <linux/ctype.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +
> +/**
> + * hex_dumper - print a text hex dump to syslog for a binary blob of data
> + * @level: kernel log level (e.g. KERN_DEBUG)
> + * @buf: data blob to dump
> + * @len: number of bytes in the @buf
> + *
> + * Given a buffer of u8 data, hex_dumper() will print a hex + ASCII dump
> + * to the kernel log at the specified kernel log level.
> + *
> + * E.g.:
> + * hex_dumper(KERN_DEBUG, frame->data, frame->len);
> + *
> + * Prints the offsets of the block of memory, not addresses:
> + * 0009ab42: 40414243 44454647 48494a4b 4c4d4e4f-@ABCDEFG HIJKLMNO

But I suspect it should be printing the addresses, for many callers.

In which case we'd need a separate arg (base_address or somesuch) so that
callers who want to show real virtual addresses can pass in `base' and
callers who want to display relative offsets can pass in 0.

Which implies that the address will need to be printed as a 16-digit number
on 64-bit kernels.

> + */
> +void hex_dumper(const char *level, void *base, int len)
> +{
> + const u8 *ptr = base;
> + int i, j;
> +
> + for (i = 0; i < len; i += 16) {
> + printk("%s%.8x:", level, i);
> + for (j = 0; (j < 16) && (i + j) < len; j++) {
> + if (!(j % 4))
> + printk(" ");
> + printk("%.2x", ptr[i + j]);
> + }
> + printk("-");
> + for (j = 0; (j < 16) && (i + j) < len; j++) {
> + printk("%c", isprint(ptr[i + j]) ? ptr[i + j] : '.');
> + if (j == 7)
> + printk(" ");
> + }
> + printk("\n");
> + }
> +}
> +EXPORT_SYMBOL(hex_dumper);

2007-05-02 22:53:34

by Randy Dunlap

[permalink] [raw]
Subject: Re: [PATCH] lib/hexdump

Andrew Morton wrote:
> On Wed, 2 May 2007 15:35:56 -0700
> Randy Dunlap <[email protected]> wrote:
>
>> From: Randy Dunlap <[email protected]>
>>
>> Based on ace_dump_mem() from Grant Likely for the Xilinx
>> SystemACE CompactFlash interface.
>>
>> Add hex_dumper() to lib/hexdump.c and linux/kernel.h.
>>
>> This patch adds the function 'hex_dumper' which can be used to perform a
>> hex + ASCII dump of data to syslog, in an easily viewable format, thus
>> providing a common text hex dump format.
>>
>> It does not provide a hexdump_to_buffer() function.
>> if someone needs that, we'll have to add it.
>>
>> Example usage:
>> hex_dumper(KERN_DEBUG, data, length);
>>
>
> Fair enough. This is the sort of thing one could easily overdesign ;)

The Intel version also returned the number of bytes printed.
and they had a hexdump_to_buffer() for sysfs output.


>> include/linux/kernel.h | 1
>> lib/Makefile | 2 -
>> lib/hexdump.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 53 insertions(+), 1 deletion(-)
>>
>> --- /dev/null
>> +++ linux-2.6.21-git4/lib/hexdump.c
>> @@ -0,0 +1,51 @@

>> +/**
>> + * hex_dumper - print a text hex dump to syslog for a binary blob of data
>> + * @level: kernel log level (e.g. KERN_DEBUG)
>> + * @buf: data blob to dump
>> + * @len: number of bytes in the @buf
>> + *
>> + * Given a buffer of u8 data, hex_dumper() will print a hex + ASCII dump
>> + * to the kernel log at the specified kernel log level.
>> + *
>> + * E.g.:
>> + * hex_dumper(KERN_DEBUG, frame->data, frame->len);
>> + *
>> + * Prints the offsets of the block of memory, not addresses:
>> + * 0009ab42: 40414243 44454647 48494a4b 4c4d4e4f-@ABCDEFG HIJKLMNO
>
> But I suspect it should be printing the addresses, for many callers.
>
> In which case we'd need a separate arg (base_address or somesuch) so that
> callers who want to show real virtual addresses can pass in `base' and
> callers who want to display relative offsets can pass in 0.

OK, that's one way to do it. I'll wait a bit for other comments.

> Which implies that the address will need to be printed as a 16-digit number
> on 64-bit kernels.

Yep.


--
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***

2007-05-02 23:06:45

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] lib/hexdump

On Wed, 02 May 2007 15:56:48 -0700
Randy Dunlap <[email protected]> wrote:

> Andrew Morton wrote:
> > On Wed, 2 May 2007 15:35:56 -0700
> > Randy Dunlap <[email protected]> wrote:
> >
> >> From: Randy Dunlap <[email protected]>
> >>
> >> Based on ace_dump_mem() from Grant Likely for the Xilinx
> >> SystemACE CompactFlash interface.
> >>
> >> Add hex_dumper() to lib/hexdump.c and linux/kernel.h.
> >>
> >> This patch adds the function 'hex_dumper' which can be used to perform a
> >> hex + ASCII dump of data to syslog, in an easily viewable format, thus
> >> providing a common text hex dump format.
> >>
> >> It does not provide a hexdump_to_buffer() function.
> >> if someone needs that, we'll have to add it.
> >>
> >> Example usage:
> >> hex_dumper(KERN_DEBUG, data, length);
> >>
> >
> > Fair enough. This is the sort of thing one could easily overdesign ;)
>
> The Intel version also returned the number of bytes printed.
> and they had a hexdump_to_buffer() for sysfs output.
>

Yeah, that's where we get into creature feeping. Really it should be
passed the address of a function which performs the per-char output and
which is passed a bunch of args so it can do its stuff. But doing printk
of a single char at a time is a bit inefficient and produces mangled output
on SMP. And then we don't know the length of the output and we'd like it
dynamically allocated and on and on.

Ho hum. Perhaps a middle ground is to implement hexdump-to-memory as the
core function. hex_dumper() becomes a simple wrapper around that. (but
how big is its buffer? One line would be OK, I guess)

> OK, that's one way to do it. I'll wait a bit for other comments.

Good luck ;)

2007-05-02 23:12:16

by Randy Dunlap

[permalink] [raw]
Subject: Re: [PATCH] lib/hexdump

On Wed, 2 May 2007 16:06:35 -0700 Andrew Morton wrote:

> On Wed, 02 May 2007 15:56:48 -0700
> Randy Dunlap <[email protected]> wrote:
>
> > Andrew Morton wrote:
> > > On Wed, 2 May 2007 15:35:56 -0700
> > > Randy Dunlap <[email protected]> wrote:
> > >
> > >> From: Randy Dunlap <[email protected]>
> > >>
> > >> Based on ace_dump_mem() from Grant Likely for the Xilinx
> > >> SystemACE CompactFlash interface.
> > >>
> > >> Add hex_dumper() to lib/hexdump.c and linux/kernel.h.
> > >>
> > >> This patch adds the function 'hex_dumper' which can be used to perform a
> > >> hex + ASCII dump of data to syslog, in an easily viewable format, thus
> > >> providing a common text hex dump format.
> > >>
> > >> It does not provide a hexdump_to_buffer() function.
> > >> if someone needs that, we'll have to add it.
> > >>
> > >> Example usage:
> > >> hex_dumper(KERN_DEBUG, data, length);
> > >>
> > >
> > > Fair enough. This is the sort of thing one could easily overdesign ;)
> >
> > The Intel version also returned the number of bytes printed.
> > and they had a hexdump_to_buffer() for sysfs output.
> >
>
> Yeah, that's where we get into creature feeping. Really it should be
> passed the address of a function which performs the per-char output and
> which is passed a bunch of args so it can do its stuff. But doing printk
> of a single char at a time is a bit inefficient and produces mangled output
> on SMP. And then we don't know the length of the output and we'd like it
> dynamically allocated and on and on.
>
> Ho hum. Perhaps a middle ground is to implement hexdump-to-memory as the
> core function. hex_dumper() becomes a simple wrapper around that. (but
> how big is its buffer? One line would be OK, I guess)

Yeah, I almost did it that way. We'll see.

> > OK, that's one way to do it. I'll wait a bit for other comments.
>
> Good luck ;)

---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***

2007-05-03 07:05:31

by Jan Engelhardt

[permalink] [raw]
Subject: Re: [PATCH] lib/hexdump


On May 2 2007 15:35, Randy Dunlap wrote:
>
>Add hex_dumper() to lib/hexdump.c and linux/kernel.h.

Right - we've got the second user already, namely the PANIC/OOPS
code print. (The last line, aka "bytes at EIP" under Windows.)

Jan 6 14:40:14 deekin kernel: Call Trace:
Jan 6 14:40:14 deekin kernel: [<c02060b3>] is_complete+0x2c3/0x310
Jan 6 14:40:14 deekin kernel: [<c02037c0>] run+0x30/0x40
Jan 6 14:40:14 deekin kernel: [<c0125b6d>] worker_thread+0x1bd/0x2b0
Jan 6 14:40:14 deekin kernel: [<c0203790>] run+0x0/0x40
Jan 6 14:40:14 deekin kernel: [<c0113b10>] default_wake_function+0x0/0x20
Jan 6 14:40:14 deekin kernel: [<c0108fd6>] ret_from_fork+0x6/0x20
Jan 6 14:40:14 deekin kernel: [<c0113b10>] default_wake_function+0x0/0x20
Jan 6 14:40:14 deekin kernel: [<c01259b0>] worker_thread+0x0/0x2b0
Jan 6 14:40:14 deekin kernel: [<c0107175>] kernel_thread_helper+0x5/0x10
Jan 6 14:40:14 deekin kernel: Code: 89 02 8b 41 04 8b 40 3c 8b 53 04 89 42 3c
8b 41 04


Jan
--

2007-05-03 16:22:33

by Randy Dunlap

[permalink] [raw]
Subject: Re: [PATCH] lib/hexdump

On Thu, 3 May 2007 09:01:31 +0200 (MEST) Jan Engelhardt wrote:

>
> On May 2 2007 15:35, Randy Dunlap wrote:
> >
> >Add hex_dumper() to lib/hexdump.c and linux/kernel.h.
>
> Right - we've got the second user already, namely the PANIC/OOPS
> code print. (The last line, aka "bytes at EIP" under Windows.)
>
> Jan 6 14:40:14 deekin kernel: Call Trace:
> Jan 6 14:40:14 deekin kernel: [<c02060b3>] is_complete+0x2c3/0x310
> Jan 6 14:40:14 deekin kernel: [<c02037c0>] run+0x30/0x40
> Jan 6 14:40:14 deekin kernel: [<c0125b6d>] worker_thread+0x1bd/0x2b0
> Jan 6 14:40:14 deekin kernel: [<c0203790>] run+0x0/0x40
> Jan 6 14:40:14 deekin kernel: [<c0113b10>] default_wake_function+0x0/0x20
> Jan 6 14:40:14 deekin kernel: [<c0108fd6>] ret_from_fork+0x6/0x20
> Jan 6 14:40:14 deekin kernel: [<c0113b10>] default_wake_function+0x0/0x20
> Jan 6 14:40:14 deekin kernel: [<c01259b0>] worker_thread+0x0/0x2b0
> Jan 6 14:40:14 deekin kernel: [<c0107175>] kernel_thread_helper+0x5/0x10
> Jan 6 14:40:14 deekin kernel: Code: 89 02 8b 41 04 8b 40 3c 8b 53 04 89 42 3c
> 8b 41 04

plus intel wireless drivers, 2 MTD/flash drivers, and search
kernel tree for hexdump (function name that I wanted to use, but
it's already used), hex_dump, dump_hex, dump_mem, etc.

Andrew says that he knew of 9 hex dumpers in-tree. :)

---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
(sorry about email address change; other address not working for some reason)

2007-05-04 00:47:11

by Randy Dunlap

[permalink] [raw]
Subject: [PATCH v2] lib/hexdump


> > Ho hum. Perhaps a middle ground is to implement hexdump-to-memory as the
> > core function. hex_dumper() becomes a simple wrapper around that. (but
> > how big is its buffer? One line would be OK, I guess)
>
> Yeah, I almost did it that way. We'll see.
>
> > > OK, that's one way to do it. I'll wait a bit for other comments.
> >
> > Good luck ;)

next try:


From: Randy Dunlap <[email protected]>

Based on ace_dump_mem() from Grant Likely for the Xilinx
SystemACE CompactFlash interface.

Add print_hex_dump() & hex_dumper() to lib/hexdump.c and linux/kernel.h.

This patch adds the functions print_hex_dump() & hex_dumper().
print_hex_dump() can be used to perform a hex + ASCII dump of data to syslog,
in an easily viewable format, thus providing a common text hex dump format.

hex_dumper() provides a dump-to-memory function. It converts one "line"
of output (16 bytes of input) at a time.

Example usages:
print_hex_dump(KERN_DEBUG, DUMP_PREFIX_ADDRESS, frame->data, frame->len);
hex_dumper(frame->data, frame->len, linebuf, sizeof(linebuf));

Example output using %DUMP_PREFIX_OFFSET:
0009ab42: 40414243 44454647 48494a4b 4c4d4e4f-@ABCDEFG HIJKLMNO
Example output using %DUMP_PREFIX_ADDRESS:
ffffffff88089af0: 70717273 74757677 78797a7b 7c7d7e7f-pqrstuvw xyz{|}~.

Signed-off-by: Randy Dunlap <[email protected]>
---

include/linux/kernel.h | 10 ++++
lib/Makefile | 2
lib/hexdump.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 116 insertions(+), 1 deletion(-)

--- linux-2.6.21-git4.orig/include/linux/kernel.h
+++ linux-2.6.21-git4/include/linux/kernel.h
@@ -202,6 +202,16 @@ extern enum system_states {

extern void dump_stack(void);

+enum {
+ DUMP_PREFIX_NONE,
+ DUMP_PREFIX_ADDRESS,
+ DUMP_PREFIX_OFFSET
+};
+extern void hex_dumper(void *buf, size_t len, char *linebuf, size_t linebuflen);
+extern void print_hex_dump(const char *level, int prefix_type,
+ void *buf, size_t len);
+#define hextoasc(x) "0123456789abcdef"[x]
+
#ifdef DEBUG
/* If you are writing a driver, please use dev_dbg instead */
#define pr_debug(fmt,arg...) \
--- linux-2.6.21-git4.orig/lib/Makefile
+++ linux-2.6.21-git4/lib/Makefile
@@ -13,7 +13,7 @@ lib-$(CONFIG_SMP) += cpumask.o
lib-y += kobject.o kref.o kobject_uevent.o klist.o

obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
- bust_spinlocks.o
+ bust_spinlocks.o hexdump.o

ifeq ($(CONFIG_DEBUG_KOBJECT),y)
CFLAGS_kobject.o += -DDEBUG
--- /dev/null
+++ linux-2.6.21-git4/lib/hexdump.c
@@ -0,0 +1,105 @@
+/*
+ * lib/hexdump.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+/**
+ * hex_dumper - convert a blob of data to "hex ASCII" in memory
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ * @linebuf: where to put the converted data
+ * @linebuflen: total size of @linebuf, including space for terminating NUL
+ *
+ * hex_dumper() works on one "line" of output at a time, i.e.,
+ * 16 bytes of input data converted to hex + ASCII output.
+ *
+ * Given a buffer of u8 data, hex_dumper() converts the input data to a
+ * hex + ASCII dump at the supplied memory location.
+ * The converted output is always NUL-terminated.
+ *
+ * E.g.:
+ * hex_dumper(frame->data, frame->len, linebuf, sizeof(linebuf));
+ *
+ * Prints the offsets of the block of memory, not addresses:
+ * 0009ab42: 40414243 44454647 48494a4b 4c4d4e4f-@ABCDEFG HIJKLMNO
+ */
+void hex_dumper(void *buf, size_t len, char *linebuf, size_t linebuflen)
+{
+ const u8 *ptr = buf;
+ u8 ch;
+ int j, lx = 0;
+
+ for (j = 0; (j < 16) && (j < len) && (lx + 3) < linebuflen; j++) {
+ if (j && !(j % 4))
+ linebuf[lx++] = ' ';
+ ch = ptr[j];
+ linebuf[lx++] = hextoasc(ch >> 4);
+ linebuf[lx++] = hextoasc(ch & 0x0f);
+ }
+ if (lx < linebuflen)
+ linebuf[lx++] = '-';
+ for (j = 0; (j < 16) && (j < len) && (lx + 2) < linebuflen; j++) {
+ linebuf[lx++] = isprint(ptr[j]) ? ptr[j] : '.';
+ if (j == 7)
+ linebuf[lx++] = ' ';
+ }
+ linebuf[lx++] = '\0';
+}
+EXPORT_SYMBOL(hex_dumper);
+
+/**
+ * print_hex_dump - print a text hex dump to syslog for a binary blob of data
+ * @level: kernel log level (e.g. KERN_DEBUG)
+ * @prefix_type: controls whether prefix of an offset, address, or none
+ * is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ *
+ * Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
+ * to the kernel log at the specified kernel log level, with an optional
+ * leading prefix.
+ *
+ * E.g.:
+ * print_hex_dump(KERN_DEBUG, DUMP_PREFIX_ADDRESS, frame->data, frame->len);
+ *
+ * Example output using %DUMP_PREFIX_OFFSET:
+ * 0009ab42: 40414243 44454647 48494a4b 4c4d4e4f-@ABCDEFG HIJKLMNO
+ * Example output using %DUMP_PREFIX_ADDRESS:
+ * ffffffff88089af0: 70717273 74757677 78797a7b 7c7d7e7f-pqrstuvw xyz{|}~.
+ */
+void print_hex_dump(const char *level, int prefix_type, void *buf, size_t len)
+{
+ u8 *ptr = buf;
+ int i, linelen, remaining = len;
+ unsigned char linebuf[100];
+
+ for (i = 0; i < len; i += 16) {
+ linelen = min(remaining, 16);
+ remaining -= 16;
+ hex_dumper(ptr + i, linelen, linebuf, sizeof(linebuf));
+
+ switch (prefix_type)
+ {
+ case DUMP_PREFIX_ADDRESS:
+ printk("%s%*p: %s\n", level,
+ (int)(2 * sizeof(void *)), ptr + i, linebuf);
+ break;
+ case DUMP_PREFIX_OFFSET:
+ printk("%s%.8x: %s\n", level, i, linebuf);
+ break;
+ default:
+ printk("%s%s\n", level, linebuf);
+ break;
+ }
+ }
+}
+EXPORT_SYMBOL(print_hex_dump);

2007-05-04 09:39:37

by Pekka Enberg

[permalink] [raw]
Subject: Re: [PATCH v2] lib/hexdump

Hi Randy,

On 5/4/07, Randy Dunlap <[email protected]> wrote:
> +extern void hex_dumper(void *buf, size_t len, char *linebuf, size_t linebuflen);

Please do s/hex_dumper/hex_dump_to_buffer/ for consistency with print_hex_dump.

2007-05-04 13:41:57

by Hugh Dickins

[permalink] [raw]
Subject: Re: [PATCH v2] lib/hexdump

On Thu, 3 May 2007, Randy Dunlap wrote:
>
> Example output using %DUMP_PREFIX_OFFSET:
> 0009ab42: 40414243 44454647 48494a4b 4c4d4e4f-@ABCDEFG HIJKLMNO
^ ^
> Example output using %DUMP_PREFIX_ADDRESS:
> ffffffff88089af0: 70717273 74757677 78797a7b 7c7d7e7f-pqrstuvw xyz{|}~.
^ ^
I see that hyphen as joining together two unlike fields rather than
separating them: maybe change it to a couple of spaces? And the space
halfway through the string is more interfering than helpful (when that
field is useful, it's a string: which shouldn't have a spurious space
inserted). Otherwise looks nice to me.

Hugh

2007-05-04 18:21:39

by Randy Dunlap

[permalink] [raw]
Subject: Re: [PATCH v2] lib/hexdump update on feedback

From: Randy Dunlap <[email protected]>

Rename hex_dumper() to hex_dump_to_buffer().
Rename hextoasc() macro to hex_asc()
[remove conflicts with sky/skfp/skge drivers].
Change output format to remove '-' in middle of ASCII output and
add space between hex and ASCII output.

Signed-off-by: Randy Dunlap <[email protected]>
---
include/linux/kernel.h | 4 ++--
lib/hexdump.c | 40 ++++++++++++++++++++--------------------
2 files changed, 22 insertions(+), 22 deletions(-)

--- linux-2.6.21-git4.orig/include/linux/kernel.h
+++ linux-2.6.21-git4/include/linux/kernel.h
@@ -207,11 +207,11 @@ enum {
DUMP_PREFIX_ADDRESS,
DUMP_PREFIX_OFFSET
};
-extern void hex_dumper(const void *buf, size_t len, char *linebuf,
+extern void hex_dump_to_buffer(const void *buf, size_t len, char *linebuf,
size_t linebuflen);
extern void print_hex_dump(const char *level, int prefix_type,
void *buf, size_t len);
-#define hextoasc(x) "0123456789abcdef"[x]
+#define hex_asc(x) "0123456789abcdef"[x]

#ifdef DEBUG
/* If you are writing a driver, please use dev_dbg instead */
--- linux-2.6.21-git4.orig/lib/hexdump.c
+++ linux-2.6.21-git4/lib/hexdump.c
@@ -13,26 +13,27 @@
#include <linux/module.h>

/**
- * hex_dumper - convert a blob of data to "hex ASCII" in memory
+ * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
* @buf: data blob to dump
* @len: number of bytes in the @buf
* @linebuf: where to put the converted data
* @linebuflen: total size of @linebuf, including space for terminating NUL
*
- * hex_dumper() works on one "line" of output at a time, i.e.,
+ * hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
* 16 bytes of input data converted to hex + ASCII output.
*
- * Given a buffer of u8 data, hex_dumper() converts the input data to a
- * hex + ASCII dump at the supplied memory location.
+ * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
+ * to a hex + ASCII dump at the supplied memory location.
* The converted output is always NUL-terminated.
*
* E.g.:
- * hex_dumper(frame->data, frame->len, linebuf, sizeof(linebuf));
+ * hex_dump_to_buffer(frame->data, frame->len, linebuf, sizeof(linebuf));
*
- * Prints the offsets of the block of memory, not addresses:
- * 0009ab42: 40414243 44454647 48494a4b 4c4d4e4f-@ABCDEFG HIJKLMNO
+ * example output buffer:
+ * 40414243 44454647 48494a4b 4c4d4e4f @ABCDEFGHIJKLMNO
*/
-void hex_dumper(const void *buf, size_t len, char *linebuf, size_t linebuflen)
+void hex_dump_to_buffer(const void *buf, size_t len, char *linebuf,
+ size_t linebuflen)
{
const u8 *ptr = buf;
u8 ch;
@@ -42,19 +43,18 @@ void hex_dumper(const void *buf, size_t
if (j && !(j % 4))
linebuf[lx++] = ' ';
ch = ptr[j];
- linebuf[lx++] = hextoasc(ch >> 4);
- linebuf[lx++] = hextoasc(ch & 0x0f);
+ linebuf[lx++] = hex_asc(ch >> 4);
+ linebuf[lx++] = hex_asc(ch & 0x0f);
}
- if (lx < linebuflen)
- linebuf[lx++] = '-';
- for (j = 0; (j < 16) && (j < len) && (lx + 2) < linebuflen; j++) {
- linebuf[lx++] = isprint(ptr[j]) ? ptr[j] : '.';
- if (j == 7)
- linebuf[lx++] = ' ';
+ if ((lx + 2) < linebuflen) {
+ linebuf[lx++] = ' ';
+ linebuf[lx++] = ' ';
}
+ for (j = 0; (j < 16) && (j < len) && (lx + 2) < linebuflen; j++)
+ linebuf[lx++] = isprint(ptr[j]) ? ptr[j] : '.';
linebuf[lx++] = '\0';
}
-EXPORT_SYMBOL(hex_dumper);
+EXPORT_SYMBOL(hex_dump_to_buffer);

/**
* print_hex_dump - print a text hex dump to syslog for a binary blob of data
@@ -72,9 +72,9 @@ EXPORT_SYMBOL(hex_dumper);
* print_hex_dump(KERN_DEBUG, DUMP_PREFIX_ADDRESS, frame->data, frame->len);
*
* Example output using %DUMP_PREFIX_OFFSET:
- * 0009ab42: 40414243 44454647 48494a4b 4c4d4e4f-@ABCDEFG HIJKLMNO
+ * 0009ab42: 40414243 44454647 48494a4b 4c4d4e4f @ABCDEFGHIJKLMNO
* Example output using %DUMP_PREFIX_ADDRESS:
- * ffffffff88089af0: 70717273 74757677 78797a7b 7c7d7e7f-pqrstuvw xyz{|}~.
+ * ffffffff88089af0: 70717273 74757677 78797a7b 7c7d7e7f pqrstuvwxyz{|}~.
*/
void print_hex_dump(const char *level, int prefix_type, void *buf, size_t len)
{
@@ -85,7 +85,7 @@ void print_hex_dump(const char *level, i
for (i = 0; i < len; i += 16) {
linelen = min(remaining, 16);
remaining -= 16;
- hex_dumper(ptr + i, linelen, linebuf, sizeof(linebuf));
+ hex_dump_to_buffer(ptr + i, linelen, linebuf, sizeof(linebuf));

switch (prefix_type) {
case DUMP_PREFIX_ADDRESS: