1 //===-- Stream.h ------------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_UTILITY_STREAM_H
10 #define LLDB_UTILITY_STREAM_H
11 
12 #include "lldb/Utility/Flags.h"
13 #include "lldb/lldb-defines.h"
14 #include "lldb/lldb-enumerations.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/Support/FormatVariadic.h"
17 #include "llvm/Support/raw_ostream.h"
18 
19 #include <cstdarg>
20 #include <cstddef>
21 #include <cstdint>
22 #include <type_traits>
23 
24 namespace lldb_private {
25 
26 /// \class Stream Stream.h "lldb/Utility/Stream.h"
27 /// A stream class that can stream formatted output to a file.
28 class Stream {
29 public:
30   /// \a m_flags bit values.
31   enum {
32     eBinary = (1 << 0) ///< Get and put data as binary instead of as the default
33                        /// string mode.
34   };
35 
36   /// Utility class for counting the bytes that were written to a stream in a
37   /// certain time span.
38   ///
39   /// \example
40   ///   ByteDelta delta(*this);
41   ///   WriteDataToStream("foo");
42   ///   return *delta;
43   class ByteDelta {
44     Stream *m_stream;
45     /// Bytes we have written so far when ByteDelta was created.
46     size_t m_start;
47 
48   public:
ByteDelta(Stream & s)49     ByteDelta(Stream &s) : m_stream(&s), m_start(s.GetWrittenBytes()) {}
50     /// Returns the number of bytes written to the given Stream since this
51     /// ByteDelta object was created.
52     size_t operator*() const { return m_stream->GetWrittenBytes() - m_start; }
53   };
54 
55   /// Construct with flags and address size and byte order.
56   ///
57   /// Construct with dump flags \a flags and the default address size. \a
58   /// flags can be any of the above enumeration logical OR'ed together.
59   Stream(uint32_t flags, uint32_t addr_size, lldb::ByteOrder byte_order,
60          bool colors = false);
61 
62   /// Construct a default Stream, not binary, host byte order and host addr
63   /// size.
64   ///
65   Stream(bool colors = false);
66 
67   // FIXME: Streams should not be copyable.
Stream(const Stream & other)68   Stream(const Stream &other) : m_forwarder(*this) { (*this) = other; }
69 
70   Stream &operator=(const Stream &rhs) {
71     m_flags = rhs.m_flags;
72     m_addr_size = rhs.m_addr_size;
73     m_byte_order = rhs.m_byte_order;
74     m_indent_level = rhs.m_indent_level;
75     return *this;
76   }
77 
78   /// Destructor
79   virtual ~Stream();
80 
81   // Subclasses must override these methods
82 
83   /// Flush the stream.
84   ///
85   /// Subclasses should flush the stream to make any output appear if the
86   /// stream has any buffering.
87   virtual void Flush() = 0;
88 
89   /// Output character bytes to the stream.
90   ///
91   /// Appends \a src_len characters from the buffer \a src to the stream.
92   ///
93   /// \param[in] src
94   ///     A buffer containing at least \a src_len bytes of data.
95   ///
96   /// \param[in] src_len
97   ///     A number of bytes to append to the stream.
98   ///
99   /// \return
100   ///     The number of bytes that were appended to the stream.
Write(const void * src,size_t src_len)101   size_t Write(const void *src, size_t src_len) {
102     size_t appended_byte_count = WriteImpl(src, src_len);
103     m_bytes_written += appended_byte_count;
104     return appended_byte_count;
105   }
106 
GetWrittenBytes()107   size_t GetWrittenBytes() const { return m_bytes_written; }
108 
109   // Member functions
110   size_t PutChar(char ch);
111 
112   /// Set the byte_order value.
113   ///
114   /// Sets the byte order of the data to extract. Extracted values will be
115   /// swapped if necessary when decoding.
116   ///
117   /// \param[in] byte_order
118   ///     The byte order value to use when extracting data.
119   ///
120   /// \return
121   ///     The old byte order value.
122   lldb::ByteOrder SetByteOrder(lldb::ByteOrder byte_order);
123 
124   /// Format a C string from a printf style format and variable arguments and
125   /// encode and append the resulting C string as hex bytes.
126   ///
127   /// \param[in] format
128   ///     A printf style format string.
129   ///
130   /// \param[in] ...
131   ///     Any additional arguments needed for the printf format string.
132   ///
133   /// \return
134   ///     The number of bytes that were appended to the stream.
135   size_t PrintfAsRawHex8(const char *format, ...)
136       __attribute__((__format__(__printf__, 2, 3)));
137 
138   /// Append an uint8_t value in the hexadecimal format to the stream.
139   ///
140   /// \param[in] uvalue
141   ///     The value to append.
142   ///
143   /// \return
144   ///     The number of bytes that were appended to the stream.
145   size_t PutHex8(uint8_t uvalue);
146 
147   size_t PutNHex8(size_t n, uint8_t uvalue);
148 
149   size_t PutHex16(uint16_t uvalue,
150                   lldb::ByteOrder byte_order = lldb::eByteOrderInvalid);
151 
152   size_t PutHex32(uint32_t uvalue,
153                   lldb::ByteOrder byte_order = lldb::eByteOrderInvalid);
154 
155   size_t PutHex64(uint64_t uvalue,
156                   lldb::ByteOrder byte_order = lldb::eByteOrderInvalid);
157 
158   size_t PutMaxHex64(uint64_t uvalue, size_t byte_size,
159                      lldb::ByteOrder byte_order = lldb::eByteOrderInvalid);
160   size_t PutFloat(float f,
161                   lldb::ByteOrder byte_order = lldb::eByteOrderInvalid);
162 
163   size_t PutDouble(double d,
164                    lldb::ByteOrder byte_order = lldb::eByteOrderInvalid);
165 
166   size_t PutLongDouble(long double ld,
167                        lldb::ByteOrder byte_order = lldb::eByteOrderInvalid);
168 
169   size_t PutPointer(void *ptr);
170 
171   // Append \a src_len bytes from \a src to the stream as hex characters (two
172   // ascii characters per byte of input data)
173   size_t
174   PutBytesAsRawHex8(const void *src, size_t src_len,
175                     lldb::ByteOrder src_byte_order = lldb::eByteOrderInvalid,
176                     lldb::ByteOrder dst_byte_order = lldb::eByteOrderInvalid);
177 
178   // Append \a src_len bytes from \a s to the stream as binary data.
179   size_t PutRawBytes(const void *s, size_t src_len,
180                      lldb::ByteOrder src_byte_order = lldb::eByteOrderInvalid,
181                      lldb::ByteOrder dst_byte_order = lldb::eByteOrderInvalid);
182 
183   size_t PutStringAsRawHex8(llvm::StringRef s);
184 
185   /// Output a NULL terminated C string \a cstr to the stream \a s.
186   ///
187   /// \param[in] cstr
188   ///     A NULL terminated C string.
189   ///
190   /// \return
191   ///     A reference to this class so multiple things can be streamed
192   ///     in one statement.
193   Stream &operator<<(const char *cstr);
194 
195   Stream &operator<<(llvm::StringRef str);
196 
197   /// Output a pointer value \a p to the stream \a s.
198   ///
199   /// \param[in] p
200   ///     A void pointer.
201   ///
202   /// \return
203   ///     A reference to this class so multiple things can be streamed
204   ///     in one statement.
205   Stream &operator<<(const void *p);
206 
207   /// Output a character \a ch to the stream \a s.
208   ///
209   /// \param[in] ch
210   ///     A printable character value.
211   ///
212   /// \return
213   ///     A reference to this class so multiple things can be streamed
214   ///     in one statement.
215   Stream &operator<<(char ch);
216 
217   Stream &operator<<(uint8_t uval) = delete;
218   Stream &operator<<(uint16_t uval) = delete;
219   Stream &operator<<(uint32_t uval) = delete;
220   Stream &operator<<(uint64_t uval) = delete;
221   Stream &operator<<(int8_t sval) = delete;
222   Stream &operator<<(int16_t sval) = delete;
223   Stream &operator<<(int32_t sval) = delete;
224   Stream &operator<<(int64_t sval) = delete;
225 
226   /// Output a C string to the stream.
227   ///
228   /// Print a C string \a cstr to the stream.
229   ///
230   /// \param[in] cstr
231   ///     The string to be output to the stream.
232   size_t PutCString(llvm::StringRef cstr);
233 
234   /// Output a C string to the stream with color highlighting.
235   ///
236   /// Print a C string \a text to the stream, applying color highlighting to
237   /// the portions of the string that match the regex pattern \a pattern. The
238   /// pattern is matched as many times as possible throughout the string. If \a
239   /// pattern is nullptr, then no highlighting is applied.
240   ///
241   /// The highlighting is applied by enclosing the matching text in ANSI color
242   /// codes. The \a prefix parameter specifies the ANSI code to start the color
243   /// (the standard value is assumed to be 'ansi.fg.red', representing red
244   /// foreground), and the \a suffix parameter specifies the ANSI code to end
245   /// the color (the standard value is assumed to be 'ansi.normal', resetting to
246   /// default text style). These constants should be defined appropriately in
247   /// your environment.
248   ///
249   /// \param[in] text
250   ///     The string to be output to the stream.
251   ///
252   /// \param[in] pattern
253   ///     The regex pattern to match against the \a text string. Portions of \a
254   ///     text matching this pattern will be colorized. If this parameter is
255   ///     nullptr, highlighting is not performed.
256   /// \param[in] prefix
257   ///     The ANSI color code to start colorization. This is
258   ///     environment-dependent.
259   /// \param[in] suffix
260   ///     The ANSI color code to end colorization. This is
261   ///     environment-dependent.
262 
263   void PutCStringColorHighlighted(llvm::StringRef text,
264                                   llvm::StringRef pattern = "",
265                                   llvm::StringRef prefix = "",
266                                   llvm::StringRef suffix = "");
267 
268   /// Output and End of Line character to the stream.
269   size_t EOL();
270 
271   /// Get the address size in bytes.
272   ///
273   /// \return
274   ///     The size of an address in bytes that is used when outputting
275   ///     address and pointer values to the stream.
276   uint32_t GetAddressByteSize() const;
277 
278   /// The flags accessor.
279   ///
280   /// \return
281   ///     A reference to the Flags member variable.
282   Flags &GetFlags();
283 
284   /// The flags const accessor.
285   ///
286   /// \return
287   ///     A const reference to the Flags member variable.
288   const Flags &GetFlags() const;
289 
290   //// The byte order accessor.
291   ////
292   //// \return
293   ////     The byte order.
294   lldb::ByteOrder GetByteOrder() const;
295 
296   /// Get the current indentation level.
297   ///
298   /// \return
299   ///     The current indentation level.
300   unsigned GetIndentLevel() const;
301 
302   /// Indent the current line in the stream.
303   ///
304   /// Indent the current line using the current indentation level and print an
305   /// optional string following the indentation spaces.
306   ///
307   /// \param[in] s
308   ///     A string to print following the indentation.
309   size_t Indent(llvm::StringRef s = "");
310 
311   /// Decrement the current indentation level.
312   void IndentLess(unsigned amount = 2);
313 
314   /// Increment the current indentation level.
315   void IndentMore(unsigned amount = 2);
316 
317   /// Output an offset value.
318   ///
319   /// Put an offset \a uval out to the stream using the printf format in \a
320   /// format.
321   ///
322   /// \param[in] offset
323   ///     The offset value.
324   ///
325   /// \param[in] format
326   ///     The printf style format to use when outputting the offset.
327   void Offset(uint32_t offset, const char *format = "0x%8.8x: ");
328 
329   /// Output printf formatted output to the stream.
330   ///
331   /// Print some formatted output to the stream.
332   ///
333   /// \param[in] format
334   ///     A printf style format string.
335   ///
336   /// \param[in] ...
337   ///     Variable arguments that are needed for the printf style
338   ///     format string \a format.
339   size_t Printf(const char *format, ...) __attribute__((format(printf, 2, 3)));
340 
341   size_t PrintfVarArg(const char *format, va_list args);
342 
Format(const char * format,Args &&...args)343   template <typename... Args> void Format(const char *format, Args &&... args) {
344     PutCString(llvm::formatv(format, std::forward<Args>(args)...).str());
345   }
346 
347   /// Output a quoted C string value to the stream.
348   ///
349   /// Print a double quoted NULL terminated C string to the stream using the
350   /// printf format in \a format.
351   ///
352   /// \param[in] cstr
353   ///     A NULL terminated C string value.
354   ///
355   /// \param[in] format
356   ///     The optional C string format that can be overridden.
357   void QuotedCString(const char *cstr, const char *format = "\"%s\"");
358 
359   /// Set the address size in bytes.
360   ///
361   /// \param[in] addr_size
362   ///     The new size in bytes of an address to use when outputting
363   ///     address and pointer values.
364   void SetAddressByteSize(uint32_t addr_size);
365 
366   /// Set the current indentation level.
367   ///
368   /// \param[in] level
369   ///     The new indentation level.
370   void SetIndentLevel(unsigned level);
371 
372   /// Output a SLEB128 number to the stream.
373   ///
374   /// Put an SLEB128 \a uval out to the stream using the printf format in \a
375   /// format.
376   ///
377   /// \param[in] uval
378   ///     A uint64_t value that was extracted as a SLEB128 value.
379   size_t PutSLEB128(int64_t uval);
380 
381   /// Output a ULEB128 number to the stream.
382   ///
383   /// Put an ULEB128 \a uval out to the stream using the printf format in \a
384   /// format.
385   ///
386   /// \param[in] uval
387   ///     A uint64_t value that was extracted as a ULEB128 value.
388   size_t PutULEB128(uint64_t uval);
389 
390   /// Returns a raw_ostream that forwards the data to this Stream object.
AsRawOstream()391   llvm::raw_ostream &AsRawOstream() {
392     return m_forwarder;
393   }
394 
395 protected:
396   // Member variables
397   Flags m_flags;        ///< Dump flags.
398   uint32_t m_addr_size = 4; ///< Size of an address in bytes.
399   lldb::ByteOrder
400       m_byte_order;   ///< Byte order to use when encoding scalar types.
401   unsigned m_indent_level = 0;     ///< Indention level.
402   std::size_t m_bytes_written = 0; ///< Number of bytes written so far.
403 
404   void _PutHex8(uint8_t uvalue, bool add_prefix);
405 
406   /// Output character bytes to the stream.
407   ///
408   /// Appends \a src_len characters from the buffer \a src to the stream.
409   ///
410   /// \param[in] src
411   ///     A buffer containing at least \a src_len bytes of data.
412   ///
413   /// \param[in] src_len
414   ///     A number of bytes to append to the stream.
415   ///
416   /// \return
417   ///     The number of bytes that were appended to the stream.
418   virtual size_t WriteImpl(const void *src, size_t src_len) = 0;
419 
420   /// \class RawOstreamForward Stream.h "lldb/Utility/Stream.h"
421   /// This is a wrapper class that exposes a raw_ostream interface that just
422   /// forwards to an LLDB stream, allowing to reuse LLVM algorithms that take
423   /// a raw_ostream within the LLDB code base.
424   class RawOstreamForward : public llvm::raw_ostream {
425     // Note: This stream must *not* maintain its own buffer, but instead
426     // directly write everything to the internal Stream class. Without this,
427     // we would run into the problem that the Stream written byte count would
428     // differ from the actually written bytes by the size of the internal
429     // raw_ostream buffer.
430 
431     Stream &m_target;
write_impl(const char * Ptr,size_t Size)432     void write_impl(const char *Ptr, size_t Size) override {
433       m_target.Write(Ptr, Size);
434     }
435 
current_pos()436     uint64_t current_pos() const override {
437       return m_target.GetWrittenBytes();
438     }
439 
440   public:
441     RawOstreamForward(Stream &target, bool colors = false)
raw_ostream(true)442         : llvm::raw_ostream(/*unbuffered*/ true), m_target(target) {
443       enable_colors(colors);
444     }
445   };
446   RawOstreamForward m_forwarder;
447 };
448 
449 /// Output an address value to this stream.
450 ///
451 /// Put an address \a addr out to the stream with optional \a prefix and \a
452 /// suffix strings.
453 ///
454 /// \param[in] s
455 ///     The output stream.
456 ///
457 /// \param[in] addr
458 ///     An address value.
459 ///
460 /// \param[in] addr_size
461 ///     Size in bytes of the address, used for formatting.
462 ///
463 /// \param[in] prefix
464 ///     A prefix C string. If nullptr, no prefix will be output.
465 ///
466 /// \param[in] suffix
467 ///     A suffix C string. If nullptr, no suffix will be output.
468 void DumpAddress(llvm::raw_ostream &s, uint64_t addr, uint32_t addr_size,
469                  const char *prefix = nullptr, const char *suffix = nullptr);
470 
471 /// Output an address range to this stream.
472 ///
473 /// Put an address range \a lo_addr - \a hi_addr out to the stream with
474 /// optional \a prefix and \a suffix strings.
475 ///
476 /// \param[in] s
477 ///     The output stream.
478 ///
479 /// \param[in] lo_addr
480 ///     The start address of the address range.
481 ///
482 /// \param[in] hi_addr
483 ///     The end address of the address range.
484 ///
485 /// \param[in] addr_size
486 ///     Size in bytes of the address, used for formatting.
487 ///
488 /// \param[in] prefix
489 ///     A prefix C string. If nullptr, no prefix will be output.
490 ///
491 /// \param[in] suffix
492 ///     A suffix C string. If nullptr, no suffix will be output.
493 void DumpAddressRange(llvm::raw_ostream &s, uint64_t lo_addr, uint64_t hi_addr,
494                       uint32_t addr_size, const char *prefix = nullptr,
495                       const char *suffix = nullptr);
496 
497 } // namespace lldb_private
498 
499 #endif // LLDB_UTILITY_STREAM_H
500