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