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