blob: 320b4d9f4557f2e67832979cd855e3e79977943f [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
Stefan Reinauer90b96b62010-01-13 21:00:23 +000046static 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,
Patrick Georgi024ec852011-01-18 12:14:08 +000049 unsigned char nonprintable);
Stefan Reinauer6540ae52007-07-12 16:35:42 +000050
51/*--------------------------------------------------------------------------
52 * hexdump
53 *
54 * Write a hex dump of 'mem' to 'outfile'.
55 *
56 * parameters:
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
65 * formatted.
66 *--------------------------------------------------------------------------*/
Stefan Reinauer90b96b62010-01-13 21:00:23 +000067void hexdump(const void *mem, int bytes, uint64_t addrprint_start,
68 FILE * outfile, const hexdump_format_t * format)
69{
70 int bytes_left, index, i;
71 const unsigned char *p;
Stefan Reinauer6540ae52007-07-12 16:35:42 +000072
Stefan Reinauer90b96b62010-01-13 21:00:23 +000073 /* Quietly return if the caller asks us to do something unreasonable. */
74 if ((format->bytes_per_line <= 0) || (bytes < 0))
75 return;
Stefan Reinauer6540ae52007-07-12 16:35:42 +000076
Stefan Reinauer90b96b62010-01-13 21:00:23 +000077 p = (const unsigned char *)mem;
78 index = 0;
Stefan Reinauer6540ae52007-07-12 16:35:42 +000079
Stefan Reinauer90b96b62010-01-13 21:00:23 +000080 /* 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.
83 */
Stefan Reinauer14e22772010-04-27 06:56:47 +000084 for (bytes_left = bytes;
Stefan Reinauer90b96b62010-01-13 21:00:23 +000085 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);
Stefan Reinauer6540ae52007-07-12 16:35:42 +000092
Stefan Reinauer90b96b62010-01-13 21:00:23 +000093 /* display the bytes in hex */
94 for (i = 0;;) {
95 hexprint(outfile, p[index++]);
Stefan Reinauer6540ae52007-07-12 16:35:42 +000096
Stefan Reinauer90b96b62010-01-13 21:00:23 +000097 if (++i >= format->bytes_per_line)
98 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +000099
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000100 fprintf(outfile, format->sep2);
101 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000102
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000103 index -= format->bytes_per_line;
104 fprintf(outfile, format->sep3);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000105
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000106 /* display the bytes as characters */
107 for (i = 0; i < format->bytes_per_line; i++)
Patrick Georgi024ec852011-01-18 12:14:08 +0000108 charprint(outfile, p[index++], format->nonprintable);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000109
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000110 fprintf(outfile, "\n");
111 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000112
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000113 if (bytes_left == 0)
114 return;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000115
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000116 /* 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);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000120
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000121 /* 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);
125 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000126
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000127 index -= bytes_left;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000128
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000129 /* pad the rest of the hex byte area with spaces */
130 for (;;) {
131 fprintf(outfile, " ");
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000132
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000133 if (++i >= format->bytes_per_line)
134 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000135
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000136 fprintf(outfile, format->sep2);
137 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000138
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000139 fprintf(outfile, format->sep3);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000140
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000141 /* display bytes for last line as characters */
142 for (i = 0; i < bytes_left; i++)
Patrick Georgi024ec852011-01-18 12:14:08 +0000143 charprint(outfile, p[index++], format->nonprintable);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000144
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000145 /* pad the rest of the character area with spaces */
146 for (; i < format->bytes_per_line; i++)
147 fprintf(outfile, " ");
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000148
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000149 fprintf(outfile, "\n");
150}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000151
152/*--------------------------------------------------------------------------
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000153 * addrprint
154 *
155 * Display an address as a hexadecimal number.
156 *
157 * parameters:
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 *--------------------------------------------------------------------------*/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000163static void addrprint(FILE * outfile, uint64_t address, int width)
164{
165 char s[17];
166 int i;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000167
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000168 /* force the user's input to be valid */
169 if (width < 1)
170 width = 1;
171 else if (width > 8)
172 width = 8;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000173
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000174 /* convert address to string */
175 sprintf(s, "%016llx", (unsigned long long)address);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000176
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000177 /* write it out, with colons separating consecutive 16-bit
178 * chunks of the address
179 */
180 for (i = 16 - (2 * width);;) {
181 fprintf(outfile, "%c", s[i]);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000182
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000183 if (++i >= 16)
184 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000185
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000186 if ((i % 4) == 0)
187 fprintf(outfile, ":");
188 }
189}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000190
191/*--------------------------------------------------------------------------
192 * hexprint
193 *
194 * Display a byte as a two digit hex value.
195 *
196 * parameters:
197 * outfile: the place where the output should be written
198 * byte: the byte to display
199 *--------------------------------------------------------------------------*/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000200static void hexprint(FILE * outfile, unsigned char byte)
201{
202 static const char tbl[] = {
203 '0', '1', '2', '3', '4', '5', '6', '7',
204 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
205 };
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000206
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000207 fprintf(outfile, "%c%c", tbl[byte >> 4], tbl[byte & 0x0f]);
208}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000209
210/*--------------------------------------------------------------------------
211 * charprint
212 *
213 * Display a byte as its character representation.
214 *
215 * parameters:
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
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000220 *--------------------------------------------------------------------------*/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000221static void charprint(FILE * outfile, unsigned char byte,
Patrick Georgi024ec852011-01-18 12:14:08 +0000222 unsigned char nonprintable)
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000223{
Patrick Georgi024ec852011-01-18 12:14:08 +0000224 fprintf(outfile, "%c", ((byte >= 0x20) && (byte <= 0x7e)) ? byte : nonprintable);
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000225}