ATLAS Offline Software
Loading...
Searching...
No Matches
hexdump.cxx
Go to the documentation of this file.
1/*
2 * Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration.
3 */
10
11
12#include "CxxUtils/hexdump.h"
13#include "CxxUtils/procmaps.h"
14#include <format>
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 s << std::format("{:016x} ", reinterpret_cast<uintptr_t>(ptr + ipos) - offset);
49 }
50 if ((ipos % 4) == 0) {
51 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 s << std::format("{:08x}", static_cast<unsigned int>(std::bit_cast<uint32_t>(bbuf)));
59 }
60 if ((ipos % width) == 0) {
61 s << " " << cbuf << "\n";
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 s << std::format("{:0{}x}", static_cast<unsigned int>(std::bit_cast<uint32_t>(bbuf)), 2*ntrail);
72 }
73 while ((ipos % width) != 0) {
74 if ((ipos % 4) == 0) {
75 s << " ";
76 }
77 s << " ";
78 cbuf[ipos % width] = ' ';
79 ++ipos;
80 }
81 s << " " << cbuf << "\n";
82 }
83}
84
85
98void safeHexdump (std::ostream& s, const void* addr, size_t n, size_t offset /*= 0*/)
99{
100 const char* ptr = reinterpret_cast<const char*> (addr);
101
102 // Adjust to start at width-byte boundary.
103 size_t nadj = reinterpret_cast<uintptr_t>(ptr) % width;
104 if (nadj > 0) {
105 ptr -= nadj;
106 n += nadj;
107 }
108
109 long pagesize_ret = sysconf (_SC_PAGESIZE);
110 if (pagesize_ret < 0 || pagesize_ret >= 1024*1024*1024) {
111 std::abort();
112 }
113 size_t pagesize = pagesize_ret;
114
115
116 procmaps m;
117
118 // Print page by page.
119 while (n > 0) {
120 uintptr_t iptr = reinterpret_cast<uintptr_t>(ptr);
121 size_t thispage = ((iptr + pagesize) & ~(pagesize-1)) - iptr;
122 if (thispage > n) {
123 thispage = n;
124 }
125 const procmaps::Entry* ent = m.getEntry (ptr);
126 if (ent && ent->readable) {
127 hexdump (s, ptr, thispage, offset);
128 }
129 else {
130 s << std::format("{:016x} --- is not readable\n",
131 reinterpret_cast<uintptr_t>(ptr) - offset);
132 if (ent) {
133 thispage = std::max (ent->endAddress - iptr, thispage);
134 }
135 }
136 ptr += thispage;
137 n -= thispage;
138 }
139}
140
141
142} // 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:98
unsigned long endAddress
Definition procmaps.h:23