hexdump.c 6.0 KB

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