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.
(Trim_Hex): New internal function to trim leading '0' characters
from a hexadecimal string.
(Load_Address): New, from call to Executable_Load_Address.
(One_If_Executable_Is_PI): New, 0 if Load_Address is null, 1 if
not.
(Max_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.
(Max_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-13 Simon Wright <[email protected]>
gcc/ada/Changelog:
PR target/117538
* libgnat/s-trasym.adb: Returns the traceback in the required
form. Note that leading zeros are trimmed from hexadecimal strings.
—
diff --git a/gcc/ada/libgnat/s-trasym.adb b/gcc/ada/libgnat/s-trasym.adb
index 894fcf37ffd..7172214453f 100644
--- a/gcc/ada/libgnat/s-trasym.adb
+++ b/gcc/ada/libgnat/s-trasym.adb
@@ -53,19 +53,75 @@ 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");
+
+ function Trim_Hex (S : String) return String;
+ function Trim_Hex (S : String) return String is
+ Non_0 : Positive;
+ begin
+ for J in S'Range loop
+ if S (J) /= '0' or else J = S'Last then
+ Non_0 := J;
+ exit;
+ end if;
+ end loop;
+ return S (Non_0 .. S'Last);
+ end Trim_Hex;
+
+ 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?
+ Max_Image_Length : constant Natural :=
+ System.Address_Image (Traceback (Traceback'First))'
+ Length;
+
+ Load_Address_Prefix : constant String :=
+ "Load address: ";
+
+ Max_Length_Needed : constant Positive :=
+ (Load_Address_Prefix'Length *
+ One_If_Executable_Is_PI) +
+ (Max_Image_Length + 3) *
+ (Traceback'Length + One_If_Executable_Is_PI) +
+ 2;
+
+ Result : String (1 .. Max_Length_Needed);
+
+ Last : Natural := 0;
begin
+
+ if One_If_Executable_Is_PI /= 0 then
+ declare
+ item : constant String :=
+ Load_Address_Prefix & "0x" &
+ Trim_Hex
+ (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 :=
+ Trim_Hex
+ (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;