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