[Ada] Robustify traceback caching for executable in current dir

Any program calling Gnat.Traceback.Symbolic.Enable_Cache for
dwarf based symbolization fails with a segmentation violation
when spawned with an inaccurate argv[0] such that it couldn't
be found on PATH.

argv[0] is most often found on PATH. One plausible case where
it isn't is when argv[0] is a mere file name and . isn't on PATH,
which might happen out of imprecise exec calls.

This change robustifies the Traceback.Symbolic implementation
to work in this case as well, by just trying to work with argv[0]
untouched as the executable file to fetch dwarf info from.

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

gcc/ada/

	* libgnat/s-trasym__dwarf.adb (Executable_Name): Return argv[0] instead
	of empty string when argv[0] couldn't be found on PATH.
	(Enable_Cache): Raise Program_Error instead of attempting a null
	pointer dereference when the Exec_Module initialization failed.

From-SVN: r260456
This commit is contained in:
Olivier Hainque 2018-05-21 14:51:09 +00:00 committed by Pierre-Marie de Rodat
parent bbb9900657
commit 18c7a4eb87
2 changed files with 37 additions and 8 deletions

View File

@ -1,3 +1,10 @@
2018-04-04 Olivier Hainque <hainque@adacore.com>
* libgnat/s-trasym__dwarf.adb (Executable_Name): Return argv[0] instead
of empty string when argv[0] couldn't be found on PATH.
(Enable_Cache): Raise Program_Error instead of attempting a null
pointer dereference when the Exec_Module initialization failed.
2018-04-04 Piotr Trojanek <trojanek@adacore.com>
* libgnarl/a-reatim.ads (Clock_Time): Remove External aspect.

View File

@ -151,8 +151,8 @@ package body System.Traceback.Symbolic is
function Executable_Name return String;
-- Returns the executable name as reported by argv[0]. If gnat_argv not
-- initialized or if argv[0] executable not found in path, function returns
-- an empty string.
-- initialized, return an empty string. If the argv[0] executable is not
-- found in the PATH, return it unresolved.
function Get_Executable_Load_Address return System.Address;
pragma Import
@ -289,6 +289,12 @@ package body System.Traceback.Symbolic is
-- Add all modules
Init_Exec_Module;
if Exec_Module_State = Failed then
raise Program_Error with
"cannot enable cache, executable state initialization failed.";
end if;
Cache_Chain := Exec_Module'Access;
if Include_Modules then
@ -347,17 +353,33 @@ package body System.Traceback.Symbolic is
return "";
end if;
-- See if we can resolve argv[0] to a full path (to a file that we will
-- be able to open). If the resolution fails, we were probably spawned
-- by an imprecise exec call, typically passing a mere file name as
-- argv[0] for a program in the current directory with '.' not on PATH.
-- Best we can do is fallback to argv[0] unchanged in this case. If we
-- fail opening that downstream, we'll just bail out.
declare
Addr : constant System.Address :=
locate_exec_on_path (Conv.To_Pointer (Gnat_Argv) (0));
Result : constant String := Value (Addr);
Argv0 : constant System.Address
:= Conv.To_Pointer (Gnat_Argv) (0);
Resolved_Argv0 : constant System.Address
:= locate_exec_on_path (Argv0);
Exe_Argv : constant System.Address
:= (if Resolved_Argv0 /= System.Null_Address
then Resolved_Argv0
else Argv0);
Result : constant String := Value (Exe_Argv);
begin
-- The buffer returned by locate_exec_on_path was allocated using
-- malloc, so we should use free to release the memory.
-- malloc and we should release this memory.
if Addr /= Null_Address then
System.CRTL.free (Addr);
if Resolved_Argv0 /= Null_Address then
System.CRTL.free (Resolved_Argv0);
end if;
return Result;