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 21 using namespace lldb; 22 using namespace lldb_private; 23 24 ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj, 25 Stream* s, 26 const DumpValueObjectOptions& options) 27 { 28 Init(valobj,s,options,options.m_max_ptr_depth,0); 29 } 30 31 ValueObjectPrinter::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 40 void 41 ValueObjectPrinter::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 66 bool 67 ValueObjectPrinter::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 95 bool 96 ValueObjectPrinter::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 139 const char* 140 ValueObjectPrinter::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 150 const char* 151 ValueObjectPrinter::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 159 bool 160 ValueObjectPrinter::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 167 bool 168 ValueObjectPrinter::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 175 bool 176 ValueObjectPrinter::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 183 bool 184 ValueObjectPrinter::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 191 bool 192 ValueObjectPrinter::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 199 bool 200 ValueObjectPrinter::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 210 bool 211 ValueObjectPrinter::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 234 bool 235 ValueObjectPrinter::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 257 bool 258 ValueObjectPrinter::CheckScopeIfNeeded () 259 { 260 if (options.m_scope_already_checked) 261 return true; 262 return m_valobj->IsInScope(); 263 } 264 265 TypeSummaryImpl* 266 ValueObjectPrinter::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 280 void 281 ValueObjectPrinter::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 319 bool 320 ValueObjectPrinter::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 360 bool 361 ValueObjectPrinter::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 390 bool 391 ValueObjectPrinter::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 if (curr_ptr_depth == 0) 426 return false; 427 } 428 429 TypeSummaryImpl* entry = GetSummaryFormatter(); 430 431 return (!entry || entry->DoesPrintChildren() || m_summary.empty()); 432 } 433 return false; 434 } 435 436 ValueObject* 437 ValueObjectPrinter::GetValueObjectForChildrenGeneration () 438 { 439 ValueObjectSP synth_valobj_sp = m_valobj->GetSyntheticValue (options.m_use_synthetic); 440 return (synth_valobj_sp ? synth_valobj_sp.get() : m_valobj); 441 } 442 443 void 444 ValueObjectPrinter::PrintChildrenPreamble () 445 { 446 if (options.m_flat_output) 447 { 448 if (ShouldPrintValueObject()) 449 m_stream->EOL(); 450 } 451 else 452 { 453 if (ShouldPrintValueObject()) 454 m_stream->PutCString(IsRef () ? ": {\n" : " {\n"); 455 m_stream->IndentMore(); 456 } 457 } 458 459 void 460 ValueObjectPrinter::PrintChild (ValueObjectSP child_sp, 461 uint32_t curr_ptr_depth) 462 { 463 DumpValueObjectOptions child_options(options); 464 child_options.SetFormat(options.m_format).SetSummary().SetRootValueObjectName(); 465 child_options.SetScopeChecked(true).SetHideName(options.m_hide_name).SetHideValue(options.m_hide_value) 466 .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0); 467 if (child_sp.get()) 468 { 469 ValueObjectPrinter child_printer(child_sp.get(), 470 m_stream, 471 child_options, 472 (IsPtr() || IsRef()) ? curr_ptr_depth - 1 : curr_ptr_depth, 473 m_curr_depth + 1); 474 child_printer.PrintValueObject(); 475 } 476 477 } 478 479 uint32_t 480 ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot) 481 { 482 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 483 484 size_t num_children = synth_m_valobj->GetNumChildren(); 485 print_dotdotdot = false; 486 if (num_children) 487 { 488 const size_t max_num_children = m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 489 490 if (num_children > max_num_children && !options.m_ignore_cap) 491 { 492 print_dotdotdot = true; 493 return max_num_children; 494 } 495 } 496 return num_children; 497 } 498 499 void 500 ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot) 501 { 502 if (!options.m_flat_output) 503 { 504 if (print_dotdotdot) 505 { 506 m_valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().ChildrenTruncated(); 507 m_stream->Indent("...\n"); 508 } 509 m_stream->IndentLess(); 510 m_stream->Indent("}\n"); 511 } 512 } 513 514 void 515 ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth) 516 { 517 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 518 519 bool print_dotdotdot = false; 520 size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); 521 if (num_children) 522 { 523 PrintChildrenPreamble (); 524 525 for (size_t idx=0; idx<num_children; ++idx) 526 { 527 ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true)); 528 PrintChild (child_sp, curr_ptr_depth); 529 } 530 531 PrintChildrenPostamble (print_dotdotdot); 532 } 533 else if (IsAggregate()) 534 { 535 // Aggregate, no children... 536 if (ShouldPrintValueObject()) 537 m_stream->PutCString(" {}\n"); 538 } 539 else 540 { 541 if (ShouldPrintValueObject()) 542 m_stream->EOL(); 543 } 544 } 545 546 bool 547 ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names) 548 { 549 if (!GetDynamicValueIfNeeded () || m_valobj == nullptr) 550 return false; 551 552 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 553 554 bool print_dotdotdot = false; 555 size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); 556 557 if (num_children) 558 { 559 m_stream->PutChar('('); 560 561 for (uint32_t idx=0; idx<num_children; ++idx) 562 { 563 lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true)); 564 lldb::ValueObjectSP child_dyn_sp = child_sp.get() ? child_sp->GetDynamicValue(options.m_use_dynamic) : child_sp; 565 if (child_dyn_sp) 566 child_sp = child_dyn_sp; 567 if (child_sp) 568 { 569 if (idx) 570 m_stream->PutCString(", "); 571 if (!hide_names) 572 { 573 const char* name = child_sp.get()->GetName().AsCString(); 574 if (name && *name) 575 { 576 m_stream->PutCString(name); 577 m_stream->PutCString(" = "); 578 } 579 } 580 child_sp->DumpPrintableRepresentation(*m_stream, 581 ValueObject::eValueObjectRepresentationStyleSummary, 582 lldb::eFormatInvalid, 583 ValueObject::ePrintableRepresentationSpecialCasesDisable); 584 } 585 } 586 587 if (print_dotdotdot) 588 m_stream->PutCString(", ...)"); 589 else 590 m_stream->PutChar(')'); 591 } 592 return true; 593 } 594 595 void 596 ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed, 597 bool summary_printed) 598 { 599 // this flag controls whether we tried to display a description for this object and failed 600 // if that happens, we want to display the children, if any 601 bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed); 602 603 uint32_t curr_ptr_depth = m_ptr_depth; 604 bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth); 605 bool print_oneline = (curr_ptr_depth > 0 || options.m_show_types || options.m_be_raw) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj); 606 607 if (print_children) 608 { 609 if (print_oneline) 610 { 611 m_stream->PutChar(' '); 612 PrintChildrenOneLiner (false); 613 m_stream->EOL(); 614 } 615 else 616 PrintChildren (curr_ptr_depth); 617 } 618 else if (m_curr_depth >= options.m_max_depth && IsAggregate() && ShouldPrintValueObject()) 619 { 620 m_stream->PutCString("{...}\n"); 621 } 622 else 623 m_stream->EOL(); 624 } 625