Commit 0f090200 by Olivier Hainque Committed by Pierre-Marie de Rodat

[Ada] Robustify traceback symbolization from dwarf info

Symbolization of traceback entries from dwarf info is
failing in multiple cases for addresses originating from
shared libraries.

Part of the problem is a confusion across different functions
regarding the kind of "address" at hand, sometimes full process
runtime addresses (e.g. in traceback entries), sometimes module
relative (e.g. in dwarf info segments).

This change fixes this by introducing the use of distinct types
for the two kinds of addresses, resorting to System.Address
for runtime addresses and to Storage_Elements.Storage_Offset
for module relative values. The accompanying code changes
tidy a few places where we can now use standard operators
to combine offets & addresses, and include a few corrections
of consistency problems at spots where comparisons were done
between runtime addresses and relative offsets.

2018-05-21  Olivier Hainque  <hainque@adacore.com>

gcc/ada/

	* libgnat/s-dwalin.ads (Dwarf_Context): Change type of Load_Address to
	Address, and type of Low, High to Storage_Offset.
	(Low): Rename as Low_Address and convey that the return value is a
	runtime reference accounting for a load address.
	* libgnat/s-dwalin.adb (Read_Aranges_Entry): Adjust to the
	address/offset type changes.
	(Aranges_Lookup): Likewise.
	(Symbolic_Address): Likewise.
	(Symbolic_Traceback): Likewise.
	(Dump_Cache): Likewise.
	(Is_Inside): Likewise.
	(Open): Likewise.
	(Set_Load_Address): Likewise.
	(Low_Address): Likewise, and account for C.Load_Address.
	* libgnat/s-trasym__dwarf.adb (Lt): Use Low_Address instead of Low.
	(Multi_Module_Symbolic_Traceback): Compare address in traceback
	with module Low_Address instead of Low.

