If s-trasym.adb (System.Traceback.Symbolic, used as a renaming by
GNAT.Traceback.Symbolic) is given a traceback from a
position-independent executable, it does not include the executable's
load address in the report. This is necessary in order to decode the
traceback report.

Note, this has already been done for s-trasym__dwarf.adb, which really
does produce a symbolic traceback; s-trasym.adb is the version used in
systems which don't actually support symbolication.

Bootstrapped and regtested (ada onlyj) on x86_64-apple-darwin.

* gcc/ada/libgnat/s-trasym.adb: Returns the traceback in the required
   form. Note that leading zeros are trimmed from hexadecimal strings.
 (Symbolic_Traceback): Import Executable_Load_Address.
 (Load_Address): New, from call to Executable_Load_Address.
 (One_If_Executable_Is_PI): New, 0 if Load_Address is null, 1 if
   not.
 (Image_Length): New, found by calling System.Address_Image on
   the first address in the traceback. NB, doesn't include "0x".
 (Load_Address_Prefix): New, String containing the required value.
 (Length_Needed): New, computed using the number of elements
   in the traceback, plus the load address if the executable is PIE.
 (Result): New String of the required length (which will be an
   overestimate).

2024-11-24  Simon Wright   <si...@pushface.org>

gcc/ada/Changelog:

PR target/117538
* libgnat/s-trasym.adb: Returns the traceback, with the program load
address if applicable.

---
diff --git a/gcc/ada/libgnat/s-trasym.adb b/gcc/ada/libgnat/s-trasym.adb
index 894fcf37ffd..5351f6fda9b 100644
--- a/gcc/ada/libgnat/s-trasym.adb
+++ b/gcc/ada/libgnat/s-trasym.adb
@@ -53,19 +53,63 @@ package body System.Traceback.Symbolic is
 
       else
          declare
-            Img : String := System.Address_Image (Traceback (Traceback'First));
-
-            Result : String (1 .. (Img'Length + 3) * Traceback'Length);
-            Last   : Natural := 0;
+            function Executable_Load_Address return System.Address;
+            pragma Import
+              (C, Executable_Load_Address,
+               "__gnat_get_executable_load_address");
+
+            Load_Address : constant System.Address :=
+              Executable_Load_Address;
+            One_If_Executable_Is_PI : constant Natural :=
+              Boolean'Pos (Load_Address /= Null_Address);
+
+            --  How long is an Address_Image? (hex digits only).
+            Image_Length : constant Natural :=
+              System.Address_Image (Traceback (Traceback'First))'
+                Length;
+
+            Load_Address_Prefix : constant String :=
+              "Load address: ";
+
+            --  For each address to be output, we need the preceding "%x"
+            --  and a trailing space, making 3 additional characters.
+            --  There are 2 additional LFs.
+            Length_Needed : constant Positive :=
+              (Load_Address_Prefix'Length *
+               One_If_Executable_Is_PI) +
+              (Image_Length + 3) *
+                (Traceback'Length + One_If_Executable_Is_PI) +
+              2;
+
+            Result : String (1 .. Length_Needed);
+
+            Last : Natural := 0;
 
          begin
+
+            if One_If_Executable_Is_PI /= 0 then
+               declare
+                  Item : constant String :=
+                    Load_Address_Prefix & "0x" &
+                    System.Address_Image (Load_Address) &
+                    ASCII.LF;
+               begin
+                  Last := Item'Length;
+                  Result (1 .. Last) := Item;
+               end;
+            end if;
+
             for J in Traceback'Range loop
-               Img := System.Address_Image (Traceback (J));
-               Result (Last + 1 .. Last + 2)          := "0x";
-               Last                                   := Last + 2;
-               Result (Last + 1 .. Last + Img'Length) := Img;
-               Last                                   := Last + Img'Length + 1;
-               Result (Last)                          := ' ';
+               declare
+                  Img : constant String :=
+                    System.Address_Image (Traceback (J));
+               begin
+                  Result (Last + 1 .. Last + 2) := "0x";
+                  Last := Last + 2;
+                  Result (Last + 1 .. Last + Img'Length) := Img;
+                  Last := Last + Img'Length + 1;
+                  Result (Last) := ' ';
+               end;
             end loop;
 
             Result (Last) := ASCII.LF;

Reply via email to