1 /*****************************************************************************\
3 \*****************************************************************************/
10 * David S. Peterson. All rights reserved.
12 * Author: David S. Peterson <dave_peterson@pobox.com>
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
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
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.)
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.
46 static void addrprint(FILE * outfile, uint64_t address, int width);
47 static void hexprint(FILE * outfile, unsigned char byte);
48 static void charprint(FILE * outfile, unsigned char byte,
49 unsigned char nonprintable);
51 /*--------------------------------------------------------------------------
54 * Write a hex dump of 'mem' to 'outfile'.
57 * mem: a pointer to the memory to display
58 * bytes: the number of bytes of data to display
59 * addrprint_start: The address to associate with the first byte of
60 * data. For instance, a value of 0 indicates that the
61 * first byte displayed should be labeled as byte 0.
62 * outfile: The place where the hex dump should be written.
63 * For instance, stdout or stderr may be passed here.
64 * format: A structure specifying how the hex dump should be
66 *--------------------------------------------------------------------------*/
67 void hexdump(const void *mem, int bytes, uint64_t addrprint_start,
68 FILE * outfile, const hexdump_format_t * format)
70 int bytes_left, index, i;
71 const unsigned char *p;
73 /* Quietly return if the caller asks us to do something unreasonable. */
74 if ((format->bytes_per_line <= 0) || (bytes < 0))
77 p = (const unsigned char *)mem;
80 /* Each iteration handles one full line of output. When loop
81 * terminates, the number of remaining bytes to display (if any)
82 * will not be enough to fill an entire line.
84 for (bytes_left = bytes;
85 bytes_left >= format->bytes_per_line;
86 bytes_left -= format->bytes_per_line) {
87 /* print start address for current line */
88 fprintf(outfile, format->indent);
89 addrprint(outfile, addrprint_start + index,
90 format->addrprint_width);
91 fprintf(outfile, format->sep1);
93 /* display the bytes in hex */
95 hexprint(outfile, p[index++]);
97 if (++i >= format->bytes_per_line)
100 fprintf(outfile, format->sep2);
103 index -= format->bytes_per_line;
104 fprintf(outfile, format->sep3);
106 /* display the bytes as characters */
107 for (i = 0; i < format->bytes_per_line; i++)
108 charprint(outfile, p[index++], format->nonprintable);
110 fprintf(outfile, "\n");
116 /* print start address for last line */
117 fprintf(outfile, format->indent);
118 addrprint(outfile, addrprint_start + index, format->addrprint_width);
119 fprintf(outfile, format->sep1);
121 /* display bytes for last line in hex */
122 for (i = 0; i < bytes_left; i++) {
123 hexprint(outfile, p[index++]);
124 fprintf(outfile, format->sep2);
129 /* pad the rest of the hex byte area with spaces */
131 fprintf(outfile, " ");
133 if (++i >= format->bytes_per_line)
136 fprintf(outfile, format->sep2);
139 fprintf(outfile, format->sep3);
141 /* display bytes for last line as characters */
142 for (i = 0; i < bytes_left; i++)
143 charprint(outfile, p[index++], format->nonprintable);
145 /* pad the rest of the character area with spaces */
146 for (; i < format->bytes_per_line; i++)
147 fprintf(outfile, " ");
149 fprintf(outfile, "\n");
152 /*--------------------------------------------------------------------------
155 * Display an address as a hexadecimal number.
158 * outfile: the place where the output should be written
159 * address: the address to display
160 * width: The number of bytes wide the address should be displayed as.
161 * Must be a value from 1 to 8.
162 *--------------------------------------------------------------------------*/
163 static void addrprint(FILE * outfile, uint64_t address, int width)
168 /* force the user's input to be valid */
174 /* convert address to string */
175 sprintf(s, "%016llx", (unsigned long long)address);
177 /* write it out, with colons separating consecutive 16-bit
178 * chunks of the address
180 for (i = 16 - (2 * width);;) {
181 fprintf(outfile, "%c", s[i]);
187 fprintf(outfile, ":");
191 /*--------------------------------------------------------------------------
194 * Display a byte as a two digit hex value.
197 * outfile: the place where the output should be written
198 * byte: the byte to display
199 *--------------------------------------------------------------------------*/
200 static void hexprint(FILE * outfile, unsigned char byte)
202 static const char tbl[] = {
203 '0', '1', '2', '3', '4', '5', '6', '7',
204 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
207 fprintf(outfile, "%c%c", tbl[byte >> 4], tbl[byte & 0x0f]);
210 /*--------------------------------------------------------------------------
213 * Display a byte as its character representation.
216 * outfile: the place where the output should be written
217 * byte: the byte to display
218 * nonprintable: a substitute character to display if the byte
219 * represents a nonprintable character
220 *--------------------------------------------------------------------------*/
221 static void charprint(FILE * outfile, unsigned char byte,
222 unsigned char nonprintable)
224 fprintf(outfile, "%c", ((byte >= 0x20) && (byte <= 0x7e)) ? byte : nonprintable);