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 ByteDelta delta(*this); 317 for (char C : buf) 318 _PutHex8(C, false); 319 320 va_end(args); 321 322 return *delta; 323 } 324 325 size_t Stream::PutNHex8(size_t n, uint8_t uvalue) { 326 ByteDelta delta(*this); 327 for (size_t i = 0; i < n; ++i) 328 _PutHex8(uvalue, false); 329 return *delta; 330 } 331 332 void Stream::_PutHex8(uint8_t uvalue, bool add_prefix) { 333 if (m_flags.Test(eBinary)) { 334 Write(&uvalue, 1); 335 } else { 336 if (add_prefix) 337 PutCString("0x"); 338 339 static char g_hex_to_ascii_hex_char[16] = {'0', '1', '2', '3', '4', '5', 340 '6', '7', '8', '9', 'a', 'b', 341 'c', 'd', 'e', 'f'}; 342 char nibble_chars[2]; 343 nibble_chars[0] = g_hex_to_ascii_hex_char[(uvalue >> 4) & 0xf]; 344 nibble_chars[1] = g_hex_to_ascii_hex_char[(uvalue >> 0) & 0xf]; 345 Write(nibble_chars, sizeof(nibble_chars)); 346 } 347 } 348 349 size_t Stream::PutHex8(uint8_t uvalue) { 350 ByteDelta delta(*this); 351 _PutHex8(uvalue, false); 352 return *delta; 353 } 354 355 size_t Stream::PutHex16(uint16_t uvalue, ByteOrder byte_order) { 356 ByteDelta delta(*this); 357 358 if (byte_order == eByteOrderInvalid) 359 byte_order = m_byte_order; 360 361 if (byte_order == eByteOrderLittle) { 362 for (size_t byte = 0; byte < sizeof(uvalue); ++byte) 363 _PutHex8((uint8_t)(uvalue >> (byte * 8)), false); 364 } else { 365 for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte) 366 _PutHex8((uint8_t)(uvalue >> (byte * 8)), false); 367 } 368 return *delta; 369 } 370 371 size_t Stream::PutHex32(uint32_t uvalue, ByteOrder byte_order) { 372 ByteDelta delta(*this); 373 374 if (byte_order == eByteOrderInvalid) 375 byte_order = m_byte_order; 376 377 if (byte_order == eByteOrderLittle) { 378 for (size_t byte = 0; byte < sizeof(uvalue); ++byte) 379 _PutHex8((uint8_t)(uvalue >> (byte * 8)), false); 380 } else { 381 for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte) 382 _PutHex8((uint8_t)(uvalue >> (byte * 8)), false); 383 } 384 return *delta; 385 } 386 387 size_t Stream::PutHex64(uint64_t uvalue, ByteOrder byte_order) { 388 ByteDelta delta(*this); 389 390 if (byte_order == eByteOrderInvalid) 391 byte_order = m_byte_order; 392 393 if (byte_order == eByteOrderLittle) { 394 for (size_t byte = 0; byte < sizeof(uvalue); ++byte) 395 _PutHex8((uint8_t)(uvalue >> (byte * 8)), false); 396 } else { 397 for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte) 398 _PutHex8((uint8_t)(uvalue >> (byte * 8)), false); 399 } 400 return *delta; 401 } 402 403 size_t Stream::PutMaxHex64(uint64_t uvalue, size_t byte_size, 404 lldb::ByteOrder byte_order) { 405 switch (byte_size) { 406 case 1: 407 return PutHex8((uint8_t)uvalue); 408 case 2: 409 return PutHex16((uint16_t)uvalue, byte_order); 410 case 4: 411 return PutHex32((uint32_t)uvalue, byte_order); 412 case 8: 413 return PutHex64(uvalue, byte_order); 414 } 415 return 0; 416 } 417 418 size_t Stream::PutPointer(void *ptr) { 419 return PutRawBytes(&ptr, sizeof(ptr), endian::InlHostByteOrder(), 420 endian::InlHostByteOrder()); 421 } 422 423 size_t Stream::PutFloat(float f, ByteOrder byte_order) { 424 if (byte_order == eByteOrderInvalid) 425 byte_order = m_byte_order; 426 427 return PutRawBytes(&f, sizeof(f), endian::InlHostByteOrder(), byte_order); 428 } 429 430 size_t Stream::PutDouble(double d, ByteOrder byte_order) { 431 if (byte_order == eByteOrderInvalid) 432 byte_order = m_byte_order; 433 434 return PutRawBytes(&d, sizeof(d), endian::InlHostByteOrder(), byte_order); 435 } 436 437 size_t Stream::PutLongDouble(long double ld, ByteOrder byte_order) { 438 if (byte_order == eByteOrderInvalid) 439 byte_order = m_byte_order; 440 441 return PutRawBytes(&ld, sizeof(ld), endian::InlHostByteOrder(), byte_order); 442 } 443 444 size_t Stream::PutRawBytes(const void *s, size_t src_len, 445 ByteOrder src_byte_order, ByteOrder dst_byte_order) { 446 ByteDelta delta(*this); 447 448 if (src_byte_order == eByteOrderInvalid) 449 src_byte_order = m_byte_order; 450 451 if (dst_byte_order == eByteOrderInvalid) 452 dst_byte_order = m_byte_order; 453 454 const uint8_t *src = (const uint8_t *)s; 455 bool binary_was_set = m_flags.Test(eBinary); 456 if (!binary_was_set) 457 m_flags.Set(eBinary); 458 if (src_byte_order == dst_byte_order) { 459 for (size_t i = 0; i < src_len; ++i) 460 _PutHex8(src[i], false); 461 } else { 462 for (size_t i = src_len - 1; i < src_len; --i) 463 _PutHex8(src[i], false); 464 } 465 if (!binary_was_set) 466 m_flags.Clear(eBinary); 467 468 return *delta; 469 } 470 471 size_t Stream::PutBytesAsRawHex8(const void *s, size_t src_len, 472 ByteOrder src_byte_order, 473 ByteOrder dst_byte_order) { 474 ByteDelta delta(*this); 475 if (src_byte_order == eByteOrderInvalid) 476 src_byte_order = m_byte_order; 477 478 if (dst_byte_order == eByteOrderInvalid) 479 dst_byte_order = m_byte_order; 480 481 const uint8_t *src = (const uint8_t *)s; 482 bool binary_is_set = m_flags.Test(eBinary); 483 m_flags.Clear(eBinary); 484 if (src_byte_order == dst_byte_order) { 485 for (size_t i = 0; i < src_len; ++i) 486 _PutHex8(src[i], false); 487 } else { 488 for (size_t i = src_len - 1; i < src_len; --i) 489 _PutHex8(src[i], false); 490 } 491 if (binary_is_set) 492 m_flags.Set(eBinary); 493 494 return *delta; 495 } 496 497 size_t Stream::PutCStringAsRawHex8(const char *s) { 498 ByteDelta delta(*this); 499 bool binary_is_set = m_flags.Test(eBinary); 500 m_flags.Clear(eBinary); 501 while(*s) { 502 _PutHex8(*s, false); 503 ++s; 504 } 505 if (binary_is_set) 506 m_flags.Set(eBinary); 507 return *delta; 508 } 509