lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStreamOptions::ReadBufferAndDumpToStreamOptions (const ReadStringAndDumpToStreamOptions& options) : ReadBufferAndDumpToStreamOptions() { SetStream(options.GetStream()); SetPrefixToken(options.GetPrefixToken()); SetSuffixToken(options.GetSuffixToken()); SetQuote(options.GetQuote()); SetEscapeNonPrintables(options.GetEscapeNonPrintables()); SetBinaryZeroIsTerminator(options.GetBinaryZeroIsTerminator()); SetLanguage(options.GetLanguage()); }
static bool ReadUTFBufferAndDumpToStream (const ReadStringAndDumpToStreamOptions& options, ConversionResult (*ConvertFunction) (const SourceDataType**, const SourceDataType*, UTF8**, UTF8*, ConversionFlags)) { assert(options.GetStream() && "need a Stream to print the string to"); if (options.GetLocation() == 0 || options.GetLocation() == LLDB_INVALID_ADDRESS) return false; lldb::ProcessSP process_sp(options.GetProcessSP()); if (!process_sp) return false; const int type_width = sizeof(SourceDataType); const int origin_encoding = 8 * type_width ; if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32) return false; // if not UTF8, I need a conversion function to return proper UTF8 if (origin_encoding != 8 && !ConvertFunction) return false; if (!options.GetStream()) return false; uint32_t sourceSize = options.GetSourceSize(); bool needs_zero_terminator = options.GetNeedsZeroTermination(); if (!sourceSize) { sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary(); needs_zero_terminator = true; } else if (!options.GetIgnoreMaxLength()) sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary()); const int bufferSPSize = sourceSize * type_width; lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0)); if (!buffer_sp->GetBytes()) return false; Error error; char *buffer = reinterpret_cast<char *>(buffer_sp->GetBytes()); if (needs_zero_terminator) process_sp->ReadStringFromMemory(options.GetLocation(), buffer, bufferSPSize, error, type_width); else process_sp->ReadMemoryFromInferior(options.GetLocation(), (char*)buffer_sp->GetBytes(), bufferSPSize, error); if (error.Fail()) { options.GetStream()->Printf("unable to read data"); return true; } DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); return DumpUTFBufferToStream(ConvertFunction, data, *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), sourceSize, options.GetEscapeNonPrintables()); }
bool ReadStringAndDumpToStream<StringElementType::ASCII> (ReadStringAndDumpToStreamOptions options) { assert(options.GetStream() && "need a Stream to print the string to"); Error my_error; ProcessSP process_sp(options.GetProcessSP()); if (process_sp.get() == nullptr || options.GetLocation() == 0) return false; size_t size; if (options.GetSourceSize() == 0) size = process_sp->GetTarget().GetMaximumSizeOfStringSummary(); else if (!options.GetIgnoreMaxLength()) size = std::min(options.GetSourceSize(),process_sp->GetTarget().GetMaximumSizeOfStringSummary()); else size = options.GetSourceSize(); lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0)); process_sp->ReadCStringFromMemory(options.GetLocation(), (char*)buffer_sp->GetBytes(), size, my_error); if (my_error.Fail()) return false; char prefix_token = options.GetPrefixToken(); char quote = options.GetQuote(); if (prefix_token != 0) options.GetStream()->Printf("%c%c",prefix_token,quote); else if (quote != 0) options.GetStream()->Printf("%c",quote); uint8_t* data_end = buffer_sp->GetBytes()+buffer_sp->GetByteSize(); // since we tend to accept partial data (and even partially malformed data) // we might end up with no NULL terminator before the end_ptr // hence we need to take a slower route and ensure we stay within boundaries for (uint8_t* data = buffer_sp->GetBytes(); *data && (data < data_end);) { if (options.GetEscapeNonPrintables()) { uint8_t* next_data = nullptr; auto printable = GetPrintable(StringElementType::ASCII, data, data_end, next_data); auto printable_bytes = printable.GetBytes(); auto printable_size = printable.GetSize(); if (!printable_bytes || !next_data) { // GetPrintable() failed on us - print one byte in a desperate resync attempt printable_bytes = data; printable_size = 1; next_data = data+1; } for (unsigned c = 0; c < printable_size; c++) options.GetStream()->Printf("%c", *(printable_bytes+c)); data = (uint8_t*)next_data; } else { options.GetStream()->Printf("%c",*data); data++; } } if (quote != 0) options.GetStream()->Printf("%c",quote); return true; }
bool StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII> (const ReadStringAndDumpToStreamOptions& options) { assert(options.GetStream() && "need a Stream to print the string to"); Error my_error; ProcessSP process_sp(options.GetProcessSP()); if (process_sp.get() == nullptr || options.GetLocation() == 0) return false; size_t size; const auto max_size = process_sp->GetTarget().GetMaximumSizeOfStringSummary(); bool is_truncated = false; if (options.GetSourceSize() == 0) size = max_size; else if (!options.GetIgnoreMaxLength()) { size = options.GetSourceSize(); if (size > max_size) { size = max_size; is_truncated = true; } } else size = options.GetSourceSize(); lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0)); process_sp->ReadCStringFromMemory(options.GetLocation(), (char*)buffer_sp->GetBytes(), size, my_error); if (my_error.Fail()) return false; const char* prefix_token = options.GetPrefixToken(); char quote = options.GetQuote(); if (prefix_token != 0) options.GetStream()->Printf("%s%c",prefix_token,quote); else if (quote != 0) options.GetStream()->Printf("%c",quote); uint8_t* data_end = buffer_sp->GetBytes()+buffer_sp->GetByteSize(); const bool escape_non_printables = options.GetEscapeNonPrintables(); lldb_private::formatters::StringPrinter::EscapingHelper escaping_callback; if (escape_non_printables) { if (Language *language = Language::FindPlugin(options.GetLanguage())) escaping_callback = language->GetStringPrinterEscapingHelper(lldb_private::formatters::StringPrinter::GetPrintableElementType::ASCII); else escaping_callback = lldb_private::formatters::StringPrinter::GetDefaultEscapingHelper(lldb_private::formatters::StringPrinter::GetPrintableElementType::ASCII); } // since we tend to accept partial data (and even partially malformed data) // we might end up with no NULL terminator before the end_ptr // hence we need to take a slower route and ensure we stay within boundaries for (uint8_t* data = buffer_sp->GetBytes(); *data && (data < data_end);) { if (escape_non_printables) { uint8_t* next_data = nullptr; auto printable = escaping_callback(data, data_end, next_data); auto printable_bytes = printable.GetBytes(); auto printable_size = printable.GetSize(); if (!printable_bytes || !next_data) { // GetPrintable() failed on us - print one byte in a desperate resync attempt printable_bytes = data; printable_size = 1; next_data = data+1; } for (unsigned c = 0; c < printable_size; c++) options.GetStream()->Printf("%c", *(printable_bytes+c)); data = (uint8_t*)next_data; } else { options.GetStream()->Printf("%c",*data); data++; } } const char* suffix_token = options.GetSuffixToken(); if (suffix_token != 0) options.GetStream()->Printf("%c%s",quote, suffix_token); else if (quote != 0) options.GetStream()->Printf("%c",quote); if (is_truncated) options.GetStream()->Printf("..."); return true; }