ValueObjectPrinter.cpp revision 263363
1131087Smarcel//===-- ValueObjectPrinter.cpp -------------------------------------*- C++ -*-===// 2131087Smarcel// 3131087Smarcel// The LLVM Compiler Infrastructure 4131087Smarcel// 5131087Smarcel// This file is distributed under the University of Illinois Open Source 6131087Smarcel// License. See LICENSE.TXT for details. 7131087Smarcel// 8131087Smarcel//===----------------------------------------------------------------------===// 9131087Smarcel 10131087Smarcel#include "lldb/DataFormatters/ValueObjectPrinter.h" 11131087Smarcel 12131087Smarcel// C Includes 13131087Smarcel// C++ Includes 14131087Smarcel// Other libraries and framework includes 15131087Smarcel// Project includes 16131087Smarcel#include "lldb/Core/Debugger.h" 17131087Smarcel#include "lldb/DataFormatters/DataVisualization.h" 18131087Smarcel#include "lldb/Interpreter/CommandInterpreter.h" 19131087Smarcel#include "lldb/Target/Target.h" 20131087Smarcel 21131087Smarcelusing namespace lldb; 22136661Sacheusing namespace lldb_private; 23211243Swill 24131087SmarcelValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj, 25131087Smarcel Stream* s, 26136661Sache const DumpValueObjectOptions& options) 27211243Swill{ 28131087Smarcel Init(valobj,s,options,options.m_max_ptr_depth,0); 29136661Sache} 30136661Sache 31136661SacheValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj, 32131087Smarcel 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 uint32_t curr_ptr_depth = m_ptr_depth; 407 408 if (is_ptr || is_ref) 409 { 410 // We have a pointer or reference whose value is an address. 411 // Make sure that address is not NULL 412 AddressType ptr_address_type; 413 if (m_valobj->GetPointerValue (&ptr_address_type) == 0) 414 return false; 415 416 else if (is_ref && m_curr_depth == 0) 417 { 418 // If this is the root object (depth is zero) that we are showing 419 // and it is a reference, and no pointer depth has been supplied 420 // print out what it references. Don't do this at deeper depths 421 // otherwise we can end up with infinite recursion... 422 curr_ptr_depth = 1; 423 } 424 425 return (curr_ptr_depth > 0); 426 } 427 428 TypeSummaryImpl* entry = GetSummaryFormatter(); 429 430 return (!entry || entry->DoesPrintChildren() || m_summary.empty()); 431 } 432 return false; 433} 434 435ValueObject* 436ValueObjectPrinter::GetValueObjectForChildrenGeneration () 437{ 438 ValueObjectSP synth_valobj_sp = m_valobj->GetSyntheticValue (options.m_use_synthetic); 439 return (synth_valobj_sp ? synth_valobj_sp.get() : m_valobj); 440} 441 442void 443ValueObjectPrinter::PrintChildrenPreamble () 444{ 445 if (options.m_flat_output) 446 { 447 if (ShouldPrintValueObject()) 448 m_stream->EOL(); 449 } 450 else 451 { 452 if (ShouldPrintValueObject()) 453 m_stream->PutCString(IsRef () ? ": {\n" : " {\n"); 454 m_stream->IndentMore(); 455 } 456} 457 458void 459ValueObjectPrinter::PrintChild (ValueObjectSP child_sp, 460 uint32_t curr_ptr_depth) 461{ 462 DumpValueObjectOptions child_options(options); 463 child_options.SetFormat(options.m_format).SetSummary().SetRootValueObjectName(); 464 child_options.SetScopeChecked(true).SetHideName(options.m_hide_name).SetHideValue(options.m_hide_value) 465 .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0); 466 if (child_sp.get()) 467 { 468 ValueObjectPrinter child_printer(child_sp.get(), 469 m_stream, 470 child_options, 471 (IsPtr() || IsRef()) ? curr_ptr_depth - 1 : curr_ptr_depth, 472 m_curr_depth + 1); 473 child_printer.PrintValueObject(); 474 } 475 476} 477 478uint32_t 479ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot) 480{ 481 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 482 483 size_t num_children = synth_m_valobj->GetNumChildren(); 484 print_dotdotdot = false; 485 if (num_children) 486 { 487 const size_t max_num_children = m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 488 489 if (num_children > max_num_children && !options.m_ignore_cap) 490 { 491 print_dotdotdot = true; 492 return max_num_children; 493 } 494 } 495 return num_children; 496} 497 498void 499ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot) 500{ 501 if (!options.m_flat_output) 502 { 503 if (print_dotdotdot) 504 { 505 m_valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().ChildrenTruncated(); 506 m_stream->Indent("...\n"); 507 } 508 m_stream->IndentLess(); 509 m_stream->Indent("}\n"); 510 } 511} 512 513void 514ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth) 515{ 516 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 517 518 bool print_dotdotdot = false; 519 size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); 520 if (num_children) 521 { 522 PrintChildrenPreamble (); 523 524 for (size_t idx=0; idx<num_children; ++idx) 525 { 526 ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true)); 527 PrintChild (child_sp, curr_ptr_depth); 528 } 529 530 PrintChildrenPostamble (print_dotdotdot); 531 } 532 else if (IsAggregate()) 533 { 534 // Aggregate, no children... 535 if (ShouldPrintValueObject()) 536 m_stream->PutCString(" {}\n"); 537 } 538 else 539 { 540 if (ShouldPrintValueObject()) 541 m_stream->EOL(); 542 } 543} 544 545bool 546ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names) 547{ 548 if (!GetDynamicValueIfNeeded () || m_valobj == nullptr) 549 return false; 550 551 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 552 553 bool print_dotdotdot = false; 554 size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); 555 556 if (num_children) 557 { 558 m_stream->PutChar('('); 559 560 for (uint32_t idx=0; idx<num_children; ++idx) 561 { 562 lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true)); 563 lldb::ValueObjectSP child_dyn_sp = child_sp.get() ? child_sp->GetDynamicValue(options.m_use_dynamic) : child_sp; 564 if (child_dyn_sp) 565 child_sp = child_dyn_sp; 566 if (child_sp) 567 { 568 if (idx) 569 m_stream->PutCString(", "); 570 if (!hide_names) 571 { 572 const char* name = child_sp.get()->GetName().AsCString(); 573 if (name && *name) 574 { 575 m_stream->PutCString(name); 576 m_stream->PutCString(" = "); 577 } 578 } 579 child_sp->DumpPrintableRepresentation(*m_stream, 580 ValueObject::eValueObjectRepresentationStyleSummary, 581 lldb::eFormatInvalid, 582 ValueObject::ePrintableRepresentationSpecialCasesDisable); 583 } 584 } 585 586 if (print_dotdotdot) 587 m_stream->PutCString(", ...)"); 588 else 589 m_stream->PutChar(')'); 590 } 591 return true; 592} 593 594void 595ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed, 596 bool summary_printed) 597{ 598 // this flag controls whether we tried to display a description for this object and failed 599 // if that happens, we want to display the children, if any 600 bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed); 601 602 uint32_t curr_ptr_depth = m_ptr_depth; 603 bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth); 604 bool print_oneline = (curr_ptr_depth > 0 || options.m_show_types || options.m_be_raw) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj); 605 606 if (print_children) 607 { 608 if (print_oneline) 609 { 610 m_stream->PutChar(' '); 611 PrintChildrenOneLiner (false); 612 m_stream->EOL(); 613 } 614 else 615 PrintChildren (curr_ptr_depth); 616 } 617 else if (m_curr_depth >= options.m_max_depth && IsAggregate() && ShouldPrintValueObject()) 618 { 619 m_stream->PutCString("{...}\n"); 620 } 621 else 622 m_stream->EOL(); 623} 624