From-SVN: r260450
parent b029cc6e
2018-04-04 Olivier Hainque <hainque@adacore.com> 2018-04-04 Olivier Hainque <hainque@adacore.com>
* libgnat/s-dwalin.ads (Dwarf_Context): Change type of Load_Address to
Address, and type of Low, High to Storage_Offset.
(Low): Rename as Low_Address and convey that the return value is a
runtime reference accounting for a load address.
* libgnat/s-dwalin.adb (Read_Aranges_Entry): Adjust to the
address/offset type changes.
(Aranges_Lookup): Likewise.
(Symbolic_Address): Likewise.
(Symbolic_Traceback): Likewise.
(Dump_Cache): Likewise.
(Is_Inside): Likewise.
(Open): Likewise.
(Set_Load_Address): Likewise.
(Low_Address): Likewise, and account for C.Load_Address.
* libgnat/s-trasym__dwarf.adb (Lt): Use Low_Address instead of Low.
(Multi_Module_Symbolic_Traceback): Compare address in traceback
with module Low_Address instead of Low.
2018-04-04 Olivier Hainque <hainque@adacore.com>
* libgnat/s-dwalin.ads (Dwarf_Context): Rename Load_Slide as * libgnat/s-dwalin.ads (Dwarf_Context): Rename Load_Slide as
Load_Address. Load_Address.
* libgnat/s-dwalin.adb (Is_Inside): Adjust accordingly. * libgnat/s-dwalin.adb (Is_Inside): Adjust accordingly.
......
...@@ -74,7 +74,7 @@ package body System.Dwarf_Lines is ...@@ -74,7 +74,7 @@ package body System.Dwarf_Lines is
procedure Read_Aranges_Entry procedure Read_Aranges_Entry
(C : in out Dwarf_Context; (C : in out Dwarf_Context;
Start : out Integer_Address; Start : out Storage_Offset;
Len : out Storage_Count); Len : out Storage_Count);
-- Read a single .debug_aranges pair -- Read a single .debug_aranges pair
...@@ -86,7 +86,7 @@ package body System.Dwarf_Lines is ...@@ -86,7 +86,7 @@ package body System.Dwarf_Lines is
procedure Aranges_Lookup procedure Aranges_Lookup
(C : in out Dwarf_Context; (C : in out Dwarf_Context;
Addr : Address; Addr : Storage_Offset;
Info_Offset : out Offset; Info_Offset : out Offset;
Success : out Boolean); Success : out Boolean);
-- Search for Addr in .debug_aranges and return offset Info_Offset in -- Search for Addr in .debug_aranges and return offset Info_Offset in
...@@ -151,7 +151,7 @@ package body System.Dwarf_Lines is ...@@ -151,7 +151,7 @@ package body System.Dwarf_Lines is
procedure Symbolic_Address procedure Symbolic_Address
(C : in out Dwarf_Context; (C : in out Dwarf_Context;
Addr : Address; Addr : Storage_Offset;
Dir_Name : out Str_Access; Dir_Name : out Str_Access;
File_Name : out Str_Access; File_Name : out Str_Access;
Subprg_Name : out String_Ptr_Len; Subprg_Name : out String_Ptr_Len;
...@@ -296,20 +296,22 @@ package body System.Dwarf_Lines is ...@@ -296,20 +296,22 @@ package body System.Dwarf_Lines is
return; return;
end if; end if;
for I in Cache'Range loop for I in Cache'Range loop
Put (System.Address_Image (C.Low + Storage_Count (Cache (I).First))); declare
E : Search_Entry renames Cache (I);
Base_Address : constant System.Address :=
To_Address (Integer_Address (C.Low + Storage_Count (E.First)));
begin
Put (System.Address_Image (Base_Address));
Put (" - "); Put (" - ");
Put Put (System.Address_Image (Base_Address + Storage_Count (E.Size)));
(System.Address_Image
(C.Low + Storage_Count (Cache (I).First + Cache (I).Size)));
Put (" l@"); Put (" l@");
Put Put (System.Address_Image (To_Address (Integer_Address (E.Line))));
(System.Address_Image
(To_Address (Integer_Address (Cache (I).Line))));
Put (": "); Put (": ");
S := Read_Symbol (C.Obj.all, Offset (Cache (I).Sym)); S := Read_Symbol (C.Obj.all, Offset (E.Sym));
Name := Object_Reader.Name (C.Obj.all, S); Name := Object_Reader.Name (C.Obj.all, S);
Put (String (Name.Ptr (1 .. Name.Len))); Put (String (Name.Ptr (1 .. Name.Len)));
New_Line; New_Line;
end;
end loop; end loop;
end Dump_Cache; end Dump_Cache;
...@@ -372,18 +374,19 @@ package body System.Dwarf_Lines is ...@@ -372,18 +374,19 @@ package body System.Dwarf_Lines is
function Is_Inside (C : Dwarf_Context; Addr : Address) return Boolean is function Is_Inside (C : Dwarf_Context; Addr : Address) return Boolean is
begin begin
return (Addr >= To_Address (To_Integer (C.Low) + C.Load_Address) return (Addr >= C.Low + C.Load_Address
and Addr <= To_Address (To_Integer (C.High) + C.Load_Address)); and then Addr <= C.High + C.Load_Address);
end Is_Inside; end Is_Inside;
--------- -----------------
-- Low -- -- Low_Address --
--------- -----------------
function Low (C : Dwarf_Context) return Address is function Low_Address (C : Dwarf_Context)
return System.Address is
begin begin
return C.Low; return C.Load_Address + C.Low;
end Low; end Low_Address;
---------- ----------
-- Open -- -- Open --
...@@ -414,8 +417,8 @@ package body System.Dwarf_Lines is ...@@ -414,8 +417,8 @@ package body System.Dwarf_Lines is
-- Get memory bounds -- Get memory bounds
Get_Memory_Bounds (C.Obj.all, Lo, Hi); Get_Memory_Bounds (C.Obj.all, Lo, Hi);
C.Low := Address (Lo); C.Low := Storage_Offset (Lo);
C.High := Address (Hi); C.High := Storage_Offset (Hi);
-- Create a stream for debug sections -- Create a stream for debug sections
...@@ -779,7 +782,7 @@ package body System.Dwarf_Lines is ...@@ -779,7 +782,7 @@ package body System.Dwarf_Lines is
procedure Set_Load_Address (C : in out Dwarf_Context; Addr : Address) is procedure Set_Load_Address (C : in out Dwarf_Context; Addr : Address) is
begin begin
C.Load_Address := To_Integer (Addr); C.Load_Address := Addr;
end Set_Load_Address; end Set_Load_Address;
------------------ ------------------
...@@ -874,7 +877,7 @@ package body System.Dwarf_Lines is ...@@ -874,7 +877,7 @@ package body System.Dwarf_Lines is
procedure Aranges_Lookup procedure Aranges_Lookup
(C : in out Dwarf_Context; (C : in out Dwarf_Context;
Addr : Address; Addr : Storage_Offset;
Info_Offset : out Offset; Info_Offset : out Offset;
Success : out Boolean) Success : out Boolean)
is is
...@@ -887,13 +890,13 @@ package body System.Dwarf_Lines is ...@@ -887,13 +890,13 @@ package body System.Dwarf_Lines is
loop loop
declare declare
Start : Integer_Address; Start : Storage_Offset;
Len : Storage_Count; Len : Storage_Count;
begin begin
Read_Aranges_Entry (C, Start, Len); Read_Aranges_Entry (C, Start, Len);
exit when Start = 0 and Len = 0; exit when Start = 0 and Len = 0;
if Addr >= To_Address (Start) if Addr >= Start
and then Addr < To_Address (Start) + Len and then Addr < Start + Len
then then
Success := True; Success := True;
return; return;
...@@ -1160,7 +1163,7 @@ package body System.Dwarf_Lines is ...@@ -1160,7 +1163,7 @@ package body System.Dwarf_Lines is
procedure Read_Aranges_Entry procedure Read_Aranges_Entry
(C : in out Dwarf_Context; (C : in out Dwarf_Context;
Start : out Integer_Address; Start : out Storage_Offset;
Len : out Storage_Count) Len : out Storage_Count)
is is
begin begin
...@@ -1171,7 +1174,7 @@ package body System.Dwarf_Lines is ...@@ -1171,7 +1174,7 @@ package body System.Dwarf_Lines is
begin begin
S := Read (C.Aranges); S := Read (C.Aranges);
L := Read (C.Aranges); L := Read (C.Aranges);
Start := Integer_Address (S); Start := Storage_Offset (S);
Len := Storage_Count (L); Len := Storage_Count (L);
end; end;
elsif Address'Size = 64 then elsif Address'Size = 64 then
...@@ -1180,7 +1183,7 @@ package body System.Dwarf_Lines is ...@@ -1180,7 +1183,7 @@ package body System.Dwarf_Lines is
begin begin
S := Read (C.Aranges); S := Read (C.Aranges);
L := Read (C.Aranges); L := Read (C.Aranges);
Start := Integer_Address (S); Start := Storage_Offset (S);
Len := Storage_Count (L); Len := Storage_Count (L);
end; end;
else else
...@@ -1249,7 +1252,7 @@ package body System.Dwarf_Lines is ...@@ -1249,7 +1252,7 @@ package body System.Dwarf_Lines is
Info_Offset : Offset; Info_Offset : Offset;
Line_Offset : Offset; Line_Offset : Offset;
Success : Boolean; Success : Boolean;
Ar_Start : Integer_Address; Ar_Start : Storage_Offset;
Ar_Len : Storage_Count; Ar_Len : Storage_Count;
Start, Len : uint32; Start, Len : uint32;
First, Last : Natural; First, Last : Natural;
...@@ -1270,7 +1273,7 @@ package body System.Dwarf_Lines is ...@@ -1270,7 +1273,7 @@ package body System.Dwarf_Lines is
exit when Ar_Start = 0 and Ar_Len = 0; exit when Ar_Start = 0 and Ar_Len = 0;
Len := uint32 (Ar_Len); Len := uint32 (Ar_Len);
Start := uint32 (Ar_Start - To_Integer (C.Low)); Start := uint32 (Ar_Start - C.Low);
-- Search START in the array -- Search START in the array
First := Cache'First; First := Cache'First;
...@@ -1319,7 +1322,7 @@ package body System.Dwarf_Lines is ...@@ -1319,7 +1322,7 @@ package body System.Dwarf_Lines is
procedure Symbolic_Address procedure Symbolic_Address
(C : in out Dwarf_Context; (C : in out Dwarf_Context;
Addr : Address; Addr : Storage_Offset;
Dir_Name : out Str_Access; Dir_Name : out Str_Access;
File_Name : out Str_Access; File_Name : out Str_Access;
Subprg_Name : out String_Ptr_Len; Subprg_Name : out String_Ptr_Len;
...@@ -1384,7 +1387,7 @@ package body System.Dwarf_Lines is ...@@ -1384,7 +1387,7 @@ package body System.Dwarf_Lines is
Line_Num := Natural (Match.Line); Line_Num := Natural (Match.Line);
end Set_Result; end Set_Result;
Addr_Int : constant Integer_Address := To_Integer (Addr); Addr_Int : constant uint64 := uint64 (Addr);
Previous_Row : Line_Info_Registers; Previous_Row : Line_Info_Registers;
Info_Offset : Offset; Info_Offset : Offset;
Line_Offset : Offset; Line_Offset : Offset;
...@@ -1431,7 +1434,7 @@ package body System.Dwarf_Lines is ...@@ -1431,7 +1434,7 @@ package body System.Dwarf_Lines is
-- Search symbol -- Search symbol
S := First_Symbol (C.Obj.all); S := First_Symbol (C.Obj.all);
while S /= Null_Symbol loop while S /= Null_Symbol loop
if Spans (S, uint64 (Addr_Int)) then if Spans (S, Addr_Int) then
Subprg_Name := Object_Reader.Name (C.Obj.all, S); Subprg_Name := Object_Reader.Name (C.Obj.all, S);
exit; exit;
end if; end if;
...@@ -1479,13 +1482,13 @@ package body System.Dwarf_Lines is ...@@ -1479,13 +1482,13 @@ package body System.Dwarf_Lines is
if C.Registers.Is_Row then if C.Registers.Is_Row then
if not Previous_Row.End_Sequence if not Previous_Row.End_Sequence
and then Addr_Int >= Integer_Address (Previous_Row.Address) and then Addr_Int >= Previous_Row.Address
and then Addr_Int < Integer_Address (C.Registers.Address) and then Addr_Int < C.Registers.Address
then then
Set_Result (Previous_Row); Set_Result (Previous_Row);
return; return;
elsif Addr_Int = Integer_Address (C.Registers.Address) then elsif Addr_Int = C.Registers.Address then
Set_Result (C.Registers); Set_Result (C.Registers);
return; return;
end if; end if;
...@@ -1526,7 +1529,7 @@ package body System.Dwarf_Lines is ...@@ -1526,7 +1529,7 @@ package body System.Dwarf_Lines is
C : Dwarf_Context := Cin; C : Dwarf_Context := Cin;
Addr_In_Traceback : Address; Addr_In_Traceback : Address;
Addr_To_Lookup : Address; Offset_To_Lookup : Storage_Offset;
Dir_Name : Str_Access; Dir_Name : Str_Access;
File_Name : Str_Access; File_Name : Str_Access;
...@@ -1547,12 +1550,11 @@ package body System.Dwarf_Lines is ...@@ -1547,12 +1550,11 @@ package body System.Dwarf_Lines is
Addr_In_Traceback := PC_For (Traceback (J)); Addr_In_Traceback := PC_For (Traceback (J));
Addr_To_Lookup := To_Address Offset_To_Lookup := Addr_In_Traceback - C.Load_Address;
(To_Integer (Addr_In_Traceback) - C.Load_Address);
Symbolic_Address Symbolic_Address
(C, (C,
Addr_To_Lookup, Offset_To_Lookup,
Dir_Name, Dir_Name,
File_Name, File_Name,
Subprg_Name, Subprg_Name,
......
...@@ -75,9 +75,10 @@ package System.Dwarf_Lines is ...@@ -75,9 +75,10 @@ package System.Dwarf_Lines is
pragma Inline (Is_Inside); pragma Inline (Is_Inside);
-- Return true iff a run-time address Addr is within the module -- Return true iff a run-time address Addr is within the module
function Low (C : Dwarf_Context) return Address; function Low_Address (C : Dwarf_Context)
pragma Inline (Low); return System.Address;
-- Return the lowest address of C, from the module object file pragma Inline (Low_Address);
-- Return the lowest address of C, accounting for the module load address
procedure Dump (C : in out Dwarf_Context); procedure Dump (C : in out Dwarf_Context);
-- Dump each row found in the object's .debug_lines section to standard out -- Dump each row found in the object's .debug_lines section to standard out
...@@ -163,13 +164,15 @@ private ...@@ -163,13 +164,15 @@ private
type Search_Array_Access is access Search_Array; type Search_Array_Access is access Search_Array;
type Dwarf_Context (In_Exception : Boolean := False) is record type Dwarf_Context (In_Exception : Boolean := False) is record
Load_Address : System.Storage_Elements.Integer_Address := 0; Low, High : System.Storage_Elements.Storage_Offset;
Low, High : Address;
-- Bounds of the module, per the module object file -- Bounds of the module, per the module object file
Obj : SOR.Object_File_Access; Obj : SOR.Object_File_Access;
-- The object file containing dwarf sections -- The object file containing dwarf sections
Load_Address : System.Address := System.Null_Address;
-- The address at which the object file was loaded at run time
Has_Debug : Boolean; Has_Debug : Boolean;
-- True if all debug sections are available -- True if all debug sections are available
......
...@@ -263,7 +263,7 @@ package body System.Traceback.Symbolic is ...@@ -263,7 +263,7 @@ package body System.Traceback.Symbolic is
function Lt (Left, Right : Module_Cache_Acc) return Boolean is function Lt (Left, Right : Module_Cache_Acc) return Boolean is
begin begin
return Low (Left.C) < Low (Right.C); return Low_Address (Left.C) < Low_Address (Right.C);
end Lt; end Lt;
----------------------------- -----------------------------
...@@ -469,7 +469,7 @@ package body System.Traceback.Symbolic is ...@@ -469,7 +469,7 @@ package body System.Traceback.Symbolic is
Hi := Modules_Cache'Last; Hi := Modules_Cache'Last;
while Lo <= Hi loop while Lo <= Hi loop
Mid := (Lo + Hi) / 2; Mid := (Lo + Hi) / 2;
if Addr < Low (Modules_Cache (Mid).C) then if Addr < Low_Address (Modules_Cache (Mid).C) then
Hi := Mid - 1; Hi := Mid - 1;
elsif Is_Inside (Modules_Cache (Mid).C, Addr) then elsif Is_Inside (Modules_Cache (Mid).C, Addr) then
Multi_Module_Symbolic_Traceback Multi_Module_Symbolic_Traceback
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment