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