blob: 5df261988123da082bd176a8f7b314f4202c76ff [file] [log] [blame]
Stefan Reinauer6540ae52007-07-12 16:35:42 +00001/*****************************************************************************\
2 * hexdump.c
Stefan Reinauer6540ae52007-07-12 16:35:42 +00003\*****************************************************************************/
4
5#include "hexdump.h"
6
7/* hexdump.c
8 *
9 * Copyright (C) 2002
10 * David S. Peterson. All rights reserved.
11 *
12 * Author: David S. Peterson <dave_peterson@pobox.com>
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met:
17 * 1. Redistributions of source code must retain the above copyright notice,
18 * this list of conditions, and the entire permission notice, including
19 * the following disclaimer of warranties.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions, and the entire permission notice,
22 * including the following disclaimer in the documentation and/or other
23 * materials provided with the distribution.
24 * 3. The name(s) of the author(s) may not be used to endorse or promote
25 * products derived from this software without specific prior written
26 * permission.
27 *
28 * ALTERNATIVELY, this product may be distributed under the terms of the GNU
29 * General Public License, in which case the provisions of the GPL are
30 * required INSTEAD OF the above restrictions. (This clause is necessary due
31 * to a potential bad interaction between the GPL and the restrictions
32 * contained in a BSD-style copyright.)
33 *
34 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
35 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
36 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
37 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
39 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
40 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
41 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 */
45
46static void addrprint (FILE *outfile, uint64_t address, int width);
47static void hexprint (FILE *outfile, unsigned char byte);
48static void charprint (FILE *outfile, unsigned char byte,
49 unsigned char nonprintable,
50 is_printable_fn_t is_printable_fn);
51
52/*--------------------------------------------------------------------------
53 * hexdump
54 *
55 * Write a hex dump of 'mem' to 'outfile'.
56 *
57 * parameters:
58 * mem: a pointer to the memory to display
59 * bytes: the number of bytes of data to display
60 * addrprint_start: The address to associate with the first byte of
61 * data. For instance, a value of 0 indicates that the
62 * first byte displayed should be labeled as byte 0.
63 * outfile: The place where the hex dump should be written.
64 * For instance, stdout or stderr may be passed here.
65 * format: A structure specifying how the hex dump should be
66 * formatted.
67 *--------------------------------------------------------------------------*/
68void hexdump (const void *mem, int bytes, uint64_t addrprint_start,
69 FILE *outfile, const hexdump_format_t *format)
70 { int bytes_left, index, i;
71 const unsigned char *p;
72 is_printable_fn_t is_printable_fn;
73
74 /* Quietly return if the caller asks us to do something unreasonable. */
75 if ((format->bytes_per_line <= 0) || (bytes < 0))
76 return;
77
78 is_printable_fn = format->is_printable_fn;
79
80 if (is_printable_fn == NULL)
81 is_printable_fn = default_is_printable_fn;
82
83 p = (const unsigned char *) mem;
84 index = 0;
85
86 /* Each iteration handles one full line of output. When loop terminates,
87 * the number of remaining bytes to display (if any) will not be enough to
88 * fill an entire line.
89 */
90 for (bytes_left = bytes;
91 bytes_left >= format->bytes_per_line;
92 bytes_left -= format->bytes_per_line)
93 { /* print start address for current line */
94 fprintf(outfile, format->indent);
95 addrprint(outfile, addrprint_start + index, format->addrprint_width);
96 fprintf(outfile, format->sep1);
97
98 /* display the bytes in hex */
99 for (i = 0; ; )
100 { hexprint(outfile, p[index++]);
101
102 if (++i >= format->bytes_per_line)
103 break;
104
105 fprintf(outfile, format->sep2);
106 }
107
108 index -= format->bytes_per_line;
109 fprintf(outfile, format->sep3);
110
111 /* display the bytes as characters */
112 for (i = 0; i < format->bytes_per_line; i++)
113 charprint(outfile, p[index++], format->nonprintable,
114 is_printable_fn);
115
116 fprintf(outfile, "\n");
117 }
118
119 if (bytes_left == 0)
120 return;
121
122 /* print start address for last line */
123 fprintf(outfile, format->indent);
124 addrprint(outfile, addrprint_start + index, format->addrprint_width);
125 fprintf(outfile, format->sep1);
126
127 /* display bytes for last line in hex */
128 for (i = 0; i < bytes_left; i++)
129 { hexprint(outfile, p[index++]);
130 fprintf(outfile, format->sep2);
131 }
132
133 index -= bytes_left;
134
135 /* pad the rest of the hex byte area with spaces */
136 for (; ; )
137 { fprintf(outfile, " ");
138
139 if (++i >= format->bytes_per_line)
140 break;
141
142 fprintf(outfile, format->sep2);
143 }
144
145 fprintf(outfile, format->sep3);
146
147 /* display bytes for last line as characters */
148 for (i = 0; i < bytes_left; i++)
149 charprint(outfile, p[index++], format->nonprintable, is_printable_fn);
150
151 /* pad the rest of the character area with spaces */
152 for (; i < format->bytes_per_line; i++)
153 fprintf(outfile, " ");
154
155 fprintf(outfile, "\n");
156 }
157
158/*--------------------------------------------------------------------------
159 * default_is_printable_fn
160 *
161 * Determine whether the input character is printable. The proper behavior
162 * for this type of function may be system-dependent. This function takes a
163 * conservative approach. If it is not adequate for your purposes, you can
164 * write your own.
165 *
166 * parameters:
167 * c: the input character
168 *
169 * return value:
170 * Return 1 if the input character is printable. Otherwise return 0.
171 *--------------------------------------------------------------------------*/
172int default_is_printable_fn (unsigned char c)
173 { return (c >= 0x20) && (c <= 0x7e); }
174
175/*--------------------------------------------------------------------------
176 * addrprint
177 *
178 * Display an address as a hexadecimal number.
179 *
180 * parameters:
181 * outfile: the place where the output should be written
182 * address: the address to display
183 * width: The number of bytes wide the address should be displayed as.
184 * Must be a value from 1 to 8.
185 *--------------------------------------------------------------------------*/
186static void addrprint (FILE *outfile, uint64_t address, int width)
187 { char s[17];
188 int i;
189
190 /* force the user's input to be valid */
191 if (width < 1)
192 width = 1;
193 else if (width > 8)
194 width = 8;
195
196 /* convert address to string */
197 sprintf(s, "%016llx", (unsigned long long) address);
198
199 /* write it out, with colons separating consecutive 16-bit chunks of the
200 * address
201 */
202 for (i = 16 - (2 * width); ; )
203 { fprintf(outfile, "%c", s[i]);
204
205 if (++i >= 16)
206 break;
207
208 if ((i % 4) == 0)
209 fprintf(outfile, ":");
210 }
211 }
212
213/*--------------------------------------------------------------------------
214 * hexprint
215 *
216 * Display a byte as a two digit hex value.
217 *
218 * parameters:
219 * outfile: the place where the output should be written
220 * byte: the byte to display
221 *--------------------------------------------------------------------------*/
222static void hexprint (FILE *outfile, unsigned char byte)
223 { static const char tbl[] =
224 { '0', '1', '2', '3', '4', '5', '6', '7',
225 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
226 };
227
228 fprintf(outfile, "%c%c", tbl[byte >> 4], tbl[byte & 0x0f]);
229 }
230
231/*--------------------------------------------------------------------------
232 * charprint
233 *
234 * Display a byte as its character representation.
235 *
236 * parameters:
237 * outfile: the place where the output should be written
238 * byte: the byte to display
239 * nonprintable: a substitute character to display if the byte
240 * represents a nonprintable character
241 * is_printable_fn: a function that returns a boolean value indicating
242 * whether a given character is printable
243 *--------------------------------------------------------------------------*/
244static void charprint (FILE *outfile, unsigned char byte,
245 unsigned char nonprintable,
246 is_printable_fn_t is_printable_fn)
247 { fprintf(outfile, "%c", is_printable_fn(byte) ? byte : nonprintable); }