Is is true that there is currently no way to debug Ada (GNAT) on Apple Silicon computers? After a great deal of fussing around, I am able only to have breakpoints honored and to see the call stack—no examination of variables except CPU registers. This works by both running lldb from a command line and starting a debug session as described in the tutorial for the AdaCore VS Code extension v26.0.202412191.
If so, can we get a conspicuous and unambiguous statement to that effect on e.g. the extension and its web site, as well as the download site for the compiler.
If not, can someone provide some guidance based e.g. on the Ada extension tutorial.
The problem is GDB. It never worked properly and never will on larger projects and/or relocatable libraries. I gave up a long time ago and am quite happy with tracing. Life is too short to let GDB in it.
You can still use the -g switch. What also may come useful when tracing is this small procedure:
with Ada.Text_IO, GNAT.Traceback, GNAT.Traceback.Symbolic;
procedure Call_Stack is
use Ada.Text_IO, GNAT.Traceback, GNAT.Traceback.Symbolic;
TB : Tracebacks_Array (1..1_000); Len : Natural;
begin
Call_Chain (TB, Len); Put_Line (Symbolic_Traceback (TB (1..Len)));
end Call_Stack;
It might not work on some targets, though. Well, being posh has its price literally and otherwise…
lldb, not gdb, is indicated for macOS on Apple Silicon, according to the AdaCore VS Code extension and other resources. lldb is what I used to get the limited operation that I described earlier.
Is this a matter of waiting for the work (finishing lldb) to be completed or is there a fundamental reason why debugging Ada on Macs won’t work?
I do not know of relocatable libraries, but compiling Ada code (with -Og and -ggdb and other GNAT checks such as -gnata) and debugging it with GDB, I have had a lot of success and quite a bit of pleasure I would say! I always start GDB with catch assertions and catch exceptions and just let the program run until it tells me what went wrong
Back to the main topic, this also works with lldb on Apple Silicon as far as I know. However, sometimes an error in the program does not lead to a crash or an exception, and that is when one needs to set breakpoints and examine variables. Someone will without doubt suggest using print statements but that is not a viable approach when the program runs an hour+ before encountering a problem.
You sit an hour+ watching it running under debugger?
An error that shows late is usually memory leak, some other resource exhaustion issue or a numeric/algorithmic issue when using naive algorithms, like summing up a large set of numbers to calculate average. You never find these under debugger. Debugger even if works has a very limited use. For anything more advanced than hello-world consider extensive unit testing and tracing to isolate the problem.
No, you’d use something like tmux and put it in a back window and set it to alert when it hits a breakpoint. Or you run it as an overnight soak test.
There’s other sorts of rare logic conditions and weird interactions that you can find in long-lived soak testings.
I looked at this only a little bit over Christmas break when I only had a Mac to write Ada. lldb was reporting “Ada95” errors on display, but I didn’t investigate to see if you might need to write something analogous to MSVC natvis files for lldb, or if there’s more effort required.
I’ve had success setting breakpoints programmatically in error routines with something like this to allow manual analysis on Mac and Linux. Maybe I need to throw it into an actual Alire crate since it has been so useful. Using the following, you just call the Breakpoint procedure when you want a breakpoint.
with Interfaces.C;
package body Rfl.Platform is
SIGTRAP : constant := 5;
function C_Raise (Sig : Interfaces.C.int) return Interfaces.C.int
with Import => True, Convention => C, External_Name => "raise";
procedure Breakpoint is
use type Interfaces.C.int;
begin
if C_Raise (SIGTRAP) /= 0 then
raise Program_Error;
end if;
end Breakpoint;
end Rfl.Platform;
No. I’m saying that GDB does not work on AArch64 on macOS as far as I know–I would love to be corrected. (Some older macOS machines still run Intel processors upon which GDB presumably still works. Apple began transitioning to ARM four years ago and now the transition is complete.) It seems that Apple Silicon requires LLDB.
FWIW, I am not running Ubuntu, but macOS with AArch64 which requires LLDB, upon which watchpoints don’t work.
Let me clarify some points which have become confused in relation to my original post as I understand them.
GDB works on Macs running Ada on Intel processors.
GDB does not work on Apple Silicon for any language.
LLDB works on Macs running on Apple Silicon for non-Ada languages but not Ada, except for the breakpoint and stack behavior as noted earlier.
Also, I considered this off-topic but apparently there is some confusion about why I would be interested in debugging a program that runs a long time. My program is a simulation. It can run from as little as a few seconds to as long as I care to wait, including some hours, by adjusting some parameters. The program exits normally, without crashes or exceptions. It just returns the wrong results. It would be helpful to view the values of some intermediate calculations before the program ends.
Even further off-topic: extended running time is an issue with Ada relative to e.g. Julia and Fortran. I am aware of the lightweight threading work at parasail/lwt at main · parasail-lang/parasail · GitHub but getting this to work on splitting loops across cores seems to exceed my resources in both skills and time.
Well, this is exactly the case when debugging does not work! I faced a similar problem that many numerical algorithms published in the literature are just wrong. They work on some inputs and fail on others. Debugger is no help because to find the issue I needed to compare execution on different sets of values and print relatively large structures of data, perform independent computations of invariants etc repeatedly. This is part debugging part programming.
As a maintainer of Julia Ada bindings. Julia is a slow interpreted language. It probably faster than Python, but nowhere close to Ada. You must have some algorithmic problem.