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