[Lldb-commits] [lldb] 2f9fc57 - [lldb] Add setting for max depth of value object printing (NFC)

Dave Lee via lldb-commits lldb-commits at lists.llvm.org
Tue May 3 10:39:51 PDT 2022


Author: Dave Lee
Date: 2022-05-03T10:39:42-07:00
New Revision: 2f9fc576be206bd5c4fddfec5f89fceb3554a8d6

URL: https://github.com/llvm/llvm-project/commit/2f9fc576be206bd5c4fddfec5f89fceb3554a8d6
DIFF: https://github.com/llvm/llvm-project/commit/2f9fc576be206bd5c4fddfec5f89fceb3554a8d6.diff

LOG: [lldb] Add setting for max depth of value object printing (NFC)

This adds a setting (`target.max-children-depth`) that will provide a default value for the `--depth` flag used by `expression` and `frame variable`.

The new setting uses the same default that's currently fixed in source: `UINT32_MAX`.

This provides two purposes:

1. Allowing downstream forks to provide a customized default.
2. Allowing users to set their own default.

Following `target.max-children-count`, a warning is emitted when the max depth is reached. The warning lets users know which flags or settings they can customize. This warning is shown only when the limit is the default value.

rdar://87466495

Differential Revision: https://reviews.llvm.org/D123954

Added: 
    

