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 "boost/io/ios_state.hpp"
15#include <iomanip>
16#include <cstdint>
17#include <array>
18#include <bit>
19#include <unistd.h>
20
21
22namespace {
23// Number of bytes to dump on one line.
24constexpr unsigned int width = 16;
25}
26
27
28namespace CxxUtils {
29
30
39void hexdump (std::ostream& s, const void* addr, size_t n, size_t offset /*= 0*/)
40{
41 const char* ptr = reinterpret_cast<const char*> (addr);
42 size_t ipos = 0;
43
44 boost::io::ios_all_saver saver (s);
45 std::hex (s);
46 s.fill ('0');
47
48 char cbuf[width + 1]{};
49 std::array<unsigned char, 4> bbuf{};
50
51 while (n-- > 0) {
52 if ((ipos % width) == 0) {
53 s << std::setw(16) << reinterpret_cast<uintptr_t>(ptr + ipos) - offset << " ";
54 }
55 if ((ipos % 4) == 0) {
56 s << " ";
57 }
58 bbuf[ipos % 4] = static_cast<unsigned char>(ptr[ipos]);
59 cbuf[ipos % width] = std::isgraph(static_cast<unsigned char>(ptr[ipos])) ? ptr[ipos] : '.';
60
61 ++ipos;
62 if ((ipos % 4) == 0) {
63 s << std::setw(8) << static_cast<unsigned int>(std::bit_cast<uint32_t>(bbuf));
64 }
65 if ((ipos % width) == 0) {
66 s << " " << cbuf << "\n";
67 }
68 }
69
70 if ((ipos % width) > 0) {
71 unsigned ntrail = (ipos % 4);
72 if (ntrail > 0) {
73 for (unsigned i = ntrail; i < 4; i++) {
74 bbuf[i] = 0;
75 }
76 s << std::setw(2*ntrail) << static_cast<unsigned int>(std::bit_cast<uint32_t>(bbuf));
77 }
78 while ((ipos % width) != 0) {
79 if ((ipos % 4) == 0) {
80 s << " ";
81 }
82 s << " ";
83 cbuf[ipos % width] = ' ';
84 ++ipos;
85 }
86 s << " " << cbuf << "\n";
87 }
88}
89
90
103void safeHexdump (std::ostream& s, const void* addr, size_t n, size_t offset /*= 0*/)
104{
105 const char* ptr = reinterpret_cast<const char*> (addr);
106
107 // Adjust to start at width-byte boundary.
108 size_t nadj = reinterpret_cast<uintptr_t>(ptr) % width;
109 if (nadj > 0) {
110 ptr -= nadj;
111 n += nadj;
112 }
113
114 long pagesize_ret = sysconf (_SC_PAGESIZE);
115 if (pagesize_ret < 0 || pagesize_ret >= 1024*1024*1024) {
116 std::abort();
117 }
118 size_t pagesize = pagesize_ret;
119
120
121 procmaps m;
122
123 // Print page by page.
124 while (n > 0) {
125 uintptr_t iptr = reinterpret_cast<uintptr_t>(ptr);
126 size_t thispage = ((iptr + pagesize) & ~(pagesize-1)) - iptr;
127 if (thispage > n) {
128 thispage = n;
129 }
130 const procmaps::Entry* ent = m.getEntry (ptr);
131 if (ent && ent->readable) {
132 hexdump (s, ptr, thispage, offset);
133 }
134 else {
135 boost::io::ios_all_saver saver (s);
136 std::hex (s);
137 s.fill ('0');
138 s << std::setw(16) << reinterpret_cast<uintptr_t>(ptr) - offset
139 << " --- is not readable\n";
140 if (ent) {
141 thispage = std::max (ent->endAddress - iptr, thispage);
142 }
143 }
144 ptr += thispage;
145 n -= thispage;
146 }
147}
148
149
150} // 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:39
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:103
unsigned long endAddress
Definition procmaps.h:23