[Ada] Robustify traceback caching for executable in current dir
authorOlivier Hainque <hainque@adacore.com>
Mon, 21 May 2018 14:51:09 +0000 (14:51 +0000)
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>
Mon, 21 May 2018 14:51:09 +0000 (14:51 +0000)
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

gcc/ada/ChangeLog
gcc/ada/libgnat/s-trasym__dwarf.adb

index a62bbe13089155a6eb9a656ab496ba07df20571c..fa449bf1a03dd6df9d45b05531556ac7b5363d5c 100644 (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.
index fb35b6066482be08b6797af82fb3d8e7cc7f57ea..732a5e21f4caf801aff6e695d400d7e3687e1d45 100644 (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;