1 //===-- StringPrinter.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/DataFormatters/StringPrinter.h" 11 12 #include "lldb/Core/DataExtractor.h" 13 #include "lldb/Core/Debugger.h" 14 #include "lldb/Core/Error.h" 15 #include "lldb/Core/ValueObject.h" 16 #include "lldb/Target/Language.h" 17 #include "lldb/Target/Process.h" 18 #include "lldb/Target/Target.h" 19 20 #include "llvm/Support/ConvertUTF.h" 21 22 #include <ctype.h> 23 #include <locale> 24 25 using namespace lldb; 26 using namespace lldb_private; 27 using namespace lldb_private::formatters; 28 29 // we define this for all values of type but only implement it for those we care about 30 // that's good because we get linker errors for any unsupported type 31 template <lldb_private::formatters::StringPrinter::StringElementType type> 32 static StringPrinter::StringPrinterBufferPointer<> 33 GetPrintableImpl(uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next); 34 35 // mimic isprint() for Unicode codepoints 36 static bool 37 isprint(char32_t codepoint) 38 { 39 if (codepoint <= 0x1F || codepoint == 0x7F) // C0 40 { 41 return false; 42 } 43 if (codepoint >= 0x80 && codepoint <= 0x9F) // C1 44 { 45 return false; 46 } 47 if (codepoint == 0x2028 || codepoint == 0x2029) // line/paragraph separators 48 { 49 return false; 50 } 51 if (codepoint == 0x200E || codepoint == 0x200F || (codepoint >= 0x202A && codepoint <= 0x202E)) // bidirectional text control 52 { 53 return false; 54 } 55 if (codepoint >= 0xFFF9 && codepoint <= 0xFFFF) // interlinears and generally specials 56 { 57 return false; 58 } 59 return true; 60 } 61 62 template <> 63 StringPrinter::StringPrinterBufferPointer<> 64 GetPrintableImpl<StringPrinter::StringElementType::ASCII> (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) 65 { 66 StringPrinter::StringPrinterBufferPointer<> retval = {nullptr}; 67 68 switch (*buffer) 69 { 70 case 0: 71 retval = {"\\0",2}; 72 break; 73 case '\a': 74 retval = {"\\a",2}; 75 break; 76 case '\b': 77 retval = {"\\b",2}; 78 break; 79 case '\f': 80 retval = {"\\f",2}; 81 break; 82 case '\n': 83 retval = {"\\n",2}; 84 break; 85 case '\r': 86 retval = {"\\r",2}; 87 break; 88 case '\t': 89 retval = {"\\t",2}; 90 break; 91 case '\v': 92 retval = {"\\v",2}; 93 break; 94 case '\"': 95 retval = {"\\\"",2}; 96 break; 97 case '\\': 98 retval = {"\\\\",2}; 99 break; 100 default: 101 if (isprint(*buffer)) 102 retval = {buffer,1}; 103 else 104 { 105 uint8_t* data = new uint8_t[5]; 106 sprintf((char*)data,"\\x%02x",*buffer); 107 retval = {data, 4, [] (const uint8_t* c) {delete[] c;} }; 108 break; 109 } 110 } 111 112 next = buffer + 1; 113 return retval; 114 } 115 116 static char32_t 117 ConvertUTF8ToCodePoint (unsigned char c0, unsigned char c1) 118 { 119 return (c0-192)*64+(c1-128); 120 } 121 static char32_t 122 ConvertUTF8ToCodePoint (unsigned char c0, unsigned char c1, unsigned char c2) 123 { 124 return (c0-224)*4096+(c1-128)*64+(c2-128); 125 } 126 static char32_t 127 ConvertUTF8ToCodePoint (unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3) 128 { 129 return (c0-240)*262144+(c2-128)*4096+(c2-128)*64+(c3-128); 130 } 131 132 template <> 133 StringPrinter::StringPrinterBufferPointer<> 134 GetPrintableImpl<StringPrinter::StringElementType::UTF8> (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) 135 { 136 StringPrinter::StringPrinterBufferPointer<> retval {nullptr}; 137 138 unsigned utf8_encoded_len = getNumBytesForUTF8(*buffer); 139 140 if (1+buffer_end-buffer < utf8_encoded_len) 141 { 142 // I don't have enough bytes - print whatever I have left 143 retval = {buffer,static_cast<size_t>(1+buffer_end-buffer)}; 144 next = buffer_end+1; 145 return retval; 146 } 147 148 char32_t codepoint = 0; 149 switch (utf8_encoded_len) 150 { 151 case 1: 152 // this is just an ASCII byte - ask ASCII 153 return GetPrintableImpl<StringPrinter::StringElementType::ASCII>(buffer, buffer_end, next); 154 case 2: 155 codepoint = ConvertUTF8ToCodePoint((unsigned char)*buffer, (unsigned char)*(buffer+1)); 156 break; 157 case 3: 158 codepoint = ConvertUTF8ToCodePoint((unsigned char)*buffer, (unsigned char)*(buffer+1), (unsigned char)*(buffer+2)); 159 break; 160 case 4: 161 codepoint = ConvertUTF8ToCodePoint((unsigned char)*buffer, (unsigned char)*(buffer+1), (unsigned char)*(buffer+2), (unsigned char)*(buffer+3)); 162 break; 163 default: 164 // this is probably some bogus non-character thing 165 // just print it as-is and hope to sync up again soon 166 retval = {buffer,1}; 167 next = buffer+1; 168 return retval; 169 } 170 171 if (codepoint) 172 { 173 switch (codepoint) 174 { 175 case 0: 176 retval = {"\\0",2}; 177 break; 178 case '\a': 179 retval = {"\\a",2}; 180 break; 181 case '\b': 182 retval = {"\\b",2}; 183 break; 184 case '\f': 185 retval = {"\\f",2}; 186 break; 187 case '\n': 188 retval = {"\\n",2}; 189 break; 190 case '\r': 191 retval = {"\\r",2}; 192 break; 193 case '\t': 194 retval = {"\\t",2}; 195 break; 196 case '\v': 197 retval = {"\\v",2}; 198 break; 199 case '\"': 200 retval = {"\\\"",2}; 201 break; 202 case '\\': 203 retval = {"\\\\",2}; 204 break; 205 default: 206 if (isprint(codepoint)) 207 retval = {buffer,utf8_encoded_len}; 208 else 209 { 210 uint8_t* data = new uint8_t[11]; 211 sprintf((char*)data,"\\U%08x",codepoint); 212 retval = { data,10,[] (const uint8_t* c) {delete[] c;} }; 213 break; 214 } 215 } 216 217 next = buffer + utf8_encoded_len; 218 return retval; 219 } 220 221 // this should not happen - but just in case.. try to resync at some point 222 retval = {buffer,1}; 223 next = buffer+1; 224 return retval; 225 } 226 227 // Given a sequence of bytes, this function returns: 228 // a sequence of bytes to actually print out + a length 229 // the following unscanned position of the buffer is in next 230 static StringPrinter::StringPrinterBufferPointer<> 231 GetPrintable(StringPrinter::StringElementType type, uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) 232 { 233 if (!buffer) 234 return {nullptr}; 235 236 switch (type) 237 { 238 case StringPrinter::StringElementType::ASCII: 239 return GetPrintableImpl<StringPrinter::StringElementType::ASCII>(buffer, buffer_end, next); 240 case StringPrinter::StringElementType::UTF8: 241 return GetPrintableImpl<StringPrinter::StringElementType::UTF8>(buffer, buffer_end, next); 242 default: 243 return {nullptr}; 244 } 245 } 246 247 StringPrinter::EscapingHelper 248 StringPrinter::GetDefaultEscapingHelper (GetPrintableElementType elem_type) 249 { 250 switch (elem_type) 251 { 252 case GetPrintableElementType::UTF8: 253 return [] (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) -> StringPrinter::StringPrinterBufferPointer<> { 254 return GetPrintable(StringPrinter::StringElementType::UTF8, buffer, buffer_end, next); 255 }; 256 case GetPrintableElementType::ASCII: 257 return [] (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) -> StringPrinter::StringPrinterBufferPointer<> { 258 return GetPrintable(StringPrinter::StringElementType::ASCII, buffer, buffer_end, next); 259 }; 260 } 261 llvm_unreachable("bad element type"); 262 } 263 264 // use this call if you already have an LLDB-side buffer for the data 265 template<typename SourceDataType> 266 static bool 267 DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**, 268 const SourceDataType*, 269 UTF8**, 270 UTF8*, 271 ConversionFlags), 272 const StringPrinter::ReadBufferAndDumpToStreamOptions& dump_options) 273 { 274 Stream &stream(*dump_options.GetStream()); 275 if (dump_options.GetPrefixToken() != 0) 276 stream.Printf("%s",dump_options.GetPrefixToken()); 277 if (dump_options.GetQuote() != 0) 278 stream.Printf("%c",dump_options.GetQuote()); 279 auto data(dump_options.GetData()); 280 auto source_size(dump_options.GetSourceSize()); 281 if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd()) 282 { 283 const int bufferSPSize = data.GetByteSize(); 284 if (dump_options.GetSourceSize() == 0) 285 { 286 const int origin_encoding = 8*sizeof(SourceDataType); 287 source_size = bufferSPSize/(origin_encoding / 4); 288 } 289 290 const SourceDataType *data_ptr = (const SourceDataType*)data.GetDataStart(); 291 const SourceDataType *data_end_ptr = data_ptr + source_size; 292 293 const bool zero_is_terminator = dump_options.GetBinaryZeroIsTerminator(); 294 295 if (zero_is_terminator) 296 { 297 while (data_ptr < data_end_ptr) 298 { 299 if (!*data_ptr) 300 { 301 data_end_ptr = data_ptr; 302 break; 303 } 304 data_ptr++; 305 } 306 307 data_ptr = (const SourceDataType*)data.GetDataStart(); 308 } 309 310 lldb::DataBufferSP utf8_data_buffer_sp; 311 UTF8* utf8_data_ptr = nullptr; 312 UTF8* utf8_data_end_ptr = nullptr; 313 314 if (ConvertFunction) 315 { 316 utf8_data_buffer_sp.reset(new DataBufferHeap(4*bufferSPSize,0)); 317 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); 318 utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize(); 319 ConvertFunction ( &data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion ); 320 if (false == zero_is_terminator) 321 utf8_data_end_ptr = utf8_data_ptr; 322 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr 323 } 324 else 325 { 326 // just copy the pointers - the cast is necessary to make the compiler happy 327 // but this should only happen if we are reading UTF8 data 328 utf8_data_ptr = const_cast<UTF8 *>(reinterpret_cast<const UTF8*>(data_ptr)); 329 utf8_data_end_ptr = const_cast<UTF8 *>(reinterpret_cast<const UTF8*>(data_end_ptr)); 330 } 331 332 const bool escape_non_printables = dump_options.GetEscapeNonPrintables(); 333 lldb_private::formatters::StringPrinter::EscapingHelper escaping_callback; 334 if (escape_non_printables) 335 { 336 if (Language *language = Language::FindPlugin(dump_options.GetLanguage())) 337 escaping_callback = language->GetStringPrinterEscapingHelper(lldb_private::formatters::StringPrinter::GetPrintableElementType::UTF8); 338 else 339 escaping_callback = lldb_private::formatters::StringPrinter::GetDefaultEscapingHelper(lldb_private::formatters::StringPrinter::GetPrintableElementType::UTF8); 340 } 341 342 // since we tend to accept partial data (and even partially malformed data) 343 // we might end up with no NULL terminator before the end_ptr 344 // hence we need to take a slower route and ensure we stay within boundaries 345 for (;utf8_data_ptr < utf8_data_end_ptr;) 346 { 347 if (zero_is_terminator && !*utf8_data_ptr) 348 break; 349 350 if (escape_non_printables) 351 { 352 uint8_t* next_data = nullptr; 353 auto printable = escaping_callback(utf8_data_ptr, utf8_data_end_ptr, next_data); 354 auto printable_bytes = printable.GetBytes(); 355 auto printable_size = printable.GetSize(); 356 if (!printable_bytes || !next_data) 357 { 358 // GetPrintable() failed on us - print one byte in a desperate resync attempt 359 printable_bytes = utf8_data_ptr; 360 printable_size = 1; 361 next_data = utf8_data_ptr+1; 362 } 363 for (unsigned c = 0; c < printable_size; c++) 364 stream.Printf("%c", *(printable_bytes+c)); 365 utf8_data_ptr = (uint8_t*)next_data; 366 } 367 else 368 { 369 stream.Printf("%c",*utf8_data_ptr); 370 utf8_data_ptr++; 371 } 372 } 373 } 374 if (dump_options.GetQuote() != 0) 375 stream.Printf("%c",dump_options.GetQuote()); 376 if (dump_options.GetSuffixToken() != 0) 377 stream.Printf("%s",dump_options.GetSuffixToken()); 378 return true; 379 } 380 381 lldb_private::formatters::StringPrinter::ReadStringAndDumpToStreamOptions::ReadStringAndDumpToStreamOptions (ValueObject& valobj) : 382 ReadStringAndDumpToStreamOptions() 383 { 384 SetEscapeNonPrintables(valobj.GetTargetSP()->GetDebugger().GetEscapeNonPrintables()); 385 } 386 387 lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStreamOptions::ReadBufferAndDumpToStreamOptions (ValueObject& valobj) : 388 ReadBufferAndDumpToStreamOptions() 389 { 390 SetEscapeNonPrintables(valobj.GetTargetSP()->GetDebugger().GetEscapeNonPrintables()); 391 } 392 393 lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStreamOptions::ReadBufferAndDumpToStreamOptions (const ReadStringAndDumpToStreamOptions& options) : 394 ReadBufferAndDumpToStreamOptions() 395 { 396 SetStream(options.GetStream()); 397 SetPrefixToken(options.GetPrefixToken()); 398 SetSuffixToken(options.GetSuffixToken()); 399 SetQuote(options.GetQuote()); 400 SetEscapeNonPrintables(options.GetEscapeNonPrintables()); 401 SetBinaryZeroIsTerminator(options.GetBinaryZeroIsTerminator()); 402 SetLanguage(options.GetLanguage()); 403 } 404 405 406 namespace lldb_private 407 { 408 409 namespace formatters 410 { 411 412 template <> 413 bool 414 StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII> (const ReadStringAndDumpToStreamOptions& options) 415 { 416 assert(options.GetStream() && "need a Stream to print the string to"); 417 Error my_error; 418 419 ProcessSP process_sp(options.GetProcessSP()); 420 421 if (process_sp.get() == nullptr || options.GetLocation() == 0) 422 return false; 423 424 size_t size; 425 426 if (options.GetSourceSize() == 0) 427 size = process_sp->GetTarget().GetMaximumSizeOfStringSummary(); 428 else if (!options.GetIgnoreMaxLength()) 429 size = std::min(options.GetSourceSize(),process_sp->GetTarget().GetMaximumSizeOfStringSummary()); 430 else 431 size = options.GetSourceSize(); 432 433 lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0)); 434 435 process_sp->ReadCStringFromMemory(options.GetLocation(), (char*)buffer_sp->GetBytes(), size, my_error); 436 437 if (my_error.Fail()) 438 return false; 439 440 const char* prefix_token = options.GetPrefixToken(); 441 char quote = options.GetQuote(); 442 443 if (prefix_token != 0) 444 options.GetStream()->Printf("%s%c",prefix_token,quote); 445 else if (quote != 0) 446 options.GetStream()->Printf("%c",quote); 447 448 uint8_t* data_end = buffer_sp->GetBytes()+buffer_sp->GetByteSize(); 449 450 const bool escape_non_printables = options.GetEscapeNonPrintables(); 451 lldb_private::formatters::StringPrinter::EscapingHelper escaping_callback; 452 if (escape_non_printables) 453 { 454 if (Language *language = Language::FindPlugin(options.GetLanguage())) 455 escaping_callback = language->GetStringPrinterEscapingHelper(lldb_private::formatters::StringPrinter::GetPrintableElementType::ASCII); 456 else 457 escaping_callback = lldb_private::formatters::StringPrinter::GetDefaultEscapingHelper(lldb_private::formatters::StringPrinter::GetPrintableElementType::ASCII); 458 } 459 460 // since we tend to accept partial data (and even partially malformed data) 461 // we might end up with no NULL terminator before the end_ptr 462 // hence we need to take a slower route and ensure we stay within boundaries 463 for (uint8_t* data = buffer_sp->GetBytes(); *data && (data < data_end);) 464 { 465 if (escape_non_printables) 466 { 467 uint8_t* next_data = nullptr; 468 auto printable = escaping_callback(data, data_end, next_data); 469 auto printable_bytes = printable.GetBytes(); 470 auto printable_size = printable.GetSize(); 471 if (!printable_bytes || !next_data) 472 { 473 // GetPrintable() failed on us - print one byte in a desperate resync attempt 474 printable_bytes = data; 475 printable_size = 1; 476 next_data = data+1; 477 } 478 for (unsigned c = 0; c < printable_size; c++) 479 options.GetStream()->Printf("%c", *(printable_bytes+c)); 480 data = (uint8_t*)next_data; 481 } 482 else 483 { 484 options.GetStream()->Printf("%c",*data); 485 data++; 486 } 487 } 488 489 const char* suffix_token = options.GetSuffixToken(); 490 491 if (suffix_token != 0) 492 options.GetStream()->Printf("%c%s",quote, suffix_token); 493 else if (quote != 0) 494 options.GetStream()->Printf("%c",quote); 495 496 return true; 497 } 498 499 template<typename SourceDataType> 500 static bool 501 ReadUTFBufferAndDumpToStream (const StringPrinter::ReadStringAndDumpToStreamOptions& options, 502 ConversionResult (*ConvertFunction) (const SourceDataType**, 503 const SourceDataType*, 504 UTF8**, 505 UTF8*, 506 ConversionFlags)) 507 { 508 assert(options.GetStream() && "need a Stream to print the string to"); 509 510 if (options.GetLocation() == 0 || options.GetLocation() == LLDB_INVALID_ADDRESS) 511 return false; 512 513 lldb::ProcessSP process_sp(options.GetProcessSP()); 514 515 if (!process_sp) 516 return false; 517 518 const int type_width = sizeof(SourceDataType); 519 const int origin_encoding = 8 * type_width ; 520 if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32) 521 return false; 522 // if not UTF8, I need a conversion function to return proper UTF8 523 if (origin_encoding != 8 && !ConvertFunction) 524 return false; 525 526 if (!options.GetStream()) 527 return false; 528 529 uint32_t sourceSize = options.GetSourceSize(); 530 bool needs_zero_terminator = options.GetNeedsZeroTermination(); 531 532 if (!sourceSize) 533 { 534 sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary(); 535 needs_zero_terminator = true; 536 } 537 else if (!options.GetIgnoreMaxLength()) 538 sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary()); 539 540 const int bufferSPSize = sourceSize * type_width; 541 542 lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0)); 543 544 if (!buffer_sp->GetBytes()) 545 return false; 546 547 Error error; 548 char *buffer = reinterpret_cast<char *>(buffer_sp->GetBytes()); 549 550 if (needs_zero_terminator) 551 process_sp->ReadStringFromMemory(options.GetLocation(), buffer, bufferSPSize, error, type_width); 552 else 553 process_sp->ReadMemoryFromInferior(options.GetLocation(), (char*)buffer_sp->GetBytes(), bufferSPSize, error); 554 555 if (error.Fail()) 556 { 557 options.GetStream()->Printf("unable to read data"); 558 return true; 559 } 560 561 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); 562 563 StringPrinter::ReadBufferAndDumpToStreamOptions dump_options(options); 564 dump_options.SetData(data); 565 dump_options.SetSourceSize(sourceSize); 566 567 return DumpUTFBufferToStream(ConvertFunction, dump_options); 568 } 569 570 template <> 571 bool 572 StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8> (const ReadStringAndDumpToStreamOptions& options) 573 { 574 return ReadUTFBufferAndDumpToStream<UTF8>(options, 575 nullptr); 576 } 577 578 template <> 579 bool 580 StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16> (const ReadStringAndDumpToStreamOptions& options) 581 { 582 return ReadUTFBufferAndDumpToStream<UTF16>(options, 583 ConvertUTF16toUTF8); 584 } 585 586 template <> 587 bool 588 StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF32> (const ReadStringAndDumpToStreamOptions& options) 589 { 590 return ReadUTFBufferAndDumpToStream<UTF32>(options, 591 ConvertUTF32toUTF8); 592 } 593 594 template <> 595 bool 596 StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF8> (const ReadBufferAndDumpToStreamOptions& options) 597 { 598 assert(options.GetStream() && "need a Stream to print the string to"); 599 600 return DumpUTFBufferToStream<UTF8>(nullptr, options); 601 } 602 603 template <> 604 bool 605 StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::ASCII> (const ReadBufferAndDumpToStreamOptions& options) 606 { 607 // treat ASCII the same as UTF8 608 // FIXME: can we optimize ASCII some more? 609 return ReadBufferAndDumpToStream<StringElementType::UTF8>(options); 610 } 611 612 template <> 613 bool 614 StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF16> (const ReadBufferAndDumpToStreamOptions& options) 615 { 616 assert(options.GetStream() && "need a Stream to print the string to"); 617 618 return DumpUTFBufferToStream(ConvertUTF16toUTF8, options); 619 } 620 621 template <> 622 bool 623 StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF32> (const ReadBufferAndDumpToStreamOptions& options) 624 { 625 assert(options.GetStream() && "need a Stream to print the string to"); 626 627 return DumpUTFBufferToStream(ConvertUTF32toUTF8, options); 628 } 629 630 } // namespace formatters 631 632 } // namespace lldb_private 633