ValueObjectPrinter.cpp revision 276479
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; 226 if (options.m_be_raw) 227 qualified_type_name = m_valobj->GetQualifiedTypeName(); 228 else 229 qualified_type_name = m_valobj->GetDisplayTypeName(); 230 if (qualified_type_name) 231 m_stream->Printf("(%s) ", qualified_type_name.GetCString()); 232 else 233 show_type = false; 234 } 235 return show_type; 236} 237 238bool 239ValueObjectPrinter::PrintNameIfNeeded (bool show_type) 240{ 241 if (options.m_flat_output) 242 { 243 // If we are showing types, also qualify the C++ base classes 244 const bool qualify_cxx_base_classes = show_type; 245 if (!options.m_hide_name) 246 { 247 m_valobj->GetExpressionPath(*m_stream, qualify_cxx_base_classes); 248 m_stream->PutCString(" ="); 249 return true; 250 } 251 } 252 else if (!options.m_hide_name) 253 { 254 const char *name_cstr = GetRootNameForDisplay(""); 255 m_stream->Printf ("%s =", name_cstr); 256 return true; 257 } 258 return false; 259} 260 261bool 262ValueObjectPrinter::CheckScopeIfNeeded () 263{ 264 if (options.m_scope_already_checked) 265 return true; 266 return m_valobj->IsInScope(); 267} 268 269TypeSummaryImpl* 270ValueObjectPrinter::GetSummaryFormatter () 271{ 272 if (m_summary_formatter.second == false) 273 { 274 TypeSummaryImpl* entry = options.m_summary_sp ? options.m_summary_sp.get() : m_valobj->GetSummaryFormat().get(); 275 276 if (options.m_omit_summary_depth > 0) 277 entry = NULL; 278 m_summary_formatter.first = entry; 279 m_summary_formatter.second = true; 280 } 281 return m_summary_formatter.first; 282} 283 284void 285ValueObjectPrinter::GetValueSummaryError (std::string& value, 286 std::string& summary, 287 std::string& error) 288{ 289 if (options.m_format != eFormatDefault && options.m_format != m_valobj->GetFormat()) 290 { 291 m_valobj->GetValueAsCString(options.m_format, 292 value); 293 } 294 else 295 { 296 const char* val_cstr = m_valobj->GetValueAsCString(); 297 if (val_cstr) 298 value.assign(val_cstr); 299 } 300 const char* err_cstr = m_valobj->GetError().AsCString(); 301 if (err_cstr) 302 error.assign(err_cstr); 303 304 if (ShouldPrintValueObject()) 305 { 306 if (IsNil()) 307 summary.assign("nil"); 308 else if (options.m_omit_summary_depth == 0) 309 { 310 TypeSummaryImpl* entry = GetSummaryFormatter(); 311 if (entry) 312 m_valobj->GetSummaryAsCString(entry, summary); 313 else 314 { 315 const char* sum_cstr = m_valobj->GetSummaryAsCString(); 316 if (sum_cstr) 317 summary.assign(sum_cstr); 318 } 319 } 320 } 321} 322 323bool 324ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed, 325 bool& summary_printed) 326{ 327 bool error_printed = false; 328 if (ShouldPrintValueObject()) 329 { 330 if (!CheckScopeIfNeeded()) 331 m_error.assign("out of scope"); 332 if (m_error.empty()) 333 { 334 GetValueSummaryError(m_value, m_summary, m_error); 335 } 336 if (m_error.size()) 337 { 338 error_printed = true; 339 m_stream->Printf (" <%s>\n", m_error.c_str()); 340 } 341 else 342 { 343 // Make sure we have a value and make sure the summary didn't 344 // specify that the value should not be printed - and do not print 345 // the value if this thing is nil 346 // (but show the value if the user passes a format explicitly) 347 TypeSummaryImpl* entry = GetSummaryFormatter(); 348 if (!IsNil() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue(m_valobj) || options.m_format != eFormatDefault) || m_summary.empty()) && !options.m_hide_value) 349 { 350 m_stream->Printf(" %s", m_value.c_str()); 351 value_printed = true; 352 } 353 354 if (m_summary.size()) 355 { 356 m_stream->Printf(" %s", m_summary.c_str()); 357 summary_printed = true; 358 } 359 } 360 } 361 return !error_printed; 362} 363 364bool 365ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed, 366 bool summary_printed) 367{ 368 if (ShouldPrintValueObject()) 369 { 370 // let's avoid the overly verbose no description error for a nil thing 371 if (options.m_use_objc && !IsNil()) 372 { 373 if (!options.m_hide_value || !options.m_hide_name) 374 m_stream->Printf(" "); 375 const char *object_desc = nullptr; 376 if (value_printed || summary_printed) 377 object_desc = m_valobj->GetObjectDescription(); 378 else 379 object_desc = GetDescriptionForDisplay(); 380 if (object_desc && *object_desc) 381 { 382 m_stream->Printf("%s\n", object_desc); 383 return true; 384 } 385 else if (value_printed == false && summary_printed == false) 386 return true; 387 else 388 return false; 389 } 390 } 391 return true; 392} 393 394bool 395ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description, 396 uint32_t& curr_ptr_depth) 397{ 398 const bool is_ref = IsRef (); 399 const bool is_ptr = IsPtr (); 400 401 if (is_failed_description || m_curr_depth < options.m_max_depth) 402 { 403 // We will show children for all concrete types. We won't show 404 // pointer contents unless a pointer depth has been specified. 405 // We won't reference contents unless the reference is the 406 // root object (depth of zero). 407 408 // Use a new temporary pointer depth in case we override the 409 // current pointer depth below... 410 411 if (is_ptr || is_ref) 412 { 413 // We have a pointer or reference whose value is an address. 414 // Make sure that address is not NULL 415 AddressType ptr_address_type; 416 if (m_valobj->GetPointerValue (&ptr_address_type) == 0) 417 return false; 418 419 else if (is_ref && m_curr_depth == 0 && curr_ptr_depth == 0) 420 { 421 // If this is the root object (depth is zero) that we are showing 422 // and it is a reference, and no pointer depth has been supplied 423 // print out what it references. Don't do this at deeper depths 424 // otherwise we can end up with infinite recursion... 425 curr_ptr_depth = 1; 426 } 427 428 return (curr_ptr_depth > 0); 429 } 430 431 TypeSummaryImpl* entry = GetSummaryFormatter(); 432 433 return (!entry || entry->DoesPrintChildren(m_valobj) || m_summary.empty()); 434 } 435 return false; 436} 437 438ValueObject* 439ValueObjectPrinter::GetValueObjectForChildrenGeneration () 440{ 441 ValueObjectSP synth_valobj_sp = m_valobj->GetSyntheticValue (options.m_use_synthetic); 442 return (synth_valobj_sp ? synth_valobj_sp.get() : m_valobj); 443} 444 445void 446ValueObjectPrinter::PrintChildrenPreamble () 447{ 448 if (options.m_flat_output) 449 { 450 if (ShouldPrintValueObject()) 451 m_stream->EOL(); 452 } 453 else 454 { 455 if (ShouldPrintValueObject()) 456 m_stream->PutCString(IsRef () ? ": {\n" : " {\n"); 457 m_stream->IndentMore(); 458 } 459} 460 461void 462ValueObjectPrinter::PrintChild (ValueObjectSP child_sp, 463 uint32_t curr_ptr_depth) 464{ 465 DumpValueObjectOptions child_options(options); 466 child_options.SetFormat(options.m_format).SetSummary().SetRootValueObjectName(); 467 child_options.SetScopeChecked(true).SetHideName(options.m_hide_name).SetHideValue(options.m_hide_value) 468 .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0); 469 if (child_sp.get()) 470 { 471 ValueObjectPrinter child_printer(child_sp.get(), 472 m_stream, 473 child_options, 474 (IsPtr() || IsRef()) && curr_ptr_depth >= 1 ? curr_ptr_depth - 1 : curr_ptr_depth, 475 m_curr_depth + 1); 476 child_printer.PrintValueObject(); 477 } 478 479} 480 481uint32_t 482ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot) 483{ 484 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 485 486 size_t num_children = synth_m_valobj->GetNumChildren(); 487 print_dotdotdot = false; 488 if (num_children) 489 { 490 const size_t max_num_children = m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 491 492 if (num_children > max_num_children && !options.m_ignore_cap) 493 { 494 print_dotdotdot = true; 495 return max_num_children; 496 } 497 } 498 return num_children; 499} 500 501void 502ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot) 503{ 504 if (!options.m_flat_output) 505 { 506 if (print_dotdotdot) 507 { 508 m_valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().ChildrenTruncated(); 509 m_stream->Indent("...\n"); 510 } 511 m_stream->IndentLess(); 512 m_stream->Indent("}\n"); 513 } 514} 515 516void 517ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth) 518{ 519 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 520 521 bool print_dotdotdot = false; 522 size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); 523 if (num_children) 524 { 525 PrintChildrenPreamble (); 526 527 for (size_t idx=0; idx<num_children; ++idx) 528 { 529 ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true)); 530 PrintChild (child_sp, curr_ptr_depth); 531 } 532 533 PrintChildrenPostamble (print_dotdotdot); 534 } 535 else if (IsAggregate()) 536 { 537 // Aggregate, no children... 538 if (ShouldPrintValueObject()) 539 m_stream->PutCString(" {}\n"); 540 } 541 else 542 { 543 if (ShouldPrintValueObject()) 544 m_stream->EOL(); 545 } 546} 547 548bool 549ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names) 550{ 551 if (!GetDynamicValueIfNeeded () || m_valobj == nullptr) 552 return false; 553 554 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 555 556 bool print_dotdotdot = false; 557 size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); 558 559 if (num_children) 560 { 561 m_stream->PutChar('('); 562 563 for (uint32_t idx=0; idx<num_children; ++idx) 564 { 565 lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true)); 566 lldb::ValueObjectSP child_dyn_sp = child_sp.get() ? child_sp->GetDynamicValue(options.m_use_dynamic) : child_sp; 567 if (child_dyn_sp) 568 child_sp = child_dyn_sp; 569 if (child_sp) 570 { 571 if (idx) 572 m_stream->PutCString(", "); 573 if (!hide_names) 574 { 575 const char* name = child_sp.get()->GetName().AsCString(); 576 if (name && *name) 577 { 578 m_stream->PutCString(name); 579 m_stream->PutCString(" = "); 580 } 581 } 582 child_sp->DumpPrintableRepresentation(*m_stream, 583 ValueObject::eValueObjectRepresentationStyleSummary, 584 lldb::eFormatInvalid, 585 ValueObject::ePrintableRepresentationSpecialCasesDisable); 586 } 587 } 588 589 if (print_dotdotdot) 590 m_stream->PutCString(", ...)"); 591 else 592 m_stream->PutChar(')'); 593 } 594 return true; 595} 596 597void 598ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed, 599 bool summary_printed) 600{ 601 // this flag controls whether we tried to display a description for this object and failed 602 // if that happens, we want to display the children, if any 603 bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed); 604 605 uint32_t curr_ptr_depth = m_ptr_depth; 606 bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth); 607 bool print_oneline = (curr_ptr_depth > 0 || options.m_show_types || options.m_be_raw) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj); 608 609 if (print_children) 610 { 611 if (print_oneline) 612 { 613 m_stream->PutChar(' '); 614 PrintChildrenOneLiner (false); 615 m_stream->EOL(); 616 } 617 else 618 PrintChildren (curr_ptr_depth); 619 } 620 else if (m_curr_depth >= options.m_max_depth && IsAggregate() && ShouldPrintValueObject()) 621 { 622 m_stream->PutCString("{...}\n"); 623 } 624 else 625 m_stream->EOL(); 626} 627