Source: gcc-13 Followup-For: Bug #1067453 The gettimeofday import issue seems specific to the time_t 64 transition in Debian.
When building C on armhf, a #define replaces gettimeofday with __gettimeofday64 so the linker finds the 64 bits version in the libc. When linking Ada code, the linker searches for the gettimeofday symbol and links with the 32 bits version, as demonstrated by the reproducer script below. Here is the output. ./c_part timeval size: 128 tv_sec offset: 0 size: 64 value: 662A7756 tv_usec offset: 8 size: 64 value: 1C54 56 77 2A 66 00 00 00 00 54 1C 00 00 00 00 00 00 ./ada_part timeval size: 128 tv_sec offset: 0 size: 64 value:16#27A9662A7756# tv_usec offset: 8 size: 64 value:-16#80B1C0708345E00# 56 77 2A 66 A9 27 00 00 00 A2 CB F7 F8 E3 F4 F7 Changing the External_Name from "gettimeofday" to "__gettimeofday64" fixes the mismatch (except for the lower microseconds of course). ./c_part 81 76 2A 66 00 00 00 00 0F E2 0C 00 00 00 00 00 ./ada_part 81 76 2A 66 00 00 00 00 CB EC 0C 00 00 00 00 00 So we have two possible work-arounds. * build a C source with a __gnat_gettimeofday wrapper. This option, implemented by my last commit, patches gcc/ada/Makefile.rtl gcc/ada/cal.c gcc/ada/gcc-interface/Makefile.in gcc/ada/libgnat-s-osprim__posix.adb and interfers with the previous commit. * simply patch gcc/ada/libgnat/s-osprim__posix.adb with - pragma Import (C, gettimeofday, "gettimeofday"); + pragma Import (C, gettimeofday, "__gettimeofday64"); This seems better, but must only be applied on targets affected by the t64 transition. I do not know which one is the best, but at least the second one explains why the first one did work. Just in case, here is the reproducer script: -- #!/bin/sh set -efuv cat > hexdump.h <<EOF extern void hexdump(char* p, int length); EOF cat > hexdump.c <<EOF #include <stdio.h> #include "hexdump.h" void hexdump(char* p, int length) { while (length--) { printf(" %02hhX", *p++); } printf("\n"); } EOF cat > c_part.c <<EOF #include <limits.h> #include <stdlib.h> #include <stdio.h> #include <sys/time.h> #include "hexdump.h" int main(int argc, const char* argv[]) { struct timeval tv; if (argc == 1) { printf(" gettimeofday returned %i\n", gettimeofday(&tv, NULL)); printf(" timeval size: %lli\n", (long long int)( CHAR_BIT * sizeof(tv))); printf(" tv_sec"); printf(" offset: %lli", (long long int)((char*)(&(tv.tv_sec)) - (char*)(&tv))); printf(" size: %lli", (long long int)(CHAR_BIT * sizeof(tv.tv_sec))); printf(" value: %llX", (long long int)tv.tv_sec); printf("\n"); printf(" tv_usec"); printf(" offset: %lli", (long long int)((char*)(&(tv.tv_usec)) - (char*)(&tv))); printf(" size: %lli", (long long int)(CHAR_BIT * sizeof(tv.tv_usec))); printf(" value: %llX", (long long int)tv.tv_usec); printf("\n"); hexdump((char*)(&tv), sizeof(tv)); } else { printf(" time_t_bits : constant := %lli;\n", (long long int)(CHAR_BIT * sizeof(tv.tv_sec))); printf(" suseconds_t_bits : constant := %lli;\n", (long long int)( CHAR_BIT * sizeof(tv.tv_usec))); } return EXIT_SUCCESS; } EOF cat > ada_part.adb <<EOF with Ada.Long_Long_Integer_Text_IO; use Ada.Long_Long_Integer_Text_IO; with Ada.Text_IO; use Ada.Text_IO; with Interfaces.C; use Interfaces.C; with System; use System; procedure Ada_Part is $(./c_part 1) type time_t is range -2**(time_t_bits - 1) .. 2**(time_t_bits - 1) - 1 with Convention => C; type suseconds_t is range -2**(suseconds_t_bits - 1) .. 2**(suseconds_t_bits - 1) - 1 with Convention => C; type timeval is record tv_sec : time_t; tv_usec : suseconds_t; end record with Convention => C; function gettimeofday (tv : access timeval; tz : Address) return int with Import, Convention => C, External_Name => "gettimeofday"; -- Here Tv : aliased timeval; function Offset (A, B : Address) return String is (Long_Long_Integer'Image (Long_Long_Integer'Value (A'Img) - Long_Long_Integer'Value (B'Img))); I : constant int := gettimeofday(Tv'Access, Null_Address); procedure hexdump(p : Address; count : Integer) with Import, Convention => C, External_Name => "hexdump"; begin Put_Line (" gettimeofday returned" & I'Img); Put_Line (" timeval size:" & Integer'Image (Tv'Size)); Put (" tv_sec offset:" & Offset (Tv.tv_sec'Address, Tv'Address) & " size:" & Integer'Image (Tv.tv_sec'Size) & " value:"); Put (Long_Long_Integer (Tv.tv_sec), Width => 0, Base => 16); New_Line; Put (" tv_usec offset:" & Offset (Tv.tv_usec'Address, Tv'Address) & " size:" & Integer'Image (Tv.tv_usec'Size) & " value:"); Put (Long_Long_Integer (Tv.tv_usec), Width => 0, Base => 16); New_Line; hexdump (Tv'Address, Tv'Size / 8); end Ada_Part; EOF gcc -c -Wall -Wextra hexdump.c -o hexdump.o gcc -Wall -Wextra c_part.c hexdump.o -o c_part gnatmake -gnat2022 -gnatwa -gnatya ada_part.adb -largs hexdump.o ./c_part ./ada_part