LLDB  mainline
FormatManager.cpp
Go to the documentation of this file.
1 //===-- FormatManager.cpp ----------------------------------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 
11 #include "llvm/ADT/STLExtras.h"
12 
13 
14 #include "lldb/Core/Debugger.h"
18 #include "lldb/Target/Language.h"
19 #include "lldb/Utility/Log.h"
20 
21 using namespace lldb;
22 using namespace lldb_private;
23 using namespace lldb_private::formatters;
24 
25 struct FormatInfo {
27  const char format_char; // One or more format characters that can be used for
28  // this format.
29  const char *format_name; // Long format name that can be used to specify the
30  // current format
31 };
32 
34  {eFormatDefault, '\0', "default"},
35  {eFormatBoolean, 'B', "boolean"},
36  {eFormatBinary, 'b', "binary"},
37  {eFormatBytes, 'y', "bytes"},
38  {eFormatBytesWithASCII, 'Y', "bytes with ASCII"},
39  {eFormatChar, 'c', "character"},
40  {eFormatCharPrintable, 'C', "printable character"},
41  {eFormatComplexFloat, 'F', "complex float"},
42  {eFormatCString, 's', "c-string"},
43  {eFormatDecimal, 'd', "decimal"},
44  {eFormatEnum, 'E', "enumeration"},
45  {eFormatHex, 'x', "hex"},
46  {eFormatHexUppercase, 'X', "uppercase hex"},
47  {eFormatFloat, 'f', "float"},
48  {eFormatOctal, 'o', "octal"},
49  {eFormatOSType, 'O', "OSType"},
50  {eFormatUnicode16, 'U', "unicode16"},
51  {eFormatUnicode32, '\0', "unicode32"},
52  {eFormatUnsigned, 'u', "unsigned decimal"},
53  {eFormatPointer, 'p', "pointer"},
54  {eFormatVectorOfChar, '\0', "char[]"},
55  {eFormatVectorOfSInt8, '\0', "int8_t[]"},
56  {eFormatVectorOfUInt8, '\0', "uint8_t[]"},
57  {eFormatVectorOfSInt16, '\0', "int16_t[]"},
58  {eFormatVectorOfUInt16, '\0', "uint16_t[]"},
59  {eFormatVectorOfSInt32, '\0', "int32_t[]"},
60  {eFormatVectorOfUInt32, '\0', "uint32_t[]"},
61  {eFormatVectorOfSInt64, '\0', "int64_t[]"},
62  {eFormatVectorOfUInt64, '\0', "uint64_t[]"},
63  {eFormatVectorOfFloat16, '\0', "float16[]"},
64  {eFormatVectorOfFloat32, '\0', "float32[]"},
65  {eFormatVectorOfFloat64, '\0', "float64[]"},
66  {eFormatVectorOfUInt128, '\0', "uint128_t[]"},
67  {eFormatComplexInteger, 'I', "complex integer"},
68  {eFormatCharArray, 'a', "character array"},
69  {eFormatAddressInfo, 'A', "address"},
70  {eFormatHexFloat, '\0', "hex float"},
71  {eFormatInstruction, 'i', "instruction"},
72  {eFormatVoid, 'v', "void"}};
73 
74 static uint32_t g_num_format_infos = llvm::array_lengthof(g_format_infos);
75 
76 static bool GetFormatFromFormatChar(char format_char, Format &format) {
77  for (uint32_t i = 0; i < g_num_format_infos; ++i) {
78  if (g_format_infos[i].format_char == format_char) {
79  format = g_format_infos[i].format;
80  return true;
81  }
82  }
83  format = eFormatInvalid;
84  return false;
85 }
86 
87 static bool GetFormatFromFormatName(const char *format_name,
88  bool partial_match_ok, Format &format) {
89  uint32_t i;
90  for (i = 0; i < g_num_format_infos; ++i) {
91  if (strcasecmp(g_format_infos[i].format_name, format_name) == 0) {
92  format = g_format_infos[i].format;
93  return true;
94  }
95  }
96 
97  if (partial_match_ok) {
98  for (i = 0; i < g_num_format_infos; ++i) {
99  if (strcasestr(g_format_infos[i].format_name, format_name) ==
100  g_format_infos[i].format_name) {
101  format = g_format_infos[i].format;
102  return true;
103  }
104  }
105  }
106  format = eFormatInvalid;
107  return false;
108 }
109 
110 void FormatManager::Changed() {
111  ++m_last_revision;
112  m_format_cache.Clear();
113  std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
114  for (auto &iter : m_language_categories_map) {
115  if (iter.second)
116  iter.second->GetFormatCache().Clear();
117  }
118 }
119 
120 bool FormatManager::GetFormatFromCString(const char *format_cstr,
121  bool partial_match_ok,
122  lldb::Format &format) {
123  bool success = false;
124  if (format_cstr && format_cstr[0]) {
125  if (format_cstr[1] == '\0') {
126  success = GetFormatFromFormatChar(format_cstr[0], format);
127  if (success)
128  return true;
129  }
130 
131  success = GetFormatFromFormatName(format_cstr, partial_match_ok, format);
132  }
133  if (!success)
134  format = eFormatInvalid;
135  return success;
136 }
137 
138 char FormatManager::GetFormatAsFormatChar(lldb::Format format) {
139  for (uint32_t i = 0; i < g_num_format_infos; ++i) {
140  if (g_format_infos[i].format == format)
141  return g_format_infos[i].format_char;
142  }
143  return '\0';
144 }
145 
146 const char *FormatManager::GetFormatAsCString(Format format) {
147  if (format >= eFormatDefault && format < kNumFormats)
148  return g_format_infos[format].format_name;
149  return NULL;
150 }
151 
152 void FormatManager::EnableAllCategories() {
153  m_categories_map.EnableAllCategories();
154  std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
155  for (auto &iter : m_language_categories_map) {
156  if (iter.second)
157  iter.second->Enable();
158  }
159 }
160 
161 void FormatManager::DisableAllCategories() {
162  m_categories_map.DisableAllCategories();
163  std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
164  for (auto &iter : m_language_categories_map) {
165  if (iter.second)
166  iter.second->Disable();
167  }
168 }
169 
170 void FormatManager::GetPossibleMatches(
171  ValueObject &valobj, CompilerType compiler_type, uint32_t reason,
172  lldb::DynamicValueType use_dynamic, FormattersMatchVector &entries,
173  bool did_strip_ptr, bool did_strip_ref, bool did_strip_typedef,
174  bool root_level) {
175  compiler_type = compiler_type.GetTypeForFormatters();
176  ConstString type_name(compiler_type.GetConstTypeName());
177  if (valobj.GetBitfieldBitSize() > 0) {
178  StreamString sstring;
179  sstring.Printf("%s:%d", type_name.AsCString(), valobj.GetBitfieldBitSize());
180  ConstString bitfieldname(sstring.GetString());
181  entries.push_back(
182  {bitfieldname, 0, did_strip_ptr, did_strip_ref, did_strip_typedef});
184  }
185 
186  if (!compiler_type.IsMeaninglessWithoutDynamicResolution()) {
187  entries.push_back(
188  {type_name, reason, did_strip_ptr, did_strip_ref, did_strip_typedef});
189 
190  ConstString display_type_name(compiler_type.GetDisplayTypeName());
191  if (display_type_name != type_name)
192  entries.push_back({display_type_name, reason, did_strip_ptr,
193  did_strip_ref, did_strip_typedef});
194  }
195 
196  for (bool is_rvalue_ref = true, j = true;
197  j && compiler_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false) {
198  CompilerType non_ref_type = compiler_type.GetNonReferenceType();
199  GetPossibleMatches(
200  valobj, non_ref_type,
201  reason |
203  use_dynamic, entries, did_strip_ptr, true, did_strip_typedef);
204  if (non_ref_type.IsTypedefType()) {
205  CompilerType deffed_referenced_type = non_ref_type.GetTypedefedType();
206  deffed_referenced_type =
207  is_rvalue_ref ? deffed_referenced_type.GetRValueReferenceType()
208  : deffed_referenced_type.GetLValueReferenceType();
209  GetPossibleMatches(
210  valobj, deffed_referenced_type,
212  use_dynamic, entries, did_strip_ptr, did_strip_ref,
213  true); // this is not exactly the usual meaning of stripping typedefs
214  }
215  }
216 
217  if (compiler_type.IsPointerType()) {
218  CompilerType non_ptr_type = compiler_type.GetPointeeType();
219  GetPossibleMatches(
220  valobj, non_ptr_type,
221  reason |
223  use_dynamic, entries, true, did_strip_ref, did_strip_typedef);
224  if (non_ptr_type.IsTypedefType()) {
225  CompilerType deffed_pointed_type =
226  non_ptr_type.GetTypedefedType().GetPointerType();
227  GetPossibleMatches(
228  valobj, deffed_pointed_type,
230  use_dynamic, entries, did_strip_ptr, did_strip_ref,
231  true); // this is not exactly the usual meaning of stripping typedefs
232  }
233  }
234 
235  for (lldb::LanguageType language_type : GetCandidateLanguages(valobj)) {
236  if (Language *language = Language::FindPlugin(language_type)) {
237  for (ConstString candidate :
238  language->GetPossibleFormattersMatches(valobj, use_dynamic)) {
239  entries.push_back(
240  {candidate,
242  did_strip_ptr, did_strip_ref, did_strip_typedef});
243  }
244  }
245  }
246 
247  // try to strip typedef chains
248  if (compiler_type.IsTypedefType()) {
249  CompilerType deffed_type = compiler_type.GetTypedefedType();
250  GetPossibleMatches(
251  valobj, deffed_type,
253  use_dynamic, entries, did_strip_ptr, did_strip_ref, true);
254  }
255 
256  if (root_level) {
257  do {
258  if (!compiler_type.IsValid())
259  break;
260 
261  CompilerType unqual_compiler_ast_type =
262  compiler_type.GetFullyUnqualifiedType();
263  if (!unqual_compiler_ast_type.IsValid())
264  break;
265  if (unqual_compiler_ast_type.GetOpaqueQualType() !=
266  compiler_type.GetOpaqueQualType())
267  GetPossibleMatches(valobj, unqual_compiler_ast_type, reason,
268  use_dynamic, entries, did_strip_ptr, did_strip_ref,
269  did_strip_typedef);
270  } while (false);
271 
272  // if all else fails, go to static type
273  if (valobj.IsDynamic()) {
274  lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue());
275  if (static_value_sp)
276  GetPossibleMatches(
277  *static_value_sp.get(), static_value_sp->GetCompilerType(),
279  use_dynamic, entries, did_strip_ptr, did_strip_ref,
280  did_strip_typedef, true);
281  }
282  }
283 }
284 
285 lldb::TypeFormatImplSP
286 FormatManager::GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp) {
287  if (!type_sp)
288  return lldb::TypeFormatImplSP();
289  lldb::TypeFormatImplSP format_chosen_sp;
290  uint32_t num_categories = m_categories_map.GetCount();
291  lldb::TypeCategoryImplSP category_sp;
292  uint32_t prio_category = UINT32_MAX;
293  for (uint32_t category_id = 0; category_id < num_categories; category_id++) {
294  category_sp = GetCategoryAtIndex(category_id);
295  if (!category_sp->IsEnabled())
296  continue;
297  lldb::TypeFormatImplSP format_current_sp =
298  category_sp->GetFormatForType(type_sp);
299  if (format_current_sp &&
300  (format_chosen_sp.get() == NULL ||
301  (prio_category > category_sp->GetEnabledPosition()))) {
302  prio_category = category_sp->GetEnabledPosition();
303  format_chosen_sp = format_current_sp;
304  }
305  }
306  return format_chosen_sp;
307 }
308 
309 lldb::TypeSummaryImplSP
310 FormatManager::GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp) {
311  if (!type_sp)
312  return lldb::TypeSummaryImplSP();
313  lldb::TypeSummaryImplSP summary_chosen_sp;
314  uint32_t num_categories = m_categories_map.GetCount();
315  lldb::TypeCategoryImplSP category_sp;
316  uint32_t prio_category = UINT32_MAX;
317  for (uint32_t category_id = 0; category_id < num_categories; category_id++) {
318  category_sp = GetCategoryAtIndex(category_id);
319  if (!category_sp->IsEnabled())
320  continue;
321  lldb::TypeSummaryImplSP summary_current_sp =
322  category_sp->GetSummaryForType(type_sp);
323  if (summary_current_sp &&
324  (summary_chosen_sp.get() == NULL ||
325  (prio_category > category_sp->GetEnabledPosition()))) {
326  prio_category = category_sp->GetEnabledPosition();
327  summary_chosen_sp = summary_current_sp;
328  }
329  }
330  return summary_chosen_sp;
331 }
332 
333 lldb::TypeFilterImplSP
334 FormatManager::GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp) {
335  if (!type_sp)
336  return lldb::TypeFilterImplSP();
337  lldb::TypeFilterImplSP filter_chosen_sp;
338  uint32_t num_categories = m_categories_map.GetCount();
339  lldb::TypeCategoryImplSP category_sp;
340  uint32_t prio_category = UINT32_MAX;
341  for (uint32_t category_id = 0; category_id < num_categories; category_id++) {
342  category_sp = GetCategoryAtIndex(category_id);
343  if (!category_sp->IsEnabled())
344  continue;
345  lldb::TypeFilterImplSP filter_current_sp(
346  (TypeFilterImpl *)category_sp->GetFilterForType(type_sp).get());
347  if (filter_current_sp &&
348  (filter_chosen_sp.get() == NULL ||
349  (prio_category > category_sp->GetEnabledPosition()))) {
350  prio_category = category_sp->GetEnabledPosition();
351  filter_chosen_sp = filter_current_sp;
352  }
353  }
354  return filter_chosen_sp;
355 }
356 
357 lldb::ScriptedSyntheticChildrenSP
358 FormatManager::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) {
359  if (!type_sp)
360  return lldb::ScriptedSyntheticChildrenSP();
361  lldb::ScriptedSyntheticChildrenSP synth_chosen_sp;
362  uint32_t num_categories = m_categories_map.GetCount();
363  lldb::TypeCategoryImplSP category_sp;
364  uint32_t prio_category = UINT32_MAX;
365  for (uint32_t category_id = 0; category_id < num_categories; category_id++) {
366  category_sp = GetCategoryAtIndex(category_id);
367  if (!category_sp->IsEnabled())
368  continue;
369  lldb::ScriptedSyntheticChildrenSP synth_current_sp(
370  (ScriptedSyntheticChildren *)category_sp->GetSyntheticForType(type_sp)
371  .get());
372  if (synth_current_sp &&
373  (synth_chosen_sp.get() == NULL ||
374  (prio_category > category_sp->GetEnabledPosition()))) {
375  prio_category = category_sp->GetEnabledPosition();
376  synth_chosen_sp = synth_current_sp;
377  }
378  }
379  return synth_chosen_sp;
380 }
381 
382 lldb::TypeValidatorImplSP
383 FormatManager::GetValidatorForType(lldb::TypeNameSpecifierImplSP type_sp) {
384  if (!type_sp)
385  return lldb::TypeValidatorImplSP();
386  lldb::TypeValidatorImplSP validator_chosen_sp;
387  uint32_t num_categories = m_categories_map.GetCount();
388  lldb::TypeCategoryImplSP category_sp;
389  uint32_t prio_category = UINT32_MAX;
390  for (uint32_t category_id = 0; category_id < num_categories; category_id++) {
391  category_sp = GetCategoryAtIndex(category_id);
392  if (!category_sp->IsEnabled())
393  continue;
394  lldb::TypeValidatorImplSP validator_current_sp(
395  category_sp->GetValidatorForType(type_sp).get());
396  if (validator_current_sp &&
397  (validator_chosen_sp.get() == NULL ||
398  (prio_category > category_sp->GetEnabledPosition()))) {
399  prio_category = category_sp->GetEnabledPosition();
400  validator_chosen_sp = validator_current_sp;
401  }
402  }
403  return validator_chosen_sp;
404 }
405 
406 void FormatManager::ForEachCategory(TypeCategoryMap::ForEachCallback callback) {
407  m_categories_map.ForEach(callback);
408  std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
409  for (const auto &entry : m_language_categories_map) {
410  if (auto category_sp = entry.second->GetCategory()) {
411  if (!callback(category_sp))
412  break;
413  }
414  }
415 }
416 
417 lldb::TypeCategoryImplSP
418 FormatManager::GetCategory(ConstString category_name, bool can_create) {
419  if (!category_name)
420  return GetCategory(m_default_category_name);
421  lldb::TypeCategoryImplSP category;
422  if (m_categories_map.Get(category_name, category))
423  return category;
424 
425  if (!can_create)
426  return lldb::TypeCategoryImplSP();
427 
428  m_categories_map.Add(
429  category_name,
430  lldb::TypeCategoryImplSP(new TypeCategoryImpl(this, category_name)));
431  return GetCategory(category_name);
432 }
433 
434 lldb::Format FormatManager::GetSingleItemFormat(lldb::Format vector_format) {
435  switch (vector_format) {
436  case eFormatVectorOfChar:
437  return eFormatCharArray;
438 
443  return eFormatDecimal;
444 
450  return eFormatHex;
451 
455  return eFormatFloat;
456 
457  default:
458  return lldb::eFormatInvalid;
459  }
460 }
461 
462 bool FormatManager::ShouldPrintAsOneLiner(ValueObject &valobj) {
463  // if settings say no oneline whatsoever
464  if (valobj.GetTargetSP().get() &&
465  !valobj.GetTargetSP()->GetDebugger().GetAutoOneLineSummaries())
466  return false; // then don't oneline
467 
468  // if this object has a summary, then ask the summary
469  if (valobj.GetSummaryFormat().get() != nullptr)
470  return valobj.GetSummaryFormat()->IsOneLiner();
471 
472  // no children, no party
473  if (valobj.GetNumChildren() == 0)
474  return false;
475 
476  // ask the type if it has any opinion about this eLazyBoolCalculate == no
477  // opinion; other values should be self explanatory
478  CompilerType compiler_type(valobj.GetCompilerType());
479  if (compiler_type.IsValid()) {
480  switch (compiler_type.ShouldPrintAsOneLiner(&valobj)) {
481  case eLazyBoolNo:
482  return false;
483  case eLazyBoolYes:
484  return true;
485  case eLazyBoolCalculate:
486  break;
487  }
488  }
489 
490  size_t total_children_name_len = 0;
491 
492  for (size_t idx = 0; idx < valobj.GetNumChildren(); idx++) {
493  bool is_synth_val = false;
494  ValueObjectSP child_sp(valobj.GetChildAtIndex(idx, true));
495  // something is wrong here - bail out
496  if (!child_sp)
497  return false;
498 
499  // also ask the child's type if it has any opinion
500  CompilerType child_compiler_type(child_sp->GetCompilerType());
501  if (child_compiler_type.IsValid()) {
502  switch (child_compiler_type.ShouldPrintAsOneLiner(child_sp.get())) {
503  case eLazyBoolYes:
504  // an opinion of yes is only binding for the child, so keep going
505  case eLazyBoolCalculate:
506  break;
507  case eLazyBoolNo:
508  // but if the child says no, then it's a veto on the whole thing
509  return false;
510  }
511  }
512 
513  // if we decided to define synthetic children for a type, we probably care
514  // enough to show them, but avoid nesting children in children
515  if (child_sp->GetSyntheticChildren().get() != nullptr) {
516  ValueObjectSP synth_sp(child_sp->GetSyntheticValue());
517  // wait.. wat? just get out of here..
518  if (!synth_sp)
519  return false;
520  // but if we only have them to provide a value, keep going
521  if (!synth_sp->MightHaveChildren() &&
522  synth_sp->DoesProvideSyntheticValue())
523  is_synth_val = true;
524  else
525  return false;
526  }
527 
528  total_children_name_len += child_sp->GetName().GetLength();
529 
530  // 50 itself is a "randomly" chosen number - the idea is that
531  // overly long structs should not get this treatment
532  // FIXME: maybe make this a user-tweakable setting?
533  if (total_children_name_len > 50)
534  return false;
535 
536  // if a summary is there..
537  if (child_sp->GetSummaryFormat()) {
538  // and it wants children, then bail out
539  if (child_sp->GetSummaryFormat()->DoesPrintChildren(child_sp.get()))
540  return false;
541  }
542 
543  // if this child has children..
544  if (child_sp->GetNumChildren()) {
545  // ...and no summary...
546  // (if it had a summary and the summary wanted children, we would have
547  // bailed out anyway
548  // so this only makes us bail out if this has no summary and we would
549  // then print children)
550  if (!child_sp->GetSummaryFormat() && !is_synth_val) // but again only do
551  // that if not a
552  // synthetic valued
553  // child
554  return false; // then bail out
555  }
556  }
557  return true;
558 }
559 
560 ConstString FormatManager::GetValidTypeName(ConstString type) {
562 }
563 
564 ConstString FormatManager::GetTypeForCache(ValueObject &valobj,
565  lldb::DynamicValueType use_dynamic) {
566  ValueObjectSP valobj_sp = valobj.GetQualifiedRepresentationIfAvailable(
567  use_dynamic, valobj.IsSynthetic());
568  if (valobj_sp && valobj_sp->GetCompilerType().IsValid()) {
569  if (!valobj_sp->GetCompilerType().IsMeaninglessWithoutDynamicResolution())
570  return valobj_sp->GetQualifiedTypeName();
571  }
572  return ConstString();
573 }
574 
575 std::vector<lldb::LanguageType>
576 FormatManager::GetCandidateLanguages(ValueObject &valobj) {
577  lldb::LanguageType lang_type = valobj.GetObjectRuntimeLanguage();
578  return GetCandidateLanguages(lang_type);
579 }
580 
581 std::vector<lldb::LanguageType>
582 FormatManager::GetCandidateLanguages(lldb::LanguageType lang_type) {
583  switch (lang_type) {
593  default:
594  return {lang_type};
595  }
596 }
597 
599 FormatManager::GetCategoryForLanguage(lldb::LanguageType lang_type) {
600  std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
601  auto iter = m_language_categories_map.find(lang_type),
602  end = m_language_categories_map.end();
603  if (iter != end)
604  return iter->second.get();
605  LanguageCategory *lang_category = new LanguageCategory(lang_type);
606  m_language_categories_map[lang_type] =
607  LanguageCategory::UniquePointer(lang_category);
608  return lang_category;
609 }
610 
611 lldb::TypeFormatImplSP
612 FormatManager::GetHardcodedFormat(FormattersMatchData &match_data) {
613  TypeFormatImplSP retval_sp;
614 
615  for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
616  if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
617  if (lang_category->GetHardcoded(*this, match_data, retval_sp))
618  break;
619  }
620  }
621 
622  return retval_sp;
623 }
624 
625 lldb::TypeFormatImplSP
626 FormatManager::GetFormat(ValueObject &valobj,
627  lldb::DynamicValueType use_dynamic) {
628  FormattersMatchData match_data(valobj, use_dynamic);
629 
630  TypeFormatImplSP retval;
632  if (match_data.GetTypeForCache()) {
633  if (log)
634  log->Printf(
635  "\n\n[FormatManager::GetFormat] Looking into cache for type %s",
636  match_data.GetTypeForCache().AsCString("<invalid>"));
637  if (m_format_cache.GetFormat(match_data.GetTypeForCache(), retval)) {
638  if (log) {
639  log->Printf(
640  "[FormatManager::GetFormat] Cache search success. Returning.");
641  LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
642  m_format_cache.GetCacheHits(),
643  m_format_cache.GetCacheMisses());
644  }
645  return retval;
646  }
647  if (log)
648  log->Printf(
649  "[FormatManager::GetFormat] Cache search failed. Going normal route");
650  }
651 
652  retval = m_categories_map.GetFormat(match_data);
653  if (!retval) {
654  if (log)
655  log->Printf("[FormatManager::GetFormat] Search failed. Giving language a "
656  "chance.");
657  for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
658  if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
659  if (lang_category->Get(match_data, retval))
660  break;
661  }
662  }
663  if (retval) {
664  if (log)
665  log->Printf(
666  "[FormatManager::GetFormat] Language search success. Returning.");
667  return retval;
668  }
669  }
670  if (!retval) {
671  if (log)
672  log->Printf("[FormatManager::GetFormat] Search failed. Giving hardcoded "
673  "a chance.");
674  retval = GetHardcodedFormat(match_data);
675  }
676 
677  if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) {
678  if (log)
679  log->Printf("[FormatManager::GetFormat] Caching %p for type %s",
680  static_cast<void *>(retval.get()),
681  match_data.GetTypeForCache().AsCString("<invalid>"));
682  m_format_cache.SetFormat(match_data.GetTypeForCache(), retval);
683  }
684  LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
685  m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
686  return retval;
687 }
688 
689 lldb::TypeSummaryImplSP
690 FormatManager::GetHardcodedSummaryFormat(FormattersMatchData &match_data) {
691  TypeSummaryImplSP retval_sp;
692 
693  for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
694  if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
695  if (lang_category->GetHardcoded(*this, match_data, retval_sp))
696  break;
697  }
698  }
699 
700  return retval_sp;
701 }
702 
703 lldb::TypeSummaryImplSP
704 FormatManager::GetSummaryFormat(ValueObject &valobj,
705  lldb::DynamicValueType use_dynamic) {
706  FormattersMatchData match_data(valobj, use_dynamic);
707 
708  TypeSummaryImplSP retval;
710  if (match_data.GetTypeForCache()) {
711  if (log)
712  log->Printf("\n\n[FormatManager::GetSummaryFormat] Looking into cache "
713  "for type %s",
714  match_data.GetTypeForCache().AsCString("<invalid>"));
715  if (m_format_cache.GetSummary(match_data.GetTypeForCache(), retval)) {
716  if (log) {
717  log->Printf("[FormatManager::GetSummaryFormat] Cache search success. "
718  "Returning.");
719  LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
720  m_format_cache.GetCacheHits(),
721  m_format_cache.GetCacheMisses());
722  }
723  return retval;
724  }
725  if (log)
726  log->Printf("[FormatManager::GetSummaryFormat] Cache search failed. "
727  "Going normal route");
728  }
729 
730  retval = m_categories_map.GetSummaryFormat(match_data);
731  if (!retval) {
732  if (log)
733  log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving "
734  "language a chance.");
735  for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
736  if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
737  if (lang_category->Get(match_data, retval))
738  break;
739  }
740  }
741  if (retval) {
742  if (log)
743  log->Printf("[FormatManager::GetSummaryFormat] Language search "
744  "success. Returning.");
745  return retval;
746  }
747  }
748  if (!retval) {
749  if (log)
750  log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving "
751  "hardcoded a chance.");
752  retval = GetHardcodedSummaryFormat(match_data);
753  }
754 
755  if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) {
756  if (log)
757  log->Printf("[FormatManager::GetSummaryFormat] Caching %p for type %s",
758  static_cast<void *>(retval.get()),
759  match_data.GetTypeForCache().AsCString("<invalid>"));
760  m_format_cache.SetSummary(match_data.GetTypeForCache(), retval);
761  }
762  LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
763  m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
764  return retval;
765 }
766 
767 lldb::SyntheticChildrenSP
768 FormatManager::GetHardcodedSyntheticChildren(FormattersMatchData &match_data) {
769  SyntheticChildrenSP retval_sp;
770 
771  for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
772  if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
773  if (lang_category->GetHardcoded(*this, match_data, retval_sp))
774  break;
775  }
776  }
777 
778  return retval_sp;
779 }
780 
781 lldb::SyntheticChildrenSP
782 FormatManager::GetSyntheticChildren(ValueObject &valobj,
783  lldb::DynamicValueType use_dynamic) {
784  FormattersMatchData match_data(valobj, use_dynamic);
785 
786  SyntheticChildrenSP retval;
788  if (match_data.GetTypeForCache()) {
789  if (log)
790  log->Printf("\n\n[FormatManager::GetSyntheticChildren] Looking into "
791  "cache for type %s",
792  match_data.GetTypeForCache().AsCString("<invalid>"));
793  if (m_format_cache.GetSynthetic(match_data.GetTypeForCache(), retval)) {
794  if (log) {
795  log->Printf("[FormatManager::GetSyntheticChildren] Cache search "
796  "success. Returning.");
797  LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
798  m_format_cache.GetCacheHits(),
799  m_format_cache.GetCacheMisses());
800  }
801  return retval;
802  }
803  if (log)
804  log->Printf("[FormatManager::GetSyntheticChildren] Cache search failed. "
805  "Going normal route");
806  }
807 
808  retval = m_categories_map.GetSyntheticChildren(match_data);
809  if (!retval) {
810  if (log)
811  log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving "
812  "language a chance.");
813  for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
814  if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
815  if (lang_category->Get(match_data, retval))
816  break;
817  }
818  }
819  if (retval) {
820  if (log)
821  log->Printf("[FormatManager::GetSyntheticChildren] Language search "
822  "success. Returning.");
823  return retval;
824  }
825  }
826  if (!retval) {
827  if (log)
828  log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving "
829  "hardcoded a chance.");
830  retval = GetHardcodedSyntheticChildren(match_data);
831  }
832 
833  if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) {
834  if (log)
835  log->Printf(
836  "[FormatManager::GetSyntheticChildren] Caching %p for type %s",
837  static_cast<void *>(retval.get()),
838  match_data.GetTypeForCache().AsCString("<invalid>"));
839  m_format_cache.SetSynthetic(match_data.GetTypeForCache(), retval);
840  }
841  LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
842  m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
843  return retval;
844 }
845 
846 lldb::TypeValidatorImplSP
847 FormatManager::GetValidator(ValueObject &valobj,
848  lldb::DynamicValueType use_dynamic) {
849  FormattersMatchData match_data(valobj, use_dynamic);
850 
851  TypeValidatorImplSP retval;
853  if (match_data.GetTypeForCache()) {
854  if (log)
855  log->Printf(
856  "\n\n[FormatManager::GetValidator] Looking into cache for type %s",
857  match_data.GetTypeForCache().AsCString("<invalid>"));
858  if (m_format_cache.GetValidator(match_data.GetTypeForCache(), retval)) {
859  if (log) {
860  log->Printf(
861  "[FormatManager::GetValidator] Cache search success. Returning.");
862  LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
863  m_format_cache.GetCacheHits(),
864  m_format_cache.GetCacheMisses());
865  }
866  return retval;
867  }
868  if (log)
869  log->Printf("[FormatManager::GetValidator] Cache search failed. Going "
870  "normal route");
871  }
872 
873  retval = m_categories_map.GetValidator(match_data);
874  if (!retval) {
875  if (log)
876  log->Printf("[FormatManager::GetValidator] Search failed. Giving "
877  "language a chance.");
878  for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
879  if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
880  if (lang_category->Get(match_data, retval))
881  break;
882  }
883  }
884  if (retval) {
885  if (log)
886  log->Printf("[FormatManager::GetValidator] Language search success. "
887  "Returning.");
888  return retval;
889  }
890  }
891  if (!retval) {
892  if (log)
893  log->Printf("[FormatManager::GetValidator] Search failed. Giving "
894  "hardcoded a chance.");
895  retval = GetHardcodedValidator(match_data);
896  }
897 
898  if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) {
899  if (log)
900  log->Printf("[FormatManager::GetValidator] Caching %p for type %s",
901  static_cast<void *>(retval.get()),
902  match_data.GetTypeForCache().AsCString("<invalid>"));
903  m_format_cache.SetValidator(match_data.GetTypeForCache(), retval);
904  }
905  LLDB_LOGV(log, "Cache hits: {0} - Cache Misses: {1}",
906  m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
907  return retval;
908 }
909 
910 lldb::TypeValidatorImplSP
911 FormatManager::GetHardcodedValidator(FormattersMatchData &match_data) {
912  TypeValidatorImplSP retval_sp;
913 
914  for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) {
915  if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) {
916  if (lang_category->GetHardcoded(*this, match_data, retval_sp))
917  break;
918  }
919  }
920 
921  return retval_sp;
922 }
923 
924 FormatManager::FormatManager()
925  : m_last_revision(0), m_format_cache(), m_language_categories_mutex(),
926  m_language_categories_map(), m_named_summaries_map(this),
927  m_categories_map(this), m_default_category_name(ConstString("default")),
928  m_system_category_name(ConstString("system")),
929  m_vectortypes_category_name(ConstString("VectorTypes")) {
930  LoadSystemFormatters();
931  LoadVectorFormatters();
932 
933  EnableCategory(m_vectortypes_category_name, TypeCategoryMap::Last,
935  EnableCategory(m_system_category_name, TypeCategoryMap::Last,
937 }
938 
939 void FormatManager::LoadSystemFormatters() {
940  TypeSummaryImpl::Flags string_flags;
941  string_flags.SetCascades(true)
942  .SetSkipPointers(true)
943  .SetSkipReferences(false)
944  .SetDontShowChildren(true)
945  .SetDontShowValue(false)
946  .SetShowMembersOneLiner(false)
947  .SetHideItemNames(false);
948 
949  TypeSummaryImpl::Flags string_array_flags;
950  string_array_flags.SetCascades(true)
951  .SetSkipPointers(true)
952  .SetSkipReferences(false)
953  .SetDontShowChildren(true)
954  .SetDontShowValue(true)
955  .SetShowMembersOneLiner(false)
956  .SetHideItemNames(false);
957 
958  lldb::TypeSummaryImplSP string_format(
959  new StringSummaryFormat(string_flags, "${var%s}"));
960 
961  lldb::TypeSummaryImplSP string_array_format(
962  new StringSummaryFormat(string_array_flags, "${var%s}"));
963 
964  lldb::RegularExpressionSP any_size_char_arr(
965  new RegularExpression(llvm::StringRef("char \\[[0-9]+\\]")));
966  lldb::RegularExpressionSP any_size_wchar_arr(
967  new RegularExpression(llvm::StringRef("wchar_t \\[[0-9]+\\]")));
968 
969  TypeCategoryImpl::SharedPointer sys_category_sp =
970  GetCategory(m_system_category_name);
971 
972  sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("char *"),
973  string_format);
974  sys_category_sp->GetTypeSummariesContainer()->Add(
975  ConstString("unsigned char *"), string_format);
976  sys_category_sp->GetRegexTypeSummariesContainer()->Add(any_size_char_arr,
977  string_array_format);
978 
979  lldb::TypeSummaryImplSP ostype_summary(
981  .SetCascades(false)
982  .SetSkipPointers(true)
983  .SetSkipReferences(true)
984  .SetDontShowChildren(true)
985  .SetDontShowValue(false)
986  .SetShowMembersOneLiner(false)
987  .SetHideItemNames(false),
988  "${var%O}"));
989 
990  sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("OSType"),
991  ostype_summary);
992 
993  TypeFormatImpl::Flags fourchar_flags;
994  fourchar_flags.SetCascades(true).SetSkipPointers(true).SetSkipReferences(
995  true);
996 
997  AddFormat(sys_category_sp, lldb::eFormatOSType, ConstString("FourCharCode"),
998  fourchar_flags);
999 }
1000 
1001 void FormatManager::LoadVectorFormatters() {
1002  TypeCategoryImpl::SharedPointer vectors_category_sp =
1003  GetCategory(m_vectortypes_category_name);
1004 
1005  TypeSummaryImpl::Flags vector_flags;
1006  vector_flags.SetCascades(true)
1007  .SetSkipPointers(true)
1008  .SetSkipReferences(false)
1009  .SetDontShowChildren(true)
1010  .SetDontShowValue(false)
1011  .SetShowMembersOneLiner(true)
1012  .SetHideItemNames(true);
1013 
1014  AddStringSummary(vectors_category_sp, "${var.uint128}",
1015  ConstString("builtin_type_vec128"), vector_flags);
1016 
1017  AddStringSummary(vectors_category_sp, "", ConstString("float [4]"),
1018  vector_flags);
1019  AddStringSummary(vectors_category_sp, "", ConstString("int32_t [4]"),
1020  vector_flags);
1021  AddStringSummary(vectors_category_sp, "", ConstString("int16_t [8]"),
1022  vector_flags);
1023  AddStringSummary(vectors_category_sp, "", ConstString("vDouble"),
1024  vector_flags);
1025  AddStringSummary(vectors_category_sp, "", ConstString("vFloat"),
1026  vector_flags);
1027  AddStringSummary(vectors_category_sp, "", ConstString("vSInt8"),
1028  vector_flags);
1029  AddStringSummary(vectors_category_sp, "", ConstString("vSInt16"),
1030  vector_flags);
1031  AddStringSummary(vectors_category_sp, "", ConstString("vSInt32"),
1032  vector_flags);
1033  AddStringSummary(vectors_category_sp, "", ConstString("vUInt16"),
1034  vector_flags);
1035  AddStringSummary(vectors_category_sp, "", ConstString("vUInt8"),
1036  vector_flags);
1037  AddStringSummary(vectors_category_sp, "", ConstString("vUInt16"),
1038  vector_flags);
1039  AddStringSummary(vectors_category_sp, "", ConstString("vUInt32"),
1040  vector_flags);
1041  AddStringSummary(vectors_category_sp, "", ConstString("vBool32"),
1042  vector_flags);
1043 }
#define LIBLLDB_LOG_DATAFORMATTERS
Definition: Logging.h:43
CompilerType GetCompilerType()
CompilerType GetNonReferenceType() const
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
Flags & SetCascades(bool value=true)
Definition: TypeSummary.h:85
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:224
Flags & SetSkipReferences(bool value=true)
Definition: TypeFormat.h:82
Flags & SetHideItemNames(bool value=true)
Definition: TypeSummary.h:176
virtual lldb::LanguageType GetObjectRuntimeLanguage()
std::shared_ptr< TypeCategoryImpl > SharedPointer
Definition: TypeCategory.h:372
std::vector< FormattersMatchCandidate > FormattersMatchVector
Definition: FormatClasses.h:86
lldb::TargetSP GetTargetSP() const
Definition: ValueObject.h:357
CompilerType GetPointeeType() const
std::unique_ptr< LanguageCategory > UniquePointer
bool IsPointerType(CompilerType *pointee_type=nullptr) const
void AddStringSummary(TypeCategoryImpl::SharedPointer category_sp, const char *string, ConstString type_name, TypeSummaryImpl::Flags flags, bool regex=false)
lldb::opaque_compiler_type_t GetOpaqueQualType() const
Definition: CompilerType.h:165
#define UINT32_MAX
Definition: lldb-defines.h:31
bool IsMeaninglessWithoutDynamicResolution() const
static uint32_t g_num_format_infos
LanguageType
Programming language type.
lldb::ValueObjectSP GetQualifiedRepresentationIfAvailable(lldb::DynamicValueType dynValue, bool synthValue)
Flags & SetDontShowValue(bool value=true)
Definition: TypeSummary.h:150
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:57
Flags & SetSkipPointers(bool value=true)
Definition: TypeSummary.h:98
bool IsReferenceType(CompilerType *pointee_type=nullptr, bool *is_rvalue=nullptr) const
std::function< bool(const ValueSP &)> ForEachCallback
virtual bool IsSynthetic()
Definition: ValueObject.h:608
llvm::StringRef GetString() const
CandidateLanguagesVector GetCandidateLanguages()
static FormatInfo g_format_infos[]
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
virtual bool IsDynamic()
Definition: ValueObject.h:647
ConstString GetDisplayTypeName() const
static ConstString GetValidTypeName_Impl(ConstString type)
CompilerType GetPointerType() const
CompilerType GetLValueReferenceType() const
const char format_char
Flags & SetDontShowChildren(bool value=true)
Definition: TypeSummary.h:124
LazyBool ShouldPrintAsOneLiner(ValueObject *valobj) const
virtual lldb::ValueObjectSP GetStaticValue()
char * strcasestr(const char *s, const char *find)
Definition: Windows.cpp:72
A uniqued constant string class.
Definition: ConstString.h:38
static const Position Last
lldb::TypeSummaryImplSP GetSummaryFormat()
Definition: ValueObject.h:725
Non-standardized C, such as K&R.
CompilerType GetFullyUnqualifiedType() const
Definition: SBAddress.h:15
lldb::TypeCategoryImplSP GetCategory(const char *category_name=nullptr, bool can_create=true)
int strcasecmp(const char *s1, const char *s2)
CompilerType GetTypedefedType() const
CompilerType GetRValueReferenceType() const
size_t GetNumChildren(uint32_t max=UINT32_MAX)
Flags & SetSkipReferences(bool value=true)
Definition: TypeSummary.h:111
Flags & SetShowMembersOneLiner(bool value=true)
Definition: TypeSummary.h:163
ConstString GetConstTypeName() const
CompilerType GetTypeForFormatters() const
Flags & SetCascades(bool value=true)
Definition: TypeFormat.h:56
static bool GetFormatFromFormatChar(char format_char, Format &format)
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
void EnableCategory(ConstString category_name, TypeCategoryMap::Position pos=TypeCategoryMap::Default)
Definition: FormatManager.h:53
const char * format_name
#define LLDB_LOGV(log,...)
Definition: Log.h:216
virtual uint32_t GetBitfieldBitSize()
Definition: ValueObject.h:439
Flags & SetSkipPointers(bool value=true)
Definition: TypeFormat.h:69
virtual lldb::ValueObjectSP GetChildAtIndex(size_t idx, bool can_create)
void AddFormat(TypeCategoryImpl::SharedPointer category_sp, lldb::Format format, ConstString type_name, TypeFormatImpl::Flags flags, bool regex=false)
static bool GetFormatFromFormatName(const char *format_name, bool partial_match_ok, Format &format)