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

