lkml.org 
[lkml]   [2019]   [May]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 5/7] lib/hexdump.c: Allow multiple groups to be separated by lines '|'
    Date
    From: Alastair D'Silva <alastair@d-silva.org>

    With the wider display format, it can become hard to identify how many
    bytes into the line you are looking at.

    The patch adds new flags to hex_dump_to_buffer() and print_hex_dump() to
    print vertical lines to separate every N groups of bytes.

    eg.
    buf:00000000: 454d414e 43415053|4e495f45 00584544 NAMESPAC|E_INDEX.
    buf:00000010: 00000000 00000002|00000000 00000000 ........|........

    Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
    ---
    include/linux/printk.h | 3 +++
    lib/hexdump.c | 59 ++++++++++++++++++++++++++++++++++++------
    2 files changed, 54 insertions(+), 8 deletions(-)

    diff --git a/include/linux/printk.h b/include/linux/printk.h
    index 00a82e468643..dc693aec394c 100644
    --- a/include/linux/printk.h
    +++ b/include/linux/printk.h
    @@ -482,6 +482,9 @@ enum {

    #define HEXDUMP_ASCII (1 << 0)
    #define HEXDUMP_SUPPRESS_REPEATED (1 << 1)
    +#define HEXDUMP_2_GRP_LINES (1 << 2)
    +#define HEXDUMP_4_GRP_LINES (1 << 3)
    +#define HEXDUMP_8_GRP_LINES (1 << 4)

    extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
    int groupsize, char *linebuf, size_t linebuflen,
    diff --git a/lib/hexdump.c b/lib/hexdump.c
    index ddd1697e5f9b..6f4d1176c332 100644
    --- a/lib/hexdump.c
    +++ b/lib/hexdump.c
    @@ -77,6 +77,23 @@ char *bin2hex(char *dst, const void *src, size_t count)
    }
    EXPORT_SYMBOL(bin2hex);

    +static const char *group_separator(int group, u64 flags)
    +{
    + if (group == 0)
    + return " ";
    +
    + if ((flags & HEXDUMP_8_GRP_LINES) && !((group) % 8))
    + return "|";
    +
    + if ((flags & HEXDUMP_4_GRP_LINES) && !((group) % 4))
    + return "|";
    +
    + if ((flags & HEXDUMP_2_GRP_LINES) && !((group) % 2))
    + return "|";
    +
    + return " ";
    +}
    +
    /**
    * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
    * @buf: data blob to dump
    @@ -87,6 +104,9 @@ EXPORT_SYMBOL(bin2hex);
    * @linebuflen: total size of @linebuf, including space for terminating NUL
    * @flags: A bitwise OR of the following flags:
    * HEXDUMP_ASCII: include ASCII after the hex output
    + * HEXDUMP_2_GRP_LINES: insert a '|' after every 2 groups
    + * HEXDUMP_4_GRP_LINES: insert a '|' after every 4 groups
    + * HEXDUMP_8_GRP_LINES: insert a '|' after every 8 groups
    *
    * hex_dump_to_buffer() works on one "line" of output at a time, converting
    * <groupsize> bytes of input to hexadecimal (and optionally printable ASCII)
    @@ -118,6 +138,7 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
    int j, lx = 0;
    int ascii_column;
    int ret;
    + int line_chars = 0;

    if (!is_power_of_2(groupsize) || groupsize > 8)
    groupsize = 1;
    @@ -144,7 +165,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,

    for (j = 0; j < ngroups; j++) {
    ret = snprintf(linebuf + lx, linebuflen - lx,
    - "%s%16.16llx", j ? " " : "",
    + "%s%16.16llx",
    + j ? group_separator(j, flags) : "",
    get_unaligned(ptr8 + j));
    if (ret >= linebuflen - lx)
    goto overflow1;
    @@ -155,7 +177,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,

    for (j = 0; j < ngroups; j++) {
    ret = snprintf(linebuf + lx, linebuflen - lx,
    - "%s%8.8x", j ? " " : "",
    + "%s%8.8x",
    + j ? group_separator(j, flags) : "",
    get_unaligned(ptr4 + j));
    if (ret >= linebuflen - lx)
    goto overflow1;
    @@ -166,7 +189,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,

    for (j = 0; j < ngroups; j++) {
    ret = snprintf(linebuf + lx, linebuflen - lx,
    - "%s%4.4x", j ? " " : "",
    + "%s%4.4x",
    + j ? group_separator(j, flags) : "",
    get_unaligned(ptr2 + j));
    if (ret >= linebuflen - lx)
    goto overflow1;
    @@ -196,11 +220,26 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
    goto overflow2;
    linebuf[lx++] = ' ';
    }
    +
    + if (flags & HEXDUMP_2_GRP_LINES)
    + line_chars = groupsize * 2;
    + if (flags & HEXDUMP_4_GRP_LINES)
    + line_chars = groupsize * 4;
    + if (flags & HEXDUMP_8_GRP_LINES)
    + line_chars = groupsize * 8;
    +
    for (j = 0; j < len; j++) {
    if (linebuflen < lx + 2)
    goto overflow2;
    ch = ptr[j];
    linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.';
    +
    + if (line_chars && ((j + 1) < len) &&
    + ((j + 1) % line_chars == 0)) {
    + if (linebuflen < lx + 2)
    + goto overflow2;
    + linebuf[lx++] = '|';
    + }
    }
    nil:
    linebuf[lx] = '\0';
    @@ -208,7 +247,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
    overflow2:
    linebuf[lx++] = '\0';
    overflow1:
    - return (flags & HEXDUMP_ASCII) ? ascii_column + len :
    + return (flags & HEXDUMP_ASCII) ? ascii_column + len +
    + (len - 1) / line_chars :
    (groupsize * 2 + 1) * ngroups - 1;
    }
    EXPORT_SYMBOL(hex_dump_to_buffer);
    @@ -246,7 +286,7 @@ static void announce_skipped(const char *level, const char *prefix_str,
    if (count == 0)
    return;

    - printk("%s%s ** Skipped %lu bytes of value 0x%x **\n",
    + printk("%s%s ** Skipped %lu bytes of value 0x%02x **\n",
    level, prefix_str, count, val);
    }

    @@ -266,6 +306,9 @@ static void announce_skipped(const char *level, const char *prefix_str,
    * HEXDUMP_ASCII: include ASCII after the hex output
    * HEXDUMP_SUPPRESS_REPEATED: suppress repeated lines of identical
    * bytes
    + * HEXDUMP_2_GRP_LINES: insert a '|' after every 2 groups
    + * HEXDUMP_4_GRP_LINES: insert a '|' after every 4 groups
    + * HEXDUMP_8_GRP_LINES: insert a '|' after every 8 groups
    *
    * 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
    @@ -295,14 +338,14 @@ void print_hex_dump_ext(const char *level, const char *prefix_str,
    u8 skipped_val = 0;
    size_t skipped = 0;

    -
    if (rowsize % groupsize)
    rowsize -= rowsize % groupsize;

    /* Worst case line length:
    - * 2 hex chars + space per byte in, 2 spaces, 1 char per byte in, NULL
    + * 2 hex chars + space per byte in, 2 spaces, 1 char per byte in,
    + * 1 char per N groups, NULL
    */
    - linebuf_len = rowsize * 3 + 2 + rowsize + 1;
    + linebuf_len = rowsize * 3 + 2 + rowsize + rowsize / groupsize + 1;
    linebuf = kzalloc(linebuf_len, GFP_KERNEL);
    if (!linebuf) {
    printk("%s%shexdump: Could not alloc %u bytes for buffer\n",
    --
    2.21.0
    \
     
     \ /
      Last update: 2019-05-08 09:04    [W:2.841 / U:0.520 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site