wallace created this revision.
wallace added a reviewer: clayborg.
wallace requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

This adds some important remarks to the data formatter documentation.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D115974

Files:
  lldb/docs/use/variable.rst

Index: lldb/docs/use/variable.rst
===================================================================
--- lldb/docs/use/variable.rst
+++ lldb/docs/use/variable.rst
@@ -29,6 +29,52 @@
    (uint8_t) x = chr='a' dec=65 hex=0x41
    (intptr_t) y = 0x76f919f
 
+In addition, some data structures can encode their data in a way that is not easily
+readable to the user, in which case a data formatter could be used to show
+the data in a human readable way. For example, without a formatter, printing a
+``std::deque<int>`` with the elements ``{2, 3, 4, 5, 6}`` would result in something
+like:
+
+::
+
+   (lldb) p a_deque
+   (std::deque<Foo, std::allocator<int> >) $0 = {
+      std::_Deque_base<Foo, std::allocator<int> > = {
+         _M_impl = {
+            _M_map = 0x000000000062ceb0
+            _M_map_size = 8
+            _M_start = {
+               _M_cur = 0x000000000062cf00
+               _M_first = 0x000000000062cf00
+               _M_last = 0x000000000062d2f4
+               _M_node = 0x000000000062cec8
+            }
+            _M_finish = {
+               _M_cur = 0x000000000062d300
+               _M_first = 0x000000000062d300
+               _M_last = 0x000000000062d6f4
+               _M_node = 0x000000000062ced0
+            }
+         }
+      }
+   }
+
+which is very hard to make sense of. On the other hand, a proper formatter could
+produce the following output
+
+::
+
+   (lldb) p a_deque
+   (std::deque<Foo, std::allocator<int> >) $0 = size=5 {
+      [0] = 2
+      [1] = 3
+      [2] = 4
+      [3] = 5
+      [4] = 6
+   }
+
+which is what the user would expect from a good debugger.
+
 There are several features related to data visualization: formats, summaries,
 filters, synthetic children.
 
@@ -871,18 +917,23 @@
          this call should return a new LLDB SBValue object representing the child at the index given as argument
       def update(self):
          this call should be used to update the internal state of this Python object whenever the state of the variables in LLDB changes.[1]
+         Also, this method is invoked before any other method in the interface.
       def has_children(self):
          this call should return True if this object might have children, and False if this object can be guaranteed not to have children.[2]
       def get_value(self):
          this call can return an SBValue to be presented as the value of the synthetic value under consideration.[3]
 
-[1] This method is optional. Also, it may optionally choose to return a value
-(starting with SVN rev153061/LLDB-134). If it returns a value, and that value
-is True, LLDB will be allowed to cache the children and the children count it
-previously obtained, and will not return to the provider class to ask. If
-nothing, None, or anything other than True is returned, LLDB will discard the
-cached information and ask. Regardless, whenever necessary LLDB will call
-update.
+As a warning, exceptions that are thrown by python formatters are caught silently by LLDB and should be handled appropriately
+by the formatter itself. Being more specific, in case of exceptions, LLDB might assume that the given object has no children
+or it might skip printing some children.
+
+[1] This method is optional. Also, a boolean value must be returned
+(starting with SVN rev153061/LLDB-134). If ``False`` is returned, then whenever
+the process reaches a new stop, this method will be invoked again to generate an
+updated list of the children for a given variable. Otherwise, if ``True`` is returned,
+then the value is cached and this method won't be called again, effectively freezing
+the state of the value in subsequent stops. Beware that returning ``True`` incorrectly
+could show misleading information to the user.
 
 [2] This method is optional (starting with SVN rev166495/LLDB-175). While
 implementing it in terms of num_children is acceptable, implementors are
@@ -972,6 +1023,22 @@
       (int) [3] = 1234
    }
 
+It's worth mentioning that LLDB invokes the synthetic child provider before invoking the
+summary string provider, which allows the latter to have access to the actual displayable
+children. This applies to both inlined summary strings and python-based summary providers.
+
+
+As a warning, when programmatically accessing the children or children count of a
+variable that has a synthetic child provider, notice that LLDB hides the actual
+raw children. For example, suppose we have a ``std::vector``, which has an actual in-memory property
+``__begin`` marking the beginning of its data. After the synthetic child provider is
+executed, the ``std::vector`` variable won't show ``__begin`` as child anymore, even through
+the SB API. It will have instead the children calculated by the provider. In case the actual raw
+children are needed, a call to ``value.GetNonSyntheticValue()`` is enough to get a raw
+version of the value. It is import to remember this when implementing summary string
+providers, as they run after the synthetic child provider.
+
+
 In some cases, if LLDB is unable to use the real object to get a child
 specified in an expression path, it will automatically refer to the synthetic
 children. While in summaries it is best to always use ${svar to make your
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to