1// Copyright 2016 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <pretty/hexdump.h>
6
7#include <ctype.h>
8#include <inttypes.h>
9#include <stdint.h>
10#include <stdio.h>
11
12#define ROUNDUP(a, b) (((a) + ((b)-1)) & ~((b)-1))
13#define MIN(a, b) (((a) < (b)) ? (a) : (b))
14
15void hexdump_ex(const void* ptr, size_t len, uint64_t disp_addr) {
16    uintptr_t address = (uintptr_t)ptr;
17    size_t count;
18
19    for (count = 0; count < len; count += 16) {
20        union {
21            uint32_t buf[4];
22            uint8_t cbuf[16];
23        } u;
24        size_t s = ROUNDUP(MIN(len - count, 16), 4);
25        size_t i;
26
27        printf(((disp_addr + len) > 0xFFFFFFFF)
28                   ? "0x%016" PRIx64 ": "
29                   : "0x%08" PRIx64 ": ",
30               disp_addr + count);
31
32        for (i = 0; i < s / 4; i++) {
33            u.buf[i] = ((const uint32_t*)address)[i];
34            printf("%08x ", u.buf[i]);
35        }
36        for (; i < 4; i++) {
37            printf("         ");
38        }
39        printf("|");
40
41        for (i = 0; i < 16; i++) {
42            char c = u.cbuf[i];
43            if (i < s && isprint(c)) {
44                printf("%c", c);
45            } else {
46                printf(".");
47            }
48        }
49        printf("|\n");
50        address += 16;
51    }
52}
53
54void hexdump8_ex(const void* ptr, size_t len, uint64_t disp_addr) {
55    uintptr_t address = (uintptr_t)ptr;
56    size_t count;
57    size_t i;
58
59    for (count = 0; count < len; count += 16) {
60        printf(((disp_addr + len) > 0xFFFFFFFF)
61                   ? "0x%016" PRIx64 ": "
62                   : "0x%08" PRIx64 ": ",
63               disp_addr + count);
64
65        for (i = 0; i < MIN(len - count, 16); i++) {
66            printf("%02hhx ", *(const uint8_t*)(address + i));
67        }
68
69        for (; i < 16; i++) {
70            printf("   ");
71        }
72
73        printf("|");
74
75        for (i = 0; i < MIN(len - count, 16); i++) {
76            char c = ((const char*)address)[i];
77            printf("%c", isprint(c) ? c : '.');
78        }
79
80        printf("\n");
81        address += 16;
82    }
83}
84