Modified: 
    lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h
    lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
    lldb/include/lldb/Interpreter/CommandInterpreter.h
    lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
    lldb/include/lldb/Interpreter/OptionValueProperties.h
    lldb/include/lldb/Target/Target.h
    lldb/source/Commands/CommandObjectFrame.cpp
    lldb/source/Commands/CommandObjectTarget.cpp
    lldb/source/DataFormatters/DumpValueObjectOptions.cpp
    lldb/source/DataFormatters/ValueObjectPrinter.cpp
    lldb/source/Interpreter/CommandInterpreter.cpp
    lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
    lldb/source/Interpreter/OptionValueProperties.cpp
    lldb/source/Target/Target.cpp
    lldb/source/Target/TargetProperties.td

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h b/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h
index cef43f45b8e41..c6306c7dab60b 100644
--- a/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h
+++ b/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h
@@ -66,7 +66,7 @@ class DumpValueObjectOptions {
   DumpValueObjectOptions &
   SetMaximumPointerDepth(PointerDepth depth = {PointerDepth::Mode::Never, 0});
 
-  DumpValueObjectOptions &SetMaximumDepth(uint32_t depth = 0);
+  DumpValueObjectOptions &SetMaximumDepth(uint32_t depth, bool is_default);
 
   DumpValueObjectOptions &SetDeclPrintingHelper(DeclPrintingHelper helper);
 
@@ -125,6 +125,7 @@ class DumpValueObjectOptions {
   SetPointerAsArray(const PointerAsArraySettings &ptr_array);
 
   uint32_t m_max_depth = UINT32_MAX;
+  bool m_max_depth_is_default = true;
   lldb::DynamicValueType m_use_dynamic = lldb::eNoDynamicValues;
   uint32_t m_omit_summary_depth = 0;
   lldb::Format m_format = lldb::eFormatDefault;

diff  --git a/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h b/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
index 833cd5eea356c..90e54021a71f7 100644
--- a/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
+++ b/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
@@ -117,6 +117,8 @@ class ValueObjectPrinter {
 
   bool PrintChildrenOneLiner(bool hide_names);
 
+  bool HasReachedMaximumDepth();
+
 private:
   ValueObject *m_orig_valobj;
   ValueObject *m_valobj;

diff  --git a/lldb/include/lldb/Interpreter/CommandInterpreter.h b/lldb/include/lldb/Interpreter/CommandInterpreter.h
index f1f715c891a5c..55971136b63b3 100644
--- a/lldb/include/lldb/Interpreter/CommandInterpreter.h
+++ b/lldb/include/lldb/Interpreter/CommandInterpreter.h
@@ -223,11 +223,11 @@ class CommandInterpreter : public Broadcaster,
     eBroadcastBitAsynchronousErrorData = (1 << 4)
   };
 
-  enum ChildrenTruncatedWarningStatus // tristate boolean to manage children
-                                      // truncation warning
-  { eNoTruncation = 0,                // never truncated
-    eUnwarnedTruncation = 1,          // truncated but did not notify
-    eWarnedTruncation = 2             // truncated and notified
+  /// Tristate boolean to manage children omission warnings.
+  enum ChildrenOmissionWarningStatus {
+    eNoOmission = 0,       ///< No children were omitted.
+    eUnwarnedOmission = 1, ///< Children omitted, and not yet notified.
+    eWarnedOmission = 2    ///< Children omitted and notified.
   };
 
   enum CommandTypes {
@@ -496,21 +496,33 @@ class CommandInterpreter : public Broadcaster,
   }
 
   void ChildrenTruncated() {
-    if (m_truncation_warning == eNoTruncation)
-      m_truncation_warning = eUnwarnedTruncation;
+    if (m_truncation_warning == eNoOmission)
+      m_truncation_warning = eUnwarnedOmission;
   }
 
-  bool TruncationWarningNecessary() {
-    return (m_truncation_warning == eUnwarnedTruncation);
+  void SetReachedMaximumDepth() {
+    if (m_max_depth_warning == eNoOmission)
+      m_max_depth_warning = eUnwarnedOmission;
   }
 
-  void TruncationWarningGiven() { m_truncation_warning = eWarnedTruncation; }
+  void PrintWarningsIfNecessary(Stream &s, const std::string &cmd_name) {
+    if (m_truncation_warning == eUnwarnedOmission) {
+      s.Printf("*** Some of the displayed variables have more members than the "
+               "debugger will show by default. To show all of them, you can "
+               "either use the --show-all-children option to %s or raise the "
+               "limit by changing the target.max-children-count setting.\n",
+               cmd_name.c_str());
+      m_truncation_warning = eWarnedOmission;
+    }
 
-  const char *TruncationWarningText() {
-    return "*** Some of your variables have more members than the debugger "
-           "will show by default. To show all of them, you can either use the "
-           "--show-all-children option to %s or raise the limit by changing "
-           "the target.max-children-count setting.\n";
+    if (m_max_depth_warning == eUnwarnedOmission) {
+      s.Printf("*** Some of the displayed variables have a greater depth of "
+               "members than the debugger will show by default. To increase "
+               "the limit, use the --depth option to %s, or raise the limit by "
+               "changing the target.max-children-depth setting.\n",
+               cmd_name.c_str());
+      m_max_depth_warning = eWarnedOmission;
+    }
   }
 
   CommandHistory &GetCommandHistory() { return m_command_history; }
@@ -701,9 +713,12 @@ class CommandInterpreter : public Broadcaster,
   lldb::IOHandlerSP m_command_io_handler_sp;
   char m_comment_char;
   bool m_batch_command_mode;
-  ChildrenTruncatedWarningStatus m_truncation_warning; // Whether we truncated
-                                                       // children and whether
-                                                       // the user has been told
+  /// Whether we truncated a value's list of children and whether the user has
+  /// been told.
+  ChildrenOmissionWarningStatus m_truncation_warning;
+  /// Whether we reached the maximum child nesting depth and whether the user
+  /// has been told.
+  ChildrenOmissionWarningStatus m_max_depth_warning;
 
   // FIXME: Stop using this to control adding to the history and then replace
   // this with m_command_source_dirs.size().

diff  --git a/lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h b/lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
index 56452f4956f25..9b545c46fba4d 100644
--- a/lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
+++ b/lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
@@ -43,7 +43,8 @@ class OptionGroupValueObjectDisplay : public OptionGroup {
       lldb::TypeSummaryImplSP summary_sp = lldb::TypeSummaryImplSP());
 
   bool show_types : 1, show_location : 1, flat_output : 1, use_objc : 1,
-      use_synth : 1, be_raw : 1, ignore_cap : 1, run_validator : 1;
+      use_synth : 1, be_raw : 1, ignore_cap : 1, run_validator : 1,
+      max_depth_is_default : 1;
 
   uint32_t no_summary_depth;
   uint32_t max_depth;

diff  --git a/lldb/include/lldb/Interpreter/OptionValueProperties.h b/lldb/include/lldb/Interpreter/OptionValueProperties.h
index 3e5685b7f0bf2..14f496bca6cdf 100644
--- a/lldb/include/lldb/Interpreter/OptionValueProperties.h
+++ b/lldb/include/lldb/Interpreter/OptionValueProperties.h
@@ -152,6 +152,10 @@ class OptionValueProperties
   GetPropertyAtIndexAsOptionValueSInt64(const ExecutionContext *exe_ctx,
                                         uint32_t idx) const;
 
+  OptionValueUInt64 *
+  GetPropertyAtIndexAsOptionValueUInt64(const ExecutionContext *exe_ctx,
+                                        uint32_t idx) const;
+
   int64_t GetPropertyAtIndexAsSInt64(const ExecutionContext *exe_ctx,
                                      uint32_t idx, int64_t fail_value) const;
 

diff  --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 59617ed63ff10..d6193ea7166f3 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -166,6 +166,15 @@ class TargetProperties : public Properties {
 
   uint32_t GetMaximumNumberOfChildrenToDisplay() const;
 
+  /// Get the max depth value, augmented with a bool to indicate whether the
+  /// depth is the default.
+  ///
+  /// When the user has customized the max depth, the bool will be false.
+  ///
+  /// \returns the max depth, and true if the max depth is the system default,
+  /// otherwise false.
+  std::pair<uint32_t, bool> GetMaximumDepthOfChildrenToDisplay() const;
+
   uint32_t GetMaximumSizeOfStringSummary() const;
 
   uint32_t GetMaximumMemReadSize() const;

diff  --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp
index ead0594bca4e4..2a1cef7264ea7 100644
--- a/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -695,11 +695,8 @@ may even involve JITing and running code in the target program.)");
       }
     }
 
-    if (m_interpreter.TruncationWarningNecessary()) {
-      result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
-                                      m_cmd_name.c_str());
-      m_interpreter.TruncationWarningGiven();
-    }
+    m_interpreter.PrintWarningsIfNecessary(result.GetOutputStream(),
+                                           m_cmd_name);
 
     // Increment statistics.
     bool res = result.Succeeded();

diff  --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index aeb65daff4cba..5a36298121630 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -972,11 +972,8 @@ class CommandObjectTargetVariable : public CommandObjectParsed {
       }
     }
 
-    if (m_interpreter.TruncationWarningNecessary()) {
-      result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
-                                      m_cmd_name.c_str());
-      m_interpreter.TruncationWarningGiven();
-    }
+    m_interpreter.PrintWarningsIfNecessary(result.GetOutputStream(),
+                                           m_cmd_name);
 
     return result.Succeeded();
   }

