ValueObjectPrinter.cpp revision 280031
1//===-- ValueObjectPrinter.cpp -------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "lldb/DataFormatters/ValueObjectPrinter.h" 11 12// C Includes 13// C++ Includes 14// Other libraries and framework includes 15// Project includes 16#include "lldb/Core/Debugger.h" 17#include "lldb/DataFormatters/DataVisualization.h" 18#include "lldb/Interpreter/CommandInterpreter.h" 19#include "lldb/Target/Target.h" 20 21using namespace lldb; 22using namespace lldb_private; 23 24ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj, 25 Stream* s, 26 const DumpValueObjectOptions& options) 27{ 28 Init(valobj,s,options,options.m_max_ptr_depth,0); 29} 30 31ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj, 32 Stream* s, 33 const DumpValueObjectOptions& options, 34 uint32_t ptr_depth, 35 uint32_t curr_depth) 36{ 37 Init(valobj,s,options,ptr_depth,curr_depth); 38} 39 40void 41ValueObjectPrinter::Init (ValueObject* valobj, 42 Stream* s, 43 const DumpValueObjectOptions& options, 44 uint32_t ptr_depth, 45 uint32_t curr_depth) 46{ 47 m_orig_valobj = valobj; 48 m_valobj = nullptr; 49 m_stream = s; 50 this->options = options; 51 m_ptr_depth = ptr_depth; 52 m_curr_depth = curr_depth; 53 assert (m_orig_valobj && "cannot print a NULL ValueObject"); 54 assert (m_stream && "cannot print to a NULL Stream"); 55 m_should_print = eLazyBoolCalculate; 56 m_is_nil = eLazyBoolCalculate; 57 m_is_ptr = eLazyBoolCalculate; 58 m_is_ref = eLazyBoolCalculate; 59 m_is_aggregate = eLazyBoolCalculate; 60 m_summary_formatter = {nullptr,false}; 61 m_value.assign(""); 62 m_summary.assign(""); 63 m_error.assign(""); 64} 65 66bool 67ValueObjectPrinter::PrintValueObject () 68{ 69 if (!GetMostSpecializedValue () || m_valobj == nullptr) 70 return false; 71 72 if (ShouldPrintValueObject()) 73 { 74 PrintValidationMarkerIfNeeded(); 75 76 PrintLocationIfNeeded(); 77 m_stream->Indent(); 78 79 bool show_type = PrintTypeIfNeeded(); 80 81 PrintNameIfNeeded(show_type); 82 } 83 84 bool value_printed = false; 85 bool summary_printed = false; 86 87 bool val_summary_ok = PrintValueAndSummaryIfNeeded (value_printed,summary_printed); 88 89 if (val_summary_ok) 90 PrintChildrenIfNeeded (value_printed, summary_printed); 91 else 92 m_stream->EOL(); 93 94 PrintValidationErrorIfNeeded(); 95 96 return true; 97} 98 99bool 100ValueObjectPrinter::GetMostSpecializedValue () 101{ 102 if (m_valobj) 103 return true; 104 bool update_success = m_orig_valobj->UpdateValueIfNeeded (true); 105 if (!update_success) 106 { 107 m_valobj = m_orig_valobj; 108 } 109 else 110 { 111 if (m_orig_valobj->IsDynamic()) 112 { 113 if (options.m_use_dynamic == eNoDynamicValues) 114 { 115 ValueObject *static_value = m_orig_valobj->GetStaticValue().get(); 116 if (static_value) 117 m_valobj = static_value; 118 else 119 m_valobj = m_orig_valobj; 120 } 121 else 122 m_valobj = m_orig_valobj; 123 } 124 else 125 { 126 if (options.m_use_dynamic != eNoDynamicValues) 127 { 128 ValueObject *dynamic_value = m_orig_valobj->GetDynamicValue(options.m_use_dynamic).get(); 129 if (dynamic_value) 130 m_valobj = dynamic_value; 131 else 132 m_valobj = m_orig_valobj; 133 } 134 else 135 m_valobj = m_orig_valobj; 136 } 137 138 if (m_valobj->IsSynthetic()) 139 { 140 if (options.m_use_synthetic == false) 141 { 142 ValueObject *non_synthetic = m_valobj->GetNonSyntheticValue().get(); 143 if (non_synthetic) 144 m_valobj = non_synthetic; 145 } 146 } 147 else 148 { 149 if (options.m_use_synthetic == true) 150 { 151 ValueObject *synthetic = m_valobj->GetSyntheticValue().get(); 152 if (synthetic) 153 m_valobj = synthetic; 154 } 155 } 156 } 157 m_clang_type = m_valobj->GetClangType(); 158 m_type_flags = m_clang_type.GetTypeInfo (); 159 return true; 160} 161 162const char* 163ValueObjectPrinter::GetDescriptionForDisplay () 164{ 165 const char* str = m_valobj->GetObjectDescription(); 166 if (!str) 167 str = m_valobj->GetSummaryAsCString(); 168 if (!str) 169 str = m_valobj->GetValueAsCString(); 170 return str; 171} 172 173const char* 174ValueObjectPrinter::GetRootNameForDisplay (const char* if_fail) 175{ 176 const char *root_valobj_name = options.m_root_valobj_name.empty() ? 177 m_valobj->GetName().AsCString() : 178 options.m_root_valobj_name.c_str(); 179 return root_valobj_name ? root_valobj_name : if_fail; 180} 181 182bool 183ValueObjectPrinter::ShouldPrintValueObject () 184{ 185 if (m_should_print == eLazyBoolCalculate) 186 m_should_print = (options.m_flat_output == false || m_type_flags.Test (eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo; 187 return m_should_print == eLazyBoolYes; 188} 189 190bool 191ValueObjectPrinter::IsNil () 192{ 193 if (m_is_nil == eLazyBoolCalculate) 194 m_is_nil = m_valobj->IsObjCNil() ? eLazyBoolYes : eLazyBoolNo; 195 return m_is_nil == eLazyBoolYes; 196} 197 198bool 199ValueObjectPrinter::IsPtr () 200{ 201 if (m_is_ptr == eLazyBoolCalculate) 202 m_is_ptr = m_type_flags.Test (eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo; 203 return m_is_ptr == eLazyBoolYes; 204} 205 206bool 207ValueObjectPrinter::IsRef () 208{ 209 if (m_is_ref == eLazyBoolCalculate) 210 m_is_ref = m_type_flags.Test (eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo; 211 return m_is_ref == eLazyBoolYes; 212} 213 214bool 215ValueObjectPrinter::IsAggregate () 216{ 217 if (m_is_aggregate == eLazyBoolCalculate) 218 m_is_aggregate = m_type_flags.Test (eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo; 219 return m_is_aggregate == eLazyBoolYes; 220} 221 222bool 223ValueObjectPrinter::PrintLocationIfNeeded () 224{ 225 if (options.m_show_location) 226 { 227 m_stream->Printf("%s: ", m_valobj->GetLocationAsCString()); 228 return true; 229 } 230 return false; 231} 232 233bool 234ValueObjectPrinter::PrintTypeIfNeeded () 235{ 236 bool show_type = true; 237 // if we are at the root-level and been asked to hide the root's type, then hide it 238 if (m_curr_depth == 0 && options.m_hide_root_type) 239 show_type = false; 240 else 241 // otherwise decide according to the usual rules (asked to show types - always at the root level) 242 show_type = options.m_show_types || (m_curr_depth == 0 && !options.m_flat_output); 243 244 if (show_type) 245 { 246 // Some ValueObjects don't have types (like registers sets). Only print 247 // the type if there is one to print 248 ConstString type_name; 249 if (options.m_use_type_display_name) 250 type_name = m_valobj->GetDisplayTypeName(); 251 else 252 type_name = m_valobj->GetQualifiedTypeName(); 253 if (type_name) 254 m_stream->Printf("(%s) ", type_name.GetCString()); 255 else 256 show_type = false; 257 } 258 return show_type; 259} 260 261bool 262ValueObjectPrinter::PrintNameIfNeeded (bool show_type) 263{ 264 if (options.m_flat_output) 265 { 266 // If we are showing types, also qualify the C++ base classes 267 const bool qualify_cxx_base_classes = show_type; 268 if (!options.m_hide_name) 269 { 270 m_valobj->GetExpressionPath(*m_stream, qualify_cxx_base_classes); 271 m_stream->PutCString(" ="); 272 return true; 273 } 274 } 275 else if (!options.m_hide_name) 276 { 277 const char *name_cstr = GetRootNameForDisplay(""); 278 m_stream->Printf ("%s =", name_cstr); 279 return true; 280 } 281 return false; 282} 283 284bool 285ValueObjectPrinter::CheckScopeIfNeeded () 286{ 287 if (options.m_scope_already_checked) 288 return true; 289 return m_valobj->IsInScope(); 290} 291 292TypeSummaryImpl* 293ValueObjectPrinter::GetSummaryFormatter () 294{ 295 if (m_summary_formatter.second == false) 296 { 297 TypeSummaryImpl* entry = options.m_summary_sp ? options.m_summary_sp.get() : m_valobj->GetSummaryFormat().get(); 298 299 if (options.m_omit_summary_depth > 0) 300 entry = NULL; 301 m_summary_formatter.first = entry; 302 m_summary_formatter.second = true; 303 } 304 return m_summary_formatter.first; 305} 306 307void 308ValueObjectPrinter::GetValueSummaryError (std::string& value, 309 std::string& summary, 310 std::string& error) 311{ 312 if (options.m_format != eFormatDefault && options.m_format != m_valobj->GetFormat()) 313 { 314 m_valobj->GetValueAsCString(options.m_format, 315 value); 316 } 317 else 318 { 319 const char* val_cstr = m_valobj->GetValueAsCString(); 320 if (val_cstr) 321 value.assign(val_cstr); 322 } 323 const char* err_cstr = m_valobj->GetError().AsCString(); 324 if (err_cstr) 325 error.assign(err_cstr); 326 327 if (ShouldPrintValueObject()) 328 { 329 if (IsNil()) 330 summary.assign("nil"); 331 else if (options.m_omit_summary_depth == 0) 332 { 333 TypeSummaryImpl* entry = GetSummaryFormatter(); 334 if (entry) 335 m_valobj->GetSummaryAsCString(entry, summary); 336 else 337 { 338 const char* sum_cstr = m_valobj->GetSummaryAsCString(); 339 if (sum_cstr) 340 summary.assign(sum_cstr); 341 } 342 } 343 } 344} 345 346bool 347ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed, 348 bool& summary_printed) 349{ 350 bool error_printed = false; 351 if (ShouldPrintValueObject()) 352 { 353 if (!CheckScopeIfNeeded()) 354 m_error.assign("out of scope"); 355 if (m_error.empty()) 356 { 357 GetValueSummaryError(m_value, m_summary, m_error); 358 } 359 if (m_error.size()) 360 { 361 error_printed = true; 362 m_stream->Printf (" <%s>\n", m_error.c_str()); 363 } 364 else 365 { 366 // Make sure we have a value and make sure the summary didn't 367 // specify that the value should not be printed - and do not print 368 // the value if this thing is nil 369 // (but show the value if the user passes a format explicitly) 370 TypeSummaryImpl* entry = GetSummaryFormatter(); 371 if (!IsNil() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue(m_valobj) || options.m_format != eFormatDefault) || m_summary.empty()) && !options.m_hide_value) 372 { 373 m_stream->Printf(" %s", m_value.c_str()); 374 value_printed = true; 375 } 376 377 if (m_summary.size()) 378 { 379 m_stream->Printf(" %s", m_summary.c_str()); 380 summary_printed = true; 381 } 382 } 383 } 384 return !error_printed; 385} 386 387bool 388ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed, 389 bool summary_printed) 390{ 391 if (ShouldPrintValueObject()) 392 { 393 // let's avoid the overly verbose no description error for a nil thing 394 if (options.m_use_objc && !IsNil()) 395 { 396 if (!options.m_hide_value || !options.m_hide_name) 397 m_stream->Printf(" "); 398 const char *object_desc = nullptr; 399 if (value_printed || summary_printed) 400 object_desc = m_valobj->GetObjectDescription(); 401 else 402 object_desc = GetDescriptionForDisplay(); 403 if (object_desc && *object_desc) 404 { 405 m_stream->Printf("%s\n", object_desc); 406 return true; 407 } 408 else if (value_printed == false && summary_printed == false) 409 return true; 410 else 411 return false; 412 } 413 } 414 return true; 415} 416 417bool 418ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description, 419 uint32_t& curr_ptr_depth) 420{ 421 const bool is_ref = IsRef (); 422 const bool is_ptr = IsPtr (); 423 424 if (is_failed_description || m_curr_depth < options.m_max_depth) 425 { 426 // We will show children for all concrete types. We won't show 427 // pointer contents unless a pointer depth has been specified. 428 // We won't reference contents unless the reference is the 429 // root object (depth of zero). 430 431 // Use a new temporary pointer depth in case we override the 432 // current pointer depth below... 433 434 if (is_ptr || is_ref) 435 { 436 // We have a pointer or reference whose value is an address. 437 // Make sure that address is not NULL 438 AddressType ptr_address_type; 439 if (m_valobj->GetPointerValue (&ptr_address_type) == 0) 440 return false; 441 442 else if (is_ref && m_curr_depth == 0 && curr_ptr_depth == 0) 443 { 444 // If this is the root object (depth is zero) that we are showing 445 // and it is a reference, and no pointer depth has been supplied 446 // print out what it references. Don't do this at deeper depths 447 // otherwise we can end up with infinite recursion... 448 curr_ptr_depth = 1; 449 } 450 451 return (curr_ptr_depth > 0); 452 } 453 454 TypeSummaryImpl* entry = GetSummaryFormatter(); 455 456 return (!entry || entry->DoesPrintChildren(m_valobj) || m_summary.empty()); 457 } 458 return false; 459} 460 461ValueObject* 462ValueObjectPrinter::GetValueObjectForChildrenGeneration () 463{ 464 return m_valobj; 465} 466 467void 468ValueObjectPrinter::PrintChildrenPreamble () 469{ 470 if (options.m_flat_output) 471 { 472 if (ShouldPrintValueObject()) 473 m_stream->EOL(); 474 } 475 else 476 { 477 if (ShouldPrintValueObject()) 478 m_stream->PutCString(IsRef () ? ": {\n" : " {\n"); 479 m_stream->IndentMore(); 480 } 481} 482 483void 484ValueObjectPrinter::PrintChild (ValueObjectSP child_sp, 485 uint32_t curr_ptr_depth) 486{ 487 DumpValueObjectOptions child_options(options); 488 child_options.SetFormat(options.m_format).SetSummary().SetRootValueObjectName(); 489 child_options.SetScopeChecked(true).SetHideName(options.m_hide_name).SetHideValue(options.m_hide_value) 490 .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0); 491 if (child_sp.get()) 492 { 493 ValueObjectPrinter child_printer(child_sp.get(), 494 m_stream, 495 child_options, 496 (IsPtr() || IsRef()) && curr_ptr_depth >= 1 ? curr_ptr_depth - 1 : curr_ptr_depth, 497 m_curr_depth + 1); 498 child_printer.PrintValueObject(); 499 } 500 501} 502 503uint32_t 504ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot) 505{ 506 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 507 508 size_t num_children = synth_m_valobj->GetNumChildren(); 509 print_dotdotdot = false; 510 if (num_children) 511 { 512 const size_t max_num_children = m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 513 514 if (num_children > max_num_children && !options.m_ignore_cap) 515 { 516 print_dotdotdot = true; 517 return max_num_children; 518 } 519 } 520 return num_children; 521} 522 523void 524ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot) 525{ 526 if (!options.m_flat_output) 527 { 528 if (print_dotdotdot) 529 { 530 m_valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().ChildrenTruncated(); 531 m_stream->Indent("...\n"); 532 } 533 m_stream->IndentLess(); 534 m_stream->Indent("}\n"); 535 } 536} 537 538void 539ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth) 540{ 541 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 542 543 bool print_dotdotdot = false; 544 size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); 545 if (num_children) 546 { 547 PrintChildrenPreamble (); 548 549 for (size_t idx=0; idx<num_children; ++idx) 550 { 551 ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true)); 552 PrintChild (child_sp, curr_ptr_depth); 553 } 554 555 PrintChildrenPostamble (print_dotdotdot); 556 } 557 else if (IsAggregate()) 558 { 559 // Aggregate, no children... 560 if (ShouldPrintValueObject()) 561 { 562 // if it has a synthetic value, then don't print {}, the synthetic children are probably only being used to vend a value 563 if (m_valobj->DoesProvideSyntheticValue()) 564 m_stream->PutCString( "\n"); 565 else 566 m_stream->PutCString(" {}\n"); 567 } 568 } 569 else 570 { 571 if (ShouldPrintValueObject()) 572 m_stream->EOL(); 573 } 574} 575 576bool 577ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names) 578{ 579 if (!GetMostSpecializedValue () || m_valobj == nullptr) 580 return false; 581 582 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 583 584 bool print_dotdotdot = false; 585 size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); 586 587 if (num_children) 588 { 589 m_stream->PutChar('('); 590 591 for (uint32_t idx=0; idx<num_children; ++idx) 592 { 593 lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true)); 594 if (child_sp) 595 child_sp = child_sp->GetQualifiedRepresentationIfAvailable(options.m_use_dynamic, options.m_use_synthetic); 596 if (child_sp) 597 { 598 if (idx) 599 m_stream->PutCString(", "); 600 if (!hide_names) 601 { 602 const char* name = child_sp.get()->GetName().AsCString(); 603 if (name && *name) 604 { 605 m_stream->PutCString(name); 606 m_stream->PutCString(" = "); 607 } 608 } 609 child_sp->DumpPrintableRepresentation(*m_stream, 610 ValueObject::eValueObjectRepresentationStyleSummary, 611 lldb::eFormatInvalid, 612 ValueObject::ePrintableRepresentationSpecialCasesDisable); 613 } 614 } 615 616 if (print_dotdotdot) 617 m_stream->PutCString(", ...)"); 618 else 619 m_stream->PutChar(')'); 620 } 621 return true; 622} 623 624void 625ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed, 626 bool summary_printed) 627{ 628 // this flag controls whether we tried to display a description for this object and failed 629 // if that happens, we want to display the children, if any 630 bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed); 631 632 uint32_t curr_ptr_depth = m_ptr_depth; 633 bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth); 634 bool print_oneline = (curr_ptr_depth > 0 || options.m_show_types || !options.m_allow_oneliner_mode) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj); 635 636 if (print_children) 637 { 638 if (print_oneline) 639 { 640 m_stream->PutChar(' '); 641 PrintChildrenOneLiner (false); 642 m_stream->EOL(); 643 } 644 else 645 PrintChildren (curr_ptr_depth); 646 } 647 else if (m_curr_depth >= options.m_max_depth && IsAggregate() && ShouldPrintValueObject()) 648 { 649 m_stream->PutCString("{...}\n"); 650 } 651 else 652 m_stream->EOL(); 653} 654 655bool 656ValueObjectPrinter::ShouldPrintValidation () 657{ 658 return options.m_run_validator; 659} 660 661bool 662ValueObjectPrinter::PrintValidationMarkerIfNeeded () 663{ 664 if (!ShouldPrintValidation()) 665 return false; 666 667 m_validation = m_valobj->GetValidationStatus(); 668 669 if (TypeValidatorResult::Failure == m_validation.first) 670 { 671 m_stream->Printf("! "); 672 return true; 673 } 674 675 return false; 676} 677 678bool 679ValueObjectPrinter::PrintValidationErrorIfNeeded () 680{ 681 if (!ShouldPrintValidation()) 682 return false; 683 684 if (TypeValidatorResult::Success == m_validation.first) 685 return false; 686 687 if (m_validation.second.empty()) 688 m_validation.second.assign("unknown error"); 689 690 m_stream->Printf(" ! validation error: %s", m_validation.second.c_str()); 691 m_stream->EOL(); 692 693 return true; 694} 695