For mixed native/Java code (or native/Python code, native/SomeFancyProgrammingLanguage code), sometimes we want a “prettier” stack trace for users.
For example, we may want to:
- skip Java->native wrapper functions, or trampolines that means nothing to users;
- merge several frames together, because in Java world it’s just one stack frame;
- do some language runtime related function calls to get certain runtime data;
- put an elephant into refrigerator.
What do you think is the best way to do this?
If possible, we want to do all these in ‘bt’ command, so it’s more intuitive for users. Or we can extend the stack annotations to do this.
But if they all seem too messy to you, we certainly can keep it out of your way and maybe write a new command for it.
Thanks in advance!
Just to expand a bit on what Tong mentioned:
When we’re running some of our Android Java code in interpreted mode (as opposed to AOT compiled), we can get multiple interpreter implementation frames (native frames) that correspond to a single user-visible Java frame. We’d like to enable hiding/collapsing those implementation details of the interpreter into the single user-visible Java frame that they’re representing. For the most part, the folks that will want to really see the interpreter implementation details are the ART developers. Most of the rest of us just want to see the Java frame.
We’d be happy to put that behavior on a flag when debugging Android mixed Java/C/C++ code.
Tong’s comment about putting it on the ‘bt’ command is meant to cover:
- having this functionality translate to API calls that get frames.
- have it be the default way back traces are displayed without requiring users to use some other “back trace-like” command. (Clearly we could implement this as another command that does the interpretation, but I suspect this would then require clients of the API to know this and call something different than the standard backtrace calls to get it).
A while back, Greg and I chatted about this on lldb-dev and I think we were looking to consider a stack annotation path to handle this, where the change needed for our purposes would be putting the annotations in-line (rather than displayed at the bottom IIRC). I think the diff now is that we see we have multiple “source” stack frames (the interpreter implementation detail frames) that map to one user-visible frame. This almost suggests a possible frame-mapping layer where there’s an underlying frame model, and a presentation of it that we show to users/API. But that can also be getting over-complicated.
Any thoughts on this would be great since it’s deep in your area. Thanks, Jason!
So we don't currently have any Java support in the expression parser, but if we did, there would be a Java Language runtime that would assist this, and also know how to do things like "step from one Java invocation to another" rather than having to plow through all the intervening interpreter code, etc... Given that the is an intrinsic part of new language support in lldb, it would be pretty natural for the LanguageRuntimes to also be able to provide "alternate backtraces". Then the backtrace command would take an "-l" option for setting the language runtime that provides the backtraces (all the C based languages would use the native unwinder.) Finally, you could have a setting to set the default backtrace language, so for your Java only developers, they would just set this setting in their .lldbinit file, and then "bt" would show then what the Java language runtime showed.
Does this sound reasonable?
And of course, you could have two "java" languages, like "pure-java" and "mixed-java" which would either provide annotated C frames, or pure Java frames.
Yeah that does sound like a reasonable way to go about it. I’ll have Tong mull that over a bit and come back with any questions.
Thanks for your thoughts, Jim!