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;