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