1254721Semaste//===-- CXXFormatterFunctions.cpp---------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/lldb-python.h" 11254721Semaste 12254721Semaste#include "lldb/DataFormatters/CXXFormatterFunctions.h" 13254721Semaste 14254721Semaste#include "llvm/Support/ConvertUTF.h" 15254721Semaste 16254721Semaste#include "lldb/Core/DataBufferHeap.h" 17254721Semaste#include "lldb/Core/Error.h" 18254721Semaste#include "lldb/Core/Stream.h" 19254721Semaste#include "lldb/Core/ValueObject.h" 20254721Semaste#include "lldb/Core/ValueObjectConstResult.h" 21254721Semaste#include "lldb/Host/Endian.h" 22254721Semaste#include "lldb/Symbol/ClangASTContext.h" 23254721Semaste#include "lldb/Target/ObjCLanguageRuntime.h" 24254721Semaste#include "lldb/Target/Target.h" 25254721Semaste 26254721Semaste#include <algorithm> 27254721Semaste 28254721Semasteusing namespace lldb; 29254721Semasteusing namespace lldb_private; 30254721Semasteusing namespace lldb_private::formatters; 31254721Semaste 32254721Semastebool 33254721Semastelldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj, 34254721Semaste const char* target_type, 35254721Semaste const char* selector, 36254721Semaste uint64_t &value) 37254721Semaste{ 38254721Semaste if (!target_type || !*target_type) 39254721Semaste return false; 40254721Semaste if (!selector || !*selector) 41254721Semaste return false; 42254721Semaste StreamString expr; 43254721Semaste expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector); 44254721Semaste ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); 45254721Semaste lldb::ValueObjectSP result_sp; 46254721Semaste Target* target = exe_ctx.GetTargetPtr(); 47254721Semaste StackFrame* stack_frame = exe_ctx.GetFramePtr(); 48254721Semaste if (!target || !stack_frame) 49254721Semaste return false; 50254721Semaste 51254721Semaste EvaluateExpressionOptions options; 52263367Semaste options.SetCoerceToId(false); 53263367Semaste options.SetUnwindOnError(true); 54263367Semaste options.SetKeepInMemory(true); 55254721Semaste 56254721Semaste target->EvaluateExpression(expr.GetData(), 57254721Semaste stack_frame, 58254721Semaste result_sp, 59254721Semaste options); 60254721Semaste if (!result_sp) 61254721Semaste return false; 62254721Semaste value = result_sp->GetValueAsUnsigned(0); 63254721Semaste return true; 64254721Semaste} 65254721Semaste 66254721Semastebool 67254721Semastelldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj, 68254721Semaste const char* target_type, 69254721Semaste const char* selector, 70254721Semaste Stream &stream) 71254721Semaste{ 72254721Semaste if (!target_type || !*target_type) 73254721Semaste return false; 74254721Semaste if (!selector || !*selector) 75254721Semaste return false; 76254721Semaste StreamString expr; 77254721Semaste expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector); 78254721Semaste ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); 79254721Semaste lldb::ValueObjectSP result_sp; 80254721Semaste Target* target = exe_ctx.GetTargetPtr(); 81254721Semaste StackFrame* stack_frame = exe_ctx.GetFramePtr(); 82254721Semaste if (!target || !stack_frame) 83254721Semaste return false; 84254721Semaste 85254721Semaste EvaluateExpressionOptions options; 86263367Semaste options.SetCoerceToId(false); 87263367Semaste options.SetUnwindOnError(true); 88263367Semaste options.SetKeepInMemory(true); 89263367Semaste options.SetUseDynamic(lldb::eDynamicCanRunTarget); 90254721Semaste 91254721Semaste target->EvaluateExpression(expr.GetData(), 92254721Semaste stack_frame, 93254721Semaste result_sp, 94254721Semaste options); 95254721Semaste if (!result_sp) 96254721Semaste return false; 97254721Semaste stream.Printf("%s",result_sp->GetSummaryAsCString()); 98254721Semaste return true; 99254721Semaste} 100254721Semaste 101254721Semastelldb::ValueObjectSP 102254721Semastelldb_private::formatters::CallSelectorOnObject (ValueObject &valobj, 103254721Semaste const char* return_type, 104254721Semaste const char* selector, 105254721Semaste uint64_t index) 106254721Semaste{ 107254721Semaste lldb::ValueObjectSP valobj_sp; 108254721Semaste if (!return_type || !*return_type) 109254721Semaste return valobj_sp; 110254721Semaste if (!selector || !*selector) 111254721Semaste return valobj_sp; 112254721Semaste StreamString expr_path_stream; 113254721Semaste valobj.GetExpressionPath(expr_path_stream, false); 114254721Semaste StreamString expr; 115254721Semaste expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index); 116254721Semaste ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); 117254721Semaste lldb::ValueObjectSP result_sp; 118254721Semaste Target* target = exe_ctx.GetTargetPtr(); 119254721Semaste StackFrame* stack_frame = exe_ctx.GetFramePtr(); 120254721Semaste if (!target || !stack_frame) 121254721Semaste return valobj_sp; 122254721Semaste 123254721Semaste EvaluateExpressionOptions options; 124263367Semaste options.SetCoerceToId(false); 125263367Semaste options.SetUnwindOnError(true); 126263367Semaste options.SetKeepInMemory(true); 127263367Semaste options.SetUseDynamic(lldb::eDynamicCanRunTarget); 128254721Semaste 129254721Semaste target->EvaluateExpression(expr.GetData(), 130254721Semaste stack_frame, 131254721Semaste valobj_sp, 132254721Semaste options); 133254721Semaste return valobj_sp; 134254721Semaste} 135254721Semaste 136254721Semastelldb::ValueObjectSP 137254721Semastelldb_private::formatters::CallSelectorOnObject (ValueObject &valobj, 138254721Semaste const char* return_type, 139254721Semaste const char* selector, 140254721Semaste const char* key) 141254721Semaste{ 142254721Semaste lldb::ValueObjectSP valobj_sp; 143254721Semaste if (!return_type || !*return_type) 144254721Semaste return valobj_sp; 145254721Semaste if (!selector || !*selector) 146254721Semaste return valobj_sp; 147254721Semaste if (!key || !*key) 148254721Semaste return valobj_sp; 149254721Semaste StreamString expr_path_stream; 150254721Semaste valobj.GetExpressionPath(expr_path_stream, false); 151254721Semaste StreamString expr; 152254721Semaste expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key); 153254721Semaste ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); 154254721Semaste lldb::ValueObjectSP result_sp; 155254721Semaste Target* target = exe_ctx.GetTargetPtr(); 156254721Semaste StackFrame* stack_frame = exe_ctx.GetFramePtr(); 157254721Semaste if (!target || !stack_frame) 158254721Semaste return valobj_sp; 159254721Semaste 160254721Semaste EvaluateExpressionOptions options; 161263367Semaste options.SetCoerceToId(false); 162263367Semaste options.SetUnwindOnError(true); 163263367Semaste options.SetKeepInMemory(true); 164263367Semaste options.SetUseDynamic(lldb::eDynamicCanRunTarget); 165254721Semaste 166254721Semaste target->EvaluateExpression(expr.GetData(), 167254721Semaste stack_frame, 168254721Semaste valobj_sp, 169254721Semaste options); 170254721Semaste return valobj_sp; 171254721Semaste} 172254721Semaste 173254721Semaste// use this call if you already have an LLDB-side buffer for the data 174254721Semastetemplate<typename SourceDataType> 175254721Semastestatic bool 176254721SemasteDumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**, 177254721Semaste const SourceDataType*, 178254721Semaste UTF8**, 179254721Semaste UTF8*, 180254721Semaste ConversionFlags), 181254721Semaste DataExtractor& data, 182254721Semaste Stream& stream, 183254721Semaste char prefix_token = '@', 184254721Semaste char quote = '"', 185254721Semaste uint32_t sourceSize = 0) 186254721Semaste{ 187254721Semaste if (prefix_token != 0) 188254721Semaste stream.Printf("%c",prefix_token); 189254721Semaste if (quote != 0) 190254721Semaste stream.Printf("%c",quote); 191254721Semaste if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd()) 192254721Semaste { 193254721Semaste const int bufferSPSize = data.GetByteSize(); 194254721Semaste if (sourceSize == 0) 195254721Semaste { 196254721Semaste const int origin_encoding = 8*sizeof(SourceDataType); 197254721Semaste sourceSize = bufferSPSize/(origin_encoding / 4); 198254721Semaste } 199254721Semaste 200254721Semaste SourceDataType *data_ptr = (SourceDataType*)data.GetDataStart(); 201254721Semaste SourceDataType *data_end_ptr = data_ptr + sourceSize; 202254721Semaste 203254721Semaste while (data_ptr < data_end_ptr) 204254721Semaste { 205254721Semaste if (!*data_ptr) 206254721Semaste { 207254721Semaste data_end_ptr = data_ptr; 208254721Semaste break; 209254721Semaste } 210254721Semaste data_ptr++; 211254721Semaste } 212254721Semaste 213254721Semaste data_ptr = (SourceDataType*)data.GetDataStart(); 214254721Semaste 215254721Semaste lldb::DataBufferSP utf8_data_buffer_sp; 216254721Semaste UTF8* utf8_data_ptr = nullptr; 217254721Semaste UTF8* utf8_data_end_ptr = nullptr; 218254721Semaste 219254721Semaste if (ConvertFunction) 220254721Semaste { 221254721Semaste utf8_data_buffer_sp.reset(new DataBufferHeap(4*bufferSPSize,0)); 222254721Semaste utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); 223254721Semaste utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize(); 224254721Semaste ConvertFunction ( (const SourceDataType**)&data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion ); 225254721Semaste utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr 226254721Semaste } 227254721Semaste else 228254721Semaste { 229254721Semaste // just copy the pointers - the cast is necessary to make the compiler happy 230254721Semaste // but this should only happen if we are reading UTF8 data 231254721Semaste utf8_data_ptr = (UTF8*)data_ptr; 232254721Semaste utf8_data_end_ptr = (UTF8*)data_end_ptr; 233254721Semaste } 234254721Semaste 235254721Semaste // since we tend to accept partial data (and even partially malformed data) 236254721Semaste // we might end up with no NULL terminator before the end_ptr 237254721Semaste // hence we need to take a slower route and ensure we stay within boundaries 238254721Semaste for (;utf8_data_ptr != utf8_data_end_ptr; utf8_data_ptr++) 239254721Semaste { 240254721Semaste if (!*utf8_data_ptr) 241254721Semaste break; 242254721Semaste stream.Printf("%c",*utf8_data_ptr); 243254721Semaste } 244254721Semaste } 245254721Semaste if (quote != 0) 246254721Semaste stream.Printf("%c",quote); 247254721Semaste return true; 248254721Semaste} 249254721Semaste 250254721Semastetemplate<typename SourceDataType> 251254721Semasteclass ReadUTFBufferAndDumpToStreamOptions 252254721Semaste{ 253254721Semastepublic: 254254721Semaste typedef ConversionResult (*ConvertFunctionType) (const SourceDataType**, 255254721Semaste const SourceDataType*, 256254721Semaste UTF8**, 257254721Semaste UTF8*, 258254721Semaste ConversionFlags); 259254721Semaste 260254721Semaste ReadUTFBufferAndDumpToStreamOptions () : 261254721Semaste m_conversion_function(NULL), 262254721Semaste m_location(0), 263254721Semaste m_process_sp(), 264254721Semaste m_stream(NULL), 265254721Semaste m_prefix_token('@'), 266254721Semaste m_quote('"'), 267254721Semaste m_source_size(0), 268254721Semaste m_needs_zero_termination(true) 269254721Semaste { 270254721Semaste } 271254721Semaste 272254721Semaste ReadUTFBufferAndDumpToStreamOptions& 273254721Semaste SetConversionFunction (ConvertFunctionType f) 274254721Semaste { 275254721Semaste m_conversion_function = f; 276254721Semaste return *this; 277254721Semaste } 278254721Semaste 279254721Semaste ConvertFunctionType 280254721Semaste GetConversionFunction () const 281254721Semaste { 282254721Semaste return m_conversion_function; 283254721Semaste } 284254721Semaste 285254721Semaste ReadUTFBufferAndDumpToStreamOptions& 286254721Semaste SetLocation (uint64_t l) 287254721Semaste { 288254721Semaste m_location = l; 289254721Semaste return *this; 290254721Semaste } 291254721Semaste 292254721Semaste uint64_t 293254721Semaste GetLocation () const 294254721Semaste { 295254721Semaste return m_location; 296254721Semaste } 297254721Semaste 298254721Semaste ReadUTFBufferAndDumpToStreamOptions& 299254721Semaste SetProcessSP (ProcessSP p) 300254721Semaste { 301254721Semaste m_process_sp = p; 302254721Semaste return *this; 303254721Semaste } 304254721Semaste 305254721Semaste ProcessSP 306254721Semaste GetProcessSP () const 307254721Semaste { 308254721Semaste return m_process_sp; 309254721Semaste } 310254721Semaste 311254721Semaste ReadUTFBufferAndDumpToStreamOptions& 312254721Semaste SetStream (Stream* s) 313254721Semaste { 314254721Semaste m_stream = s; 315254721Semaste return *this; 316254721Semaste } 317254721Semaste 318254721Semaste Stream* 319254721Semaste GetStream () const 320254721Semaste { 321254721Semaste return m_stream; 322254721Semaste } 323254721Semaste 324254721Semaste ReadUTFBufferAndDumpToStreamOptions& 325254721Semaste SetPrefixToken (char p) 326254721Semaste { 327254721Semaste m_prefix_token = p; 328254721Semaste return *this; 329254721Semaste } 330254721Semaste 331254721Semaste char 332254721Semaste GetPrefixToken () const 333254721Semaste { 334254721Semaste return m_prefix_token; 335254721Semaste } 336254721Semaste 337254721Semaste ReadUTFBufferAndDumpToStreamOptions& 338254721Semaste SetQuote (char q) 339254721Semaste { 340254721Semaste m_quote = q; 341254721Semaste return *this; 342254721Semaste } 343254721Semaste 344254721Semaste char 345254721Semaste GetQuote () const 346254721Semaste { 347254721Semaste return m_quote; 348254721Semaste } 349254721Semaste 350254721Semaste ReadUTFBufferAndDumpToStreamOptions& 351254721Semaste SetSourceSize (uint32_t s) 352254721Semaste { 353254721Semaste m_source_size = s; 354254721Semaste return *this; 355254721Semaste } 356254721Semaste 357254721Semaste uint32_t 358254721Semaste GetSourceSize () const 359254721Semaste { 360254721Semaste return m_source_size; 361254721Semaste } 362254721Semaste 363254721Semaste ReadUTFBufferAndDumpToStreamOptions& 364254721Semaste SetNeedsZeroTermination (bool z) 365254721Semaste { 366254721Semaste m_needs_zero_termination = z; 367254721Semaste return *this; 368254721Semaste } 369254721Semaste 370254721Semaste bool 371254721Semaste GetNeedsZeroTermination () const 372254721Semaste { 373254721Semaste return m_needs_zero_termination; 374254721Semaste } 375254721Semaste 376254721Semasteprivate: 377254721Semaste ConvertFunctionType m_conversion_function; 378254721Semaste uint64_t m_location; 379254721Semaste ProcessSP m_process_sp; 380254721Semaste Stream* m_stream; 381254721Semaste char m_prefix_token; 382254721Semaste char m_quote; 383254721Semaste uint32_t m_source_size; 384254721Semaste bool m_needs_zero_termination; 385254721Semaste}; 386254721Semaste 387254721Semastetemplate<typename SourceDataType> 388254721Semastestatic bool 389254721SemasteReadUTFBufferAndDumpToStream (const ReadUTFBufferAndDumpToStreamOptions<SourceDataType>& options) 390254721Semaste{ 391254721Semaste if (options.GetLocation() == 0 || options.GetLocation() == LLDB_INVALID_ADDRESS) 392254721Semaste return false; 393254721Semaste 394254721Semaste ProcessSP process_sp(options.GetProcessSP()); 395254721Semaste 396254721Semaste if (!process_sp) 397254721Semaste return false; 398254721Semaste 399254721Semaste const int type_width = sizeof(SourceDataType); 400254721Semaste const int origin_encoding = 8 * type_width ; 401254721Semaste if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32) 402254721Semaste return false; 403254721Semaste // if not UTF8, I need a conversion function to return proper UTF8 404254721Semaste if (origin_encoding != 8 && !options.GetConversionFunction()) 405254721Semaste return false; 406254721Semaste 407254721Semaste if (!options.GetStream()) 408254721Semaste return false; 409254721Semaste 410254721Semaste uint32_t sourceSize = options.GetSourceSize(); 411254721Semaste bool needs_zero_terminator = options.GetNeedsZeroTermination(); 412254721Semaste 413254721Semaste if (!sourceSize) 414254721Semaste { 415254721Semaste sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary(); 416254721Semaste needs_zero_terminator = true; 417254721Semaste } 418254721Semaste else 419254721Semaste sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary()); 420254721Semaste 421254721Semaste const int bufferSPSize = sourceSize * type_width; 422254721Semaste 423254721Semaste lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0)); 424254721Semaste 425254721Semaste if (!buffer_sp->GetBytes()) 426254721Semaste return false; 427254721Semaste 428254721Semaste Error error; 429254721Semaste char *buffer = reinterpret_cast<char *>(buffer_sp->GetBytes()); 430254721Semaste 431254721Semaste size_t data_read = 0; 432254721Semaste if (needs_zero_terminator) 433254721Semaste data_read = process_sp->ReadStringFromMemory(options.GetLocation(), buffer, bufferSPSize, error, type_width); 434254721Semaste else 435254721Semaste data_read = process_sp->ReadMemoryFromInferior(options.GetLocation(), (char*)buffer_sp->GetBytes(), bufferSPSize, error); 436254721Semaste 437254721Semaste if (error.Fail() || data_read == 0) 438254721Semaste { 439254721Semaste options.GetStream()->Printf("unable to read data"); 440254721Semaste return true; 441254721Semaste } 442254721Semaste 443254721Semaste DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); 444254721Semaste 445254721Semaste return DumpUTFBufferToStream(options.GetConversionFunction(), data, *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), sourceSize); 446254721Semaste} 447254721Semaste 448254721Semastebool 449254721Semastelldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream) 450254721Semaste{ 451254721Semaste ProcessSP process_sp = valobj.GetProcessSP(); 452254721Semaste if (!process_sp) 453254721Semaste return false; 454254721Semaste 455254721Semaste lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); 456254721Semaste 457254721Semaste if (!valobj_addr) 458254721Semaste return false; 459254721Semaste 460254721Semaste ReadUTFBufferAndDumpToStreamOptions<UTF16> options; 461254721Semaste options.SetLocation(valobj_addr); 462254721Semaste options.SetConversionFunction(ConvertUTF16toUTF8); 463254721Semaste options.SetProcessSP(process_sp); 464254721Semaste options.SetStream(&stream); 465254721Semaste options.SetPrefixToken('u'); 466254721Semaste 467254721Semaste if (!ReadUTFBufferAndDumpToStream(options)) 468254721Semaste { 469254721Semaste stream.Printf("Summary Unavailable"); 470254721Semaste return true; 471254721Semaste } 472254721Semaste 473254721Semaste return true; 474254721Semaste} 475254721Semaste 476254721Semastebool 477254721Semastelldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream) 478254721Semaste{ 479254721Semaste ProcessSP process_sp = valobj.GetProcessSP(); 480254721Semaste if (!process_sp) 481254721Semaste return false; 482254721Semaste 483254721Semaste lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); 484254721Semaste 485254721Semaste if (!valobj_addr) 486254721Semaste return false; 487254721Semaste 488254721Semaste ReadUTFBufferAndDumpToStreamOptions<UTF32> options; 489254721Semaste options.SetLocation(valobj_addr); 490254721Semaste options.SetConversionFunction(ConvertUTF32toUTF8); 491254721Semaste options.SetProcessSP(process_sp); 492254721Semaste options.SetStream(&stream); 493254721Semaste options.SetPrefixToken('U'); 494254721Semaste 495254721Semaste if (!ReadUTFBufferAndDumpToStream(options)) 496254721Semaste { 497254721Semaste stream.Printf("Summary Unavailable"); 498254721Semaste return true; 499254721Semaste } 500254721Semaste 501254721Semaste return true; 502254721Semaste} 503254721Semaste 504254721Semastebool 505254721Semastelldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream) 506254721Semaste{ 507254721Semaste ProcessSP process_sp = valobj.GetProcessSP(); 508254721Semaste if (!process_sp) 509254721Semaste return false; 510254721Semaste 511254721Semaste lldb::addr_t data_addr = 0; 512254721Semaste 513254721Semaste if (valobj.IsPointerType()) 514254721Semaste data_addr = valobj.GetValueAsUnsigned(0); 515254721Semaste else if (valobj.IsArrayType()) 516254721Semaste data_addr = valobj.GetAddressOf(); 517254721Semaste 518254721Semaste if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS) 519254721Semaste return false; 520254721Semaste 521254721Semaste clang::ASTContext* ast = valobj.GetClangType().GetASTContext(); 522254721Semaste 523254721Semaste if (!ast) 524254721Semaste return false; 525254721Semaste 526254721Semaste ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar); 527254721Semaste const uint32_t wchar_size = wchar_clang_type.GetBitSize(); 528254721Semaste 529254721Semaste switch (wchar_size) 530254721Semaste { 531254721Semaste case 8: 532254721Semaste { 533254721Semaste // utf 8 534254721Semaste 535254721Semaste ReadUTFBufferAndDumpToStreamOptions<UTF8> options; 536254721Semaste options.SetLocation(data_addr); 537254721Semaste options.SetConversionFunction(nullptr); 538254721Semaste options.SetProcessSP(process_sp); 539254721Semaste options.SetStream(&stream); 540254721Semaste options.SetPrefixToken('L'); 541254721Semaste 542254721Semaste return ReadUTFBufferAndDumpToStream(options); 543254721Semaste } 544254721Semaste case 16: 545254721Semaste { 546254721Semaste // utf 16 547254721Semaste ReadUTFBufferAndDumpToStreamOptions<UTF16> options; 548254721Semaste options.SetLocation(data_addr); 549254721Semaste options.SetConversionFunction(ConvertUTF16toUTF8); 550254721Semaste options.SetProcessSP(process_sp); 551254721Semaste options.SetStream(&stream); 552254721Semaste options.SetPrefixToken('L'); 553254721Semaste 554254721Semaste return ReadUTFBufferAndDumpToStream(options); 555254721Semaste } 556254721Semaste case 32: 557254721Semaste { 558254721Semaste // utf 32 559254721Semaste ReadUTFBufferAndDumpToStreamOptions<UTF32> options; 560254721Semaste options.SetLocation(data_addr); 561254721Semaste options.SetConversionFunction(ConvertUTF32toUTF8); 562254721Semaste options.SetProcessSP(process_sp); 563254721Semaste options.SetStream(&stream); 564254721Semaste options.SetPrefixToken('L'); 565254721Semaste 566254721Semaste return ReadUTFBufferAndDumpToStream(options); 567254721Semaste } 568254721Semaste default: 569254721Semaste stream.Printf("size for wchar_t is not valid"); 570254721Semaste return true; 571254721Semaste } 572254721Semaste return true; 573254721Semaste} 574254721Semaste 575254721Semastebool 576254721Semastelldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream) 577254721Semaste{ 578254721Semaste DataExtractor data; 579254721Semaste valobj.GetData(data); 580254721Semaste 581254721Semaste std::string value; 582254721Semaste valobj.GetValueAsCString(lldb::eFormatUnicode16, value); 583254721Semaste if (!value.empty()) 584254721Semaste stream.Printf("%s ", value.c_str()); 585254721Semaste 586254721Semaste return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,data,stream, 'u','\'',1); 587254721Semaste} 588254721Semaste 589254721Semastebool 590254721Semastelldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream) 591254721Semaste{ 592254721Semaste DataExtractor data; 593254721Semaste valobj.GetData(data); 594254721Semaste 595254721Semaste std::string value; 596254721Semaste valobj.GetValueAsCString(lldb::eFormatUnicode32, value); 597254721Semaste if (!value.empty()) 598254721Semaste stream.Printf("%s ", value.c_str()); 599254721Semaste 600254721Semaste return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,data,stream, 'U','\'',1); 601254721Semaste} 602254721Semaste 603254721Semastebool 604254721Semastelldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream) 605254721Semaste{ 606254721Semaste DataExtractor data; 607254721Semaste valobj.GetData(data); 608254721Semaste 609254721Semaste clang::ASTContext* ast = valobj.GetClangType().GetASTContext(); 610254721Semaste 611254721Semaste if (!ast) 612254721Semaste return false; 613254721Semaste 614254721Semaste ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar); 615254721Semaste const uint32_t wchar_size = wchar_clang_type.GetBitSize(); 616254721Semaste std::string value; 617254721Semaste 618254721Semaste switch (wchar_size) 619254721Semaste { 620254721Semaste case 8: 621254721Semaste // utf 8 622254721Semaste valobj.GetValueAsCString(lldb::eFormatChar, value); 623254721Semaste if (!value.empty()) 624254721Semaste stream.Printf("%s ", value.c_str()); 625254721Semaste return DumpUTFBufferToStream<UTF8>(nullptr, 626254721Semaste data, 627254721Semaste stream, 628254721Semaste 'L', 629254721Semaste '\'', 630254721Semaste 1); 631254721Semaste case 16: 632254721Semaste // utf 16 633254721Semaste valobj.GetValueAsCString(lldb::eFormatUnicode16, value); 634254721Semaste if (!value.empty()) 635254721Semaste stream.Printf("%s ", value.c_str()); 636254721Semaste return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8, 637254721Semaste data, 638254721Semaste stream, 639254721Semaste 'L', 640254721Semaste '\'', 641254721Semaste 1); 642254721Semaste case 32: 643254721Semaste // utf 32 644254721Semaste valobj.GetValueAsCString(lldb::eFormatUnicode32, value); 645254721Semaste if (!value.empty()) 646254721Semaste stream.Printf("%s ", value.c_str()); 647254721Semaste return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8, 648254721Semaste data, 649254721Semaste stream, 650254721Semaste 'L', 651254721Semaste '\'', 652254721Semaste 1); 653254721Semaste default: 654254721Semaste stream.Printf("size for wchar_t is not valid"); 655254721Semaste return true; 656254721Semaste } 657254721Semaste return true; 658254721Semaste} 659254721Semaste 660254721Semaste// the field layout in a libc++ string (cap, side, data or data, size, cap) 661254721Semasteenum LibcxxStringLayoutMode 662254721Semaste{ 663254721Semaste eLibcxxStringLayoutModeCSD = 0, 664254721Semaste eLibcxxStringLayoutModeDSC = 1, 665254721Semaste eLibcxxStringLayoutModeInvalid = 0xffff 666254721Semaste}; 667254721Semaste 668254721Semaste// this function abstracts away the layout and mode details of a libc++ string 669254721Semaste// and returns the address of the data and the size ready for callers to consume 670254721Semastestatic bool 671254721SemasteExtractLibcxxStringInfo (ValueObject& valobj, 672254721Semaste ValueObjectSP &location_sp, 673254721Semaste uint64_t& size) 674254721Semaste{ 675254721Semaste ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0})); 676254721Semaste if (!D) 677254721Semaste return false; 678254721Semaste 679254721Semaste ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0})); 680254721Semaste 681254721Semaste // this child should exist 682254721Semaste if (!layout_decider) 683254721Semaste return false; 684254721Semaste 685254721Semaste ConstString g_data_name("__data_"); 686254721Semaste ConstString g_size_name("__size_"); 687254721Semaste bool short_mode = false; // this means the string is in short-mode and the data is stored inline 688254721Semaste LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD; 689254721Semaste uint64_t size_mode_value = 0; 690254721Semaste 691254721Semaste if (layout == eLibcxxStringLayoutModeDSC) 692254721Semaste { 693254721Semaste ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0})); 694254721Semaste if (!size_mode) 695254721Semaste return false; 696254721Semaste 697254721Semaste if (size_mode->GetName() != g_size_name) 698254721Semaste { 699254721Semaste // we are hitting the padding structure, move along 700254721Semaste size_mode = D->GetChildAtIndexPath({1,1,1}); 701254721Semaste if (!size_mode) 702254721Semaste return false; 703254721Semaste } 704254721Semaste 705254721Semaste size_mode_value = (size_mode->GetValueAsUnsigned(0)); 706254721Semaste short_mode = ((size_mode_value & 0x80) == 0); 707254721Semaste } 708254721Semaste else 709254721Semaste { 710254721Semaste ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0})); 711254721Semaste if (!size_mode) 712254721Semaste return false; 713254721Semaste 714254721Semaste size_mode_value = (size_mode->GetValueAsUnsigned(0)); 715254721Semaste short_mode = ((size_mode_value & 1) == 0); 716254721Semaste } 717254721Semaste 718254721Semaste if (short_mode) 719254721Semaste { 720254721Semaste ValueObjectSP s(D->GetChildAtIndex(1, true)); 721254721Semaste if (!s) 722254721Semaste return false; 723254721Semaste location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true); 724254721Semaste size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256); 725254721Semaste return (location_sp.get() != nullptr); 726254721Semaste } 727254721Semaste else 728254721Semaste { 729254721Semaste ValueObjectSP l(D->GetChildAtIndex(0, true)); 730254721Semaste if (!l) 731254721Semaste return false; 732254721Semaste // we can use the layout_decider object as the data pointer 733254721Semaste location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true); 734254721Semaste ValueObjectSP size_vo(l->GetChildAtIndex(1, true)); 735254721Semaste if (!size_vo || !location_sp) 736254721Semaste return false; 737254721Semaste size = size_vo->GetValueAsUnsigned(0); 738254721Semaste return true; 739254721Semaste } 740254721Semaste} 741254721Semaste 742254721Semastebool 743254721Semastelldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream) 744254721Semaste{ 745254721Semaste uint64_t size = 0; 746254721Semaste ValueObjectSP location_sp((ValueObject*)nullptr); 747254721Semaste if (!ExtractLibcxxStringInfo(valobj, location_sp, size)) 748254721Semaste return false; 749254721Semaste if (size == 0) 750254721Semaste { 751254721Semaste stream.Printf("L\"\""); 752254721Semaste return true; 753254721Semaste } 754254721Semaste if (!location_sp) 755254721Semaste return false; 756254721Semaste return WCharStringSummaryProvider(*location_sp.get(), stream); 757254721Semaste} 758254721Semaste 759254721Semastebool 760254721Semastelldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream) 761254721Semaste{ 762254721Semaste uint64_t size = 0; 763254721Semaste ValueObjectSP location_sp((ValueObject*)nullptr); 764254721Semaste if (!ExtractLibcxxStringInfo(valobj, location_sp, size)) 765254721Semaste return false; 766254721Semaste if (size == 0) 767254721Semaste { 768254721Semaste stream.Printf("\"\""); 769254721Semaste return true; 770254721Semaste } 771254721Semaste if (!location_sp) 772254721Semaste return false; 773254721Semaste Error error; 774254721Semaste if (location_sp->ReadPointedString(stream, 775254721Semaste error, 776254721Semaste 0, // max length is decided by the settings 777254721Semaste false) == 0) // do not honor array (terminates on first 0 byte even for a char[]) 778254721Semaste stream.Printf("\"\""); // if nothing was read, print an empty string 779254721Semaste return error.Success(); 780254721Semaste} 781254721Semaste 782254721Semastebool 783254721Semastelldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream) 784254721Semaste{ 785254721Semaste ProcessSP process_sp = valobj.GetProcessSP(); 786254721Semaste if (!process_sp) 787254721Semaste return false; 788254721Semaste 789254721Semaste ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); 790254721Semaste 791254721Semaste if (!runtime) 792254721Semaste return false; 793254721Semaste 794254721Semaste ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0))); 795254721Semaste 796254721Semaste if (!descriptor.get() || !descriptor->IsValid()) 797254721Semaste return false; 798254721Semaste 799254721Semaste const char* class_name = descriptor->GetClassName().GetCString(); 800254721Semaste 801254721Semaste if (!class_name || !*class_name) 802254721Semaste return false; 803254721Semaste 804254721Semaste stream.Printf("%s",class_name); 805254721Semaste return true; 806254721Semaste} 807254721Semaste 808254721Semasteclass ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd 809254721Semaste{ 810254721Semastepublic: 811254721Semaste ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) : 812254721Semaste SyntheticChildrenFrontEnd(*valobj_sp.get()) 813254721Semaste { 814254721Semaste } 815254721Semaste 816254721Semaste virtual size_t 817254721Semaste CalculateNumChildren () 818254721Semaste { 819254721Semaste return 0; 820254721Semaste } 821254721Semaste 822254721Semaste virtual lldb::ValueObjectSP 823254721Semaste GetChildAtIndex (size_t idx) 824254721Semaste { 825254721Semaste return lldb::ValueObjectSP(); 826254721Semaste } 827254721Semaste 828254721Semaste virtual bool 829254721Semaste Update() 830254721Semaste { 831254721Semaste return false; 832254721Semaste } 833254721Semaste 834254721Semaste virtual bool 835254721Semaste MightHaveChildren () 836254721Semaste { 837254721Semaste return false; 838254721Semaste } 839254721Semaste 840254721Semaste virtual size_t 841254721Semaste GetIndexOfChildWithName (const ConstString &name) 842254721Semaste { 843254721Semaste return UINT32_MAX; 844254721Semaste } 845254721Semaste 846254721Semaste virtual 847254721Semaste ~ObjCClassSyntheticChildrenFrontEnd () 848254721Semaste { 849254721Semaste } 850254721Semaste}; 851254721Semaste 852254721SemasteSyntheticChildrenFrontEnd* 853254721Semastelldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 854254721Semaste{ 855254721Semaste return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp); 856254721Semaste} 857254721Semaste 858254721Semastetemplate<bool needs_at> 859254721Semastebool 860254721Semastelldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream) 861254721Semaste{ 862254721Semaste ProcessSP process_sp = valobj.GetProcessSP(); 863254721Semaste if (!process_sp) 864254721Semaste return false; 865254721Semaste 866254721Semaste ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); 867254721Semaste 868254721Semaste if (!runtime) 869254721Semaste return false; 870254721Semaste 871254721Semaste ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); 872254721Semaste 873254721Semaste if (!descriptor.get() || !descriptor->IsValid()) 874254721Semaste return false; 875254721Semaste 876254721Semaste bool is_64bit = (process_sp->GetAddressByteSize() == 8); 877254721Semaste lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); 878254721Semaste 879254721Semaste if (!valobj_addr) 880254721Semaste return false; 881254721Semaste 882254721Semaste uint64_t value = 0; 883254721Semaste 884254721Semaste const char* class_name = descriptor->GetClassName().GetCString(); 885254721Semaste 886254721Semaste if (!class_name || !*class_name) 887254721Semaste return false; 888254721Semaste 889254721Semaste if (!strcmp(class_name,"NSConcreteData") || 890254721Semaste !strcmp(class_name,"NSConcreteMutableData") || 891254721Semaste !strcmp(class_name,"__NSCFData")) 892254721Semaste { 893254721Semaste uint32_t offset = (is_64bit ? 16 : 8); 894254721Semaste Error error; 895254721Semaste value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error); 896254721Semaste if (error.Fail()) 897254721Semaste return false; 898254721Semaste } 899254721Semaste else 900254721Semaste { 901254721Semaste if (!ExtractValueFromObjCExpression(valobj, "int", "length", value)) 902254721Semaste return false; 903254721Semaste } 904254721Semaste 905254721Semaste stream.Printf("%s%" PRIu64 " byte%s%s", 906254721Semaste (needs_at ? "@\"" : ""), 907254721Semaste value, 908254721Semaste (value != 1 ? "s" : ""), 909254721Semaste (needs_at ? "\"" : "")); 910254721Semaste 911254721Semaste return true; 912254721Semaste} 913254721Semaste 914254721Semastestatic bool 915254721SemasteReadAsciiBufferAndDumpToStream (lldb::addr_t location, 916254721Semaste lldb::ProcessSP& process_sp, 917254721Semaste Stream& dest, 918254721Semaste uint32_t size = 0, 919254721Semaste Error* error = NULL, 920254721Semaste size_t *data_read = NULL, 921254721Semaste char prefix_token = '@', 922254721Semaste char quote = '"') 923254721Semaste{ 924254721Semaste Error my_error; 925254721Semaste size_t my_data_read; 926254721Semaste if (!process_sp || location == 0) 927254721Semaste return false; 928254721Semaste 929254721Semaste if (!size) 930254721Semaste size = process_sp->GetTarget().GetMaximumSizeOfStringSummary(); 931254721Semaste else 932254721Semaste size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary()); 933254721Semaste 934254721Semaste lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0)); 935254721Semaste 936254721Semaste my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error); 937254721Semaste 938254721Semaste if (error) 939254721Semaste *error = my_error; 940254721Semaste if (data_read) 941254721Semaste *data_read = my_data_read; 942254721Semaste 943254721Semaste if (my_error.Fail()) 944254721Semaste return false; 945254721Semaste 946254721Semaste dest.Printf("%c%c",prefix_token,quote); 947254721Semaste 948254721Semaste if (my_data_read) 949254721Semaste dest.Printf("%s",(char*)buffer_sp->GetBytes()); 950254721Semaste 951254721Semaste dest.Printf("%c",quote); 952254721Semaste 953254721Semaste return true; 954254721Semaste} 955254721Semaste 956254721Semastebool 957254721Semastelldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream) 958254721Semaste{ 959254721Semaste ProcessSP process_sp = valobj.GetProcessSP(); 960254721Semaste if (!process_sp) 961254721Semaste return false; 962254721Semaste 963254721Semaste ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); 964254721Semaste 965254721Semaste if (!runtime) 966254721Semaste return false; 967254721Semaste 968254721Semaste ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); 969254721Semaste 970254721Semaste if (!descriptor.get() || !descriptor->IsValid()) 971254721Semaste return false; 972254721Semaste 973254721Semaste uint32_t ptr_size = process_sp->GetAddressByteSize(); 974254721Semaste 975254721Semaste lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); 976254721Semaste 977254721Semaste if (!valobj_addr) 978254721Semaste return false; 979254721Semaste 980254721Semaste const char* class_name = descriptor->GetClassName().GetCString(); 981254721Semaste 982254721Semaste if (!class_name || !*class_name) 983254721Semaste return false; 984254721Semaste 985254721Semaste uint64_t info_bits_location = valobj_addr + ptr_size; 986254721Semaste if (process_sp->GetByteOrder() != lldb::eByteOrderLittle) 987254721Semaste info_bits_location += 3; 988254721Semaste 989254721Semaste Error error; 990254721Semaste 991254721Semaste uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error); 992254721Semaste if (error.Fail()) 993254721Semaste return false; 994254721Semaste 995254721Semaste bool is_mutable = (info_bits & 1) == 1; 996254721Semaste bool is_inline = (info_bits & 0x60) == 0; 997254721Semaste bool has_explicit_length = (info_bits & (1 | 4)) != 4; 998254721Semaste bool is_unicode = (info_bits & 0x10) == 0x10; 999254721Semaste bool is_special = strcmp(class_name,"NSPathStore2") == 0; 1000254721Semaste bool has_null = (info_bits & 8) == 8; 1001254721Semaste 1002254721Semaste size_t explicit_length = 0; 1003254721Semaste if (!has_null && has_explicit_length && !is_special) 1004254721Semaste { 1005254721Semaste lldb::addr_t explicit_length_offset = 2*ptr_size; 1006263363Semaste if (is_mutable && !is_inline) 1007254721Semaste explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length; 1008254721Semaste else if (is_inline) 1009254721Semaste explicit_length = explicit_length + 0; // inline1.length; 1010263363Semaste else if (!is_inline && !is_mutable) 1011254721Semaste explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length; 1012254721Semaste else 1013254721Semaste explicit_length_offset = 0; 1014254721Semaste 1015254721Semaste if (explicit_length_offset) 1016254721Semaste { 1017254721Semaste explicit_length_offset = valobj_addr + explicit_length_offset; 1018254721Semaste explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error); 1019254721Semaste } 1020254721Semaste } 1021254721Semaste 1022254721Semaste if (strcmp(class_name,"NSString") && 1023254721Semaste strcmp(class_name,"CFStringRef") && 1024254721Semaste strcmp(class_name,"CFMutableStringRef") && 1025254721Semaste strcmp(class_name,"__NSCFConstantString") && 1026254721Semaste strcmp(class_name,"__NSCFString") && 1027254721Semaste strcmp(class_name,"NSCFConstantString") && 1028254721Semaste strcmp(class_name,"NSCFString") && 1029254721Semaste strcmp(class_name,"NSPathStore2")) 1030254721Semaste { 1031254721Semaste // not one of us - but tell me class name 1032254721Semaste stream.Printf("class name = %s",class_name); 1033254721Semaste return true; 1034254721Semaste } 1035254721Semaste 1036254721Semaste if (is_mutable) 1037254721Semaste { 1038254721Semaste uint64_t location = 2 * ptr_size + valobj_addr; 1039254721Semaste location = process_sp->ReadPointerFromMemory(location, error); 1040254721Semaste if (error.Fail()) 1041254721Semaste return false; 1042263363Semaste if (has_explicit_length && is_unicode) 1043254721Semaste { 1044254721Semaste ReadUTFBufferAndDumpToStreamOptions<UTF16> options; 1045254721Semaste options.SetConversionFunction(ConvertUTF16toUTF8); 1046254721Semaste options.SetLocation(location); 1047254721Semaste options.SetProcessSP(process_sp); 1048254721Semaste options.SetStream(&stream); 1049254721Semaste options.SetPrefixToken('@'); 1050254721Semaste options.SetQuote('"'); 1051254721Semaste options.SetSourceSize(explicit_length); 1052254721Semaste options.SetNeedsZeroTermination(false); 1053254721Semaste return ReadUTFBufferAndDumpToStream (options); 1054254721Semaste } 1055254721Semaste else 1056254721Semaste return ReadAsciiBufferAndDumpToStream(location+1,process_sp,stream, explicit_length); 1057254721Semaste } 1058254721Semaste else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable) 1059254721Semaste { 1060254721Semaste uint64_t location = 3 * ptr_size + valobj_addr; 1061254721Semaste return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length); 1062254721Semaste } 1063254721Semaste else if (is_unicode) 1064254721Semaste { 1065254721Semaste uint64_t location = valobj_addr + 2*ptr_size; 1066254721Semaste if (is_inline) 1067254721Semaste { 1068254721Semaste if (!has_explicit_length) 1069254721Semaste { 1070254721Semaste stream.Printf("found new combo"); 1071254721Semaste return true; 1072254721Semaste } 1073254721Semaste else 1074254721Semaste location += ptr_size; 1075254721Semaste } 1076254721Semaste else 1077254721Semaste { 1078254721Semaste location = process_sp->ReadPointerFromMemory(location, error); 1079254721Semaste if (error.Fail()) 1080254721Semaste return false; 1081254721Semaste } 1082254721Semaste ReadUTFBufferAndDumpToStreamOptions<UTF16> options; 1083254721Semaste options.SetConversionFunction(ConvertUTF16toUTF8); 1084254721Semaste options.SetLocation(location); 1085254721Semaste options.SetProcessSP(process_sp); 1086254721Semaste options.SetStream(&stream); 1087254721Semaste options.SetPrefixToken('@'); 1088254721Semaste options.SetQuote('"'); 1089254721Semaste options.SetSourceSize(explicit_length); 1090254721Semaste options.SetNeedsZeroTermination(has_explicit_length == false); 1091254721Semaste return ReadUTFBufferAndDumpToStream (options); 1092254721Semaste } 1093254721Semaste else if (is_special) 1094254721Semaste { 1095254721Semaste uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8); 1096254721Semaste ReadUTFBufferAndDumpToStreamOptions<UTF16> options; 1097254721Semaste options.SetConversionFunction(ConvertUTF16toUTF8); 1098254721Semaste options.SetLocation(location); 1099254721Semaste options.SetProcessSP(process_sp); 1100254721Semaste options.SetStream(&stream); 1101254721Semaste options.SetPrefixToken('@'); 1102254721Semaste options.SetQuote('"'); 1103254721Semaste options.SetSourceSize(explicit_length); 1104254721Semaste options.SetNeedsZeroTermination(has_explicit_length == false); 1105254721Semaste return ReadUTFBufferAndDumpToStream (options); 1106254721Semaste } 1107254721Semaste else if (is_inline) 1108254721Semaste { 1109254721Semaste uint64_t location = valobj_addr + 2*ptr_size; 1110254721Semaste if (!has_explicit_length) 1111254721Semaste location++; 1112254721Semaste return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length); 1113254721Semaste } 1114254721Semaste else 1115254721Semaste { 1116254721Semaste uint64_t location = valobj_addr + 2*ptr_size; 1117254721Semaste location = process_sp->ReadPointerFromMemory(location, error); 1118254721Semaste if (error.Fail()) 1119254721Semaste return false; 1120254721Semaste if (has_explicit_length && !has_null) 1121254721Semaste explicit_length++; // account for the fact that there is no NULL and we need to have one added 1122254721Semaste return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length); 1123254721Semaste } 1124254721Semaste 1125254721Semaste stream.Printf("class name = %s",class_name); 1126254721Semaste return true; 1127254721Semaste 1128254721Semaste} 1129254721Semaste 1130254721Semastebool 1131254721Semastelldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream) 1132254721Semaste{ 1133254721Semaste TargetSP target_sp(valobj.GetTargetSP()); 1134254721Semaste if (!target_sp) 1135254721Semaste return false; 1136254721Semaste uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize(); 1137254721Semaste uint64_t pointer_value = valobj.GetValueAsUnsigned(0); 1138254721Semaste if (!pointer_value) 1139254721Semaste return false; 1140254721Semaste pointer_value += addr_size; 1141254721Semaste ClangASTType type(valobj.GetClangType()); 1142254721Semaste ExecutionContext exe_ctx(target_sp,false); 1143254721Semaste ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type)); 1144254721Semaste if (!child_ptr_sp) 1145254721Semaste return false; 1146254721Semaste DataExtractor data; 1147254721Semaste child_ptr_sp->GetData(data); 1148254721Semaste ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type)); 1149254721Semaste child_sp->GetValueAsUnsigned(0); 1150254721Semaste if (child_sp) 1151254721Semaste return NSStringSummaryProvider(*child_sp, stream); 1152254721Semaste return false; 1153254721Semaste} 1154254721Semaste 1155254721Semastebool 1156254721Semastelldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream) 1157254721Semaste{ 1158254721Semaste return NSAttributedStringSummaryProvider(valobj, stream); 1159254721Semaste} 1160254721Semaste 1161254721Semastebool 1162254721Semastelldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream) 1163254721Semaste{ 1164254721Semaste stream.Printf("%s",valobj.GetObjectDescription()); 1165254721Semaste return true; 1166254721Semaste} 1167254721Semaste 1168254721Semastebool 1169254721Semastelldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream) 1170254721Semaste{ 1171254721Semaste const uint32_t type_info = valobj.GetClangType().GetTypeInfo(); 1172254721Semaste 1173254721Semaste ValueObjectSP real_guy_sp = valobj.GetSP(); 1174254721Semaste 1175254721Semaste if (type_info & ClangASTType::eTypeIsPointer) 1176254721Semaste { 1177254721Semaste Error err; 1178254721Semaste real_guy_sp = valobj.Dereference(err); 1179254721Semaste if (err.Fail() || !real_guy_sp) 1180254721Semaste return false; 1181254721Semaste } 1182254721Semaste else if (type_info & ClangASTType::eTypeIsReference) 1183254721Semaste { 1184254721Semaste real_guy_sp = valobj.GetChildAtIndex(0, true); 1185254721Semaste if (!real_guy_sp) 1186254721Semaste return false; 1187254721Semaste } 1188254721Semaste uint64_t value = real_guy_sp->GetValueAsUnsigned(0); 1189254721Semaste if (value == 0) 1190254721Semaste { 1191254721Semaste stream.Printf("NO"); 1192254721Semaste return true; 1193254721Semaste } 1194254721Semaste stream.Printf("YES"); 1195254721Semaste return true; 1196254721Semaste} 1197254721Semaste 1198254721Semastetemplate <bool is_sel_ptr> 1199254721Semastebool 1200254721Semastelldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream) 1201254721Semaste{ 1202254721Semaste lldb::ValueObjectSP valobj_sp; 1203254721Semaste 1204254721Semaste ClangASTType charstar (valobj.GetClangType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType()); 1205254721Semaste 1206254721Semaste if (!charstar) 1207254721Semaste return false; 1208254721Semaste 1209254721Semaste ExecutionContext exe_ctx(valobj.GetExecutionContextRef()); 1210254721Semaste 1211254721Semaste if (is_sel_ptr) 1212254721Semaste { 1213254721Semaste lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); 1214254721Semaste if (data_address == LLDB_INVALID_ADDRESS) 1215254721Semaste return false; 1216254721Semaste valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar); 1217254721Semaste } 1218254721Semaste else 1219254721Semaste { 1220254721Semaste DataExtractor data; 1221254721Semaste valobj.GetData(data); 1222254721Semaste valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar); 1223254721Semaste } 1224254721Semaste 1225254721Semaste if (!valobj_sp) 1226254721Semaste return false; 1227254721Semaste 1228254721Semaste stream.Printf("%s",valobj_sp->GetSummaryAsCString()); 1229254721Semaste return true; 1230254721Semaste} 1231254721Semaste 1232254721Semaste// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001 1233254721Semaste// this call gives the POSIX equivalent of the Cocoa epoch 1234254721Semastetime_t 1235254721Semastelldb_private::formatters::GetOSXEpoch () 1236254721Semaste{ 1237254721Semaste static time_t epoch = 0; 1238254721Semaste if (!epoch) 1239254721Semaste { 1240263363Semaste#ifndef _WIN32 1241254721Semaste tzset(); 1242254721Semaste tm tm_epoch; 1243254721Semaste tm_epoch.tm_sec = 0; 1244254721Semaste tm_epoch.tm_hour = 0; 1245254721Semaste tm_epoch.tm_min = 0; 1246254721Semaste tm_epoch.tm_mon = 0; 1247254721Semaste tm_epoch.tm_mday = 1; 1248254721Semaste tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why. 1249254721Semaste tm_epoch.tm_isdst = -1; 1250254721Semaste tm_epoch.tm_gmtoff = 0; 1251254721Semaste tm_epoch.tm_zone = NULL; 1252254721Semaste epoch = timegm(&tm_epoch); 1253263363Semaste#endif 1254254721Semaste } 1255254721Semaste return epoch; 1256254721Semaste} 1257254721Semaste 1258254721Semastesize_t 1259254721Semastelldb_private::formatters::ExtractIndexFromString (const char* item_name) 1260254721Semaste{ 1261254721Semaste if (!item_name || !*item_name) 1262254721Semaste return UINT32_MAX; 1263254721Semaste if (*item_name != '[') 1264254721Semaste return UINT32_MAX; 1265254721Semaste item_name++; 1266254721Semaste char* endptr = NULL; 1267254721Semaste unsigned long int idx = ::strtoul(item_name, &endptr, 0); 1268254721Semaste if (idx == 0 && endptr == item_name) 1269254721Semaste return UINT32_MAX; 1270254721Semaste if (idx == ULONG_MAX) 1271254721Semaste return UINT32_MAX; 1272254721Semaste return idx; 1273254721Semaste} 1274254721Semaste 1275254721Semastelldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp, 1276254721Semaste ConstString item_name) : 1277254721SemasteSyntheticChildrenFrontEnd(*valobj_sp.get()), 1278254721Semastem_exe_ctx_ref(), 1279254721Semastem_item_name(item_name), 1280254721Semastem_item_sp() 1281254721Semaste{ 1282254721Semaste if (valobj_sp) 1283254721Semaste Update(); 1284254721Semaste} 1285254721Semaste 1286254721Semastebool 1287254721Semastelldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update() 1288254721Semaste{ 1289254721Semaste m_item_sp.reset(); 1290254721Semaste 1291254721Semaste ValueObjectSP valobj_sp = m_backend.GetSP(); 1292254721Semaste if (!valobj_sp) 1293254721Semaste return false; 1294254721Semaste 1295254721Semaste if (!valobj_sp) 1296254721Semaste return false; 1297254721Semaste 1298254721Semaste ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true)); 1299254721Semaste if (!item_ptr) 1300254721Semaste return false; 1301254721Semaste if (item_ptr->GetValueAsUnsigned(0) == 0) 1302254721Semaste return false; 1303254721Semaste Error err; 1304254721Semaste m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 1305254721Semaste m_item_sp = ValueObject::CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType()); 1306254721Semaste if (err.Fail()) 1307254721Semaste m_item_sp.reset(); 1308254721Semaste return false; 1309254721Semaste} 1310254721Semaste 1311254721Semastesize_t 1312254721Semastelldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren () 1313254721Semaste{ 1314254721Semaste return 1; 1315254721Semaste} 1316254721Semaste 1317254721Semastelldb::ValueObjectSP 1318254721Semastelldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx) 1319254721Semaste{ 1320254721Semaste if (idx == 0) 1321254721Semaste return m_item_sp; 1322254721Semaste return lldb::ValueObjectSP(); 1323254721Semaste} 1324254721Semaste 1325254721Semastebool 1326254721Semastelldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren () 1327254721Semaste{ 1328254721Semaste return true; 1329254721Semaste} 1330254721Semaste 1331254721Semastesize_t 1332254721Semastelldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 1333254721Semaste{ 1334254721Semaste if (name == ConstString("item")) 1335254721Semaste return 0; 1336254721Semaste return UINT32_MAX; 1337254721Semaste} 1338254721Semaste 1339254721Semastelldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd () 1340254721Semaste{ 1341254721Semaste} 1342254721Semaste 1343254721Semastetemplate bool 1344254721Semastelldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ; 1345254721Semaste 1346254721Semastetemplate bool 1347254721Semastelldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ; 1348254721Semaste 1349254721Semastetemplate bool 1350254721Semastelldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ; 1351254721Semaste 1352254721Semastetemplate bool 1353254721Semastelldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ; 1354