Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hexdump.c
Go to the documentation of this file.
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";
17 
25 int hex_to_bin(char ch)
26 {
27  if ((ch >= '0') && (ch <= '9'))
28  return ch - '0';
29  ch = tolower(ch);
30  if ((ch >= 'a') && (ch <= 'f'))
31  return ch - 'a' + 10;
32  return -1;
33 }
35 
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 }
58 
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 }
163 
164 #ifdef CONFIG_PRINTK
165 
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 
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