From 18c7a4eb877d3c3df5975a3841f76cb05897d1e9 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Mon, 21 May 2018 14:51:09 +0000 Subject: [PATCH] [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 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 --- gcc/ada/ChangeLog | 7 ++++++ gcc/ada/libgnat/s-trasym__dwarf.adb | 38 +++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index a62bbe13089..fa449bf1a03 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2018-04-04 Olivier Hainque + + * 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 * libgnarl/a-reatim.ads (Clock_Time): Remove External aspect. diff --git a/gcc/ada/libgnat/s-trasym__dwarf.adb b/gcc/ada/libgnat/s-trasym__dwarf.adb index fb35b606648..732a5e21f4c 100644 --- a/gcc/ada/libgnat/s-trasym__dwarf.adb +++ b/gcc/ada/libgnat/s-trasym__dwarf.adb @@ -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; -- 2.30.2