Debugging methodology

Hi,

When faced with an error which causes an exception, what is your approach for debugging the issue?

I have tried using -Es in Binder accompanied with -g in Compiler and Binder. However, this just gives me a stack trace with addresses, which then passing to addr2line does not seem to work ( maybe because of it being PIE ? ).

EDIT: it actually gives different addresses for what is the same call stack in different runs

Furthermore, I have tried using gdb’s command catch exception but it complains that the runtime does not have the necessary debugging information. For this it may be useful to note that I am using voidlinux-musl.

Best regards
– zen

There is a package: GNAT.Exception_Actions. Use it to set an exception handler. Inside the handler you can trace the exception and print the call stack using this snippet:

procedure Call_Stack is
   use 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;

As for the rest, from my experience:

  • -Es does not work
  • gdb is useless in most cases
  • expect nasty surprizes on ARM targets
  • expect issues with tracing relocatable libraries

I never develop on ARM. First I make it work on x86 under Windows. Then I do a short check under a Linux for x86. If both work chances are good that ARM would be OK.

I am in X86, just using the musl libc implementation. I tried your snippet but it works the same as -Es for me, it just gives the backtrace addresses but nothing else :confused: .

example:

raised ADA.ASSERTIONS.ASSERTION_ERROR : failed precondition from rv-instruction-encoding.adb:728
0x7f752b2b6c21 ??? at ???
0x560b6e4fb8ba ??? at ???
0x560b6e4fe48f ??? at ???
0x560b6e525955 ??? at ???
0x560b6e525e5a ??? at ???
0x560b6e4f2ebd ??? at ???
0x560b6e4f3490 ??? at ???
0x7f752b52ae09 ??? at ???

Check -g switch and that symbols are not stripped by the tool chain.

I have .debug_info and peers in the executable elf. Also, gdb seems to work just fine for stepping, next, etc. Using backtrace gives the backtrace correctly, with symbols included.

Can you get call stack from Hello_World?

Does this help you execute “catch exception”?

apk add musl-dbg

main.gpr

project Main is

    for Main use ("main.adb");

    for Source_Files use ("main.adb");
    for Object_Dir use "obj";


    package Compiler is
      for Default_Switches ("Ada") use ("-g");
    end Compiler;

    package Binder is
      for Default_Switches ("Ada") use ("-g", "-Es");
    end Binder;

end Main;

Explicit exception

main.adb

with Ada.Text_IO;

procedure Main is
begin
    Ada.Text_IO.Put_Line ("~ Ada Lovelace ~");
    raise Program_Error;
end Main;

output

~ Ada Lovelace ~

raised PROGRAM_ERROR : main.adb:7 explicit raise
0x56094691244b ??? at ???
0x560946912940 ??? at ???
0x7f89b38fee09 ??? at ???

Call_Stack

main.adb

with Ada.Text_IO;
with GNAT.Traceback, GNAT.Traceback.Symbolic;

procedure Main is
   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;
begin
    Ada.Text_IO.Put_Line ("~ Ada Lovelace ~");
    Call_Stack;
end Main;

output

~ Ada Lovelace ~
0x5577db8594e3 ??? at ???
0x5577db859648 ??? at ???
0x5577db859b6a ??? at ???
0x7f5284bdfe09 ??? at ???

Void Linux does not appear to have a similar package to that one. I have seen that package is availiable in Alpine Linux. /usr/lib/libc.so does have debug_info and others too. :thinking:

Here is what it looks like in the debugger:

Reading symbols from ./obj/main...
(gdb) start
Temporary breakpoint 1 at 0x3608: file /home/xxxx/Codeberg/rv_emu/hello_world/main.adb, line 5.
Starting program: /home/xxxx/Codeberg/rv_emu/hello_world/obj/main 

Temporary breakpoint 1, main () at /home/xxxx/Codeberg/rv_emu/hello_world/main.adb:5
5	procedure Main is
(gdb) catch exception
❌️ Your Ada runtime appears to be missing some debugging information.
Cannot insert Ada exception catchpoint in this configuration.
(gdb) 

I recommend the following flags: -Og (optimize for debugging), -ggdb generate GDB friendly info, -gnatVa enable all checks, -gnatwa enable all common warnings. Then in GDB do the catch exception as you did but also catch assert, which seems to be also taking place for you. You can also rebuild the entire RunTime System (RTS) with these flags and if the error takes place in the RTS, you will get all the symbols. For this, please, refer to 3. The GNAT Compilation Model — GNAT User's Guide for Native Platforms 27.0w documentation

Best regards,
Fer