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