From: Olivier Hainque <hain...@adacore.com>

A previous change arranged for the common definition of
struct_sigaction in s-osinte__android.ads to work both for
ARM and aarch64 by way of representation clauses with
field offsets taken from specialized versions of s-linux
(one for ARM, one for aarch64).

The aarch64 variant had the offsets wrong, placing the
sa_handler pointer at offset 4, following the sa_flags int
at offset 0. The pointer is 8 bytes wide so should be
placed at an offset multiple of 8. This caused a discrepancy
between the Ada runtime actions and the expectations of the
underlying libc functions called.

This change refactors the struct_sigaction definition
to instanciate an entire type provided by s-linux instead,
parametrized by sigset_t which needs to remain provided
by the common System.OS_Interface spec.

gcc/ada/ChangeLog:

        * libgnarl/s-linux__android-aarch64.ads: Provide an
        Android_Sigaction generic package to expose an aarch64
        version of struct_sigation, using a provided sigset_t
        for sa_flags.
        * libgnarl/s-linux__android-arm.ads: Likewise, for ARM
        rather than aarch64.
        * libgnarl/s-osinte__android.ads: Move sigset_t definition
        to the visible part and use it to instantiate the Android_Sigation
        generic provided by System.Linux, which is specialized for ARM vs
        aarch64. Define struct_sigaction out of the Android_Sigaction
        instance, remove the local representation clauses.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/libgnarl/s-linux__android-aarch64.ads | 18 ++++++---
 gcc/ada/libgnarl/s-linux__android-arm.ads     | 16 ++++++--
 gcc/ada/libgnarl/s-osinte__android.ads        | 40 +++++++------------
 3 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/gcc/ada/libgnarl/s-linux__android-aarch64.ads 
b/gcc/ada/libgnarl/s-linux__android-aarch64.ads
index 4f9e81ddf65..537c46b5d3c 100644
--- a/gcc/ada/libgnarl/s-linux__android-aarch64.ads
+++ b/gcc/ada/libgnarl/s-linux__android-aarch64.ads
@@ -118,13 +118,19 @@ package System.Linux is
    SIG33      : constant := 33; --  glibc internal signal
    SIG34      : constant := 34; --  glibc internal signal
 
-   --  struct_sigaction offsets
+   --  struct_sigaction
 
-   --  sa_flags come first on aarch64-android (sa_flags, sa_handler, sa_mask)
-
-   sa_flags_pos   : constant := 0;
-   sa_handler_pos : constant := sa_flags_pos + Interfaces.C.int'Size / 8;
-   sa_mask_pos    : constant := sa_handler_pos + Standard'Address_Size / 8;
+   generic
+      type sigset_t is private;
+   package Android_Sigaction is
+      type struct_sigaction is record
+         sa_flags    : Interfaces.C.int;
+         sa_handler  : System.Address;
+         sa_mask     : sigset_t;
+         sa_restorer : System.Address;
+      end record;
+      pragma Convention (C, struct_sigaction);
+   end Android_Sigaction;
 
    SA_SIGINFO  : constant := 16#00000004#;
    SA_ONSTACK  : constant := 16#08000000#;
diff --git a/gcc/ada/libgnarl/s-linux__android-arm.ads 
b/gcc/ada/libgnarl/s-linux__android-arm.ads
index 3e0325e1902..07bca55f6c4 100644
--- a/gcc/ada/libgnarl/s-linux__android-arm.ads
+++ b/gcc/ada/libgnarl/s-linux__android-arm.ads
@@ -118,11 +118,19 @@ package System.Linux is
    SIG33      : constant := 33; --  glibc internal signal
    SIG34      : constant := 34; --  glibc internal signal
 
-   --  struct_sigaction offsets
+   --  struct_sigaction
 
-   sa_handler_pos : constant := 0;
-   sa_mask_pos    : constant := Standard'Address_Size / 8;
-   sa_flags_pos   : constant := 4 + sa_mask_pos;
+   generic
+      type sigset_t is private;
+   package Android_Sigaction is
+      type struct_sigaction is record
+         sa_handler  : System.Address;
+         sa_mask     : sigset_t;
+         sa_flags    : Interfaces.C.int;
+         sa_restorer : System.Address;
+      end record;
+      pragma Convention (C, struct_sigaction);
+   end Android_Sigaction;
 
    SA_SIGINFO  : constant := 16#00000004#;
    SA_ONSTACK  : constant := 16#08000000#;
diff --git a/gcc/ada/libgnarl/s-osinte__android.ads 
b/gcc/ada/libgnarl/s-osinte__android.ads
index d74589047e7..4383860ed2b 100644
--- a/gcc/ada/libgnarl/s-osinte__android.ads
+++ b/gcc/ada/libgnarl/s-osinte__android.ads
@@ -147,7 +147,20 @@ package System.OS_Interface is
    --  Not clear why these two signals are reserved. Perhaps they are not
    --  supported by this version of GNU/Linux ???
 
-   type sigset_t is private;
+   --  struct sigaction fields are of different sizes and come in different
+   --  order on ARM vs aarch64.  As this source is shared by the two
+   --  configurations, fetch the type definition through System.Linux, which
+   --  is specialized.
+
+   type sigset_t is
+     array (0 .. OS_Constants.SIZEOF_sigset - 1) of Interfaces.C.unsigned_char;
+   pragma Convention (C, sigset_t);
+   for sigset_t'Alignment use Interfaces.C.unsigned_long'Alignment;
+
+   package Android_Sigaction is new
+     System.Linux.Android_Sigaction (sigset_t => sigset_t);
+
+   type struct_sigaction is new Android_Sigaction.struct_sigaction;
 
    function sigaddset (set : access sigset_t; sig : Signal) return int;
    pragma Import (C, sigaddset, "_sigaddset");
@@ -173,14 +186,6 @@ package System.OS_Interface is
    end record;
    pragma Convention (C, siginfo_t);
 
-   type struct_sigaction is record
-      sa_handler  : System.Address;
-      sa_mask     : sigset_t;
-      sa_flags    : Interfaces.C.int;
-      sa_restorer : System.Address;
-   end record;
-   pragma Convention (C, struct_sigaction);
-
    type struct_sigaction_ptr is access all struct_sigaction;
 
    SA_SIGINFO : constant := System.Linux.SA_SIGINFO;
@@ -623,23 +628,6 @@ package System.OS_Interface is
 
 private
 
-   type sigset_t is
-     array (0 .. OS_Constants.SIZEOF_sigset - 1) of unsigned_char;
-   pragma Convention (C, sigset_t);
-   for sigset_t'Alignment use Interfaces.C.unsigned_long'Alignment;
-
-   pragma Warnings (Off);
-   for struct_sigaction use record
-      sa_handler at Linux.sa_handler_pos range 0 .. Standard'Address_Size - 1;
-      sa_mask    at Linux.sa_mask_pos
-        range 0 .. OS_Constants.SIZEOF_sigset * 8 - 1;
-      sa_flags   at Linux.sa_flags_pos
-        range 0 .. Interfaces.C.int'Size - 1;
-   end record;
-   --  We intentionally leave sa_restorer unspecified and let the compiler
-   --  append it after the last field, so disable corresponding warning.
-   pragma Warnings (On);
-
    type pid_t is new int;
 
    type time_t is range -2 ** (System.Parameters.time_t_bits - 1)
-- 
2.43.0

Reply via email to