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