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/Core/Stream.h" 11 #include "lldb/Host/Endian.h" 12 #include <stddef.h> 13 #include <stdio.h> 14 #include <string.h> 15 #include <stdlib.h> 16 17 #include <inttypes.h> 18 19 using namespace lldb; 20 using namespace lldb_private; 21 22 Stream::Stream (uint32_t flags, uint32_t addr_size, ByteOrder byte_order) : 23 m_flags (flags), 24 m_addr_size (addr_size), 25 m_byte_order (byte_order), 26 m_indent_level(0) 27 { 28 } 29 30 Stream::Stream () : 31 m_flags (0), 32 m_addr_size (4), 33 m_byte_order (lldb::endian::InlHostByteOrder()), 34 m_indent_level(0) 35 { 36 } 37 38 //------------------------------------------------------------------ 39 // Destructor 40 //------------------------------------------------------------------ 41 Stream::~Stream () 42 { 43 } 44 45 ByteOrder 46 Stream::SetByteOrder (ByteOrder byte_order) 47 { 48 ByteOrder old_byte_order = m_byte_order; 49 m_byte_order = byte_order; 50 return old_byte_order; 51 } 52 53 //------------------------------------------------------------------ 54 // Put an offset "uval" out to the stream using the printf format 55 // in "format". 56 //------------------------------------------------------------------ 57 void 58 Stream::Offset (uint32_t uval, const char *format) 59 { 60 Printf (format, uval); 61 } 62 63 //------------------------------------------------------------------ 64 // Put an SLEB128 "uval" out to the stream using the printf format 65 // in "format". 66 //------------------------------------------------------------------ 67 size_t 68 Stream::PutSLEB128 (int64_t sval) 69 { 70 size_t bytes_written = 0; 71 if (m_flags.Test(eBinary)) 72 { 73 bool more = true; 74 while (more) 75 { 76 uint8_t byte = sval & 0x7fu; 77 sval >>= 7; 78 /* sign bit of byte is 2nd high order bit (0x40) */ 79 if ((sval == 0 && !(byte & 0x40)) || 80 (sval == -1 && (byte & 0x40)) ) 81 more = false; 82 else 83 // more bytes to come 84 byte |= 0x80u; 85 bytes_written += Write(&byte, 1); 86 } 87 } 88 else 89 { 90 bytes_written = Printf ("0x%" PRIi64, sval); 91 } 92 93 return bytes_written; 94 95 } 96 97 //------------------------------------------------------------------ 98 // Put an ULEB128 "uval" out to the stream using the printf format 99 // in "format". 100 //------------------------------------------------------------------ 101 size_t 102 Stream::PutULEB128 (uint64_t uval) 103 { 104 size_t bytes_written = 0; 105 if (m_flags.Test(eBinary)) 106 { 107 do 108 { 109 110 uint8_t byte = uval & 0x7fu; 111 uval >>= 7; 112 if (uval != 0) 113 { 114 // more bytes to come 115 byte |= 0x80u; 116 } 117 bytes_written += Write(&byte, 1); 118 } while (uval != 0); 119 } 120 else 121 { 122 bytes_written = Printf ("0x%" PRIx64, uval); 123 } 124 return bytes_written; 125 } 126 127 //------------------------------------------------------------------ 128 // Print a raw NULL terminated C string to the stream. 129 //------------------------------------------------------------------ 130 size_t 131 Stream::PutCString (const char *cstr) 132 { 133 size_t cstr_len = strlen(cstr); 134 // when in binary mode, emit the NULL terminator 135 if (m_flags.Test(eBinary)) 136 ++cstr_len; 137 return Write (cstr, cstr_len); 138 } 139 140 //------------------------------------------------------------------ 141 // Print a double quoted NULL terminated C string to the stream 142 // using the printf format in "format". 143 //------------------------------------------------------------------ 144 void 145 Stream::QuotedCString (const char *cstr, const char *format) 146 { 147 Printf (format, cstr); 148 } 149 150 //------------------------------------------------------------------ 151 // Put an address "addr" out to the stream with optional prefix 152 // and suffix strings. 153 //------------------------------------------------------------------ 154 void 155 Stream::Address (uint64_t addr, uint32_t addr_size, const char *prefix, const char *suffix) 156 { 157 if (prefix == NULL) 158 prefix = ""; 159 if (suffix == NULL) 160 suffix = ""; 161 // int addr_width = m_addr_size << 1; 162 // Printf ("%s0x%0*" PRIx64 "%s", prefix, addr_width, addr, suffix); 163 Printf ("%s0x%0*" PRIx64 "%s", prefix, addr_size * 2, (uint64_t)addr, suffix); 164 } 165 166 //------------------------------------------------------------------ 167 // Put an address range out to the stream with optional prefix 168 // and suffix strings. 169 //------------------------------------------------------------------ 170 void 171 Stream::AddressRange(uint64_t lo_addr, uint64_t hi_addr, uint32_t addr_size, const char *prefix, const char *suffix) 172 { 173 if (prefix && prefix[0]) 174 PutCString (prefix); 175 Address (lo_addr, addr_size, "["); 176 Address (hi_addr, addr_size, "-", ")"); 177 if (suffix && suffix[0]) 178 PutCString (suffix); 179 } 180 181 182 size_t 183 Stream::PutChar (char ch) 184 { 185 return Write (&ch, 1); 186 } 187 188 189 //------------------------------------------------------------------ 190 // Print some formatted output to the stream. 191 //------------------------------------------------------------------ 192 size_t 193 Stream::Printf (const char *format, ...) 194 { 195 va_list args; 196 va_start (args, format); 197 size_t result = PrintfVarArg(format, args); 198 va_end (args); 199 return result; 200 } 201 202 //------------------------------------------------------------------ 203 // Print some formatted output to the stream. 204 //------------------------------------------------------------------ 205 size_t 206 Stream::PrintfVarArg (const char *format, va_list args) 207 { 208 char str[1024]; 209 va_list args_copy; 210 211 va_copy (args_copy, args); 212 213 size_t bytes_written = 0; 214 // Try and format our string into a fixed buffer first and see if it fits 215 size_t length = ::vsnprintf (str, sizeof(str), format, args); 216 if (length < sizeof(str)) 217 { 218 // Include the NULL termination byte for binary output 219 if (m_flags.Test(eBinary)) 220 length += 1; 221 // The formatted string fit into our stack based buffer, so we can just 222 // append that to our packet 223 bytes_written = Write (str, length); 224 } 225 else 226 { 227 // Our stack buffer wasn't big enough to contain the entire formatted 228 // string, so lets let vasprintf create the string for us! 229 char *str_ptr = NULL; 230 length = ::vasprintf (&str_ptr, format, args_copy); 231 if (str_ptr) 232 { 233 // Include the NULL termination byte for binary output 234 if (m_flags.Test(eBinary)) 235 length += 1; 236 bytes_written = Write (str_ptr, length); 237 ::free (str_ptr); 238 } 239 } 240 va_end (args_copy); 241 return bytes_written; 242 } 243 244 //------------------------------------------------------------------ 245 // Print and End of Line character to the stream 246 //------------------------------------------------------------------ 247 size_t 248 Stream::EOL() 249 { 250 return PutChar ('\n'); 251 } 252 253 //------------------------------------------------------------------ 254 // Indent the current line using the current indentation level and 255 // print an optional string following the idenatation spaces. 256 //------------------------------------------------------------------ 257 size_t 258 Stream::Indent(const char *s) 259 { 260 return Printf ("%*.*s%s", m_indent_level, m_indent_level, "", s ? s : ""); 261 } 262 263 //------------------------------------------------------------------ 264 // Stream a character "ch" out to this stream. 265 //------------------------------------------------------------------ 266 Stream& 267 Stream::operator<< (char ch) 268 { 269 PutChar (ch); 270 return *this; 271 } 272 273 //------------------------------------------------------------------ 274 // Stream the NULL terminated C string out to this stream. 275 //------------------------------------------------------------------ 276 Stream& 277 Stream::operator<< (const char *s) 278 { 279 Printf ("%s", s); 280 return *this; 281 } 282 283 //------------------------------------------------------------------ 284 // Stream the pointer value out to this stream. 285 //------------------------------------------------------------------ 286 Stream& 287 Stream::operator<< (void *p) 288 { 289 Printf ("0x%.*tx", (int)sizeof(void*) * 2, (ptrdiff_t)p); 290 return *this; 291 } 292 293 //------------------------------------------------------------------ 294 // Stream a uint8_t "uval" out to this stream. 295 //------------------------------------------------------------------ 296 Stream& 297 Stream::operator<< (uint8_t uval) 298 { 299 PutHex8(uval); 300 return *this; 301 } 302 303 //------------------------------------------------------------------ 304 // Stream a uint16_t "uval" out to this stream. 305 //------------------------------------------------------------------ 306 Stream& 307 Stream::operator<< (uint16_t uval) 308 { 309 PutHex16(uval, m_byte_order); 310 return *this; 311 } 312 313 //------------------------------------------------------------------ 314 // Stream a uint32_t "uval" out to this stream. 315 //------------------------------------------------------------------ 316 Stream& 317 Stream::operator<< (uint32_t uval) 318 { 319 PutHex32(uval, m_byte_order); 320 return *this; 321 } 322 323 //------------------------------------------------------------------ 324 // Stream a uint64_t "uval" out to this stream. 325 //------------------------------------------------------------------ 326 Stream& 327 Stream::operator<< (uint64_t uval) 328 { 329 PutHex64(uval, m_byte_order); 330 return *this; 331 } 332 333 //------------------------------------------------------------------ 334 // Stream a int8_t "sval" out to this stream. 335 //------------------------------------------------------------------ 336 Stream& 337 Stream::operator<< (int8_t sval) 338 { 339 Printf ("%i", (int)sval); 340 return *this; 341 } 342 343 //------------------------------------------------------------------ 344 // Stream a int16_t "sval" out to this stream. 345 //------------------------------------------------------------------ 346 Stream& 347 Stream::operator<< (int16_t sval) 348 { 349 Printf ("%i", (int)sval); 350 return *this; 351 } 352 353 //------------------------------------------------------------------ 354 // Stream a int32_t "sval" out to this stream. 355 //------------------------------------------------------------------ 356 Stream& 357 Stream::operator<< (int32_t sval) 358 { 359 Printf ("%i", (int)sval); 360 return *this; 361 } 362 363 //------------------------------------------------------------------ 364 // Stream a int64_t "sval" out to this stream. 365 //------------------------------------------------------------------ 366 Stream& 367 Stream::operator<< (int64_t sval) 368 { 369 Printf ("%" PRIi64, sval); 370 return *this; 371 } 372 373 //------------------------------------------------------------------ 374 // Get the current indentation level 375 //------------------------------------------------------------------ 376 int 377 Stream::GetIndentLevel() const 378 { 379 return m_indent_level; 380 } 381 382 //------------------------------------------------------------------ 383 // Set the current indentation level 384 //------------------------------------------------------------------ 385 void 386 Stream::SetIndentLevel(int indent_level) 387 { 388 m_indent_level = indent_level; 389 } 390 391 //------------------------------------------------------------------ 392 // Increment the current indentation level 393 //------------------------------------------------------------------ 394 void 395 Stream::IndentMore(int amount) 396 { 397 m_indent_level += amount; 398 } 399 400 //------------------------------------------------------------------ 401 // Decrement the current indentation level 402 //------------------------------------------------------------------ 403 void 404 Stream::IndentLess (int amount) 405 { 406 if (m_indent_level >= amount) 407 m_indent_level -= amount; 408 else 409 m_indent_level = 0; 410 } 411 412 //------------------------------------------------------------------ 413 // Get the address size in bytes 414 //------------------------------------------------------------------ 415 uint32_t 416 Stream::GetAddressByteSize() const 417 { 418 return m_addr_size; 419 } 420 421 //------------------------------------------------------------------ 422 // Set the address size in bytes 423 //------------------------------------------------------------------ 424 void 425 Stream::SetAddressByteSize(uint32_t addr_size) 426 { 427 m_addr_size = addr_size; 428 } 429 430 //------------------------------------------------------------------ 431 // Returns true if the verbose flag bit is set in this stream. 432 //------------------------------------------------------------------ 433 bool 434 Stream::GetVerbose() const 435 { 436 return m_flags.Test(eVerbose); 437 } 438 439 //------------------------------------------------------------------ 440 // Returns true if the debug flag bit is set in this stream. 441 //------------------------------------------------------------------ 442 bool 443 Stream::GetDebug() const 444 { 445 return m_flags.Test(eDebug); 446 } 447 448 //------------------------------------------------------------------ 449 // The flags get accessor 450 //------------------------------------------------------------------ 451 Flags& 452 Stream::GetFlags() 453 { 454 return m_flags; 455 } 456 457 //------------------------------------------------------------------ 458 // The flags const get accessor 459 //------------------------------------------------------------------ 460 const Flags& 461 Stream::GetFlags() const 462 { 463 return m_flags; 464 } 465 466 //------------------------------------------------------------------ 467 // The byte order get accessor 468 //------------------------------------------------------------------ 469 470 lldb::ByteOrder 471 Stream::GetByteOrder() const 472 { 473 return m_byte_order; 474 } 475 476 size_t 477 Stream::PrintfAsRawHex8 (const char *format, ...) 478 { 479 va_list args; 480 va_list args_copy; 481 va_start (args, format); 482 va_copy (args, args_copy); // Copy this so we 483 484 char str[1024]; 485 size_t bytes_written = 0; 486 // Try and format our string into a fixed buffer first and see if it fits 487 size_t length = ::vsnprintf (str, sizeof(str), format, args); 488 if (length < sizeof(str)) 489 { 490 // The formatted string fit into our stack based buffer, so we can just 491 // append that to our packet 492 for (size_t i=0; i<length; ++i) 493 bytes_written += _PutHex8 (str[i], false); 494 } 495 else 496 { 497 // Our stack buffer wasn't big enough to contain the entire formatted 498 // string, so lets let vasprintf create the string for us! 499 char *str_ptr = NULL; 500 length = ::vasprintf (&str_ptr, format, args_copy); 501 if (str_ptr) 502 { 503 for (size_t i=0; i<length; ++i) 504 bytes_written += _PutHex8 (str_ptr[i], false); 505 ::free (str_ptr); 506 } 507 } 508 va_end (args); 509 va_end (args_copy); 510 511 return bytes_written; 512 } 513 514 size_t 515 Stream::PutNHex8 (size_t n, uint8_t uvalue) 516 { 517 size_t bytes_written = 0; 518 for (size_t i=0; i<n; ++i) 519 bytes_written += _PutHex8 (uvalue, m_flags.Test(eAddPrefix)); 520 return bytes_written; 521 } 522 523 size_t 524 Stream::_PutHex8 (uint8_t uvalue, bool add_prefix) 525 { 526 size_t bytes_written = 0; 527 if (m_flags.Test(eBinary)) 528 { 529 bytes_written = Write (&uvalue, 1); 530 } 531 else 532 { 533 if (add_prefix) 534 PutCString("0x"); 535 536 static char g_hex_to_ascii_hex_char[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 537 char nibble_chars[2]; 538 nibble_chars[0] = g_hex_to_ascii_hex_char[(uvalue >> 4) & 0xf]; 539 nibble_chars[1] = g_hex_to_ascii_hex_char[(uvalue >> 0) & 0xf]; 540 bytes_written = Write (nibble_chars, sizeof(nibble_chars)); 541 } 542 return bytes_written; 543 } 544 545 size_t 546 Stream::PutHex8 (uint8_t uvalue) 547 { 548 return _PutHex8 (uvalue, m_flags.Test(eAddPrefix)); 549 } 550 551 size_t 552 Stream::PutHex16 (uint16_t uvalue, ByteOrder byte_order) 553 { 554 if (byte_order == eByteOrderInvalid) 555 byte_order = m_byte_order; 556 557 bool add_prefix = m_flags.Test(eAddPrefix); 558 size_t bytes_written = 0; 559 if (byte_order == eByteOrderLittle) 560 { 561 for (size_t byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false) 562 bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix); 563 } 564 else 565 { 566 for (size_t byte = sizeof(uvalue)-1; byte < sizeof(uvalue); --byte, add_prefix = false) 567 bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix); 568 } 569 return bytes_written; 570 } 571 572 size_t 573 Stream::PutHex32(uint32_t uvalue, ByteOrder byte_order) 574 { 575 if (byte_order == eByteOrderInvalid) 576 byte_order = m_byte_order; 577 578 bool add_prefix = m_flags.Test(eAddPrefix); 579 size_t bytes_written = 0; 580 if (byte_order == eByteOrderLittle) 581 { 582 for (size_t byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false) 583 bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix); 584 } 585 else 586 { 587 for (size_t byte = sizeof(uvalue)-1; byte < sizeof(uvalue); --byte, add_prefix = false) 588 bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix); 589 } 590 return bytes_written; 591 } 592 593 size_t 594 Stream::PutHex64(uint64_t uvalue, ByteOrder byte_order) 595 { 596 if (byte_order == eByteOrderInvalid) 597 byte_order = m_byte_order; 598 599 bool add_prefix = m_flags.Test(eAddPrefix); 600 size_t bytes_written = 0; 601 if (byte_order == eByteOrderLittle) 602 { 603 for (size_t byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false) 604 bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix); 605 } 606 else 607 { 608 for (size_t byte = sizeof(uvalue)-1; byte < sizeof(uvalue); --byte, add_prefix = false) 609 bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix); 610 } 611 return bytes_written; 612 } 613 614 size_t 615 Stream::PutMaxHex64 616 ( 617 uint64_t uvalue, 618 size_t byte_size, 619 lldb::ByteOrder byte_order 620 ) 621 { 622 switch (byte_size) 623 { 624 case 1: return PutHex8 ((uint8_t)uvalue); 625 case 2: return PutHex16 ((uint16_t)uvalue); 626 case 4: return PutHex32 ((uint32_t)uvalue); 627 case 8: return PutHex64 (uvalue); 628 } 629 return 0; 630 } 631 632 size_t 633 Stream::PutPointer (void *ptr) 634 { 635 return PutRawBytes (&ptr, sizeof(ptr), lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder()); 636 } 637 638 size_t 639 Stream::PutFloat(float f, ByteOrder byte_order) 640 { 641 if (byte_order == eByteOrderInvalid) 642 byte_order = m_byte_order; 643 644 return PutRawBytes (&f, sizeof(f), lldb::endian::InlHostByteOrder(), byte_order); 645 } 646 647 size_t 648 Stream::PutDouble(double d, ByteOrder byte_order) 649 { 650 if (byte_order == eByteOrderInvalid) 651 byte_order = m_byte_order; 652 653 return PutRawBytes (&d, sizeof(d), lldb::endian::InlHostByteOrder(), byte_order); 654 } 655 656 size_t 657 Stream::PutLongDouble(long double ld, ByteOrder byte_order) 658 { 659 if (byte_order == eByteOrderInvalid) 660 byte_order = m_byte_order; 661 662 return PutRawBytes (&ld, sizeof(ld), lldb::endian::InlHostByteOrder(), byte_order); 663 } 664 665 size_t 666 Stream::PutRawBytes (const void *s, size_t src_len, ByteOrder src_byte_order, ByteOrder dst_byte_order) 667 { 668 if (src_byte_order == eByteOrderInvalid) 669 src_byte_order = m_byte_order; 670 671 if (dst_byte_order == eByteOrderInvalid) 672 dst_byte_order = m_byte_order; 673 674 size_t bytes_written = 0; 675 const uint8_t *src = (const uint8_t *)s; 676 bool binary_was_set = m_flags.Test (eBinary); 677 if (!binary_was_set) 678 m_flags.Set (eBinary); 679 if (src_byte_order == dst_byte_order) 680 { 681 for (size_t i = 0; i < src_len; ++i) 682 bytes_written += _PutHex8 (src[i], false); 683 } 684 else 685 { 686 for (size_t i = src_len-1; i < src_len; --i) 687 bytes_written += _PutHex8 (src[i], false); 688 } 689 if (!binary_was_set) 690 m_flags.Clear (eBinary); 691 692 return bytes_written; 693 } 694 695 size_t 696 Stream::PutBytesAsRawHex8 (const void *s, size_t src_len, ByteOrder src_byte_order, ByteOrder dst_byte_order) 697 { 698 if (src_byte_order == eByteOrderInvalid) 699 src_byte_order = m_byte_order; 700 701 if (dst_byte_order == eByteOrderInvalid) 702 dst_byte_order = m_byte_order; 703 704 size_t bytes_written = 0; 705 const uint8_t *src = (const uint8_t *)s; 706 bool binary_is_set = m_flags.Test(eBinary); 707 m_flags.Clear(eBinary); 708 if (src_byte_order == dst_byte_order) 709 { 710 for (size_t i = 0; i < src_len; ++i) 711 bytes_written += _PutHex8 (src[i], false); 712 } 713 else 714 { 715 for (size_t i = src_len-1; i < src_len; --i) 716 bytes_written += _PutHex8 (src[i], false); 717 } 718 if (binary_is_set) 719 m_flags.Set(eBinary); 720 721 return bytes_written; 722 } 723 724 size_t 725 Stream::PutCStringAsRawHex8 (const char *s) 726 { 727 size_t bytes_written = 0; 728 bool binary_is_set = m_flags.Test(eBinary); 729 m_flags.Clear(eBinary); 730 do 731 { 732 bytes_written += _PutHex8 (*s, false); 733 ++s; 734 } while (*s); 735 if (binary_is_set) 736 m_flags.Set(eBinary); 737 return bytes_written; 738 } 739 740 void 741 Stream::UnitTest(Stream *s) 742 { 743 s->PutHex8(0x12); 744 745 s->PutChar(' '); 746 s->PutHex16(0x3456, lldb::endian::InlHostByteOrder()); 747 s->PutChar(' '); 748 s->PutHex16(0x3456, eByteOrderBig); 749 s->PutChar(' '); 750 s->PutHex16(0x3456, eByteOrderLittle); 751 752 s->PutChar(' '); 753 s->PutHex32(0x789abcde, lldb::endian::InlHostByteOrder()); 754 s->PutChar(' '); 755 s->PutHex32(0x789abcde, eByteOrderBig); 756 s->PutChar(' '); 757 s->PutHex32(0x789abcde, eByteOrderLittle); 758 759 s->PutChar(' '); 760 s->PutHex64(0x1122334455667788ull, lldb::endian::InlHostByteOrder()); 761 s->PutChar(' '); 762 s->PutHex64(0x1122334455667788ull, eByteOrderBig); 763 s->PutChar(' '); 764 s->PutHex64(0x1122334455667788ull, eByteOrderLittle); 765 766 const char *hola = "Hello World!!!"; 767 s->PutChar(' '); 768 s->PutCString (hola); 769 770 s->PutChar(' '); 771 s->Write (hola, 5); 772 773 s->PutChar(' '); 774 s->PutCStringAsRawHex8 (hola); 775 776 s->PutChar(' '); 777 s->PutCStringAsRawHex8 ("01234"); 778 779 s->PutChar(' '); 780 s->Printf ("pid=%i", 12733); 781 782 s->PutChar(' '); 783 s->PrintfAsRawHex8 ("pid=%i", 12733); 784 s->PutChar('\n'); 785 } 786 787