I set a breakpoint in hello_world.adb and attempted to debug the program. The debugging session starts correctly, and I can step through the code. However, I’m unable to inspect the value of any variable.
Here’s the error message I receive:
Could not find type system for language ada83: typesystem for language ada83 doesn't exist
lldb -o "breakpoint set -f hello_world.adb -l 15" -o "run" -o "e Text" /opt/adatutorial/.objs/hello_world
(lldb) target create "/opt/adatutorial/.objs/hello_world"
Current executable set to '/opt/adatutorial/.objs/hello_world' (x86_64).
(lldb) breakpoint set -f hello_world.adb -l 15
Breakpoint 1: where = hello_world`_ada_hello_world + 115, address = 0x0000000100000e29
warning: libobjc.A.dylib is being read from process memory. This indicates that LLDB could not read from the host's in-memory shared cache. This will likely reduce debugging performance.
Hello Ada World!!
warning: This version of LLDB has no plugin for the language "ada83". Inspection of frame variables will be limited.
Process 16399 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000e29 hello_world`_ada_hello_world at hello_world.adb:15:4
14 Text := "xxxxx Ada World!!";
-> 15 Print(Text);
16 end Hello_World;
Target 0: (hello_world) stopped.
Process 16399 launched: '/opt/adatutorial/.objs/hello_world' (x86_64)
(lldb) e Text
error: Could not find type system for language ada83: TypeSystem for language ada83 doesn't exist
Is there an LLDB plugin I need to install to support Ada debugging? I’ve searched extensively but haven’t found anything. Any assistance would be greatly appreciated.
The current hack for Rust support in lldb is to tell lldb that Rust is the same as C++, so that at least some expressions work, though many do not. Then the Rust folks have added a handful of data formatters that will get frame var to usefully present the Rust types that aren’t enough like C++ for lldb to comprehend them as C++ types.
This seems to make lldb at least somewhat useful for Rust.
If you want to support Ada for real in lldb, then you need to implement the TypeSystem interfaces for Ada, and you will likely also need a LanguageRuntime for Ada to handle things like “step across dispatch” if Ada does that and “Dynamic Type resolution” - again if that’s a thing in Ada.
You could compare the swift-enabled lldb fork to the non-swift one to get a bit of a sense of what this involves, though that implementation is somewhat more complex that the Ada job would be because of the way swift represents debug information, and because of the tight coupling between the Swift and ObjC languages.
In addition to what David and Jim have already said about adding support for Ada, I’d like to point out that you’re using lldb’s expression evaluation feature to try to get the value in a variable (The command e is just short for the expression command here). In order to do expression evaluation, lldb integrates a portion of a compiler into itself (clang for C/C++/ObjC/ObjC++ and Swift in apple’s fork). Since lldb has no explicit Ada support, this will always fail.
Instead of doing e Text to try to get the value, consider using frame variable Text command (or v Text for short). That should try to get the value based on the DWARF description of it (which I’m assuming you have because that’s the only way LLDB could know you’re dealing with Ada in the first place).
You can fix only so much with formatters. The language’s type system must be sufficiently close to C/C++ for LLDB to be able to parse DWARF debug info emitted by the compiler. I know next to nothing about Ada’s debug info, however I know of at least one language construct that has no analogues in C++: the discriminated unions. I would guess that trying to load Ada’s debug info as if it were C++ was broken badly enough, so LLDB devs had disabled this altogether.
BTW, Rust has a similar problem with its enums, and for a long time did not emit DW_TAG_variant (designed for exactly this purpose) in debug info, just so that debuggers would be able to parse its data structures, which would be later fixed up by type formatters. More recently, Rust support was added in mainline GDB, and there is an out-of-tree Rust type system implementation for LLDB. Current rustc does emit DW_TAG_variant. On the flip side, unmodified LLDB can no longer be used to debug Rust.
@juananpe The “hack” @jingham was referring to is probably this, which tells LLDB that it can use TypeSystemClang for Rust.
BTW, Rust has a similar problem with its enums, and for a long time did not emit DW_TAG_variant (designed for exactly this purpose) in debug info, just so that debuggers would be able to parse its data structures, which would be later fixed up by type formatters. More recently, Rust support was added in mainline GDB, and there is an out-of-tree Rust type system implementation for LLDB. Current rustc does emit DW_TAG_variant . On the flip side, unmodified LLDB can no longer be used to debug Rust.
FYI, there was a proposal recently to support DW_TAG_variant in the current C++ TypeSystem as a near-term solution to rust debugging: https://reviews.llvm.org/D149213
Looks like it was accepted but not committed yet.
The first step to getting lldb to parse DWARF and try to construct types for a given language is to make an lldb TypeSystem for it. Rust doesn’t have a Rust specific TypeSystem in lldb, but it fakes that by saying that the current clang TypeSystem supports Rust. That’s done in TypeSystemClangSupportsLanguage. Note that D, Pascal, and Dylan are also going along for that ride. That’s the hack I was mentioning.
Once you tell lldb that is can try to ingest Ada DWARF into the Clang TypeSystem, you can start to see whether lldb can actually do that, or whether the differences in the DWARF cause that to fail.
Then, as was discussed, for types that can’t be faithfully represented by a C++ focused DWARF parser (provided they don’t cause the parser to crash…) you can improve the data presentation using formatters as the Rust examples you found show.
There’s also some code in lldb to handle the Rust demangler. If Ada uses it’s own mangling scheme you will need to add support for that as well.
This question comes up occasionally (I remember a similar discussion about Rust). It would be nice if we could document this and make it part of the website so folks willing to add support for new languages can easily discover what the expectations (and challenges) are.
I’m running into the same issue(s) so thank you for sharing your solution. Would you mind also sharing your build options/script?
I don’t mind playing some with config options and learning, but I’ve never built LLVM/LLDB before so definitely appreciative of any tips. Based on the the “official” build instructions for LLDB, I was going to start out with the options below and then go on from there.
Thanks @juananpe, that was very helpful. It’s working!
I did get an error after applying the patch in TypeSystemClang.cpp related to undeclared identifiers for later Ada language definitions.
error: use of undeclared identifier 'eLanguageTypeAda2005'
language == eLanguageTypeAda2005 || language == eLanguageTypeAda2012 ||
error: use of undeclared identifier 'eLanguageTypeAda2012'
language == eLanguageTypeAda2005 || language == eLanguageTypeAda2012 ||
2 errors generated.
Removing the line and just leaving the older Ada enums worked for me.
// Use Clang for Ada until there is a proper language plugin for it
language == eLanguageTypeAda83 || language == eLanguageTypeAda95 ||
//language == eLanguageTypeAda2005 || language == eLanguageTypeAda2012 ||