Does anyone have an answer to this question:
Thank you.
Does anyone have an answer to this question:
Thank you.
Can you post a small buildable piece of code that demonstrates the situation?
Here is a working example:
struct Top
{
int t;
Top():t(123) {}
};
struct Middle : public Top
{
int m;
Middle():m(456){}
};
struct Bottom : public Middle
{
int b;
Bottom():b(789){}
};
int main(int argc, char *argv[])
{
Bottom bottom;
return 0;
}
/*
Run in LLDB with a breakpoint at the statement "return 0;"
(lldb) frame variable bottom
>(Bottom) bottom = {
> Middle = {
> Top = (t = 123)
> m = 456
> }
> b = 789
>}
I have this:
>(lldb) frame variable bottom -T -D1 -P1
>(Bottom) bottom = {
> (Middle) Middle ={...}
> (int) b = 789
>}
I want something like this instead:
>(lldb) frame variable bottom -T -D1 -P1
>(Bottom) bottom = {
> (int) t = 123
> (int) m = 456
> (int) b = 789
>}
*/
Thanks, I reproduced what you got.
First attempt, this at least gets you the indentation you want:
(lldb) frame variable bottom -T -F
(int) bottom.t = 123
(int) bottom.m = 456
(int) bottom.b = 789
The formatters are outside of my expertise but @werat did just post an RFC on this topic so they might be able to help.
If you could also say why you specifically need the format this way. Are you parsing it or perhaps diffing outputs, all that will influence what info is important. For example in my use of -F
you don’t get the type name just the instance name, I don’t know if that’s a problem for you.
First attempt, this at least gets you the indentation you want:
Thanks.
As mentioned the -F option is not suitable for my purpose (here is what I do with the output: LeanCreator/lldbengine2.cpp at master · rochus-keller/LeanCreator · GitHub). I have to fetch level by level because I need all information including the summary.
I would prefer a solution which doesn’t depend on a specific (future) version of LLDB. I would actually be surprised if I was the first to have this need, or if there wasn’t yet some command option, settings value, or Python trick to achieve this. I just couldn’t find anything in the available doc or examples yet, and before I should start to analyze the LLDB source code it’s better to ask.
The RFC David mentioned is mostly about the input language not the SBValue presentation. So I don’t think it’s relevant to this discussion.
You could do this with a synthetic child provider, just recurse through the base classes to build a flat list of ivars (these might not be unique, of course) and then present them as the children of the class.
https://lldb.llvm.org/use/variable.html#synthetic-children
for more details.
Thanks.
do this with a synthetic child provider, just recurse through the base classes
Is there really no other way to do this? I consider the synthetic provider a rather unattractive solution, because I would have to register it essentially for all possible classes, and it would just undo with a lot of effort what LLDB did: separate the members in the memory block according to the class hierarchy.
–
Is there at least a way to reference the superclass in the designator used in frame variable <designator>
so I could focus the query to only this subset?
Specifically in my example above after calling
>(lldb) frame variable bottom -T -D1 -P1
>(Bottom) bottom = {
> (Middle) Middle ={...}
I would now call something like
>(lldb) frame variable bottom::Middle -T -D1 -P1
Is there a syntax for <variable-name>
which supports this? The help <variable-name>
doesn’t provide any details about the syntax.
There are “python recognizer based synthetic child providers” that provide a method to decide whether the current value is one the provider can format. See:
https://lldb.llvm.org/use/variable.html#id12
If the recognizer says it can’t handle the type, the other formatters are tried. Since lldb’s SBTypes hold base classes separately from ivars, if you wanted to flatten all C++ derived classes, your recognizer would just check whether the SBType of the object you are formatting has bases or not. Or you could do "all values whose types are in namespace MyCode
or whatever strategy seemed good.
The other benefit of having a synthetic child provider is that that gets applied everywhere that lldb displays values, it will even show up this way in the variables views of Xcode or VSCode, etc.
I don’t understand the “undo with a lot of effort…” comment. You are explicitly asking somebody to do that work so you can see the values the way you want to not the way lldb represents them natively. I don’t see that it formally matters whether you are asking core lldb to do it or doing it by hand in a synthetic child provider.
On your last point, there isn’t a way in the current “frame variable language” to specify the base class traversal. There really should be a way to do that, probably something to add to the DIL RFC.
Thanks. It’s unfortunate though that I would have to introduce such a complex and expensive solution for such a trivial requirement.
I now changed my parser such that it can cope with queries with unbounded -D and also the nested superclass syntax.
And yet I hit another seemingly trivial problem where I cannot find a solution. How can I reference a variable in the superclass having the same name as a variable in the subclass?
Here is an example:
struct Top2
{
int t, b;
Top2():t(123),b(456) {}
};
struct Bottom2 : public Top2
{
int b;
Bottom2():b(789){}
};
int main(int argc, char *argv[])
{
Bottom bottom;
return 0;
}
Again I have a breakpoint at return 0;
, and I get the right value when executing frame variable bottom.t
or frame variable bottom.b
. But how would I access the b
member in the Top2
class? The C++ syntax bottom.Top::b
doesn’t seem to work, and neither other idea I had worked so far.
Please advise.