diff --git a/headers/header_spec.txt b/headers/header_spec.txt
index 81ea66623889de33690c7d2cfd92aa261053deb6..23e24fa4d73ef6939753a9a7177bc6a8b73f3708 100644
--- a/headers/header_spec.txt
+++ b/headers/header_spec.txt
@@ -180,6 +180,7 @@ share/libc/__fc_define_clockid_t.h: CEA_LGPL
 share/libc/__fc_define_dev_t.h: CEA_LGPL
 share/libc/__fc_define_eof.h: CEA_LGPL
 share/libc/__fc_define_fd_set_t.h: CEA_LGPL
+share/libc/__fc_define_fds.h: CEA_LGPL
 share/libc/__fc_define_file.h: CEA_LGPL
 share/libc/__fc_define_fpos_t.h: CEA_LGPL
 share/libc/__fc_define_fs_cnt.h: CEA_LGPL
@@ -206,6 +207,7 @@ share/libc/__fc_define_suseconds_t.h: CEA_LGPL
 share/libc/__fc_define_time_t.h: CEA_LGPL
 share/libc/__fc_define_timer_t.h: CEA_LGPL
 share/libc/__fc_define_timespec.h: CEA_LGPL
+share/libc/__fc_define_timeval.h: CEA_LGPL
 share/libc/__fc_define_uid_and_gid.h: CEA_LGPL
 share/libc/__fc_define_useconds_t.h: CEA_LGPL
 share/libc/__fc_define_wchar_t.h: CEA_LGPL
diff --git a/share/libc/__fc_define_fd_set_t.h b/share/libc/__fc_define_fd_set_t.h
index 5f9b7c721b2124a2158961a07c7db38eda5506e3..5e6bbe0272593c03712707a3966a0cd086f32250 100644
--- a/share/libc/__fc_define_fd_set_t.h
+++ b/share/libc/__fc_define_fd_set_t.h
@@ -29,40 +29,6 @@ __PUSH_FC_STDLIB
 __BEGIN_DECLS
 typedef struct __fc_fd_set { long __fc_fd_set[FD_SETSIZE / NFDBITS]; } fd_set;
 
-/*@
-  requires valid_fdset: \valid(fdset);
-  requires initialization: \initialized(fdset);
-  assigns *fdset \from *fdset, indirect:fd;
-*/
-extern void FD_CLR(int fd, fd_set *fdset);
-#define FD_CLR FD_CLR
-
-// Note: the 2nd argument in FD_ISSET is not const in some implementations
-// due to historical and compatibility reasons.
-/*@
-  requires valid_fdset: \valid_read(fdset);
-  requires initialization: \initialized(fdset);
-  assigns \result \from indirect:*fdset, indirect:fd;
-*/
-extern int FD_ISSET(int fd, const fd_set *fdset);
-#define FD_ISSET FD_ISSET
-
-/*@
-  requires valid_fdset: \valid(fdset);
-  requires initialization: \initialized(fdset);
-  assigns *fdset \from *fdset, indirect:fd;
-*/
-extern void FD_SET(int fd, fd_set *fdset);
-#define FD_SET FD_SET
-
-/*@
-  requires valid_fdset: \valid(fdset);
-  assigns *fdset \from \nothing;
-  ensures initialization: \initialized(fdset);
-*/
-extern void FD_ZERO(fd_set *fdset);
-#define FD_ZERO FD_ZERO
-
 __END_DECLS
 __POP_FC_STDLIB
 #endif
diff --git a/share/libc/__fc_define_fds.h b/share/libc/__fc_define_fds.h
new file mode 100644
index 0000000000000000000000000000000000000000..6905aad49acb612be5e77082bcd23d64356053a9
--- /dev/null
+++ b/share/libc/__fc_define_fds.h
@@ -0,0 +1,40 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2021                                               */
+/*    CEA (Commissariat à l'énergie atomique et aux énergies              */
+/*         alternatives)                                                  */
+/*                                                                        */
+/*  you can redistribute it and/or modify it under the terms of the GNU   */
+/*  Lesser General Public License as published by the Free Software       */
+/*  Foundation, version 2.1.                                              */
+/*                                                                        */
+/*  It is distributed in the hope that it will be useful,                 */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
+/*  GNU Lesser General Public License for more details.                   */
+/*                                                                        */
+/*  See the GNU Lesser General Public License version 2.1                 */
+/*  for more details (enclosed in the file licenses/LGPLv2.1).            */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef __FC_DEFINE_FDS
+#define __FC_DEFINE_FDS
+#include "features.h"
+__PUSH_FC_STDLIB
+__BEGIN_DECLS
+
+// arbitrary number
+#ifndef __FC_MAX_OPEN_FILES
+#define __FC_MAX_OPEN_FILES 1024
+#endif
+
+// __fc_fds represents the state of open file descriptors.
+extern volatile int __fc_fds[__FC_MAX_OPEN_FILES];
+
+__END_DECLS
+
+__POP_FC_STDLIB
+#endif
diff --git a/share/libc/__fc_define_timeval.h b/share/libc/__fc_define_timeval.h
new file mode 100644
index 0000000000000000000000000000000000000000..34db8894a582b2e7a28779182505194efadaed79
--- /dev/null
+++ b/share/libc/__fc_define_timeval.h
@@ -0,0 +1,36 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of Frama-C.                                         */
+/*                                                                        */
+/*  Copyright (C) 2007-2021                                               */
+/*    CEA (Commissariat à l'énergie atomique et aux énergies              */
+/*         alternatives)                                                  */
+/*                                                                        */
+/*  you can redistribute it and/or modify it under the terms of the GNU   */
+/*  Lesser General Public License as published by the Free Software       */
+/*  Foundation, version 2.1.                                              */
+/*                                                                        */
+/*  It is distributed in the hope that it will be useful,                 */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
+/*  GNU Lesser General Public License for more details.                   */
+/*                                                                        */
+/*  See the GNU Lesser General Public License version 2.1                 */
+/*  for more details (enclosed in the file licenses/LGPLv2.1).            */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef __FC_DEFINE_TIMEVAL
+#define __FC_DEFINE_TIMEVAL
+#include "features.h"
+__PUSH_FC_STDLIB
+__BEGIN_DECLS
+#include "__fc_define_suseconds_t.h"
+#include "__fc_define_time_t.h"
+struct timeval {
+  time_t         tv_sec;
+  suseconds_t    tv_usec;
+};
+__END_DECLS
+__POP_FC_STDLIB
+#endif
diff --git a/share/libc/__fc_select.h b/share/libc/__fc_select.h
index 4fc0f3b0aa6e161a24d6daefa686adb5e5223392..1fad5956e876ce077f8db6bfccda7db5ddd8c7d4 100644
--- a/share/libc/__fc_select.h
+++ b/share/libc/__fc_select.h
@@ -24,13 +24,11 @@
 #define __FC_SELECT__
 #include "features.h"
 __PUSH_FC_STDLIB
-#include "__fc_define_time_t.h"
-#include "__fc_define_suseconds_t.h"
 #include "__fc_define_fd_set_t.h"
 #include "__fc_define_sigset_t.h"
-
-#include "sys/time.h"
-
+#include "__fc_define_suseconds_t.h"
+#include "__fc_define_timeval.h"
+#include "__fc_define_timespec.h"
 __BEGIN_DECLS
 
 /* assigns \result \from nfds, *readfds, *writefds,*errorfds,*timeout,*sigmask;
diff --git a/share/libc/getopt.h b/share/libc/getopt.h
index ed3f45384b71e51ed761a1e0d67c7f38462eb608..380abc7f5aba56b890fa82bd197dbce6e5acead3 100644
--- a/share/libc/getopt.h
+++ b/share/libc/getopt.h
@@ -24,10 +24,9 @@
 #define __FC_GETOPT_H
 #include "features.h"
 __PUSH_FC_STDLIB
-
+#include "unistd.h"
 __BEGIN_DECLS
 
-#include "unistd.h"
 
 /* GNU specific */
 struct option
diff --git a/share/libc/limits.h b/share/libc/limits.h
index be32d497acd2883f59ef9096978290932287fc37..7c19508f17883e2954384f61b9d79f6ca228440a 100644
--- a/share/libc/limits.h
+++ b/share/libc/limits.h
@@ -95,4 +95,9 @@
  */
 #define ARG_MAX 4096
 
+// POSIX; used by <sys/uio.h>.
+// Must be >= _XOPEN_IOV_MAX, which is 16.
+// 1024 is the value used by some Linux implementations.
+#define IOV_MAX 1024
+
 #endif
diff --git a/share/libc/sys/select.h b/share/libc/sys/select.h
index c680c04d2e2ec48a879ee4b74dccc8468abfbdd2..d3ceb4b58487f35543d5c5fdf13ec56deea00c6a 100644
--- a/share/libc/sys/select.h
+++ b/share/libc/sys/select.h
@@ -28,6 +28,40 @@ __BEGIN_DECLS
 
 #include "../__fc_select.h"
 
+/*@
+  requires valid_fdset: \valid(fdset);
+  requires initialization: \initialized(fdset);
+  assigns *fdset \from *fdset, indirect:fd;
+*/
+extern void FD_CLR(int fd, fd_set *fdset);
+#define FD_CLR FD_CLR
+
+// Note: the 2nd argument in FD_ISSET is not const in some implementations
+// due to historical and compatibility reasons.
+/*@
+  requires valid_fdset: \valid_read(fdset);
+  requires initialization: \initialized(fdset);
+  assigns \result \from indirect:*fdset, indirect:fd;
+*/
+extern int FD_ISSET(int fd, const fd_set *fdset);
+#define FD_ISSET FD_ISSET
+
+/*@
+  requires valid_fdset: \valid(fdset);
+  requires initialization: \initialized(fdset);
+  assigns *fdset \from *fdset, indirect:fd;
+*/
+extern void FD_SET(int fd, fd_set *fdset);
+#define FD_SET FD_SET
+
+/*@
+  requires valid_fdset: \valid(fdset);
+  assigns *fdset \from \nothing;
+  ensures initialization: \initialized(fdset);
+*/
+extern void FD_ZERO(fd_set *fdset);
+#define FD_ZERO FD_ZERO
+
 __END_DECLS
 __POP_FC_STDLIB
 #endif
diff --git a/share/libc/sys/time.h b/share/libc/sys/time.h
index fbd3da31927d47879bb7ef0c81bf878ba4b5fbc7..db0a5b17b0b5ce5a9eaac4e983ac9bdd0eb45abd 100644
--- a/share/libc/sys/time.h
+++ b/share/libc/sys/time.h
@@ -24,17 +24,12 @@
 #define __FC_SYS_TIME_H__
 #include "../features.h"
 __PUSH_FC_STDLIB
-__BEGIN_DECLS
-
-#include "../__fc_define_time_t.h"
-#include "../__fc_define_suseconds_t.h"
 #include "../__fc_define_fd_set_t.h"
-#include "../__fc_define_timespec.h"
+#include "../__fc_define_suseconds_t.h"
+#include "../__fc_define_time_t.h"
+#include "../__fc_define_timeval.h"
 #include "../__fc_string_axiomatic.h"
