linux/lib/hexdump.c
<<
>>
Prefs
   1/*
   2 * lib/hexdump.c
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation. See README and COPYING for
   7 * more details.
   8 */
   9
  10#include <linux/types.h>
  11#include <linux/ctype.h>
  12#include <linux/kernel.h>
  13#include <linux/module.h>
  14
  15/**
  16 * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
  17 * @buf: data blob to dump
  18 * @len: number of bytes in the @buf
  19 * @rowsize: number of bytes to print per line; must be 16 or 32
  20 * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
  21 * @linebuf: where to put the converted data
  22 * @linebuflen: total size of @linebuf, including space for terminating NUL
  23 * @ascii: include ASCII after the hex output
  24 *
  25 * hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
  26 * 16 or 32 bytes of input data converted to hex + ASCII output.
  27 *
  28 * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
  29 * to a hex + ASCII dump at the supplied memory location.
  30 * The converted output is always NUL-terminated.
  31 *
  32 * E.g.:
  33 *   hex_dump_to_buffer(frame->data, frame->len, 16, 1,
  34 *                      linebuf, sizeof(linebuf), 1);
  35 *
  36 * example output buffer:
  37 * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f  @ABCDEFGHIJKLMNO
  38 */
  39void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
  40                        int groupsize, char *linebuf, size_t linebuflen,
  41                        bool ascii)
  42{
  43        const u8 *ptr = buf;
  44        u8 ch;
  45        int j, lx = 0;
  46        int ascii_column;
  47
  48        if (rowsize != 16 && rowsize != 32)
  49                rowsize = 16;
  50
  51        if (!len)
  52                goto nil;
  53        if (len > rowsize)              /* limit to one line at a time */
  54                len = rowsize;
  55        if ((len % groupsize) != 0)     /* no mixed size output */
  56                groupsize = 1;
  57
  58        switch (groupsize) {
  59        case 8: {
  60                const u64 *ptr8 = buf;
  61                int ngroups = len / groupsize;
  62
  63                for (j = 0; j < ngroups; j++)
  64                        lx += scnprintf(linebuf + lx, linebuflen - lx,
  65                                "%16.16llx ", (unsigned long long)*(ptr8 + j));
  66                ascii_column = 17 * ngroups + 2;
  67                break;
  68        }
  69
  70        case 4: {
  71                const u32 *ptr4 = buf;
  72                int ngroups = len / groupsize;
  73
  74                for (j = 0; j < ngroups; j++)
  75                        lx += scnprintf(linebuf + lx, linebuflen - lx,
  76                                "%8.8x ", *(ptr4 + j));
  77                ascii_column = 9 * ngroups + 2;
  78                break;
  79        }
  80
  81        case 2: {
  82                const u16 *ptr2 = buf;
  83                int ngroups = len / groupsize;
  84
  85                for (j = 0; j < ngroups; j++)
  86                        lx += scnprintf(linebuf + lx, linebuflen - lx,
  87                                "%4.4x ", *(ptr2 + j));
  88                ascii_column = 5 * ngroups + 2;
  89                break;
  90        }
  91
  92        default:
  93                for (j = 0; (j < rowsize) && (j < len) && (lx + 4) < linebuflen;
  94                     j++) {
  95                        ch = ptr[j];
  96                        linebuf[lx++] = hex_asc(ch >> 4);
  97                        linebuf[lx++] = hex_asc(ch & 0x0f);
  98                        linebuf[lx++] = ' ';
  99                }
 100                ascii_column = 3 * rowsize + 2;
 101                break;
 102        }
 103        if (!ascii)
 104                goto nil;
 105
 106        while (lx < (linebuflen - 1) && lx < (ascii_column - 1))
 107                linebuf[lx++] = ' ';
 108        for (j = 0; (j < rowsize) && (j < len) && (lx + 2) < linebuflen; j++)
 109                linebuf[lx++] = (isascii(ptr[j]) && isprint(ptr[j])) ? ptr[j]
 110                                : '.';
 111nil:
 112        linebuf[lx++] = '\0';
 113}
 114EXPORT_SYMBOL(hex_dump_to_buffer);
 115
 116/**
 117 * print_hex_dump - print a text hex dump to syslog for a binary blob of data
 118 * @level: kernel log level (e.g. KERN_DEBUG)
 119 * @prefix_str: string to prefix each line with;
 120 *  caller supplies trailing spaces for alignment if desired
 121 * @prefix_type: controls whether prefix of an offset, address, or none
 122 *  is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
 123 * @rowsize: number of bytes to print per line; must be 16 or 32
 124 * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
 125 * @buf: data blob to dump
 126 * @len: number of bytes in the @buf
 127 * @ascii: include ASCII after the hex output
 128 *
 129 * Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
 130 * to the kernel log at the specified kernel log level, with an optional
 131 * leading prefix.
 132 *
 133 * print_hex_dump() works on one "line" of output at a time, i.e.,
 134 * 16 or 32 bytes of input data converted to hex + ASCII output.
 135 * print_hex_dump() iterates over the entire input @buf, breaking it into
 136 * "line size" chunks to format and print.
 137 *
 138 * E.g.:
 139 *   print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS,
 140 *              16, 1, frame->data, frame->len, 1);
 141 *
 142 * Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
 143 * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f  @ABCDEFGHIJKLMNO
 144 * Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
 145 * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c  pqrstuvwxyz{|}~.
 146 */
 147void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
 148                        int rowsize, int groupsize,
 149                        const void *buf, size_t len, bool ascii)
 150{
 151        const u8 *ptr = buf;
 152        int i, linelen, remaining = len;
 153        unsigned char linebuf[200];
 154
 155        if (rowsize != 16 && rowsize != 32)
 156                rowsize = 16;
 157
 158        for (i = 0; i < len; i += rowsize) {
 159                linelen = min(remaining, rowsize);
 160                remaining -= rowsize;
 161                hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
 162                                linebuf, sizeof(linebuf), ascii);
 163
 164                switch (prefix_type) {
 165                case DUMP_PREFIX_ADDRESS:
 166                        printk("%s%s%*p: %s\n", level, prefix_str,
 167                                (int)(2 * sizeof(void *)), ptr + i, linebuf);
 168                        break;
 169                case DUMP_PREFIX_OFFSET:
 170                        printk("%s%s%.8x: %s\n", level, prefix_str, i, linebuf);
 171                        break;
 172                default:
 173                        printk("%s%s%s\n", level, prefix_str, linebuf);
 174                        break;
 175                }
 176        }
 177}
 178EXPORT_SYMBOL(print_hex_dump);
 179
 180/**
 181 * print_hex_dump_bytes - shorthand form of print_hex_dump() with default params
 182 * @prefix_str: string to prefix each line with;
 183 *  caller supplies trailing spaces for alignment if desired
 184 * @prefix_type: controls whether prefix of an offset, address, or none
 185 *  is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
 186 * @buf: data blob to dump
 187 * @len: number of bytes in the @buf
 188 *
 189 * Calls print_hex_dump(), with log level of KERN_DEBUG,
 190 * rowsize of 16, groupsize of 1, and ASCII output included.
 191 */
 192void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
 193                        const void *buf, size_t len)
 194{
 195        print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
 196                        buf, len, 1);
 197}
 198EXPORT_SYMBOL(print_hex_dump_bytes);
 199
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.