https://gcc.gnu.org/g:509cc70fbbba911722a428f3a8bb01edbb90a7eb

commit r15-3115-g509cc70fbbba911722a428f3a8bb01edbb90a7eb
Author: Sebastian Poeplau <poep...@adacore.com>
Date:   Wed Aug 7 11:21:25 2024 +0200

    ada: Fix incorrect tracebacks on Windows
    
    PECOFF symbols don't have a size attached to them. The symbol size that
    System.Object_Reader.Read_Symbol guesses to make up for the lack of
    information can be wrong when the symbol table doesn't match the
    algorithm's expectations; in particular that's the case when function
    symbols aren't sorted by address.
    
    To avoid incorrect tracebacks caused by wrong symbol size guesses, don't
    use the symbol size for PECOFF files when producing a traceback and
    instead pick the symbol with the highest address lower than the target
    address.
    
    gcc/ada/
    
            * libgnat/s-dwalin.adb (Symbolic_Address): Ignore symbol size in
            address-to-symbol translation for PECOFF files.

Diff:
---
 gcc/ada/libgnat/s-dwalin.adb | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/gcc/ada/libgnat/s-dwalin.adb b/gcc/ada/libgnat/s-dwalin.adb
index 46a7d61e78db..028a55d1f20b 100644
--- a/gcc/ada/libgnat/s-dwalin.adb
+++ b/gcc/ada/libgnat/s-dwalin.adb
@@ -1753,6 +1753,7 @@ package body System.Dwarf_Lines is
       Success      : Boolean;
       Done         : Boolean;
       S            : Object_Symbol;
+      Closest_S    : Object_Symbol := Null_Symbol;
 
    begin
       --  Initialize result
@@ -1801,7 +1802,22 @@ package body System.Dwarf_Lines is
       else
          S := First_Symbol (C.Obj.all);
          while S /= Null_Symbol loop
-            if Spans (S, Addr_Int) then
+            if Format (C.Obj.all) = PECOFF
+              or else Format (C.Obj.all) = PECOFF_PLUS
+            then
+               --  Don't use the size of symbols from PECOFF files; it's
+               --  just a guess and can be unreliable. Instead, iterate
+               --  over the entire symbol table and use the symbol with the
+               --  highest address lower than Addr_Int.
+
+               if Closest_S = Null_Symbol
+                 or else (Closest_S.Value < S.Value
+                   and then S.Value <= Addr_Int)
+               then
+                  Closest_S := S;
+               end if;
+
+            elsif Spans (S, Addr_Int) then
                Subprg_Name := Object_Reader.Name (C.Obj.all, S);
                exit;
             end if;
@@ -1809,6 +1825,14 @@ package body System.Dwarf_Lines is
             S := Next_Symbol (C.Obj.all, S);
          end loop;
 
+         if (Format (C.Obj.all) = PECOFF
+             or else Format (C.Obj.all) = PECOFF_PLUS)
+           and then Closest_S /= Null_Symbol
+         then
+            S := Closest_S;     --  for consistency with non-PECOFF
+            Subprg_Name := Object_Reader.Name (C.Obj.all, S);
+         end if;
+
          --  Search address in aranges table
 
          Aranges_Lookup (C, Addr, Info_Offset, Success);

Reply via email to