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