ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Hexdump.C
Go to the documentation of this file.
1 /* Functions that produce output reminiscent of the Unix "hexdump" command. */
2 // tps (01/14/2010) : Switching from rose.h to sage3.
3 #include "sage3basic.h"
4 #include <stdarg.h>
5 
6 /* Helper function that safely sprintfs to a buffer, allocation the buffer as needed. Note that the buffer is never freed (so
7  * we don't have to allocate/free each time in, but that the conversion to std::string copies it. */
8 static std::string
9 str_printf(const char *fmt, ...)
10 {
11  va_list ap;
12  static size_t bufsz = 128;
13  static char *buf = new char[bufsz];
14  va_start(ap, fmt);
15 
16  size_t need;
17  while ((need=vsnprintf(buf, bufsz, fmt, ap))>bufsz) {
18  delete[] buf;
19  bufsz = need+1;
20  buf = new char[bufsz];
21  }
22  va_end(ap);
23  return buf;
24 }
25 
26 /*************************************************************************************************************************
27  * C++ Stream Output
28  *************************************************************************************************************************/
29 
32 void
33 SgAsmExecutableFileFormat::hexdump(std::ostream &f, rose_addr_t base_addr, const unsigned char *data,
34  size_t n, const HexdumpFormat &fmt)
35 {
36  /* Provide default formats. This is done here so that the header file doesn't depend on <inttypes.h> */
37  const char *addr_fmt = fmt.addr_fmt ? fmt.addr_fmt : "0x%08"PRIx64": ";
38  const char *numeric_fmt = fmt.numeric_fmt ? fmt.numeric_fmt : "%02x";
39  const char *numeric_sep = fmt.numeric_sep ? fmt.numeric_sep : " ";
40  const char *prefix = fmt.prefix ? fmt.prefix : "";
41 
42  char s[1024];
43  sprintf(s, numeric_fmt, 0u);
44  int numeric_width = strlen(s);
45 
46  if (fmt.multiline)
47  f <<prefix;
48 
49  for (size_t i=0; i<n; i+=fmt.width) {
50  /* Prefix and/or address */
51  if (i>0)
52  f <<"\n" <<prefix;
53  f <<str_printf(addr_fmt, base_addr+i);
54 
55  /* Numeric byte values */
56  if (fmt.show_numeric) {
57  for (size_t j=0; j<fmt.width; j++) {
58  if (i+j<n) {
59  if (j>0)
60  f <<numeric_sep;
61  if (j>0 && 0 == j % fmt.colsize)
62  f <<" ";
63  f <<str_printf(numeric_fmt, data[i+j]);
64  } else if (fmt.pad_numeric) {
65  if (j>0)
66  f <<numeric_sep;
67  if (j>0 && 0 == j % fmt.colsize)
68  f <<" ";
69  f <<str_printf("%*s", numeric_width, "");
70  }
71  }
72  }
73 
74  if (fmt.show_numeric && fmt.show_chars)
75  f <<" |";
76 
77  /* Character byte values */
78  if (fmt.show_chars) {
79  for (size_t j=0; j<fmt.width; j++) {
80  if (i+j>=n) {
81  if (fmt.pad_chars)
82  f <<" ";
83  } else if (isprint(data[i+j])) {
84  f <<data[i+j];
85  } else {
86  f <<".";
87  }
88  }
89  f <<"|";
90  }
91  }
92 
93  if (fmt.multiline)
94  f <<"\n";
95 }
96 
97 /* Stream output for old-style arguments. */
98 void
99 SgAsmExecutableFileFormat::hexdump(std::ostream &f, rose_addr_t base_addr, const std::string &prefix,
100  const SgUnsignedCharList &data, bool multiline)
101 {
102  if (!data.empty()) {
103  HexdumpFormat fmt;
104  fmt.multiline = multiline;
105  fmt.prefix = prefix.c_str();
106  hexdump(f, base_addr, &(data[0]), data.size(), fmt);
107  }
108 }
109 
110 /* Stream output for SgFileContentList */
111 void
112 SgAsmExecutableFileFormat::hexdump(std::ostream &f, rose_addr_t base_addr, const std::string &prefix,
113  const SgFileContentList &data, bool multiline)
114 {
115 
116  if (!data.empty()) {
117  HexdumpFormat fmt;
118  fmt.multiline = multiline;
119  fmt.prefix = prefix.c_str();
120  hexdump(f, base_addr, &(data[0]), data.size(), fmt);
121  }
122 }
123 
124 /*************************************************************************************************************************
125  * C++ String Output
126  *************************************************************************************************************************/
127 
128 /* String output with new-style arguments. */
129 std::string
130 SgAsmExecutableFileFormat::hexdump(rose_addr_t base_addr, const unsigned char *data, size_t n, const HexdumpFormat &fmt)
131 {
132  std::ostringstream s;
133  hexdump(s, base_addr, data, n, fmt);
134  return s.str();
135 }
136 
137 /* String output with old-style arguments. */
138 std::string
140  bool multiline)
141 {
142  if (data.empty()) return "";
143  HexdumpFormat fmt;
144  fmt.multiline = multiline;
145  fmt.prefix = prefix.c_str();
146  return hexdump(base_addr, &(data[0]), data.size(), fmt);
147 }
148 
149 /* String output for SgFileContentList */
150 std::string
152  bool multiline)
153 {
154  if (data.empty()) return "";
155  HexdumpFormat fmt;
156  fmt.multiline = multiline;
157  fmt.prefix = prefix.c_str();
158  return hexdump(base_addr, &(data[0]), data.size(), fmt);
159 }
160 
161 /*************************************************************************************************************************
162  * C File Output
163  *************************************************************************************************************************/
164 
165 /* File output with new-style arguments */
166 void
167 SgAsmExecutableFileFormat::hexdump(FILE *f, rose_addr_t base_addr, const unsigned char *data, size_t n, const HexdumpFormat &fmt)
168 {
169  if (f)
170  fputs(hexdump(base_addr, data, n, fmt).c_str(), f);
171 }
172 
173 /* File output with old-style arguments */
174 void
176  bool multiline)
177 {
178  if (f)
179  fputs(hexdump(base_addr, prefix, data, multiline).c_str(), f);
180 }
181 
182 /* File output for SgFileContentList */
183 void
185  bool multiline)
186 {
187  if (f)
188  fputs(hexdump(base_addr, prefix, data, multiline).c_str(), f);
189 }