1 //===-- Stream.cpp ----------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Utility/Stream.h"
11 
12 #include "lldb/Utility/Endian.h"
13 #include "lldb/Utility/VASPrintf.h"
14 #include "llvm/ADT/SmallString.h" // for SmallString
15 #include "llvm/Support/LEB128.h"
16 
17 #include <string>
18 
19 #include <inttypes.h>
20 #include <stddef.h>
21 
22 using namespace lldb;
23 using namespace lldb_private;
24 
25 Stream::Stream(uint32_t flags, uint32_t addr_size, ByteOrder byte_order)
26     : m_flags(flags), m_addr_size(addr_size), m_byte_order(byte_order),
27       m_indent_level(0), m_forwarder(*this) {}
28 
29 Stream::Stream()
30     : m_flags(0), m_addr_size(4), m_byte_order(endian::InlHostByteOrder()),
31       m_indent_level(0), m_forwarder(*this) {}
32 
33 //------------------------------------------------------------------
34 // Destructor
35 //------------------------------------------------------------------
36 Stream::~Stream() {}
37 
38 ByteOrder Stream::SetByteOrder(ByteOrder byte_order) {
39   ByteOrder old_byte_order = m_byte_order;
40   m_byte_order = byte_order;
41   return old_byte_order;
42 }
43 
44 //------------------------------------------------------------------
45 // Put an offset "uval" out to the stream using the printf format in "format".
46 //------------------------------------------------------------------
47 void Stream::Offset(uint32_t uval, const char *format) { Printf(format, uval); }
48 
49 //------------------------------------------------------------------
50 // Put an SLEB128 "uval" out to the stream using the printf format in "format".
51 //------------------------------------------------------------------
52 size_t Stream::PutSLEB128(int64_t sval) {
53   if (m_flags.Test(eBinary))
54     return llvm::encodeSLEB128(sval, m_forwarder);
55   else
56     return Printf("0x%" PRIi64, sval);
57 }
58 
59 //------------------------------------------------------------------
60 // Put an ULEB128 "uval" out to the stream using the printf format in "format".
61 //------------------------------------------------------------------
62 size_t Stream::PutULEB128(uint64_t uval) {
63   if (m_flags.Test(eBinary))
64     return llvm::encodeULEB128(uval, m_forwarder);
65   else
66     return Printf("0x%" PRIx64, uval);
67 }
68 
69 //------------------------------------------------------------------
70 // Print a raw NULL terminated C string to the stream.
71 //------------------------------------------------------------------
72 size_t Stream::PutCString(llvm::StringRef str) {
73   size_t bytes_written = 0;
74   bytes_written = Write(str.data(), str.size());
75 
76   // when in binary mode, emit the NULL terminator
77   if (m_flags.Test(eBinary))
78     bytes_written += PutChar('\0');
79   return bytes_written;
80 }
81 
82 //------------------------------------------------------------------
83 // Print a double quoted NULL terminated C string to the stream using the
84 // printf format in "format".
85 //------------------------------------------------------------------
86 void Stream::QuotedCString(const char *cstr, const char *format) {
87   Printf(format, cstr);
88 }
89 
90 //------------------------------------------------------------------
91 // Put an address "addr" out to the stream with optional prefix and suffix
92 // strings.
93 //------------------------------------------------------------------
94 void Stream::Address(uint64_t addr, uint32_t addr_size, const char *prefix,
95                      const char *suffix) {
96   if (prefix == NULL)
97     prefix = "";
98   if (suffix == NULL)
99     suffix = "";
100   //    int addr_width = m_addr_size << 1;
101   //    Printf ("%s0x%0*" PRIx64 "%s", prefix, addr_width, addr, suffix);
102   Printf("%s0x%0*" PRIx64 "%s", prefix, addr_size * 2, (uint64_t)addr, suffix);
103 }
104 
105 //------------------------------------------------------------------
106 // Put an address range out to the stream with optional prefix and suffix
107 // strings.
108 //------------------------------------------------------------------
109 void Stream::AddressRange(uint64_t lo_addr, uint64_t hi_addr,
110                           uint32_t addr_size, const char *prefix,
111                           const char *suffix) {
112   if (prefix && prefix[0])
113     PutCString(prefix);
114   Address(lo_addr, addr_size, "[");
115   Address(hi_addr, addr_size, "-", ")");
116   if (suffix && suffix[0])
117     PutCString(suffix);
118 }
119 
120 size_t Stream::PutChar(char ch) { return Write(&ch, 1); }
121 
122 //------------------------------------------------------------------
123 // Print some formatted output to the stream.
124 //------------------------------------------------------------------
125 size_t Stream::Printf(const char *format, ...) {
126   va_list args;
127   va_start(args, format);
128   size_t result = PrintfVarArg(format, args);
129   va_end(args);
130   return result;
131 }
132 
133 //------------------------------------------------------------------
134 // Print some formatted output to the stream.
135 //------------------------------------------------------------------
136 size_t Stream::PrintfVarArg(const char *format, va_list args) {
137   llvm::SmallString<1024> buf;
138   VASprintf(buf, format, args);
139 
140   // Include the NULL termination byte for binary output
141   size_t length = buf.size();
142   if (m_flags.Test(eBinary))
143     ++length;
144   return Write(buf.c_str(), length);
145 }
146 
147 //------------------------------------------------------------------
148 // Print and End of Line character to the stream
149 //------------------------------------------------------------------
150 size_t Stream::EOL() { return PutChar('\n'); }
151 
152 //------------------------------------------------------------------
153 // Indent the current line using the current indentation level and print an
154 // optional string following the indentation spaces.
155 //------------------------------------------------------------------
156 size_t Stream::Indent(const char *s) {
157   return Printf("%*.*s%s", m_indent_level, m_indent_level, "", s ? s : "");
158 }
159 
160 size_t Stream::Indent(llvm::StringRef str) {
161   return Printf("%*.*s%s", m_indent_level, m_indent_level, "",
162                 str.str().c_str());
163 }
164 
165 //------------------------------------------------------------------
166 // Stream a character "ch" out to this stream.
167 //------------------------------------------------------------------
168 Stream &Stream::operator<<(char ch) {
169   PutChar(ch);
170   return *this;
171 }
172 
173 //------------------------------------------------------------------
174 // Stream the NULL terminated C string out to this stream.
175 //------------------------------------------------------------------
176 Stream &Stream::operator<<(const char *s) {
177   Printf("%s", s);
178   return *this;
179 }
180 
181 Stream &Stream::operator<<(llvm::StringRef str) {
182   Write(str.data(), str.size());
183   return *this;
184 }
185 
186 //------------------------------------------------------------------
187 // Stream the pointer value out to this stream.
188 //------------------------------------------------------------------
189 Stream &Stream::operator<<(const void *p) {
190   Printf("0x%.*tx", (int)sizeof(const void *) * 2, (ptrdiff_t)p);
191   return *this;
192 }
193 
194 //------------------------------------------------------------------
195 // Stream a uint8_t "uval" out to this stream.
196 //------------------------------------------------------------------
197 Stream &Stream::operator<<(uint8_t uval) {
198   PutHex8(uval);
199   return *this;
200 }
201 
202 //------------------------------------------------------------------
203 // Stream a uint16_t "uval" out to this stream.
204 //------------------------------------------------------------------
205 Stream &Stream::operator<<(uint16_t uval) {
206   PutHex16(uval, m_byte_order);
207   return *this;
208 }
209 
210 //------------------------------------------------------------------
211 // Stream a uint32_t "uval" out to this stream.
212 //------------------------------------------------------------------
213 Stream &Stream::operator<<(uint32_t uval) {
214   PutHex32(uval, m_byte_order);
215   return *this;
216 }
217 
218 //------------------------------------------------------------------
219 // Stream a uint64_t "uval" out to this stream.
220 //------------------------------------------------------------------
221 Stream &Stream::operator<<(uint64_t uval) {
222   PutHex64(uval, m_byte_order);
223   return *this;
224 }
225 
226 //------------------------------------------------------------------
227 // Stream a int8_t "sval" out to this stream.
228 //------------------------------------------------------------------
229 Stream &Stream::operator<<(int8_t sval) {
230   Printf("%i", (int)sval);
231   return *this;
232 }
233 
234 //------------------------------------------------------------------
235 // Stream a int16_t "sval" out to this stream.
236 //------------------------------------------------------------------
237 Stream &Stream::operator<<(int16_t sval) {
238   Printf("%i", (int)sval);
239   return *this;
240 }
241 
242 //------------------------------------------------------------------
243 // Stream a int32_t "sval" out to this stream.
244 //------------------------------------------------------------------
245 Stream &Stream::operator<<(int32_t sval) {
246   Printf("%i", (int)sval);
247   return *this;
248 }
249 
250 //------------------------------------------------------------------
251 // Stream a int64_t "sval" out to this stream.
252 //------------------------------------------------------------------
253 Stream &Stream::operator<<(int64_t sval) {
254   Printf("%" PRIi64, sval);
255   return *this;
256 }
257 
258 //------------------------------------------------------------------
259 // Get the current indentation level
260 //------------------------------------------------------------------
261 int Stream::GetIndentLevel() const { return m_indent_level; }
262 
263 //------------------------------------------------------------------
264 // Set the current indentation level
265 //------------------------------------------------------------------
266 void Stream::SetIndentLevel(int indent_level) { m_indent_level = indent_level; }
267 
268 //------------------------------------------------------------------
269 // Increment the current indentation level
270 //------------------------------------------------------------------
271 void Stream::IndentMore(int amount) { m_indent_level += amount; }
272 
273 //------------------------------------------------------------------
274 // Decrement the current indentation level
275 //------------------------------------------------------------------
276 void Stream::IndentLess(int amount) {
277   if (m_indent_level >= amount)
278     m_indent_level -= amount;
279   else
280     m_indent_level = 0;
281 }
282 
283 //------------------------------------------------------------------
284 // Get the address size in bytes
285 //------------------------------------------------------------------
286 uint32_t Stream::GetAddressByteSize() const { return m_addr_size; }
287 
288 //------------------------------------------------------------------
289 // Set the address size in bytes
290 //------------------------------------------------------------------
291 void Stream::SetAddressByteSize(uint32_t addr_size) { m_addr_size = addr_size; }
292 
293 //------------------------------------------------------------------
294 // The flags get accessor
295 //------------------------------------------------------------------
296 Flags &Stream::GetFlags() { return m_flags; }
297 
298 //------------------------------------------------------------------
299 // The flags const get accessor
300 //------------------------------------------------------------------
301 const Flags &Stream::GetFlags() const { return m_flags; }
302 
303 //------------------------------------------------------------------
304 // The byte order get accessor
305 //------------------------------------------------------------------
306 
307 lldb::ByteOrder Stream::GetByteOrder() const { return m_byte_order; }
308 
309 size_t Stream::PrintfAsRawHex8(const char *format, ...) {
310   va_list args;
311   va_start(args, format);
312 
313   llvm::SmallString<1024> buf;
314   VASprintf(buf, format, args);
315 
316   size_t length = 0;
317   for (char C : buf)
318     length += _PutHex8(C, false);
319 
320   va_end(args);
321 
322   return length;
323 }
324 
325 size_t Stream::PutNHex8(size_t n, uint8_t uvalue) {
326   size_t bytes_written = 0;
327   for (size_t i = 0; i < n; ++i)
328     bytes_written += _PutHex8(uvalue, false);
329   return bytes_written;
330 }
331 
332 size_t Stream::_PutHex8(uint8_t uvalue, bool add_prefix) {
333   size_t bytes_written = 0;
334   if (m_flags.Test(eBinary)) {
335     bytes_written = Write(&uvalue, 1);
336   } else {
337     if (add_prefix)
338       PutCString("0x");
339 
340     static char g_hex_to_ascii_hex_char[16] = {'0', '1', '2', '3', '4', '5',
341                                                '6', '7', '8', '9', 'a', 'b',
342                                                'c', 'd', 'e', 'f'};
343     char nibble_chars[2];
344     nibble_chars[0] = g_hex_to_ascii_hex_char[(uvalue >> 4) & 0xf];
345     nibble_chars[1] = g_hex_to_ascii_hex_char[(uvalue >> 0) & 0xf];
346     bytes_written = Write(nibble_chars, sizeof(nibble_chars));
347   }
348   return bytes_written;
349 }
350 
351 size_t Stream::PutHex8(uint8_t uvalue) { return _PutHex8(uvalue, false); }
352 
353 size_t Stream::PutHex16(uint16_t uvalue, ByteOrder byte_order) {
354   if (byte_order == eByteOrderInvalid)
355     byte_order = m_byte_order;
356 
357   size_t bytes_written = 0;
358   if (byte_order == eByteOrderLittle) {
359     for (size_t byte = 0; byte < sizeof(uvalue); ++byte)
360       bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
361   } else {
362     for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte)
363       bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
364   }
365   return bytes_written;
366 }
367 
368 size_t Stream::PutHex32(uint32_t uvalue, ByteOrder byte_order) {
369   if (byte_order == eByteOrderInvalid)
370     byte_order = m_byte_order;
371 
372   size_t bytes_written = 0;
373   if (byte_order == eByteOrderLittle) {
374     for (size_t byte = 0; byte < sizeof(uvalue); ++byte)
375       bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
376   } else {
377     for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte)
378       bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
379   }
380   return bytes_written;
381 }
382 
383 size_t Stream::PutHex64(uint64_t uvalue, ByteOrder byte_order) {
384   if (byte_order == eByteOrderInvalid)
385     byte_order = m_byte_order;
386 
387   size_t bytes_written = 0;
388   if (byte_order == eByteOrderLittle) {
389     for (size_t byte = 0; byte < sizeof(uvalue); ++byte)
390       bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
391   } else {
392     for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte)
393       bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
394   }
395   return bytes_written;
396 }
397 
398 size_t Stream::PutMaxHex64(uint64_t uvalue, size_t byte_size,
399                            lldb::ByteOrder byte_order) {
400   switch (byte_size) {
401   case 1:
402     return PutHex8((uint8_t)uvalue);
403   case 2:
404     return PutHex16((uint16_t)uvalue, byte_order);
405   case 4:
406     return PutHex32((uint32_t)uvalue, byte_order);
407   case 8:
408     return PutHex64(uvalue, byte_order);
409   }
410   return 0;
411 }
412 
413 size_t Stream::PutPointer(void *ptr) {
414   return PutRawBytes(&ptr, sizeof(ptr), endian::InlHostByteOrder(),
415                      endian::InlHostByteOrder());
416 }
417 
418 size_t Stream::PutFloat(float f, ByteOrder byte_order) {
419   if (byte_order == eByteOrderInvalid)
420     byte_order = m_byte_order;
421 
422   return PutRawBytes(&f, sizeof(f), endian::InlHostByteOrder(), byte_order);
423 }
424 
425 size_t Stream::PutDouble(double d, ByteOrder byte_order) {
426   if (byte_order == eByteOrderInvalid)
427     byte_order = m_byte_order;
428 
429   return PutRawBytes(&d, sizeof(d), endian::InlHostByteOrder(), byte_order);
430 }
431 
432 size_t Stream::PutLongDouble(long double ld, ByteOrder byte_order) {
433   if (byte_order == eByteOrderInvalid)
434     byte_order = m_byte_order;
435 
436   return PutRawBytes(&ld, sizeof(ld), endian::InlHostByteOrder(), byte_order);
437 }
438 
439 size_t Stream::PutRawBytes(const void *s, size_t src_len,
440                            ByteOrder src_byte_order, ByteOrder dst_byte_order) {
441   if (src_byte_order == eByteOrderInvalid)
442     src_byte_order = m_byte_order;
443 
444   if (dst_byte_order == eByteOrderInvalid)
445     dst_byte_order = m_byte_order;
446 
447   size_t bytes_written = 0;
448   const uint8_t *src = (const uint8_t *)s;
449   bool binary_was_set = m_flags.Test(eBinary);
450   if (!binary_was_set)
451     m_flags.Set(eBinary);
452   if (src_byte_order == dst_byte_order) {
453     for (size_t i = 0; i < src_len; ++i)
454       bytes_written += _PutHex8(src[i], false);
455   } else {
456     for (size_t i = src_len - 1; i < src_len; --i)
457       bytes_written += _PutHex8(src[i], false);
458   }
459   if (!binary_was_set)
460     m_flags.Clear(eBinary);
461 
462   return bytes_written;
463 }
464 
465 size_t Stream::PutBytesAsRawHex8(const void *s, size_t src_len,
466                                  ByteOrder src_byte_order,
467                                  ByteOrder dst_byte_order) {
468   if (src_byte_order == eByteOrderInvalid)
469     src_byte_order = m_byte_order;
470 
471   if (dst_byte_order == eByteOrderInvalid)
472     dst_byte_order = m_byte_order;
473 
474   size_t bytes_written = 0;
475   const uint8_t *src = (const uint8_t *)s;
476   bool binary_is_set = m_flags.Test(eBinary);
477   m_flags.Clear(eBinary);
478   if (src_byte_order == dst_byte_order) {
479     for (size_t i = 0; i < src_len; ++i)
480       bytes_written += _PutHex8(src[i], false);
481   } else {
482     for (size_t i = src_len - 1; i < src_len; --i)
483       bytes_written += _PutHex8(src[i], false);
484   }
485   if (binary_is_set)
486     m_flags.Set(eBinary);
487 
488   return bytes_written;
489 }
490 
491 size_t Stream::PutCStringAsRawHex8(const char *s) {
492   size_t bytes_written = 0;
493   bool binary_is_set = m_flags.Test(eBinary);
494   m_flags.Clear(eBinary);
495   while(*s) {
496     bytes_written += _PutHex8(*s, false);
497     ++s;
498   }
499   if (binary_is_set)
500     m_flags.Set(eBinary);
501   return bytes_written;
502 }
503