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 19using namespace lldb; 20using namespace lldb_private; 21 22Stream::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 30Stream::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//------------------------------------------------------------------ 41Stream::~Stream () 42{ 43} 44 45ByteOrder 46Stream::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//------------------------------------------------------------------ 57void 58Stream::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//------------------------------------------------------------------ 67size_t 68Stream::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//------------------------------------------------------------------ 101size_t 102Stream::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//------------------------------------------------------------------ 130size_t 131Stream::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//------------------------------------------------------------------ 144void 145Stream::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//------------------------------------------------------------------ 154void 155Stream::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//------------------------------------------------------------------ 170void 171Stream::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 182size_t 183Stream::PutChar (char ch) 184{ 185 return Write (&ch, 1); 186} 187 188 189//------------------------------------------------------------------ 190// Print some formatted output to the stream. 191//------------------------------------------------------------------ 192size_t 193Stream::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//------------------------------------------------------------------ 205size_t 206Stream::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//------------------------------------------------------------------ 247size_t 248Stream::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//------------------------------------------------------------------ 257size_t 258Stream::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//------------------------------------------------------------------ 266Stream& 267Stream::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//------------------------------------------------------------------ 276Stream& 277Stream::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//------------------------------------------------------------------ 286Stream& 287Stream::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//------------------------------------------------------------------ 296Stream& 297Stream::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//------------------------------------------------------------------ 306Stream& 307Stream::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//------------------------------------------------------------------ 316Stream& 317Stream::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//------------------------------------------------------------------ 326Stream& 327Stream::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//------------------------------------------------------------------ 336Stream& 337Stream::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//------------------------------------------------------------------ 346Stream& 347Stream::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//------------------------------------------------------------------ 356Stream& 357Stream::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//------------------------------------------------------------------ 366Stream& 367Stream::operator<< (int64_t sval) 368{ 369 Printf ("%" PRIi64, sval); 370 return *this; 371} 372 373//------------------------------------------------------------------ 374// Get the current indentation level 375//------------------------------------------------------------------ 376int 377Stream::GetIndentLevel() const 378{ 379 return m_indent_level; 380} 381 382//------------------------------------------------------------------ 383// Set the current indentation level 384//------------------------------------------------------------------ 385void 386Stream::SetIndentLevel(int indent_level) 387{ 388 m_indent_level = indent_level; 389} 390 391//------------------------------------------------------------------ 392// Increment the current indentation level 393//------------------------------------------------------------------ 394void 395Stream::IndentMore(int amount) 396{ 397 m_indent_level += amount; 398} 399 400//------------------------------------------------------------------ 401// Decrement the current indentation level 402//------------------------------------------------------------------ 403void 404Stream::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//------------------------------------------------------------------ 415uint32_t 416Stream::GetAddressByteSize() const 417{ 418 return m_addr_size; 419} 420 421//------------------------------------------------------------------ 422// Set the address size in bytes 423//------------------------------------------------------------------ 424void 425Stream::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//------------------------------------------------------------------ 433bool 434Stream::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//------------------------------------------------------------------ 442bool 443Stream::GetDebug() const 444{ 445 return m_flags.Test(eDebug); 446} 447 448//------------------------------------------------------------------ 449// The flags get accessor 450//------------------------------------------------------------------ 451Flags& 452Stream::GetFlags() 453{ 454 return m_flags; 455} 456 457//------------------------------------------------------------------ 458// The flags const get accessor 459//------------------------------------------------------------------ 460const Flags& 461Stream::GetFlags() const 462{ 463 return m_flags; 464} 465 466//------------------------------------------------------------------ 467// The byte order get accessor 468//------------------------------------------------------------------ 469 470lldb::ByteOrder 471Stream::GetByteOrder() const 472{ 473 return m_byte_order; 474} 475 476size_t 477Stream::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 514size_t 515Stream::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 523size_t 524Stream::_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 545size_t 546Stream::PutHex8 (uint8_t uvalue) 547{ 548 return _PutHex8 (uvalue, m_flags.Test(eAddPrefix)); 549} 550 551size_t 552Stream::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 572size_t 573Stream::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 593size_t 594Stream::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 614size_t 615Stream::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 632size_t 633Stream::PutPointer (void *ptr) 634{ 635 return PutRawBytes (&ptr, sizeof(ptr), lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder()); 636} 637 638size_t 639Stream::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 647size_t 648Stream::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 656size_t 657Stream::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 665size_t 666Stream::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 695size_t 696Stream::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 724size_t 725Stream::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 740void 741Stream::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