-struct timeval {
-  time_t         tv_sec;
-  suseconds_t    tv_usec;
-};
+__BEGIN_DECLS
 
 struct timezone {
   int tz_minuteswest;
diff --git a/share/libc/sys/uio.h b/share/libc/sys/uio.h
index 7ef6ce26a73b7c58c36a3413b228658349faa9ff..b46a65c70647568e1d8dd517c2be12e83bd64bc7 100644
--- a/share/libc/sys/uio.h
+++ b/share/libc/sys/uio.h
@@ -28,15 +28,49 @@ __PUSH_FC_STDLIB
 #include "../__fc_define_ssize_t.h"
 #include "../__fc_define_size_t.h"
 #include "../__fc_define_iovec.h"
+#include "../__fc_define_fds.h"
+#include "../limits.h"
 
 __BEGIN_DECLS
 
-/*@ requires valid_read_iov: \valid_read( &iov[0..iovcnt-1] );
-// Value cannot yet interpret the precise assigns clause; we use the weaker one as a fallback.
-//@ assigns { ((char *) iov[i].iov_base)[0..iov[i].iov_len - 1] | integer i; 0 <= i < iovcnt };
-  @ assigns   ((char *) iov[0..iovcnt -1].iov_base)[0..];
+
+
+/*@
+  requires valid_fd: 0 <= fd < __FC_MAX_OPEN_FILES;
+  requires initialization:initialized_inputs:
+    \forall integer i; 0 <= i < iovcnt ==>
+      \initialized(&iov[i].iov_base) && \initialized(&iov[i].iov_len);
+  requires valid_iov: \forall integer i; 0 <= i < iovcnt ==>
+    \valid( ((char*)&iov[i].iov_base)+(0 .. iov[i].iov_len-1));
+  requires bounded_iovcnt: 0 <= iovcnt <= IOV_MAX;
+  assigns { ((char*)iov[i].iov_base)[j] |
+            integer i, j; 0 <= i < iovcnt && 0 <= j < iov[i].iov_len }
+    \from indirect:fd, indirect:iovcnt, indirect:__fc_fds[fd];
+  assigns \result \from indirect:fd, indirect:__fc_fds[fd], indirect:iov[0 ..],
+                        indirect:iovcnt;
+  ensures result_error_or_read_bytes: \result == -1 ||
+            0 <= \result <= \sum(0,iovcnt-1, \lambda integer k; iov[k].iov_len);
  */
 extern ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
+
+/*@
+  requires valid_fd: 0 <= fd < __FC_MAX_OPEN_FILES;
+  requires initialization:initialized_inputs:
+    \forall integer i; 0 <= i < iovcnt ==>
+      \initialized(&iov[i].iov_base) && \initialized(&iov[i].iov_len);
+  requires valid_read_iov: \valid_read(&iov[0 .. iovcnt-1]);
+  requires valid_read_iov_bases:
+    \forall integer i; 0 <= i < iovcnt ==>
+      \valid_read(((char*)iov[i].iov_base) + (0 .. iov[i].iov_len-1));
+  requires bounded_iovcnt: 0 <= iovcnt <= IOV_MAX;
+  requires bounded_lengths:
+     \sum(0, iovcnt-1, \lambda integer k; iov[k].iov_len) <= SSIZE_MAX;
+  assigns \result \from indirect:fd, indirect:__fc_fds[fd], indirect:iov[0 ..],
+                        indirect:iovcnt;
+  assigns __fc_fds[fd] \from indirect:iov[0 ..], indirect:iovcnt;
+  ensures result_error_or_written_bytes: \result == -1 ||
+          0 <= \result <= \sum(0, iovcnt-1, \lambda integer k; iov[k].iov_len);
+ */
 extern ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
 
 __END_DECLS
diff --git a/share/libc/time.h b/share/libc/time.h
index d156b59c620e759c9709a9b8da294049b57e0476..fe6304ce88d58490ddb41494e6608c6ffed332b0 100644
--- a/share/libc/time.h
+++ b/share/libc/time.h
@@ -24,14 +24,16 @@
 #define __FC_TIME_H
 #include "features.h"
 __PUSH_FC_STDLIB
+#include "__fc_define_clockid_t.h"
 #include "__fc_define_null.h"
 #include "__fc_define_size_t.h"
-#include "__fc_define_clockid_t.h"
+#include "__fc_define_time_t.h"
 #include "__fc_define_timer_t.h"
+#include "__fc_define_timespec.h"
 #include "__fc_string_axiomatic.h"
-
 #include "errno.h"
 #include "signal.h"
+
 /*
  * Names of the interval timers, and structure
  * defining a timer setting:
@@ -47,7 +49,6 @@ __BEGIN_DECLS
 typedef unsigned int clock_t;
 #define __clock_t_defined
 #endif
-#include "__fc_define_time_t.h"
 // From POSIX.1-2008: "The value of CLOCKS_PER_SEC shall be 1 million on
 // XSI-conformant systems. [...]"
 #define CLOCKS_PER_SEC ((time_t)1000000)
@@ -64,8 +65,6 @@ struct tm {
   int tm_isdst; // Daylight Saving Time flag
 };
 
-#include "__fc_define_timespec.h"
-
 struct itimerspec {
   struct timespec  it_interval;
   struct timespec  it_value;
diff --git a/share/libc/unistd.h b/share/libc/unistd.h
index a8c71c4da66bfde812e77250d56ab9b6192509b8..5979b51c4d998f8883c3d332861a36a51cd86688 100644
--- a/share/libc/unistd.h
+++ b/share/libc/unistd.h
@@ -29,16 +29,16 @@ __PUSH_FC_STDLIB
 #include "__fc_define_max_open_files.h"
 #include "__fc_define_size_t.h"
 #include "__fc_define_null.h"
+#include "__fc_define_seek_macros.h"
 #include "__fc_define_ssize_t.h"
 #include "__fc_define_uid_and_gid.h"
 #include "__fc_define_off_t.h"
 #include "__fc_define_pid_t.h"
 #include "__fc_define_useconds_t.h"
 #include "__fc_define_intptr_t.h"
-
-
-
+#include "__fc_define_fds.h"
 #include "limits.h"
+__BEGIN_DECLS
 
 extern volatile int Frama_C_entropy_source;
 
@@ -54,8 +54,6 @@ extern volatile int Frama_C_entropy_source;
 #define	STDOUT_FILENO	1	/* Standard output.  */
 #define	STDERR_FILENO	2	/* Standard error output.  */
 
-#include "__fc_define_seek_macros.h"
-
 /* compatibility macros */
 
 #ifndef __FC_NO_MONOTONIC_CLOCK
@@ -66,8 +64,6 @@ extern volatile int Frama_C_entropy_source;
 #define _POSIX_MONOTONIC_CLOCK 0
 #endif
 
-__BEGIN_DECLS
-
 /* Values for the NAME argument to `pathconf' and `fpathconf'.  */
 enum __fc_pathconf_name
   {
@@ -722,16 +718,6 @@ enum __fc_confstr_name
 #define _CS_V7_ENV			_CS_V7_ENV
   };
 
-
-// arbitrary number
-#define __FC_MAX_OPEN_FILES 1024
-
-// __fc_fds represents the state of open file descriptors.
-//@ ghost int __fc_fds[__FC_MAX_OPEN_FILES];
-// TODO: Model the state of some functions more precisely.
-// TODO: define __fc_fds as volatile.
-
-
 /*@ // missing: may assign to errno: EACCES, ELOOP, ENAMETOOLONG, ENOENT,
     //                               ENOTDIR, EROFS, ETXTBSY
     //                               (EINVAL prevented by precondition)
diff --git a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcat.c b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcat.c
index 1a7afd5bee9eaa585b2e079469cfdabf548079f3..313fcf00ef198538e9a90fa4e936f8e944731937 100644
--- a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcat.c
+++ b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcat.c
@@ -342,7 +342,7 @@ pid_t __gen_e_acsl_fork(void)
     else __gen_e_acsl_or_2 = __retres == -1;
     __e_acsl_assert(__gen_e_acsl_or_2,1,"Postcondition","fork",
                     "result_ok_child_or_error: \\result == 0 || \\result > 0 || \\result == -1",
-                    "FRAMAC_SHARE/libc/unistd.h",860);
+                    "FRAMAC_SHARE/libc/unistd.h",846);
     return __retres;
   }
 }
diff --git a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcmp.c b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcmp.c
index 487f9d89b834415fa5940e86bf8bd1822b28bedc..cb77e05860c921f2af86471a47a16fd3556fad20 100644
--- a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcmp.c
+++ b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcmp.c
@@ -187,7 +187,7 @@ pid_t __gen_e_acsl_fork(void)
     else __gen_e_acsl_or_2 = __retres == -1;
     __e_acsl_assert(__gen_e_acsl_or_2,1,"Postcondition","fork",
                     "result_ok_child_or_error: \\result == 0 || \\result > 0 || \\result == -1",
-                    "FRAMAC_SHARE/libc/unistd.h",860);
+                    "FRAMAC_SHARE/libc/unistd.h",846);
     return __retres;
   }
 }
diff --git a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcpy.c b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcpy.c
index 2e37d64c5d53416ced6c10ada81782b526bf3fb9..bb72f2bbc63f1b9bba44621ad6fa764bf561cf00 100644
--- a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcpy.c
+++ b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcpy.c
@@ -366,7 +366,7 @@ pid_t __gen_e_acsl_fork(void)
     else __gen_e_acsl_or_2 = __retres == -1;
     __e_acsl_assert(__gen_e_acsl_or_2,1,"Postcondition","fork",
                     "result_ok_child_or_error: \\result == 0 || \\result > 0 || \\result == -1",
-                    "FRAMAC_SHARE/libc/unistd.h",860);
+                    "FRAMAC_SHARE/libc/unistd.h",846);
     return __retres;
   }
 }
diff --git a/src/plugins/e-acsl/tests/builtin/oracle/gen_strlen.c b/src/plugins/e-acsl/tests/builtin/oracle/gen_strlen.c
index 44170551c065847fe09d7c0e1cebbfc1f4e0d11b..5288ad885239b257ee03115041beef1d1b10e5e5 100644
--- a/src/plugins/e-acsl/tests/builtin/oracle/gen_strlen.c
+++ b/src/plugins/e-acsl/tests/builtin/oracle/gen_strlen.c
@@ -161,7 +161,7 @@ pid_t __gen_e_acsl_fork(void)
     else __gen_e_acsl_or_2 = __retres == -1;
     __e_acsl_assert(__gen_e_acsl_or_2,1,"Postcondition","fork",
                     "result_ok_child_or_error: \\result == 0 || \\result > 0 || \\result == -1",
-                    "FRAMAC_SHARE/libc/unistd.h",860);
+                    "FRAMAC_SHARE/libc/unistd.h",846);
     return __retres;
   }
 }
diff --git a/src/plugins/e-acsl/tests/builtin/oracle/strcat.res.oracle b/src/plugins/e-acsl/tests/builtin/oracle/strcat.res.oracle
index e5596bda75141d559c531b4d72aeb27b6bf732cd..355bf7bb1f029994a75c785588cf61c82170aeb9 100644
--- a/src/plugins/e-acsl/tests/builtin/oracle/strcat.res.oracle
+++ b/src/plugins/e-acsl/tests/builtin/oracle/strcat.res.oracle
@@ -8,7 +8,7 @@
 [e-acsl] Warning: annotating undefined function `fork':
   the generated program may miss memory instrumentation
   if there are memory-related annotations.
-[e-acsl] FRAMAC_SHARE/libc/unistd.h:857: Warning: 
+[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:79: Warning: 
diff --git a/src/plugins/e-acsl/tests/builtin/oracle/strcmp.res.oracle b/src/plugins/e-acsl/tests/builtin/oracle/strcmp.res.oracle
index 077e7e1b7111003c5ae82c748c084ea16eaf0819..62a192f51bb497bafc4593371ad9b0a29aa1e3ef 100644
--- a/src/plugins/e-acsl/tests/builtin/oracle/strcmp.res.oracle
+++ b/src/plugins/e-acsl/tests/builtin/oracle/strcmp.res.oracle
@@ -66,7 +66,7 @@
 [e-acsl] FRAMAC_SHARE/libc/string.h:493: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
-[e-acsl] FRAMAC_SHARE/libc/unistd.h:857: Warning: 
+[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:79: Warning: 
diff --git a/src/plugins/e-acsl/tests/builtin/oracle/strcpy.res.oracle b/src/plugins/e-acsl/tests/builtin/oracle/strcpy.res.oracle
index 406978ac5f39a280b111b1dc00a11a06c240af64..6d74b78c4afc235b980f246374e40a7ed1a19c5c 100644
--- a/src/plugins/e-acsl/tests/builtin/oracle/strcpy.res.oracle
+++ b/src/plugins/e-acsl/tests/builtin/oracle/strcpy.res.oracle
@@ -60,7 +60,7 @@
 [e-acsl] FRAMAC_SHARE/libc/string.h:493: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
-[e-acsl] FRAMAC_SHARE/libc/unistd.h:857: Warning: 
+[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:79: Warning: 
diff --git a/src/plugins/e-acsl/tests/builtin/oracle/strlen.res.oracle b/src/plugins/e-acsl/tests/builtin/oracle/strlen.res.oracle
index b1e0c13ab7c0c81ddca966a75862fbafdb2ce343..2a293aeb5a71df9b7843ceaf791a0bc6ab4ed61f 100644
--- a/src/plugins/e-acsl/tests/builtin/oracle/strlen.res.oracle
+++ b/src/plugins/e-acsl/tests/builtin/oracle/strlen.res.oracle
@@ -63,7 +63,7 @@
 [e-acsl] FRAMAC_SHARE/libc/string.h:493: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
-[e-acsl] FRAMAC_SHARE/libc/unistd.h:857: Warning: 
+[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:79: Warning: 
diff --git a/src/plugins/e-acsl/tests/format/oracle/fprintf.res.oracle b/src/plugins/e-acsl/tests/format/oracle/fprintf.res.oracle
index 2ce7032a3b70da634ea4cb3411354f33cc617c46..665e3c0b1cc2ecddafda0d677d2f1f1a72337ef9 100644
--- a/src/plugins/e-acsl/tests/format/oracle/fprintf.res.oracle
+++ b/src/plugins/e-acsl/tests/format/oracle/fprintf.res.oracle
@@ -19,7 +19,7 @@
   `logic functions or predicates with no definition nor reads clause'
   is not yet supported.
   Ignoring annotation.
-[e-acsl] FRAMAC_SHARE/libc/unistd.h:857: Warning: 
+[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:79: Warning: 
diff --git a/src/plugins/e-acsl/tests/format/oracle/gen_fprintf.c b/src/plugins/e-acsl/tests/format/oracle/gen_fprintf.c
index 0fb3e03f963f1ca84c2d99208f7a971bf4e3ab08..09a3554adf54d4a676e021dc16c0d7fb3e087768 100644
--- a/src/plugins/e-acsl/tests/format/oracle/gen_fprintf.c
+++ b/src/plugins/e-acsl/tests/format/oracle/gen_fprintf.c
@@ -110,7 +110,7 @@ pid_t __gen_e_acsl_fork(void)
     else __gen_e_acsl_or_2 = __retres == -1;
     __e_acsl_assert(__gen_e_acsl_or_2,1,"Postcondition","fork",
                     "result_ok_child_or_error: \\result == 0 || \\result > 0 || \\result == -1",
-                    "FRAMAC_SHARE/libc/unistd.h",860);
+                    "FRAMAC_SHARE/libc/unistd.h",846);
     return __retres;
   }
 }
diff --git a/src/plugins/e-acsl/tests/format/oracle/gen_printf.c b/src/plugins/e-acsl/tests/format/oracle/gen_printf.c
index 3db1acf837ee0515dc48f8c484b27563489afa38..a4f24c803d736d1fbbdf9803ba71b612cb937a6a 100644
--- a/src/plugins/e-acsl/tests/format/oracle/gen_printf.c
+++ b/src/plugins/e-acsl/tests/format/oracle/gen_printf.c
@@ -903,7 +903,7 @@ pid_t __gen_e_acsl_fork(void)
     else __gen_e_acsl_or_2 = __retres == -1;
     __e_acsl_assert(__gen_e_acsl_or_2,1,"Postcondition","fork",
                     "result_ok_child_or_error: \\result == 0 || \\result > 0 || \\result == -1",
-                    "FRAMAC_SHARE/libc/unistd.h",860);
+                    "FRAMAC_SHARE/libc/unistd.h",846);
     return __retres;
   }
 }
diff --git a/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle b/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle
index 98b179a6be2383e26aac0d389ef7972ac799ecac..b09140dee729c28a7f1f65cee93f96e57c0e5fdc 100644
--- a/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle
+++ b/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle
@@ -96,7 +96,7 @@
 [e-acsl] FRAMAC_SHARE/libc/string.h:141: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
-[e-acsl] FRAMAC_SHARE/libc/unistd.h:857: Warning: 
+[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:79: Warning: 
diff --git a/src/plugins/variadic/tests/erroneous/oracle/exec.res.oracle b/src/plugins/variadic/tests/erroneous/oracle/exec.res.oracle
index 3964a37c4107508e018d69cb6119d25a96bbcbe6..d28bedfb6dede9344daeab4b60386b4636bcb9e2 100644
--- a/src/plugins/variadic/tests/erroneous/oracle/exec.res.oracle
+++ b/src/plugins/variadic/tests/erroneous/oracle/exec.res.oracle
@@ -1,8 +1,8 @@
-[variadic] FRAMAC_SHARE/libc/unistd.h:814: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:800: 
   Declaration of variadic function execl.
-[variadic] FRAMAC_SHARE/libc/unistd.h:819: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:805: 
   Declaration of variadic function execle.
-[variadic] FRAMAC_SHARE/libc/unistd.h:824: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:810: 
   Declaration of variadic function execlp.
 [variadic] tests/erroneous/exec.c:5: Warning: 
   Incorrect type for argument 3. The argument will be cast from int to char *.
diff --git a/src/plugins/variadic/tests/known/oracle/exec.res.oracle b/src/plugins/variadic/tests/known/oracle/exec.res.oracle
index d3df0e6caaecd4de576cc56e389dabf8762146eb..85b39e35a56ab3ba5e2efcf128af74add1b33744 100644
--- a/src/plugins/variadic/tests/known/oracle/exec.res.oracle
+++ b/src/plugins/variadic/tests/known/oracle/exec.res.oracle
@@ -1,8 +1,8 @@
-[variadic] FRAMAC_SHARE/libc/unistd.h:814: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:800: 
   Declaration of variadic function execl.
-[variadic] FRAMAC_SHARE/libc/unistd.h:819: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:805: 
   Declaration of variadic function execle.
-[variadic] FRAMAC_SHARE/libc/unistd.h:824: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:810: 
   Declaration of variadic function execlp.
 [variadic] tests/known/exec.c:9: Translating call to execle to a call to execve.
 [variadic] tests/known/exec.c:11: Warning: 
diff --git a/src/plugins/variadic/tests/known/oracle/exec_failed_requirement.res.oracle b/src/plugins/variadic/tests/known/oracle/exec_failed_requirement.res.oracle
index a8e29aef564f9e3150640adc472080a1bb437a93..f04568a4d68f71534e09b863b40a96c050d3b06a 100644
--- a/src/plugins/variadic/tests/known/oracle/exec_failed_requirement.res.oracle
+++ b/src/plugins/variadic/tests/known/oracle/exec_failed_requirement.res.oracle
@@ -1,8 +1,8 @@
-[variadic] FRAMAC_SHARE/libc/unistd.h:814: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:800: 
   Declaration of variadic function execl.
-[variadic] FRAMAC_SHARE/libc/unistd.h:819: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:805: 
   Declaration of variadic function execle.
-[variadic] FRAMAC_SHARE/libc/unistd.h:824: 
+[variadic] FRAMAC_SHARE/libc/unistd.h:810: 
   Declaration of variadic function execlp.
 [variadic] tests/known/exec_failed_requirement.c:7: 
   Translating call to execl to a call to execv.
diff --git a/tests/libc/check_compliance.ml b/tests/libc/check_compliance.ml
index 3fab55c7989fe06a0dd332dafeb7f3bb9c6c47d8..fabf605d2b8d14f9aa8503e6553d945e16256a37 100644
--- a/tests/libc/check_compliance.ml
+++ b/tests/libc/check_compliance.ml
@@ -81,6 +81,49 @@ struct
       table
 end
 
+let ident_to_be_ignored id headers =
+  Extlib.string_prefix "__" id ||
+  Extlib.string_prefix "Frama_C" id ||
+  List.filter (fun h -> not (Extlib.string_prefix "__fc" h)) headers = []
+
+let check_ident c11 posix glibc nonstandard c11_headers id headers =
+  if ident_to_be_ignored id headers then (* nothing to check *) ()
+  else begin
+    if Hashtbl.mem c11 id then begin
+      (* Check that the header is the expected one.
+         Note that some symbols may appear in more than one header,
+         possibly due to collisions
+         e.g. 'flock' as type and function). *)
+      let h = Hashtbl.find c11 id in
+      if not (StringSet.mem h c11_headers) then
+        Kernel.warning "<%a>:%s : C11 says %s"
+          (Pretty_utils.pp_list ~sep:"," Format.pp_print_string) headers
+          id h
+    end
+    else if Hashtbl.mem posix id then begin
+      (* check that the header is the expected one *)
+      let (h, _) = Hashtbl.find posix id in
+      (* arpa/inet.h and netinet/in.h are special cases: due to mutual
+         inclusion, there are always issues with their symbols;
+         also, timezone is a special case, since it is a type in
+         sys/time.h, but a variable in time.h in POSIX. However, its
+         declaration as extern is erased by rmtmps, since it is
+         unused. *)
+      if not (List.mem h headers) &&
+         not (List.mem "arpa/inet.h" headers && h = "netinet/in.h" ||
+              List.mem "netinet/in.h" headers && h = "arpa/inet.h") &&
+         id <> "timezone"
+      then
+        Kernel.warning "<%a>:%s : POSIX says %s"
+          (Pretty_utils.pp_list ~sep:"," Format.pp_print_string) headers
+          id h
+    end
+    else if not (StringSet.(mem id glibc || mem id nonstandard)) then
+      Kernel.warning "<%a>:%s : unknown identifier"
+        (Pretty_utils.pp_list ~sep:"," Format.pp_print_string) headers
+        id
+  end
+
 let () =
   Db.Main.extend (fun () ->
       if not !run_once then begin
@@ -94,49 +137,6 @@ let () =
         and glibc_idents = Json.(to_set (parse dir "glibc_functions.json"))
         and posix_idents = Json.(to_table HeadersAndExtensions (parse dir "posix_identifiers.json"))
         and nonstandard_idents = Json.(keys (parse dir "nonstandard_identifiers.json")) in
-        Hashtbl.iter (fun id headers ->
-            if not (Extlib.string_prefix "__" id) &&
-               not (Extlib.string_prefix "Frama_C" id) &&
-               List.filter (fun h -> not (Extlib.string_prefix "__fc" h))
-                 headers <> []
-            then
-              let id_in_c11 = Hashtbl.mem c11_idents id in
-              let id_in_posix = Hashtbl.mem posix_idents id in
-              let id_in_glibc = StringSet.mem id glibc_idents in
-              let id_in_nonstd = StringSet.mem id nonstandard_idents in
-              let header_in_c11 h = StringSet.mem h c11_headers in
-              if id_in_c11 then begin
-                (* Check that the header is the expected one.
-                   Note that some symbols may appear in more than one header,
-                   possibly due to collisions
-                   (e.g. 'flock' as type and function). *)
-                let h = Hashtbl.find c11_idents id in
-                if not (header_in_c11 h) then
-                  Kernel.warning "<%a>:%s : C11 says %s"
-                    (Pretty_utils.pp_list ~sep:"," Format.pp_print_string) headers
-                    id h
-              end
-              else if id_in_posix then begin
-                (* check the header is the expected one *)
-                let (h, _) = Hashtbl.find posix_idents id in
-                (* arpa/inet.h and netinet/in.h are special cases: due to mutual
-                   inclusion, there are always issues with their symbols;
-                   also, timezone is a special case, since it is a type in
-                   sys/time.h, but a variable in time.h in POSIX. However, its
-                   declaration as extern is erased by rmtmps, since it is
-                   unused. *)
-                if not (List.mem h headers) &&
-                   not (List.mem "arpa/inet.h" headers && h = "netinet/in.h" ||
-                        List.mem "netinet/in.h" headers && h = "arpa/inet.h") &&
-                   id <> "timezone"
-                then
-                  Kernel.warning "<%a>:%s : POSIX says %s"
-                    (Pretty_utils.pp_list ~sep:"," Format.pp_print_string) headers
-                    id h
-              end
-              else if not (id_in_glibc || id_in_nonstd) then
-                Kernel.warning "<%a>:%s : unknown identifier"
-                  (Pretty_utils.pp_list ~sep:"," Format.pp_print_string) headers
-                  id
-          ) fc_stdlib_idents;
+        let check_ident_fun = check_ident c11_idents posix_idents glibc_idents nonstandard_idents c11_headers in
+        Hashtbl.iter check_ident_fun fc_stdlib_idents
       end)
diff --git a/tests/libc/fc_libc.c b/tests/libc/fc_libc.c
index 1345145e950c37a80e559c9426ab5a2ce0dc968e..53b38f02cd517ecf8d921d0aefa51f5aa9693d40 100644
--- a/tests/libc/fc_libc.c
+++ b/tests/libc/fc_libc.c
@@ -44,6 +44,7 @@
 #include "__fc_define_dev_t.h"
 #include "__fc_define_eof.h"
 #include "__fc_define_fd_set_t.h"
+#include "__fc_define_fds.h"
 #include "__fc_define_file.h"
 #include "__fc_define_fpos_t.h"
 #include "__fc_define_fs_cnt.h"
@@ -67,9 +68,10 @@
 #include "__fc_define_ssize_t.h"
 #include "__fc_define_stat.h"
 #include "__fc_define_suseconds_t.h"
-#include "__fc_define_timespec.h"
 #include "__fc_define_time_t.h"
 #include "__fc_define_timer_t.h"
+#include "__fc_define_timespec.h"
+#include "__fc_define_timeval.h"
 #include "__fc_define_uid_and_gid.h"
 #include "__fc_define_useconds_t.h"
 #include "__fc_define_wchar_t.h"
diff --git a/tests/libc/oracle/fc_libc.0.res.oracle b/tests/libc/oracle/fc_libc.0.res.oracle
index 881040218e6562ae1c75d17f17b57abbc7866064..c300bb3596b525db3b01f89b6ba8215600e143c2 100644
--- a/tests/libc/oracle/fc_libc.0.res.oracle
+++ b/tests/libc/oracle/fc_libc.0.res.oracle
@@ -4,10 +4,10 @@
 [eva] Initial state computed
 [eva:initial-state] Values of globals at initialization
   
-[eva] tests/libc/fc_libc.c:164: assertion got status valid.
-[eva] tests/libc/fc_libc.c:165: assertion got status valid.
 [eva] tests/libc/fc_libc.c:166: assertion got status valid.
 [eva] tests/libc/fc_libc.c:167: assertion got status valid.
+[eva] tests/libc/fc_libc.c:168: assertion got status valid.
+[eva] tests/libc/fc_libc.c:169: assertion got status valid.
 [eva] Recording results for main
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
@@ -47,7 +47,7 @@
    wcslen (3 calls); wcsncat (0 call); wcsncpy (0 call); wmemcpy (1 call);
    wmemset (0 call); 
   
-  Specified-only functions (426)
+  Specified-only functions (427)
   ==============================
    FD_CLR (0 call); FD_ISSET (0 call); FD_SET (0 call); FD_ZERO (0 call);
    Frama_C_int_interval (0 call); Frama_C_long_interval (0 call);
@@ -175,20 +175,20 @@
    wcscmp (0 call); wcscspn (0 call); wcslcat (0 call); wcslcpy (0 call);
    wcsncmp (0 call); wcspbrk (0 call); wcsrchr (0 call); wcsspn (0 call);
    wcsstr (0 call); wcstombs (0 call); wctomb (0 call); wmemchr (0 call);
-   wmemcmp (0 call); wmemmove (0 call); write (0 call); 
+   wmemcmp (0 call); wmemmove (0 call); write (0 call); writev (0 call); 
   
   Undefined and unspecified functions (1)
   =======================================
    __builtin_abort (1 call); 
   
-  'Extern' global variables (21)
+  'Extern' global variables (22)
   ==============================
-   __fc_basename; __fc_dirname; __fc_getpwuid_pw_dir; __fc_getpwuid_pw_name;
-   __fc_getpwuid_pw_passwd; __fc_getpwuid_pw_shell; __fc_heap_status;
-   __fc_hostname; __fc_locale; __fc_locale_names; __fc_mblen_state;
-   __fc_mbtowc_state; __fc_random_counter; __fc_socket_counter;
-   __fc_stack_status; __fc_tz; __fc_wctomb_state; optarg; opterr; optopt;
-   tzname
+   __fc_basename; __fc_dirname; __fc_fds; __fc_getpwuid_pw_dir;
+   __fc_getpwuid_pw_name; __fc_getpwuid_pw_passwd; __fc_getpwuid_pw_shell;
+   __fc_heap_status; __fc_hostname; __fc_locale; __fc_locale_names;
+   __fc_mblen_state; __fc_mbtowc_state; __fc_random_counter;
+   __fc_socket_counter; __fc_stack_status; __fc_tz; __fc_wctomb_state; optarg;
+   opterr; optopt; tzname
   
   Potential entry points (1)
   ==========================
@@ -204,7 +204,7 @@
   Goto = 113
   Assignment = 625
   Exit point = 100
-  Function = 527
+  Function = 528
   Function call = 144
   Pointer dereferencing = 254
   Cyclomatic complexity = 371
@@ -214,6 +214,7 @@
 #include "__fc_builtin.c"
 #include "__fc_builtin.h"
 #include "__fc_define_fd_set_t.h"
+#include "__fc_define_timeval.h"
 #include "__fc_gcc_builtins.h"
 #include "__fc_integer.h"
 #include "__fc_select.h"
@@ -264,6 +265,7 @@
 #include "stropts.h"
 #include "sys/file.h"
 #include "sys/resource.h"
+#include "sys/select.h"
 #include "sys/sendfile.h"
 #include "sys/socket.h"
 #include "sys/stat.h"
diff --git a/tests/libc/oracle/fc_libc.1.res.oracle b/tests/libc/oracle/fc_libc.1.res.oracle
index c794e4be1b1caaec773f9e4c3f342430a01ce82f..38af9dde42f8d8384e4405f44b8a48c050d6ff67 100644
--- a/tests/libc/oracle/fc_libc.1.res.oracle
+++ b/tests/libc/oracle/fc_libc.1.res.oracle
@@ -270,6 +270,10 @@ typedef struct __fc_FILE FILE;
 typedef unsigned int id_t;
 typedef int suseconds_t;
 typedef int clockid_t;
+struct timespec {
+   long tv_sec ;
+   long tv_nsec ;
+};
 typedef unsigned int clock_t;
 struct tm {
    int tm_sec ;
@@ -282,10 +286,6 @@ struct tm {
    int tm_yday ;
    int tm_isdst ;
 };
-struct timespec {
-   long tv_sec ;
-   long tv_nsec ;
-};
 struct dirent {
    ino_t d_ino ;
    off_t d_off ;
@@ -304,6 +304,10 @@ struct __fc_fd_set {
    long __fc_fd_set[(unsigned int)1024 / ((unsigned int)8 * sizeof(long))] ;
 };
 typedef struct __fc_fd_set fd_set;
+struct timeval {
+   time_t tv_sec ;
+   suseconds_t tv_usec ;
+};
 struct flock {
    short l_type ;
    short l_whence ;
@@ -311,18 +315,6 @@ struct flock {
    off_t l_len ;
    pid_t l_pid ;
 };
-struct timeval {
-   time_t tv_sec ;
-   suseconds_t tv_usec ;
-};
-struct timezone {
-   int tz_minuteswest ;
-   int tz_dsttime ;
-};
-struct itimerval {
-   struct timeval it_interval ;
-   struct timeval it_value ;
-};
 typedef void * iconv_t;
 struct pollfd {
    int fd ;
@@ -350,6 +342,14 @@ struct __fc_code {
    int c_val ;
 };
 typedef struct __fc_code CODE;
+struct timezone {
+   int tz_minuteswest ;
+   int tz_dsttime ;
+};
+struct itimerval {
+   struct timeval it_interval ;
+   struct timeval it_value ;
+};
 typedef unsigned long rlim_t;
 struct rlimit {
    rlim_t rlim_cur ;
@@ -2875,7 +2875,8 @@ int fesetenv(fenv_t const *envp)
   return __retres;
 }
 
-/*@ ghost int __fc_fds[1024]; */
+extern int volatile __fc_fds[1024];
+
 /*@ requires valid_string_path: valid_read_string(path);
     requires valid_amode: (amode & ~((4 | 2) | 1)) ≡ 0 ∨ amode ≡ 0;
     ensures result_ok_or_error: \result ≡ 0 ∨ \result ≡ -1;
@@ -4518,11 +4519,70 @@ extern int kill(pid_t pid, int sig);
  */
 extern int killpg(pid_t pgrp, int sig);
 
-/*@ requires valid_read_iov: \valid_read(iov + (0 .. iovcnt - 1));
-    assigns *((char *)(iov + (0 .. iovcnt - 1))->iov_base + (0 ..));
+/*@ requires valid_fd: 0 ≤ fd < 1024;
+    requires
+      initialization: initialized_inputs:
+        ∀ ℤ i;
+          0 ≤ i < iovcnt ⇒
+          \initialized(&(iov + i)->iov_base) ∧
+          \initialized(&(iov + i)->iov_len);
+    requires
+      valid_iov:
+        ∀ ℤ i;
+          0 ≤ i < iovcnt ⇒
+          \valid((char *)(&(iov + i)->iov_base) +
+                 (0 .. (iov + i)->iov_len - 1));
+    requires bounded_iovcnt: 0 ≤ iovcnt ≤ 1024;
+    ensures
+      result_error_or_read_bytes:
+        \result ≡ -1 ∨
+        (0 ≤ \result ≤
+         \sum(0, \old(iovcnt) - 1, \lambda ℤ k; (\old(iov) + k)->iov_len));
+    assigns {*((char *)(iov + i)->iov_base + j) |
+             ℤ i, ℤ j; 0 ≤ i < iovcnt ∧ 0 ≤ j < (iov + i)->iov_len},
+            \result;
+    assigns
+    {*((char *)(iov + i)->iov_base + j) |
+     ℤ i, ℤ j; 0 ≤ i < iovcnt ∧ 0 ≤ j < (iov + i)->iov_len}
+      \from (indirect: fd), (indirect: iovcnt), (indirect: __fc_fds[fd]);
+    assigns \result
+      \from (indirect: fd), (indirect: __fc_fds[fd]),
+            (indirect: *(iov + (0 ..))), (indirect: iovcnt);
  */
 extern ssize_t readv(int fd, struct iovec const *iov, int iovcnt);
 
+/*@ requires valid_fd: 0 ≤ fd < 1024;
+    requires
+      initialization: initialized_inputs:
+        ∀ ℤ i;
+          0 ≤ i < iovcnt ⇒
+          \initialized(&(iov + i)->iov_base) ∧
+          \initialized(&(iov + i)->iov_len);
+    requires valid_read_iov: \valid_read(iov + (0 .. iovcnt - 1));
+    requires
+      valid_read_iov_bases:
+        ∀ ℤ i;
+          0 ≤ i < iovcnt ⇒
+          \valid_read((char *)(iov + i)->iov_base +
+                      (0 .. (iov + i)->iov_len - 1));
+    requires bounded_iovcnt: 0 ≤ iovcnt ≤ 1024;
+    requires
+      bounded_lengths:
+        \sum(0, iovcnt - 1, \lambda ℤ k; (iov + k)->iov_len) ≤ 2147483647;
+    ensures
+      result_error_or_written_bytes:
+        \result ≡ -1 ∨
+        (0 ≤ \result ≤
+         \sum(0, \old(iovcnt) - 1, \lambda ℤ k; (\old(iov) + k)->iov_len));
+    assigns \result, __fc_fds[fd];
+    assigns \result
+      \from (indirect: fd), (indirect: __fc_fds[fd]),
+            (indirect: *(iov + (0 ..))), (indirect: iovcnt);
+    assigns __fc_fds[fd]
+      \from (indirect: *(iov + (0 ..))), (indirect: iovcnt);
+ */
+extern ssize_t writev(int fd, struct iovec const *iov, int iovcnt);
+
 /*@ ghost struct __fc_sockfds_type __fc_sockfds[1024]; */
 /*@ ghost extern int __fc_socket_counter; */
 
@@ -7777,34 +7837,6 @@ extern DIR *opendir(char const *path);
  */
 extern struct dirent *readdir(DIR *dirp);
 
-/*@ requires valid_fdset: \valid(fdset);
-    requires initialization: \initialized(fdset);
-    assigns *fdset;
-    assigns *fdset \from *fdset, (indirect: fd);
- */
-extern void FD_CLR(int fd, fd_set *fdset);
-
-/*@ requires valid_fdset: \valid_read(fdset);
-    requires initialization: \initialized(fdset);
-    assigns \result;
-    assigns \result \from (indirect: *fdset), (indirect: fd);
- */
-extern int FD_ISSET(int fd, fd_set const *fdset);
-
-/*@ requires valid_fdset: \valid(fdset);
-    requires initialization: \initialized(fdset);
-    assigns *fdset;
-    assigns *fdset \from *fdset, (indirect: fd);
- */
-extern void FD_SET(int fd, fd_set *fdset);
-
-/*@ requires valid_fdset: \valid(fdset);
-    ensures initialization: \initialized(\old(fdset));
-    assigns *fdset;
-    assigns *fdset \from \nothing;
- */
-extern void FD_ZERO(fd_set *fdset);
-
 /*@ requires valid_res: \valid(res);
     ensures initialization: res: \initialized(\old(res));
     ensures res_wrapped: *\old(res) ≡ (int)(\old(a) + \old(b));
@@ -8220,192 +8252,6 @@ extern int __va_openat_void(int dirfd, char const *filename, int flags);
 extern int __va_openat_mode_t(int dirfd, char const *filename, int flags,
                               mode_t mode);
 
-/*@ ghost extern int __fc_tz; */
-
-/*@ requires valid_path: valid_read_string(path);
-    requires
-      valid_times_or_null: \valid_read(times + (0 .. 1)) ∨ times ≡ \null;
-    assigns \result;
-    assigns \result
-      \from (indirect: *(path + (0 .. strlen{Old}(path)))),
-            (indirect: times), (indirect: *(times + (0 .. 1)));
- */
-extern int utimes(char const *path, struct timeval const times[2]);
-
-/*@ ensures result_ok_or_error: \result ≡ 0 ∨ \result ≡ -1;
-    assigns tv->tv_sec, tv->tv_usec, *((struct timezone *)tz), \result;
-    assigns tv->tv_sec \from __fc_time;
-    assigns tv->tv_usec \from __fc_time;
-    assigns *((struct timezone *)tz) \from __fc_tz;
-    assigns \result
-      \from (indirect: tv), (indirect: tz), *tv, *((struct timezone *)tz),
-            __fc_tz;
-    
-    behavior tv_and_tz_null:
-      assumes null_tv_tz: tv ≡ \null ∧ tz ≡ \null;
-      assigns \result;
-      assigns \result \from (indirect: __fc_tz);
-    
-    behavior tv_not_null:
-      assumes non_null_tv_null_tz: tv ≢ \null ∧ tz ≡ \null;
-      ensures
-        initialization: tv_sec: tv_usec:
-          \initialized(&\old(tv)->tv_sec) ∧
-          \initialized(&\old(tv)->tv_usec);
-      ensures tv_usec_bounded: 0 ≤ \old(tv)->tv_usec ≤ 999999;
-      assigns tv->tv_sec, tv->tv_usec, \result;
-      assigns tv->tv_sec \from (indirect: __fc_time);
-      assigns tv->tv_usec \from (indirect: __fc_time);
-      assigns \result \from (indirect: *tv), (indirect: __fc_tz);
-    
-    behavior tz_not_null:
-      assumes null_tv_non_null_tz: tv ≡ \null ∧ tz ≢ \null;
-      ensures initialization: tz: \initialized((struct timezone *)\old(tz));
-      assigns *((struct timezone *)tz), \result;
-      assigns *((struct timezone *)tz) \from __fc_tz;
-      assigns \result
-        \from (indirect: *((struct timezone *)tz)), (indirect: __fc_tz);
-    
-    behavior tv_and_tz_not_null:
-      assumes non_null_tv_tz: tv ≢ \null ∧ tz ≢ \null;
-      ensures
-        initialization: tv_sec: tv_usec:
-          \initialized(&\old(tv)->tv_sec) ∧
-          \initialized(&\old(tv)->tv_usec);
-      ensures initialization: tz: \initialized((struct timezone *)\old(tz));
-      assigns tv->tv_sec, tv->tv_usec, *((struct timezone *)tz), \result;
-      assigns tv->tv_sec \from (indirect: __fc_time);
-      assigns tv->tv_usec \from (indirect: __fc_time);
-      assigns *((struct timezone *)tz) \from __fc_tz;
-      assigns \result
-        \from (indirect: *tv), (indirect: *((struct timezone *)tz)),
-              (indirect: __fc_tz);
-    
-    complete behaviors tv_and_tz_not_null,
-                       tz_not_null,
-                       tv_not_null,
-                       tv_and_tz_null;
-    disjoint behaviors tv_and_tz_not_null,
-                       tz_not_null,
-                       tv_not_null,
-                       tv_and_tz_null;
- */
-extern int gettimeofday(struct timeval * restrict tv, void * restrict tz);
-
-/*@ requires valid_tv_or_null: \valid_read(tv) ∨ tv ≡ \null;
-    requires valid_tz_or_null: \valid_read(tz) ∨ tz ≡ \null;
-    ensures result_ok_or_error: \result ≡ 0 ∨ \result ≡ -1;
-    assigns __fc_time, __fc_tz, \result;
-    assigns __fc_time
-      \from tv->tv_sec, tv->tv_usec, tz->tz_dsttime, tz->tz_minuteswest;
-    assigns __fc_tz
-      \from tv->tv_sec, tv->tv_usec, tz->tz_dsttime, tz->tz_minuteswest;
-    assigns \result \from (indirect: *tv), (indirect: *tz);
- */
-extern int settimeofday(struct timeval const *tv, struct timezone const *tz);
-
-/*@ ghost struct itimerval volatile __fc_itimer_real; */
-/*@ ghost struct itimerval volatile __fc_itimer_virtual; */
-/*@ ghost struct itimerval volatile __fc_itimer_prof; */
-/*@ requires valid_curr_value: \valid(curr_value);
-    ensures initialization: curr_value: \initialized(\old(curr_value));
-    assigns \result, *curr_value;
-    assigns \result \from (indirect: which);
-    assigns *curr_value
-      \from __fc_itimer_real, __fc_itimer_virtual, __fc_itimer_prof;
-    
-    behavior real:
-      assumes itimer_real: which ≡ 0;
-      ensures result_ok: \result ≡ 0;
-      assigns \result, *curr_value;
-      assigns \result \from \nothing;
-      assigns *curr_value \from __fc_itimer_real;
-    
-    behavior virtual:
-      assumes itimer_virtual: which ≡ 1;
-      ensures result_ok: \result ≡ 0;
-      assigns \result, *curr_value;
-      assigns \result \from \nothing;
-      assigns *curr_value \from __fc_itimer_virtual;
-    
-    behavior prof:
-      assumes itimer_prof: which ≡ 2;
-      ensures result_ok: \result ≡ 0;
-      assigns \result, *curr_value;
-      assigns \result \from \nothing;
-      assigns *curr_value \from __fc_itimer_prof;
-    
-    behavior invalid:
-      assumes invalid_which: which ≢ 0 ∧ which ≢ 1 ∧ which ≢ 2;
-      ensures result_error: \result ≡ -1;
-      assigns \result;
-      assigns \result \from \nothing;
-    
-    complete behaviors invalid, prof, virtual, real;
-    disjoint behaviors invalid, prof, virtual, real;
- */
-extern int getitimer(int which, struct itimerval *curr_value);
-
-/*@ requires valid_new_value: \valid_read(new_value);
-    requires
-      old_value_null_or_valid: old_value ≡ \null ∨ \valid(old_value);
-    ensures result_ok_or_error: \result ≡ 0 ∨ \result ≡ -1;
-    assigns *old_value, \result;
-    assigns *old_value
-      \from (indirect: which), (indirect: old_value), (indirect: new_value),
-            __fc_itimer_real, __fc_itimer_virtual, __fc_itimer_prof;
-    assigns \result
-      \from (indirect: which), (indirect: new_value), (indirect: *new_value);
-    
-    behavior real:
-      assumes
-        itimer_real_and_valid:
-          which ≡ 0 ≤ new_value->it_value.tv_usec ≤ 999999 ∧
-          0 ≤ new_value->it_interval.tv_usec ≤ 999999;
-      ensures result_ok: \result ≡ 0;
-      ensures initialization: old_value: \initialized(\old(old_value));
-      assigns \result, *old_value, __fc_itimer_real;
-      assigns \result \from \nothing;
-      assigns *old_value \from __fc_itimer_real;
-      assigns __fc_itimer_real \from *new_value;
-    
-    behavior virtual:
-      assumes
-        itimer_virtual_and_valid:
-          which ≡ 1 ∧ 0 ≤ new_value->it_value.tv_usec ≤ 999999 ∧
-          0 ≤ new_value->it_interval.tv_usec ≤ 999999;
-      ensures result_ok: \result ≡ 0;
-      ensures initialization: old_value: \initialized(\old(old_value));
-      assigns \result, *old_value;
-      assigns \result \from \nothing;
-      assigns *old_value \from __fc_itimer_virtual;
-    
-    behavior prof:
-      assumes
-        itimer_prof_and_valid:
-          which ≡ 2 ∧ 0 ≤ new_value->it_value.tv_usec ≤ 999999 ∧
-          0 ≤ new_value->it_interval.tv_usec ≤ 999999;
-      ensures result_ok: \result ≡ 0;
-      ensures initialization: old_value: \initialized(\old(old_value));
-      assigns \result, *old_value;
-      assigns \result \from \nothing;
-      assigns *old_value \from __fc_itimer_prof;
-    
-    behavior invalid:
-      assumes
-        invalid_itimer_or_new_value:
-          (which ≢ 0 ∧ which ≢ 1 ∧ which ≢ 2) ∨
-          ¬(0 ≤ new_value->it_value.tv_usec ≤ 999999 ∧
-             0 ≤ new_value->it_interval.tv_usec ≤ 999999);
-      ensures result_error: \result ≡ -1;
-      assigns \result;
-      assigns \result \from \nothing;
-    
-    disjoint behaviors invalid, prof, virtual, real;
- */
-extern int setitimer(int which, struct itimerval const * restrict new_value,
-                     struct itimerval * restrict old_value);
-
 /*@ ghost int volatile __fc_fds_state; */
 /*@ requires nfds: nfds ≥ 0;
     requires readfs: readfds ≡ \null ∨ \valid(readfds);
@@ -8861,6 +8707,220 @@ extern void syslog(int __x0, char const *__x1, void * const *__va_params);
 /*@ assigns \nothing; */
 extern void vsyslog(int __x0, char const *__x1, va_list __x2);
 
+/*@ ghost extern int __fc_tz; */
+
+/*@ requires valid_path: valid_read_string(path);
+    requires
+      valid_times_or_null: \valid_read(times + (0 .. 1)) ∨ times ≡ \null;
+    assigns \result;
+    assigns \result
+      \from (indirect: *(path + (0 .. strlen{Old}(path)))),
+            (indirect: times), (indirect: *(times + (0 .. 1)));
+ */
+extern int utimes(char const *path, struct timeval const times[2]);
+
+/*@ ensures result_ok_or_error: \result ≡ 0 ∨ \result ≡ -1;
+    assigns tv->tv_sec, tv->tv_usec, *((struct timezone *)tz), \result;
+    assigns tv->tv_sec \from __fc_time;
+    assigns tv->tv_usec \from __fc_time;
+    assigns *((struct timezone *)tz) \from __fc_tz;
+    assigns \result
+      \from (indirect: tv), (indirect: tz), *tv, *((struct timezone *)tz),
+            __fc_tz;
+    
+    behavior tv_and_tz_null:
+      assumes null_tv_tz: tv ≡ \null ∧ tz ≡ \null;
+      assigns \result;
+      assigns \result \from (indirect: __fc_tz);
+    
+    behavior tv_not_null:
+      assumes non_null_tv_null_tz: tv ≢ \null ∧ tz ≡ \null;
+      ensures
+        initialization: tv_sec: tv_usec:
+          \initialized(&\old(tv)->tv_sec) ∧
+          \initialized(&\old(tv)->tv_usec);
+      ensures tv_usec_bounded: 0 ≤ \old(tv)->tv_usec ≤ 999999;
+      assigns tv->tv_sec, tv->tv_usec, \result;
+      assigns tv->tv_sec \from (indirect: __fc_time);
+      assigns tv->tv_usec \from (indirect: __fc_time);
+      assigns \result \from (indirect: *tv), (indirect: __fc_tz);
+    
+    behavior tz_not_null:
+      assumes null_tv_non_null_tz: tv ≡ \null ∧ tz ≢ \null;
+      ensures initialization: tz: \initialized((struct timezone *)\old(tz));
+      assigns *((struct timezone *)tz), \result;
+      assigns *((struct timezone *)tz) \from __fc_tz;
+      assigns \result
+        \from (indirect: *((struct timezone *)tz)), (indirect: __fc_tz);
+    
+    behavior tv_and_tz_not_null:
+      assumes non_null_tv_tz: tv ≢ \null ∧ tz ≢ \null;
+      ensures
+        initialization: tv_sec: tv_usec:
+          \initialized(&\old(tv)->tv_sec) ∧
+          \initialized(&\old(tv)->tv_usec);
+      ensures initialization: tz: \initialized((struct timezone *)\old(tz));
+      assigns tv->tv_sec, tv->tv_usec, *((struct timezone *)tz), \result;
+      assigns tv->tv_sec \from (indirect: __fc_time);
+      assigns tv->tv_usec \from (indirect: __fc_time);
+      assigns *((struct timezone *)tz) \from __fc_tz;
+      assigns \result
+        \from (indirect: *tv), (indirect: *((struct timezone *)tz)),
+              (indirect: __fc_tz);
+    
+    complete behaviors tv_and_tz_not_null,
+                       tz_not_null,
+                       tv_not_null,
+                       tv_and_tz_null;
+    disjoint behaviors tv_and_tz_not_null,
+                       tz_not_null,
+                       tv_not_null,
+                       tv_and_tz_null;
+ */
+extern int gettimeofday(struct timeval * restrict tv, void * restrict tz);
+
+/*@ requires valid_tv_or_null: \valid_read(tv) ∨ tv ≡ \null;
+    requires valid_tz_or_null: \valid_read(tz) ∨ tz ≡ \null;
+    ensures result_ok_or_error: \result ≡ 0 ∨ \result ≡ -1;
+    assigns __fc_time, __fc_tz, \result;
+    assigns __fc_time
+      \from tv->tv_sec, tv->tv_usec, tz->tz_dsttime, tz->tz_minuteswest;
+    assigns __fc_tz
+      \from tv->tv_sec, tv->tv_usec, tz->tz_dsttime, tz->tz_minuteswest;
+    assigns \result \from (indirect: *tv), (indirect: *tz);
+ */
+extern int settimeofday(struct timeval const *tv, struct timezone const *tz);
+
+/*@ ghost struct itimerval volatile __fc_itimer_real; */
+/*@ ghost struct itimerval volatile __fc_itimer_virtual; */
+/*@ ghost struct itimerval volatile __fc_itimer_prof; */
+/*@ requires valid_curr_value: \valid(curr_value);
+    ensures initialization: curr_value: \initialized(\old(curr_value));
+    assigns \result, *curr_value;
+    assigns \result \from (indirect: which);
+    assigns *curr_value
+      \from __fc_itimer_real, __fc_itimer_virtual, __fc_itimer_prof;
+    
+    behavior real:
+      assumes itimer_real: which ≡ 0;
+      ensures result_ok: \result ≡ 0;
+      assigns \result, *curr_value;
+      assigns \result \from \nothing;
+      assigns *curr_value \from __fc_itimer_real;
+    
+    behavior virtual:
+      assumes itimer_virtual: which ≡ 1;
+      ensures result_ok: \result ≡ 0;
+      assigns \result, *curr_value;
+      assigns \result \from \nothing;
+      assigns *curr_value \from __fc_itimer_virtual;
+    
+    behavior prof:
+      assumes itimer_prof: which ≡ 2;
+      ensures result_ok: \result ≡ 0;
+      assigns \result, *curr_value;
+      assigns \result \from \nothing;
+      assigns *curr_value \from __fc_itimer_prof;
+    
+    behavior invalid:
+      assumes invalid_which: which ≢ 0 ∧ which ≢ 1 ∧ which ≢ 2;
+      ensures result_error: \result ≡ -1;
+      assigns \result;
+      assigns \result \from \nothing;
+    
+    complete behaviors invalid, prof, virtual, real;
+    disjoint behaviors invalid, prof, virtual, real;
+ */
+extern int getitimer(int which, struct itimerval *curr_value);
+
+/*@ requires valid_new_value: \valid_read(new_value);
+    requires
+      old_value_null_or_valid: old_value ≡ \null ∨ \valid(old_value);
+    ensures result_ok_or_error: \result ≡ 0 ∨ \result ≡ -1;
+    assigns *old_value, \result;
+    assigns *old_value
+      \from (indirect: which), (indirect: old_value), (indirect: new_value),
+            __fc_itimer_real, __fc_itimer_virtual, __fc_itimer_prof;
+    assigns \result
+      \from (indirect: which), (indirect: new_value), (indirect: *new_value);
+    
+    behavior real:
+      assumes
+        itimer_real_and_valid:
+          which ≡ 0 ≤ new_value->it_value.tv_usec ≤ 999999 ∧
+          0 ≤ new_value->it_interval.tv_usec ≤ 999999;
+      ensures result_ok: \result ≡ 0;
+      ensures initialization: old_value: \initialized(\old(old_value));
+      assigns \result, *old_value, __fc_itimer_real;
+      assigns \result \from \nothing;
+      assigns *old_value \from __fc_itimer_real;
+      assigns __fc_itimer_real \from *new_value;
+    
+    behavior virtual:
+      assumes
+        itimer_virtual_and_valid:
+          which ≡ 1 ∧ 0 ≤ new_value->it_value.tv_usec ≤ 999999 ∧
+          0 ≤ new_value->it_interval.tv_usec ≤ 999999;
+      ensures result_ok: \result ≡ 0;
+      ensures initialization: old_value: \initialized(\old(old_value));
+      assigns \result, *old_value;
+      assigns \result \from \nothing;
+      assigns *old_value \from __fc_itimer_virtual;
+    
+    behavior prof:
+      assumes
+        itimer_prof_and_valid:
+          which ≡ 2 ∧ 0 ≤ new_value->it_value.tv_usec ≤ 999999 ∧
+          0 ≤ new_value->it_interval.tv_usec ≤ 999999;
+      ensures result_ok: \result ≡ 0;
+      ensures initialization: old_value: \initialized(\old(old_value));
+      assigns \result, *old_value;
+      assigns \result \from \nothing;
+      assigns *old_value \from __fc_itimer_prof;
+    
+    behavior invalid:
+      assumes
+        invalid_itimer_or_new_value:
+          (which ≢ 0 ∧ which ≢ 1 ∧ which ≢ 2) ∨
+          ¬(0 ≤ new_value->it_value.tv_usec ≤ 999999 ∧
+             0 ≤ new_value->it_interval.tv_usec ≤ 999999);
+      ensures result_error: \result ≡ -1;
+      assigns \result;
+      assigns \result \from \nothing;
+    
+    disjoint behaviors invalid, prof, virtual, real;
+ */
+extern int setitimer(int which, struct itimerval const * restrict new_value,
+                     struct itimerval * restrict old_value);
+
+/*@ requires valid_fdset: \valid(fdset);
+    requires initialization: \initialized(fdset);
+    assigns *fdset;
+    assigns *fdset \from *fdset, (indirect: fd);
+ */
+extern void FD_CLR(int fd, fd_set *fdset);
+
+/*@ requires valid_fdset: \valid_read(fdset);
+    requires initialization: \initialized(fdset);
+    assigns \result;
+    assigns \result \from (indirect: *fdset), (indirect: fd);
+ */
+extern int FD_ISSET(int fd, fd_set const *fdset);
+
+/*@ requires valid_fdset: \valid(fdset);
+    requires initialization: \initialized(fdset);
+    assigns *fdset;
+    assigns *fdset \from *fdset, (indirect: fd);
+ */
+extern void FD_SET(int fd, fd_set *fdset);
+
+/*@ requires valid_fdset: \valid(fdset);
+    ensures initialization: \initialized(\old(fdset));
+    assigns *fdset;
+    assigns *fdset \from \nothing;
+ */
+extern void FD_ZERO(fd_set *fdset);
+
 /*@ assigns \result;
     assigns \result \from which, who; */
 extern int getpriority(int which, id_t who);
diff --git a/tests/libc/oracle/fc_libc.2.res.oracle b/tests/libc/oracle/fc_libc.2.res.oracle
index 815b277af9e8e3fecf6f395a1b1b023ea8dd3ffa..eca9057a10e161facaeb91f1b8b069d8788ad038 100644
--- a/tests/libc/oracle/fc_libc.2.res.oracle
+++ b/tests/libc/oracle/fc_libc.2.res.oracle
@@ -6,6 +6,7 @@
 [kernel] Parsing share/libc/__fc_define_dev_t.h (with preprocessing)
 [kernel] Parsing share/libc/__fc_define_eof.h (with preprocessing)
 [kernel] Parsing share/libc/__fc_define_fd_set_t.h (with preprocessing)
+[kernel] Parsing share/libc/__fc_define_fds.h (with preprocessing)
 [kernel] Parsing share/libc/__fc_define_file.h (with preprocessing)
 [kernel] Parsing share/libc/__fc_define_fpos_t.h (with preprocessing)
 [kernel] Parsing share/libc/__fc_define_fs_cnt.h (with preprocessing)
@@ -32,6 +33,7 @@
 [kernel] Parsing share/libc/__fc_define_time_t.h (with preprocessing)
 [kernel] Parsing share/libc/__fc_define_timer_t.h (with preprocessing)
 [kernel] Parsing share/libc/__fc_define_timespec.h (with preprocessing)
+[kernel] Parsing share/libc/__fc_define_timeval.h (with preprocessing)
 [kernel] Parsing share/libc/__fc_define_uid_and_gid.h (with preprocessing)
 [kernel] Parsing share/libc/__fc_define_useconds_t.h (with preprocessing)
 [kernel] Parsing share/libc/__fc_define_wchar_t.h (with preprocessing)
diff --git a/tests/libc/oracle/netdb_c.res.oracle b/tests/libc/oracle/netdb_c.res.oracle
index 75b421147917c7fdf6b9f9bcbd1001f867f21829..884473c2427f4106a9d6c5fded60ee06f15b1c86 100644
--- a/tests/libc/oracle/netdb_c.res.oracle
+++ b/tests/libc/oracle/netdb_c.res.oracle
@@ -317,8 +317,8 @@
 [eva:final-states] Values at end of function main:
   __fc_errno ∈ [--..--]
   __fc_heap_status ∈ [--..--]
+  __fc_fds[0..1023] ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
-  __fc_fds[0..1023] ∈ {0}
   __fc_sockfds[0..1023] ∈ [--..--]
   __fc_socket_counter ∈ [--..--]
   __fc_ghbn.host.h_name ∈ {{ NULL ; &__fc_ghbn.hostbuf[0] }}
diff --git a/tests/libc/oracle/socket.0.res.oracle b/tests/libc/oracle/socket.0.res.oracle
index c0f9285b9913c93af17f9c46cecdd5f9e2b994d1..276fcf21362da709bfb1e3539c7ad646d8272d88 100644
--- a/tests/libc/oracle/socket.0.res.oracle
+++ b/tests/libc/oracle/socket.0.res.oracle
@@ -68,24 +68,20 @@
 [eva] Done for function test_read
 [eva] computing for function test_readv <- main.
   Called from tests/libc/socket.c:127.
-[eva] computing for function init_reception <- test_readv <- main.
-  Called from tests/libc/socket.c:68.
-[eva] computing for function bzero <- init_reception <- test_readv <- main.
-  Called from tests/libc/socket.c:43.
-[eva] Done for function bzero
-[eva] computing for function write <- init_reception <- test_readv <- main.
-  Called from tests/libc/socket.c:44.
-[eva] Done for function write
-[eva] Recording results for init_reception
-[eva] Done for function init_reception
+[eva] tests/libc/socket.c:68: Reusing old results for call to init_reception
 [eva] computing for function readv <- test_readv <- main.
   Called from tests/libc/socket.c:69.
 [eva] using specification for function readv
 [eva] tests/libc/socket.c:69: 
-  function readv: precondition 'valid_read_iov' got status valid.
-[eva] share/libc/sys/uio.h:37: Warning: 
-  no \from part
-  for clause 'assigns *((char *)(iov + (0 .. iovcnt - 1))->iov_base + (0 ..));'
+  function readv: precondition 'valid_fd' got status valid.
+[eva] tests/libc/socket.c:69: 
+  function readv: precondition 'initialization,initialized_inputs' got status valid.
+[eva] tests/libc/socket.c:69: 
+  function readv: precondition 'valid_iov' got status valid.
+[eva] tests/libc/socket.c:69: 
+  function readv: precondition 'bounded_iovcnt' got status valid.
+[eva] share/libc/sys/uio.h:52: 
+  cannot evaluate ACSL term, unsupported ACSL construct: logic function \sum
 [eva] Done for function readv
 [eva:alarm] tests/libc/socket.c:72: Warning: 
   accessing uninitialized left-value.
@@ -240,8 +236,8 @@
                             [2].iov_len ∈ {3}
   S___fc_stdout[0..1] ∈ [--..--]
 [eva:final-states] Values at end of function test_recvmsg:
-  __fc_sockfds[0..1023] ∈ [--..--]
   __fc_fds[0..1023] ∈ [--..--]
+  __fc_sockfds[0..1023] ∈ [--..--]
   rcv_buffer[0..9] ∈ {0}
   rcv_buffer_scattered1[0] ∈ [--..--]
                        [1] ∈ [--..--] or UNINITIALIZED
@@ -265,9 +261,9 @@
      .msg_flags ∈ [--..--] or UNINITIALIZED
   S___fc_stdout[0..1] ∈ [--..--]
 [eva:final-states] Values at end of function test_server_echo:
+  __fc_fds[0..1023] ∈ [--..--]
   __fc_sockfds[0..1023] ∈ [--..--]
   __fc_socket_counter ∈ [--..--]
-  __fc_fds[0..1023] ∈ [--..--]
   fd ∈ [-1..1023]
   addr ∈ [--..--] or UNINITIALIZED
   addrlen ∈ {8}
@@ -276,9 +272,9 @@
   r ∈ [-1..64]
   __retres ∈ {0; 1; 5; 20; 100; 200; 300; 400}
 [eva:final-states] Values at end of function main:
+  __fc_fds[0..1023] ∈ [--..--]
   __fc_sockfds[0..1023] ∈ [--..--]
   __fc_socket_counter ∈ [--..--]
-  __fc_fds[0..1023] ∈ [--..--]
   rcv_buffer[0..9] ∈ {0}
   socket_fd[0..1] ∈ [0..1023]
   r ∈ {0; 1; 5; 20; 100; 200; 300; 400}
diff --git a/tests/libc/oracle/socket.1.res.oracle b/tests/libc/oracle/socket.1.res.oracle
index a60c6913b0fb68fee18a85d1c2bc363f9fadb3a7..82d1a5a2090728ffd2cadaba116d11e3f9084d6a 100644
--- a/tests/libc/oracle/socket.1.res.oracle
+++ b/tests/libc/oracle/socket.1.res.oracle
@@ -68,24 +68,20 @@
 [eva] Done for function test_read
 [eva] computing for function test_readv <- main.
   Called from tests/libc/socket.c:127.
-[eva] computing for function init_reception <- test_readv <- main.
-  Called from tests/libc/socket.c:68.
-[eva] computing for function bzero <- init_reception <- test_readv <- main.
-  Called from tests/libc/socket.c:43.
-[eva] Done for function bzero
-[eva] computing for function write <- init_reception <- test_readv <- main.
-  Called from tests/libc/socket.c:44.
-[eva] Done for function write
-[eva] Recording results for init_reception
-[eva] Done for function init_reception
+[eva] tests/libc/socket.c:68: Reusing old results for call to init_reception
 [eva] computing for function readv <- test_readv <- main.
   Called from tests/libc/socket.c:69.
 [eva] using specification for function readv
 [eva] tests/libc/socket.c:69: 
-  function readv: precondition 'valid_read_iov' got status valid.
-[eva] share/libc/sys/uio.h:37: Warning: 
-  no \from part
-  for clause 'assigns *((char *)(iov + (0 .. iovcnt - 1))->iov_base + (0 ..));'
+  function readv: precondition 'valid_fd' got status valid.
+[eva] tests/libc/socket.c:69: 
+  function readv: precondition 'initialization,initialized_inputs' got status valid.
+[eva] tests/libc/socket.c:69: 
+  function readv: precondition 'valid_iov' got status valid.
+[eva] tests/libc/socket.c:69: 
+  function readv: precondition 'bounded_iovcnt' got status valid.
+[eva] share/libc/sys/uio.h:52: 
+  cannot evaluate ACSL term, unsupported ACSL construct: logic function \sum
 [eva] Done for function readv
 [eva:alarm] tests/libc/socket.c:72: Warning: 
   accessing uninitialized left-value.
@@ -240,8 +236,8 @@
                             [2].iov_len ∈ {3}
   S___fc_stdout[0..1] ∈ [--..--]
 [eva:final-states] Values at end of function test_recvmsg:
-  __fc_sockfds[0..1023] ∈ [--..--]
   __fc_fds[0..1023] ∈ [--..--]
+  __fc_sockfds[0..1023] ∈ [--..--]
   rcv_buffer[0..9] ∈ {0}
   rcv_buffer_scattered1[0] ∈ [--..--]
                        [1] ∈ [--..--] or UNINITIALIZED
@@ -267,9 +263,9 @@
      .msg_flags ∈ [--..--] or UNINITIALIZED
   S___fc_stdout[0..1] ∈ [--..--]
 [eva:final-states] Values at end of function test_server_echo:
+  __fc_fds[0..1023] ∈ [--..--]
   __fc_sockfds[0..1023] ∈ [--..--]
   __fc_socket_counter ∈ [--..--]
-  __fc_fds[0..1023] ∈ [--..--]
   fd ∈ [-1..1023]
   addr ∈ [--..--] or UNINITIALIZED
   addrlen ∈ {8}
@@ -278,9 +274,9 @@
   r ∈ [-1..64]
   __retres ∈ {0; 1; 5; 20; 100; 200; 300; 400}
 [eva:final-states] Values at end of function main:
+  __fc_fds[0..1023] ∈ [--..--]
   __fc_sockfds[0..1023] ∈ [--..--]
   __fc_socket_counter ∈ [--..--]
-  __fc_fds[0..1023] ∈ [--..--]
   rcv_buffer[0..9] ∈ {0}
   socket_fd[0..1] ∈ [0..1023]
   r ∈ {0; 1; 5; 20; 100; 200; 300; 400}
diff --git a/tests/libc/oracle/sys_uio_h.res.oracle b/tests/libc/oracle/sys_uio_h.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..feee0f8a0d4570603b66fd56bf5d8a7389ebe5d3
--- /dev/null
+++ b/tests/libc/oracle/sys_uio_h.res.oracle
@@ -0,0 +1,112 @@
+[kernel] Parsing tests/libc/sys_uio_h.c (with preprocessing)
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  nondet ∈ [--..--]
+[eva] computing for function __va_open_mode_t <- main.
+  Called from tests/libc/sys_uio_h.c:17.
+[eva] using specification for function __va_open_mode_t
+[eva] tests/libc/sys_uio_h.c:17: 
+  function __va_open_mode_t: precondition 'valid_filename' got status valid.
+[eva] Done for function __va_open_mode_t
+[eva] tests/libc/sys_uio_h.c:19: assertion got status valid.
+[eva] tests/libc/sys_uio_h.c:20: assertion got status valid.
+[eva] tests/libc/sys_uio_h.c:21: assertion got status valid.
+[eva] computing for function writev <- main.
+  Called from tests/libc/sys_uio_h.c:22.
+[eva] using specification for function writev
+[eva] tests/libc/sys_uio_h.c:22: 
+  function writev: precondition 'valid_fd' got status valid.
+[eva] tests/libc/sys_uio_h.c:22: 
+  function writev: precondition 'initialization,initialized_inputs' got status valid.
+[eva] tests/libc/sys_uio_h.c:22: 
+  function writev: precondition 'valid_read_iov' got status valid.
+[eva:alarm] tests/libc/sys_uio_h.c:22: Warning: 
+  function writev: precondition 'valid_read_iov_bases' got status unknown.
+[eva] tests/libc/sys_uio_h.c:22: 
+  function writev: precondition 'bounded_iovcnt' got status valid.
+[eva] share/libc/sys/uio.h:67: 
+  cannot evaluate ACSL term, unsupported ACSL construct: logic function \sum
+[eva:alarm] tests/libc/sys_uio_h.c:22: Warning: 
+  function writev: precondition 'bounded_lengths' got status unknown.
+[eva] share/libc/sys/uio.h:72: 
+  cannot evaluate ACSL term, unsupported ACSL construct: logic function \sum
+[eva] Done for function writev
+[eva] computing for function close <- main.
+  Called from tests/libc/sys_uio_h.c:23.
+[eva] using specification for function close
+[eva] tests/libc/sys_uio_h.c:23: 
+  function close: precondition 'valid_fd' got status valid.
+[eva] Done for function close
+[eva] computing for function __va_open_void <- main.
+  Called from tests/libc/sys_uio_h.c:24.
+[eva] using specification for function __va_open_void
+[eva] tests/libc/sys_uio_h.c:24: 
+  function __va_open_void: precondition 'valid_filename' got status valid.
+[eva] tests/libc/sys_uio_h.c:24: 
+  function __va_open_void: precondition 'flag_not_CREAT' got status valid.
+[eva] Done for function __va_open_void
+[eva] computing for function readv <- main.
+  Called from tests/libc/sys_uio_h.c:25.
+[eva] using specification for function readv
+[eva:alarm] tests/libc/sys_uio_h.c:25: Warning: 
+  function readv: precondition 'valid_fd' got status unknown.
+[eva] tests/libc/sys_uio_h.c:25: 
+  function readv: precondition 'initialization,initialized_inputs' got status valid.
+[eva:alarm] tests/libc/sys_uio_h.c:25: Warning: 
+  function readv: precondition 'valid_iov' got status unknown.
+[eva] tests/libc/sys_uio_h.c:25: 
+  function readv: precondition 'bounded_iovcnt' got status valid.
+[eva] share/libc/sys/uio.h:52: 
+  cannot evaluate ACSL term, unsupported ACSL construct: logic function \sum
+[eva] Done for function readv
+[eva] computing for function close <- main.
+  Called from tests/libc/sys_uio_h.c:26.
+[eva] tests/libc/sys_uio_h.c:26: 
+  function close: precondition 'valid_fd' got status valid.
+[eva] Done for function close
+[eva] computing for function __va_open_mode_t <- main.
+  Called from tests/libc/sys_uio_h.c:37.
+[eva] tests/libc/sys_uio_h.c:37: 
+  function __va_open_mode_t: precondition 'valid_filename' got status valid.
+[eva] Done for function __va_open_mode_t
+[eva] computing for function writev <- main.
+  Called from tests/libc/sys_uio_h.c:39.
+[eva] tests/libc/sys_uio_h.c:39: 
+  function writev: precondition 'valid_fd' got status valid.
+[eva] tests/libc/sys_uio_h.c:39: 
+  function writev: precondition 'initialization,initialized_inputs' got status valid.
+[eva] tests/libc/sys_uio_h.c:39: 
+  function writev: precondition 'valid_read_iov' got status valid.
+[eva:alarm] tests/libc/sys_uio_h.c:39: Warning: 
+  function writev: precondition 'valid_read_iov_bases' got status unknown.
+[eva] tests/libc/sys_uio_h.c:39: 
+  function writev: precondition 'bounded_iovcnt' got status valid.
+[eva:alarm] tests/libc/sys_uio_h.c:39: Warning: 
+  function writev: precondition 'bounded_lengths' got status unknown.
+[eva] Done for function writev
+[eva:alarm] tests/libc/sys_uio_h.c:40: Warning: 
+  assertion 'unreachable' got status invalid (stopping propagation).
+[eva:alarm] tests/libc/sys_uio_h.c:43: Warning: 
+  signed overflow. assert w + r ≤ 2147483647;
+[eva] Recording results for main
+[eva] done for function main
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function main:
+  __fc_fds[0..1023] ∈ [--..--]
+  str ∈ {{ "A small string" }}
+  empty_buf ∈ {0}
+  buf[0..9] ∈ [--..--]
+  buf2[0..13] ∈ [--..--] or UNINITIALIZED
+  v[0].iov_base ∈ {{ "A small string" }}
+   [0].iov_len ∈ {15}
+   [1] ∈ {0}
+   [2].iov_base ∈ {{ (void *)&buf }}
+   [2].iov_len ∈ {10}
+   [3].iov_base ∈ {{ (void *)&buf2 }}
+   [3].iov_len ∈ {14}
+  fd ∈ [-1..1023]
+  w ∈ [-1..2147483647]
+  r ∈ [-1..2147483647]
+  __retres ∈ [-2..2147483647]
diff --git a/tests/libc/oracle/unistd_h.0.res.oracle b/tests/libc/oracle/unistd_h.0.res.oracle
index 55e6a1c528de73a57f89e7f4b640206bc2f38233..5173981ab82804e60d054d1f19aea51cd3f81bc2 100644
--- a/tests/libc/oracle/unistd_h.0.res.oracle
+++ b/tests/libc/oracle/unistd_h.0.res.oracle
@@ -570,9 +570,8 @@
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
 [eva:final-states] Values at end of function main:
+  __fc_fds[0..1023] ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
-  __fc_fds[0] ∈ {0}
-          [1..1023] ∈ [--..--]
   r ∈ {-1; 0}
   hostname[0..255] ∈ [--..--] or UNINITIALIZED
   fd ∈ [-1..1023]
diff --git a/tests/libc/oracle/unistd_h.1.res.oracle b/tests/libc/oracle/unistd_h.1.res.oracle
index 1ce6be573a566003223a378d330cfdb7e4c1744b..fa6d33a9d1b05edf653138dc9d4527f5421f3532 100644
--- a/tests/libc/oracle/unistd_h.1.res.oracle
+++ b/tests/libc/oracle/unistd_h.1.res.oracle
@@ -570,9 +570,8 @@
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
 [eva:final-states] Values at end of function main:
+  __fc_fds[0..1023] ∈ [--..--]
   Frama_C_entropy_source ∈ [--..--]
-  __fc_fds[0] ∈ {0}
-          [1..1023] ∈ [--..--]
   r ∈ {-1; 0}
   hostname[0..255] ∈ [--..--] or UNINITIALIZED
   fd ∈ [-1..1023]
diff --git a/tests/libc/sys_uio_h.c b/tests/libc/sys_uio_h.c
new file mode 100644
index 0000000000000000000000000000000000000000..2bde83999ac582c7c96456c572735e9c3ceef108
--- /dev/null
+++ b/tests/libc/sys_uio_h.c
@@ -0,0 +1,44 @@
+#include <sys/uio.h>
+#include <unistd.h>
+#include <fcntl.h>
+volatile int nondet;
+int main() {
+  char *str = "A small string";
+  char *empty_buf = 0;
+  char buf[10] = "\n\n\nbuffer";
+  char buf2[14];
+  struct iovec v[4] =
+    {
+     {str, 15},
+     {empty_buf, 0},
+     {buf, 10},
+     {buf2, 14},
+    };
+  int fd = open("/tmp/uio.txt", O_WRONLY | O_CREAT, 0660);
+  if (fd < 0) return 1;
+  //@ assert \valid_read(((char*)v[0].iov_base) + (0 .. v[0].iov_len-1));
+  //@ assert \valid_read(((char*)v[1].iov_base) + (0 .. v[1].iov_len-1));
+  //@ assert \valid_read(((char*)v[2].iov_base) + (0 .. v[2].iov_len-1));
+  ssize_t w = writev(fd, v, 3);
+  close(fd);
+  fd = open("/tmp/uio.txt", O_RDONLY);
+  ssize_t r = readv(fd, v+2, 2);
+  close(fd);
+
+  if (nondet) {
+    char buf3[10] = "\n\n\nbuffer";
+    char buf4[14];
+    struct iovec v2[4] =
+      {
+        {str, 15},
+        {empty_buf, 0},
+        {buf3, 11}, // invalid length
+      };
+    int fd2 = open("/tmp/uio2.txt", O_WRONLY | O_CREAT, 0660);
+    if (fd2 < 0) return 1;
+    ssize_t w = writev(fd2, v2, 3); // must fail
+    //@ assert unreachable: \false;
+  }
+
+  return w + r;
+}
diff --git a/tests/metrics/oracle/libc.1.res.oracle b/tests/metrics/oracle/libc.1.res.oracle
index a57305d1570190ba61230b014b4c0bec1da423ae..189a5298dc644b531bbc585f569754593b007010 100644
--- a/tests/metrics/oracle/libc.1.res.oracle
+++ b/tests/metrics/oracle/libc.1.res.oracle
@@ -44,10 +44,11 @@
   =======================================
    
   
-  'Extern' global variables (11)
+  'Extern' global variables (12)
   ==============================
-   Frama_C_entropy_source; __fc_errno; __fc_heap_status; __fc_hostname;
-   __fc_stdin; __fc_stdout; __fc_ttyname; optarg; opterr; optind; optopt
+   Frama_C_entropy_source; __fc_errno; __fc_fds; __fc_heap_status;
+   __fc_hostname; __fc_stdin; __fc_stdout; __fc_ttyname; optarg; opterr;
+   optind; optopt
   
   Potential entry points (2)
   ==========================
diff --git a/tests/metrics/oracle/libc.json b/tests/metrics/oracle/libc.json
index afe73bccdad6b27be86cc5b509fb01fda44e6ce4..de14067e7a65d53a82dd943adb71c6cb31536f68 100644
--- a/tests/metrics/oracle/libc.json
+++ b/tests/metrics/oracle/libc.json
@@ -136,7 +136,7 @@
   ],
   "undefined-functions": [],
   "extern-global-vars": [
-    "Frama_C_entropy_source", "__fc_errno", "__fc_heap_status",
+    "Frama_C_entropy_source", "__fc_errno", "__fc_fds", "__fc_heap_status",
     "__fc_hostname", "__fc_stdin", "__fc_stdout", "__fc_ttyname", "optarg",
     "opterr", "optind", "optopt"
   ],