xref: /openbmc/qemu/util/hexdump.c (revision db2feb2df8d19592c9859efb3f682404e0052957)
16ff66f50SPeter Crosthwaite /*
26ff66f50SPeter Crosthwaite * Helper to hexdump a buffer
36ff66f50SPeter Crosthwaite  *
46ff66f50SPeter Crosthwaite  * Copyright (c) 2013 Red Hat, Inc.
56ff66f50SPeter Crosthwaite  * Copyright (c) 2013 Gerd Hoffmann <kraxel@redhat.com>
66ff66f50SPeter Crosthwaite  * Copyright (c) 2013 Peter Crosthwaite <peter.crosthwaite@xilinx.com>
76ff66f50SPeter Crosthwaite  * Copyright (c) 2013 Xilinx, Inc
86ff66f50SPeter Crosthwaite  *
96ff66f50SPeter Crosthwaite  * This work is licensed under the terms of the GNU GPL, version 2.  See
106ff66f50SPeter Crosthwaite  * the COPYING file in the top-level directory.
116ff66f50SPeter Crosthwaite  *
126ff66f50SPeter Crosthwaite  * Contributions after 2012-01-13 are licensed under the terms of the
136ff66f50SPeter Crosthwaite  * GNU GPL, version 2 or (at your option) any later version.
146ff66f50SPeter Crosthwaite  */
156ff66f50SPeter Crosthwaite 
16aafd7584SPeter Maydell #include "qemu/osdep.h"
17415b7327SMarc-André Lureau #include "qemu/cutils.h"
186ff66f50SPeter Crosthwaite 
hexdump_nibble(unsigned x)19*10e4927bSRichard Henderson static inline char hexdump_nibble(unsigned x)
20*10e4927bSRichard Henderson {
21*10e4927bSRichard Henderson     return (x < 10 ? '0' : 'a' - 10) + x;
22*10e4927bSRichard Henderson }
23*10e4927bSRichard Henderson 
qemu_hexdump_line(GString * str,const void * vbuf,size_t len,size_t unit_len,size_t block_len)24c49d1c37SRichard Henderson GString *qemu_hexdump_line(GString *str, const void *vbuf, size_t len,
25c49d1c37SRichard Henderson                            size_t unit_len, size_t block_len)
266ff66f50SPeter Crosthwaite {
2753ee5f55SRichard Henderson     const uint8_t *buf = vbuf;
28c49d1c37SRichard Henderson     size_t u, b;
296ff66f50SPeter Crosthwaite 
3053ee5f55SRichard Henderson     if (str == NULL) {
3153ee5f55SRichard Henderson         /* Estimate the length of the output to avoid reallocs. */
32c49d1c37SRichard Henderson         size_t est = len * 2;
33c49d1c37SRichard Henderson         if (unit_len) {
34c49d1c37SRichard Henderson             est += len / unit_len;
35c49d1c37SRichard Henderson         }
36c49d1c37SRichard Henderson         if (block_len) {
37c49d1c37SRichard Henderson             est += len / block_len;
38c49d1c37SRichard Henderson         }
39c49d1c37SRichard Henderson         str = g_string_sized_new(est + 1);
406ff66f50SPeter Crosthwaite     }
41bbb16908SLaurent Vivier 
42c49d1c37SRichard Henderson     for (u = 0, b = 0; len; u++, b++, len--, buf++) {
43*10e4927bSRichard Henderson         uint8_t c;
44*10e4927bSRichard Henderson 
45c49d1c37SRichard Henderson         if (unit_len && u == unit_len) {
4653ee5f55SRichard Henderson             g_string_append_c(str, ' ');
47c49d1c37SRichard Henderson             u = 0;
486ff66f50SPeter Crosthwaite         }
49c49d1c37SRichard Henderson         if (block_len && b == block_len) {
50c49d1c37SRichard Henderson             g_string_append_c(str, ' ');
51c49d1c37SRichard Henderson             b = 0;
52c49d1c37SRichard Henderson         }
53*10e4927bSRichard Henderson 
54*10e4927bSRichard Henderson         c = *buf;
55*10e4927bSRichard Henderson         g_string_append_c(str, hexdump_nibble(c / 16));
56*10e4927bSRichard Henderson         g_string_append_c(str, hexdump_nibble(c % 16));
576ff66f50SPeter Crosthwaite     }
5853ee5f55SRichard Henderson 
5953ee5f55SRichard Henderson     return str;
606ff66f50SPeter Crosthwaite }
6113dfa933SRichard Henderson 
asciidump_line(char * line,const void * bufptr,size_t len)6213dfa933SRichard Henderson static void asciidump_line(char *line, const void *bufptr, size_t len)
6313dfa933SRichard Henderson {
6413dfa933SRichard Henderson     const char *buf = bufptr;
6513dfa933SRichard Henderson 
6613dfa933SRichard Henderson     for (size_t i = 0; i < len; i++) {
6713dfa933SRichard Henderson         char c = buf[i];
6813dfa933SRichard Henderson 
69a1555559SIsaac Lozano         if (c < ' ' || c > '~') {
70a1555559SIsaac Lozano             c = '.';
71a1555559SIsaac Lozano         }
72bbb16908SLaurent Vivier         *line++ = c;
73a1555559SIsaac Lozano     }
74bbb16908SLaurent Vivier     *line = '\0';
75bbb16908SLaurent Vivier }
76bbb16908SLaurent Vivier 
7753ee5f55SRichard Henderson #define QEMU_HEXDUMP_LINE_BYTES 16
7813dfa933SRichard Henderson #define QEMU_HEXDUMP_LINE_WIDTH \
7913dfa933SRichard Henderson     (QEMU_HEXDUMP_LINE_BYTES * 2 + QEMU_HEXDUMP_LINE_BYTES / 4)
8013dfa933SRichard Henderson 
qemu_hexdump(FILE * fp,const char * prefix,const void * bufptr,size_t size)81bbb16908SLaurent Vivier void qemu_hexdump(FILE *fp, const char *prefix,
82bbb16908SLaurent Vivier                   const void *bufptr, size_t size)
83bbb16908SLaurent Vivier {
8453ee5f55SRichard Henderson     g_autoptr(GString) str = g_string_sized_new(QEMU_HEXDUMP_LINE_WIDTH + 1);
8513dfa933SRichard Henderson     char ascii[QEMU_HEXDUMP_LINE_BYTES + 1];
8613dfa933SRichard Henderson     size_t b, len;
87bbb16908SLaurent Vivier 
8813dfa933SRichard Henderson     for (b = 0; b < size; b += len) {
8913dfa933SRichard Henderson         len = MIN(size - b, QEMU_HEXDUMP_LINE_BYTES);
9013dfa933SRichard Henderson 
9153ee5f55SRichard Henderson         g_string_truncate(str, 0);
92c49d1c37SRichard Henderson         qemu_hexdump_line(str, bufptr + b, len, 1, 4);
9313dfa933SRichard Henderson         asciidump_line(ascii, bufptr + b, len);
9413dfa933SRichard Henderson 
9513dfa933SRichard Henderson         fprintf(fp, "%s: %04zx: %-*s %s\n",
9653ee5f55SRichard Henderson                 prefix, b, QEMU_HEXDUMP_LINE_WIDTH, str->str, ascii);
97bbb16908SLaurent Vivier     }
98bbb16908SLaurent Vivier 
996ff66f50SPeter Crosthwaite }
100