diff  --git a/lldb/source/DataFormatters/DumpValueObjectOptions.cpp b/lldb/source/DataFormatters/DumpValueObjectOptions.cpp
index 46a2a489586b8..38de4428bb235 100644
--- a/lldb/source/DataFormatters/DumpValueObjectOptions.cpp
+++ b/lldb/source/DataFormatters/DumpValueObjectOptions.cpp
@@ -38,8 +38,9 @@ DumpValueObjectOptions::SetMaximumPointerDepth(PointerDepth depth) {
 }
 
 DumpValueObjectOptions &
-DumpValueObjectOptions::SetMaximumDepth(uint32_t depth) {
+DumpValueObjectOptions::SetMaximumDepth(uint32_t depth, bool is_default) {
   m_max_depth = depth;
+  m_max_depth_is_default = is_default;
   return *this;
 }
 

diff  --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
index 082ad344d2d10..6fd6308ded5d9 100644
--- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp
+++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
@@ -500,7 +500,7 @@ bool ValueObjectPrinter::ShouldPrintChildren(
   if (m_options.m_use_objc)
     return false;
 
-  if (is_failed_description || m_curr_depth < m_options.m_max_depth) {
+  if (is_failed_description || !HasReachedMaximumDepth()) {
     // We will show children for all concrete types. We won't show pointer
     // contents unless a pointer depth has been specified. We won't reference
     // contents unless the reference is the root object (depth of zero).
@@ -786,9 +786,22 @@ void ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,
       m_stream->EOL();
     } else
       PrintChildren(value_printed, summary_printed, curr_ptr_depth);
-  } else if (m_curr_depth >= m_options.m_max_depth && IsAggregate() &&
+  } else if (HasReachedMaximumDepth() && IsAggregate() &&
              ShouldPrintValueObject()) {
     m_stream->PutCString("{...}\n");
+    // The maximum child depth has been reached. If `m_max_depth` is the default
+    // (i.e. the user has _not_ customized it), then lldb presents a warning to
+    // the user. The warning tells the user that the limit has been reached, but
+    // more importantly tells them how to expand the limit if desired.
+    if (m_options.m_max_depth_is_default)
+      m_valobj->GetTargetSP()
+          ->GetDebugger()
+          .GetCommandInterpreter()
+          .SetReachedMaximumDepth();
   } else
     m_stream->EOL();
 }
+
+bool ValueObjectPrinter::HasReachedMaximumDepth() {
+  return m_curr_depth >= m_options.m_max_depth;
+}

diff  --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index c779795509a22..01a2e3f950aa7 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -128,7 +128,8 @@ CommandInterpreter::CommandInterpreter(Debugger &debugger,
       m_debugger(debugger), m_synchronous_execution(true),
       m_skip_lldbinit_files(false), m_skip_app_init_files(false),
       m_comment_char('#'), m_batch_command_mode(false),
-      m_truncation_warning(eNoTruncation), m_command_source_depth(0) {
+      m_truncation_warning(eNoOmission), m_max_depth_warning(eNoOmission),
+      m_command_source_depth(0) {
   SetEventName(eBroadcastBitThreadShouldExit, "thread-should-exit");
   SetEventName(eBroadcastBitResetPrompt, "reset-prompt");
   SetEventName(eBroadcastBitQuitCommandReceived, "quit");

diff  --git a/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
index 04861b539650d..57b593020b140 100644
--- a/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
+++ b/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
@@ -104,6 +104,8 @@ Status OptionGroupValueObjectDisplay::SetOptionValue(
       max_depth = UINT32_MAX;
       error.SetErrorStringWithFormat("invalid max depth '%s'",
                                      option_arg.str().c_str());
+    } else {
+      max_depth_is_default = false;
     }
     break;
 
@@ -163,6 +165,7 @@ void OptionGroupValueObjectDisplay::OptionParsingStarting(
   flat_output = false;
   use_objc = false;
   max_depth = UINT32_MAX;
+  max_depth_is_default = true;
   ptr_depth = 0;
   elem_count = 0;
   use_synth = true;
@@ -172,9 +175,12 @@ void OptionGroupValueObjectDisplay::OptionParsingStarting(
 
   TargetSP target_sp =
       execution_context ? execution_context->GetTargetSP() : TargetSP();
-  if (target_sp)
+  if (target_sp) {
     use_dynamic = target_sp->GetPreferDynamicValue();
-  else {
+    auto max_depth_config = target_sp->GetMaximumDepthOfChildrenToDisplay();
+    max_depth = std::get<uint32_t>(max_depth_config);
+    max_depth_is_default = std::get<bool>(max_depth_config);
+  } else {
     // If we don't have any targets, then dynamic values won't do us much good.
     use_dynamic = lldb::eNoDynamicValues;
   }
@@ -190,7 +196,7 @@ DumpValueObjectOptions OptionGroupValueObjectDisplay::GetAsDumpOptions(
     options.SetShowSummary(false);
   else
     options.SetOmitSummaryDepth(no_summary_depth);
-  options.SetMaximumDepth(max_depth)
+  options.SetMaximumDepth(max_depth, max_depth_is_default)
       .SetShowTypes(show_types)
       .SetShowLocation(show_location)
       .SetUseObjectiveC(use_objc)

diff  --git a/lldb/source/Interpreter/OptionValueProperties.cpp b/lldb/source/Interpreter/OptionValueProperties.cpp
index 6e6580574edf7..b216557b808f8 100644
--- a/lldb/source/Interpreter/OptionValueProperties.cpp
+++ b/lldb/source/Interpreter/OptionValueProperties.cpp
@@ -412,6 +412,17 @@ OptionValueSInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64(
   return nullptr;
 }
 
+OptionValueUInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueUInt64(
+    const ExecutionContext *exe_ctx, uint32_t idx) const {
+  const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
+  if (property) {
+    OptionValue *value = property->GetValue().get();
+    if (value)
+      return value->GetAsUInt64();
+  }
+  return nullptr;
+}
+
 int64_t OptionValueProperties::GetPropertyAtIndexAsSInt64(
     const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
   const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);

diff  --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 8f0a8be50ff6d..ed733f2645c3a 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -4236,6 +4236,15 @@ uint32_t TargetProperties::GetMaximumNumberOfChildrenToDisplay() const {
       nullptr, idx, g_target_properties[idx].default_uint_value);
 }
 
+std::pair<uint32_t, bool>
+TargetProperties::GetMaximumDepthOfChildrenToDisplay() const {
+  const uint32_t idx = ePropertyMaxChildrenDepth;
+  auto *option_value =
+      m_collection_sp->GetPropertyAtIndexAsOptionValueUInt64(nullptr, idx);
+  bool is_default = !option_value->OptionWasSet();
+  return {option_value->GetCurrentValue(), is_default};
+}
+
 uint32_t TargetProperties::GetMaximumSizeOfStringSummary() const {
   const uint32_t idx = ePropertyMaxSummaryLength;
   return m_collection_sp->GetPropertyAtIndexAsSInt64(

diff  --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td
index 0f46b4ca854cc..62d2c866bba99 100644
--- a/lldb/source/Target/TargetProperties.td
+++ b/lldb/source/Target/TargetProperties.td
@@ -72,6 +72,9 @@ let Definition = "target" in {
   def MaxChildrenCount: Property<"max-children-count", "SInt64">,
     DefaultUnsignedValue<256>,
     Desc<"Maximum number of children to expand in any level of depth.">;
+  def MaxChildrenDepth: Property<"max-children-depth", "UInt64">,
+    DefaultUnsignedValue<0xFFFFFFFF>,
+    Desc<"Maximum depth to expand children.">;
   def MaxSummaryLength: Property<"max-string-summary-length", "SInt64">,
     DefaultUnsignedValue<1024>,
     Desc<"Maximum number of characters to show when using %s in summary strings.">;


        


More information about the lldb-commits mailing list