ATLAS Offline Software
Loading...
Searching...
No Matches
hexdump.cxx
Go to the documentation of this file.
1/*
2 * Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration.
3 */
10
11
12#include "CxxUtils/hexdump.h"
13#include "CxxUtils/procmaps.h"
14#include <print>
15#include <cstdint>
16#include <array>
17#include <bit>
18#include <unistd.h>
19
20
21namespace {
22// Number of bytes to dump on one line.
23constexpr unsigned int width = 16;
24}
25
26
27namespace CxxUtils {
28
29
38void hexdump (std::ostream& s, const void* addr, size_t n, size_t offset /*= 0*/)
39{
40 const char* ptr = reinterpret_cast<const char*> (addr);
41 size_t ipos = 0;
42
43 char cbuf[width + 1]{};
44 std::array<unsigned char, 4> bbuf{};
45
46 while (n-- > 0) {
47 if ((ipos % width) == 0) {
48 std::print (s, "{:016x} ", reinterpret_cast<uintptr_t>(ptr + ipos) - offset);
49 }
50 if ((ipos % 4) == 0) {
51 std::print (s, " " );
52 }
53 bbuf[ipos % 4] = static_cast<unsigned char>(ptr[ipos]);
54 cbuf[ipos % width] = std::isgraph(static_cast<unsigned char>(ptr[ipos])) ? ptr[ipos] : '.';
55
56 ++ipos;
57 if ((ipos % 4) == 0) {
58 std::print (s, "{:08x}", static_cast<unsigned int>(std::bit_cast<uint32_t>(bbuf)));
59 }
60 if ((ipos % width) == 0) {
61 std::println (s, " {}", cbuf);
62 }
63 }
64
65 if ((ipos % width) > 0) {
66 unsigned ntrail = (ipos % 4);
67 if (ntrail > 0) {
68 for (unsigned i = ntrail; i < 4; i++) {
69 bbuf[i] = 0;
70 }
71 std::print (s, "{:0{}x}",
72 static_cast<unsigned int>(std::bit_cast<uint32_t>(bbuf)), 2*ntrail);
73 }
74 while ((ipos % width) != 0) {
75 if ((ipos % 4) == 0) {
76 std::print (s, " ");
77 }
78 std::print (s, " ");
79 cbuf[ipos % width] = ' ';
80 ++ipos;
81 }
82 std::println (s, " {}", cbuf);
83 }
84}
85
86
99void safeHexdump (std::ostream& s, const void* addr, size_t n, size_t offset /*= 0*/)
100{
101 const char* ptr = reinterpret_cast<const char*> (addr);
102
103 // Adjust to start at width-byte boundary.
104 size_t nadj = reinterpret_cast<uintptr_t>(ptr) % width;
105 if (nadj > 0) {
106 ptr -= nadj;
107 n += nadj;
108 }
109
110 long pagesize_ret = sysconf (_SC_PAGESIZE);
111 if (pagesize_ret < 0 || pagesize_ret >= 1024*1024*1024) {
112 std::abort();
113 }
114 size_t pagesize = pagesize_ret;
115
116
117 procmaps m;
118
119 // Print page by page.
120 while (n > 0) {
121 uintptr_t iptr = reinterpret_cast<uintptr_t>(ptr);
122 size_t thispage = ((iptr + pagesize) & ~(pagesize-1)) - iptr;
123 if (thispage > n) {
124 thispage = n;
125 }
126 const procmaps::Entry* ent = m.getEntry (ptr);
127 if (ent && ent->readable) {
128 hexdump (s, ptr, thispage, offset);
129 }
130 else {
131 std::println ("{:016x} --- is not readable",
132 reinterpret_cast<uintptr_t>(ptr) - offset);
133 if (ent) {
134 thispage = std::max (ent->endAddress - iptr, thispage);
135 }
136 }
137 ptr += thispage;
138 n -= thispage;
139 }
140}
141
142
143} // namespace CxxUtils
const double width
On stopMonitoring/finalize the handler is uninstalled.
Definition procmaps.h:18
Helpers to make a nice dump of a region of memory.
void hexdump(std::ostream &s, const void *addr, size_t n, size_t offset=0)
Make a hex dump of memory.
Definition hexdump.cxx:38
void safeHexdump(std::ostream &s, const void *addr, size_t n, size_t offset=0)
Make a hex dump of memory, protected against bad reads.
Definition hexdump.cxx:99
unsigned long endAddress
Definition procmaps.h:23