The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/lib/hexdump.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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/export.h>
   14 
   15 const char hex_asc[] = "0123456789abcdef";
   16 EXPORT_SYMBOL(hex_asc);
   17 
   18 /**
   19  * hex_to_bin - convert a hex digit to its real value
   20  * @ch: ascii character represents hex digit
   21  *
   22  * hex_to_bin() converts one hex digit to its actual value or -1 in case of bad
   23  * input.
   24  */
   25 int hex_to_bin(char ch)
   26 {
   27         if ((ch >= '') && (ch <= '9'))
   28                 return ch - '';
   29         ch = tolower(ch);
   30         if ((ch >= 'a') && (ch <= 'f'))
   31                 return ch - 'a' + 10;
   32         return -1;
   33 }
   34 EXPORT_SYMBOL(hex_to_bin);
   35 
   36 /**
   37  * hex2bin - convert an ascii hexadecimal string to its binary representation
   38  * @dst: binary result
   39  * @src: ascii hexadecimal string
   40  * @count: result length
   41  *
   42  * Return 0 on success, -1 in case of bad input.
   43  */
   44 int hex2bin(u8 *dst, const char *src, size_t count)
   45 {
   46         while (count--) {
   47                 int hi = hex_to_bin(*src++);
   48                 int lo = hex_to_bin(*src++);
   49 
   50                 if ((hi < 0) || (lo < 0))
   51                         return -1;
   52 
   53                 *dst++ = (hi << 4) | lo;
   54         }
   55         return 0;
   56 }
   57 EXPORT_SYMBOL(hex2bin);
   58 
   59 /**
   60  * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
   61  * @buf: data blob to dump
   62  * @len: number of bytes in the @buf
   63  * @rowsize: number of bytes to print per line; must be 16 or 32
   64  * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
   65  * @linebuf: where to put the converted data
   66  * @linebuflen: total size of @linebuf, including space for terminating NUL
   67  * @ascii: include ASCII after the hex output
   68  *
   69  * hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
   70  * 16 or 32 bytes of input data converted to hex + ASCII output.
   71  *
   72  * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
   73  * to a hex + ASCII dump at the supplied memory location.
   74  * The converted output is always NUL-terminated.
   75  *
   76  * E.g.:
   77  *   hex_dump_to_buffer(frame->data, frame->len, 16, 1,
   78  *                      linebuf, sizeof(linebuf), true);
   79  *
   80  * example output buffer:
   81  * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f  @ABCDEFGHIJKLMNO
   82  */
   83 void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
   84                         int groupsize, char *linebuf, size_t linebuflen,
   85                         bool ascii)
   86 {
   87         const u8 *ptr = buf;
   88         u8 ch;
   89         int j, lx = 0;
   90         int ascii_column;
   91 
   92         if (rowsize != 16 && rowsize != 32)
   93                 rowsize = 16;
   94 
   95         if (!len)
   96                 goto nil;
   97         if (len > rowsize)              /* limit to one line at a time */
   98                 len = rowsize;
   99         if ((len % groupsize) != 0)     /* no mixed size output */
  100                 groupsize = 1;
  101 
  102         switch (groupsize) {
  103         case 8: {
  104                 const u64 *ptr8 = buf;
  105                 int ngroups = len / groupsize;
  106 
  107                 for (j = 0; j < ngroups; j++)
  108                         lx += scnprintf(linebuf + lx, linebuflen - lx,
  109                                         "%s%16.16llx", j ? " " : "",
  110                                         (unsigned long long)*(ptr8 + j));
  111                 ascii_column = 17 * ngroups + 2;
  112                 break;
  113         }
  114 
  115         case 4: {
  116                 const u32 *ptr4 = buf;
  117                 int ngroups = len / groupsize;
  118 
  119                 for (j = 0; j < ngroups; j++)
  120                         lx += scnprintf(linebuf + lx, linebuflen - lx,
  121                                         "%s%8.8x", j ? " " : "", *(ptr4 + j));
  122                 ascii_column = 9 * ngroups + 2;
  123                 break;
  124         }
  125 
  126         case 2: {
  127                 const u16 *ptr2 = buf;
  128                 int ngroups = len / groupsize;
  129 
  130                 for (j = 0; j < ngroups; j++)
  131                         lx += scnprintf(linebuf + lx, linebuflen - lx,
  132                                         "%s%4.4x", j ? " " : "", *(ptr2 + j));
  133                 ascii_column = 5 * ngroups + 2;
  134                 break;
  135         }
  136 
  137         default:
  138                 for (j = 0; (j < len) && (lx + 3) <= linebuflen; j++) {
  139                         ch = ptr[j];
  140                         linebuf[lx++] = hex_asc_hi(ch);
  141                         linebuf[lx++] = hex_asc_lo(ch);
  142                         linebuf[lx++] = ' ';
  143                 }
  144                 if (j)
  145                         lx--;
  146 
  147                 ascii_column = 3 * rowsize + 2;
  148                 break;
  149         }
  150         if (!ascii)
  151                 goto nil;
  152 
  153         while (lx < (linebuflen - 1) && lx < (ascii_column - 1))
  154                 linebuf[lx++] = ' ';
  155         for (j = 0; (j < len) && (lx + 2) < linebuflen; j++) {
  156                 ch = ptr[j];
  157                 linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.';
  158         }
  159 nil:
  160         linebuf[lx++] = '\0';
  161 }
  162 EXPORT_SYMBOL(hex_dump_to_buffer);
  163 
  164 #ifdef CONFIG_PRINTK
  165 /**
  166  * print_hex_dump - print a text hex dump to syslog for a binary blob of data
  167  * @level: kernel log level (e.g. KERN_DEBUG)
  168  * @prefix_str: string to prefix each line with;
  169  *  caller supplies trailing spaces for alignment if desired
  170  * @prefix_type: controls whether prefix of an offset, address, or none
  171  *  is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
  172  * @rowsize: number of bytes to print per line; must be 16 or 32
  173  * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
  174  * @buf: data blob to dump
  175  * @len: number of bytes in the @buf
  176  * @ascii: include ASCII after the hex output
  177  *
  178  * Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
  179  * to the kernel log at the specified kernel log level, with an optional
  180  * leading prefix.
  181  *
  182  * print_hex_dump() works on one "line" of output at a time, i.e.,
  183  * 16 or 32 bytes of input data converted to hex + ASCII output.
  184  * print_hex_dump() iterates over the entire input @buf, breaking it into
  185  * "line size" chunks to format and print.
  186  *
  187  * E.g.:
  188  *   print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS,
  189  *                  16, 1, frame->data, frame->len, true);
  190  *
  191  * Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
  192  * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f  @ABCDEFGHIJKLMNO
  193  * Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
  194  * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c  pqrstuvwxyz{|}~.
  195  */
  196 void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
  197                     int rowsize, int groupsize,
  198                     const void *buf, size_t len, bool ascii)
  199 {
  200         const u8 *ptr = buf;
  201         int i, linelen, remaining = len;
  202         unsigned char linebuf[32 * 3 + 2 + 32 + 1];
  203 
  204         if (rowsize != 16 && rowsize != 32)
  205                 rowsize = 16;
  206 
  207         for (i = 0; i < len; i += rowsize) {
  208                 linelen = min(remaining, rowsize);
  209                 remaining -= rowsize;
  210 
  211                 hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
  212                                    linebuf, sizeof(linebuf), ascii);
  213 
  214                 switch (prefix_type) {
  215                 case DUMP_PREFIX_ADDRESS:
  216                         printk("%s%s%p: %s\n",
  217                                level, prefix_str, ptr + i, linebuf);
  218                         break;
  219                 case DUMP_PREFIX_OFFSET:
  220                         printk("%s%s%.8x: %s\n", level, prefix_str, i, linebuf);
  221                         break;
  222                 default:
  223                         printk("%s%s%s\n", level, prefix_str, linebuf);
  224                         break;
  225                 }
  226         }
  227 }
  228 EXPORT_SYMBOL(print_hex_dump);
  229 
  230 /**
  231  * print_hex_dump_bytes - shorthand form of print_hex_dump() with default params
  232  * @prefix_str: string to prefix each line with;
  233  *  caller supplies trailing spaces for alignment if desired
  234  * @prefix_type: controls whether prefix of an offset, address, or none
  235  *  is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
  236  * @buf: data blob to dump
  237  * @len: number of bytes in the @buf
  238  *
  239  * Calls print_hex_dump(), with log level of KERN_DEBUG,
  240  * rowsize of 16, groupsize of 1, and ASCII output included.
  241  */
  242 void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
  243                           const void *buf, size_t len)
  244 {
  245         print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
  246                        buf, len, true);
  247 }
  248 EXPORT_SYMBOL(print_hex_dump_bytes);
  249 #endif

Cache object: 12c735a7f7685263d6c2f38e447fb534


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.