diff --git a/headers/header_spec.txt b/headers/header_spec.txt
index 424d9a2a67667859cf5b297c541bbb81075e88ac..1b31299d8c2ad05fe41c32e4e1ec5b49bb003981 100644
--- a/headers/header_spec.txt
+++ b/headers/header_spec.txt
@@ -296,6 +296,7 @@ share/libc/sys/param.h: CEA_LGPL
 share/libc/sys/random.h: CEA_LGPL
 share/libc/sys/resource.h: CEA_LGPL
 share/libc/sys/select.h: CEA_LGPL
+share/libc/sys/sendfile.h: CEA_LGPL
 share/libc/sys/shm.h: CEA_LGPL
 share/libc/sys/signal.h: CEA_LGPL
 share/libc/sys/socket.h: CEA_LGPL
diff --git a/share/compliance/nonstandard_identifiers.json b/share/compliance/nonstandard_identifiers.json
index 597eb9212001ea484dce3c52deff1c1b902a9bd9..3e921766cd4c962142d20d13ad2e5645fa9afdb0 100644
--- a/share/compliance/nonstandard_identifiers.json
+++ b/share/compliance/nonstandard_identifiers.json
@@ -8,6 +8,7 @@
         "makedev": {"header":"sys/types.h"},
         "option": {"header":"getopt.h"},
         "prioritynames": {"header":"syslog.h"},
+        "sendfile": {"header":"sys/sendfile.h"},
         "setresgid": {"header":"unistd.h"},
         "setresuid": {"header":"unistd.h"},
         "strcspn": {"header":"string.h"},
diff --git a/share/libc/__fc_libc.h b/share/libc/__fc_libc.h
index f48c2a451635a25714abca51a28b18f3442e7d2b..6e43667ac7d10ff995a1a2977499d078c211dbd6 100644
--- a/share/libc/__fc_libc.h
+++ b/share/libc/__fc_libc.h
@@ -88,6 +88,7 @@
 #include "sys/random.h"
 #include "sys/resource.h"
 #include "sys/select.h"
+#include "sys/sendfile.h"
 #include "sys/shm.h"
 #include "sys/signal.h"
 #include "sys/socket.h"
diff --git a/share/libc/sys/sendfile.h b/share/libc/sys/sendfile.h
new file mode 100644
index 0000000000000000000000000000000000000000..9636ecebbf0103c85d7ddd35e4a0b47252991153
--- /dev/null
+++ b/share/libc/sys/sendfile.h
@@ -0,0 +1,56 @@
+/**************************************************************************/
+/*                                                                        */
+/*  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).            */
+/*                                                                        */
+/**************************************************************************/
+
+// Non-POSIX; Linux-specific
+
+#ifndef __FC_SYS_SENDFILE_H__
+#define __FC_SYS_SENDFILE_H__
+
+#include "../features.h"
+__PUSH_FC_STDLIB
+__BEGIN_DECLS
+
+#include "../__fc_define_max_open_files.h"
+#include "../__fc_define_off_t.h"
+#include "../__fc_define_size_t.h"
+#include "../__fc_define_ssize_t.h"
+#include "../errno.h"
+
+/*@
+  //missing: requires in_fd opened for reading
+  //missing: requires out_fd opened for writing
+  requires valid_in_fd: 0 <= in_fd < __FC_MAX_OPEN_FILES;
+  requires valid_out_fd: 0 <= out_fd < __FC_MAX_OPEN_FILES;
+  requires valid_offset_or_null: offset == \null || \valid(offset);
+  requires initialization:offset: offset == \null || \initialized(offset);
+  assigns errno, \result, *offset \from indirect:out_fd, indirect:in_fd,
+                                        indirect:offset, indirect:count;
+  //missing: assigns "out_fd's state (offset/buffer if file; or socket's state)"
+  //missing: assigns "in_fd's offset, if offset == null"
+  ensures error_or_chars_sent: \result == -1 || 0 <= \result <= count;
+  ensures initialization:offset: \initialized(offset);
+ */
+ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
+
+__END_DECLS
+__POP_FC_STDLIB
+#endif
diff --git a/tests/libc/fc_libc.c b/tests/libc/fc_libc.c
index c222f77c8033529b9f07801298f9ab474d5dc783..2010e74f9536538808b93fe910035b7b948f485d 100644
--- a/tests/libc/fc_libc.c
+++ b/tests/libc/fc_libc.c
@@ -130,6 +130,7 @@
 #include "sys/random.h"
 #include "sys/resource.h"
 #include "sys/select.h"
+#include "sys/sendfile.h"
 #include "sys/shm.h"
 #include "sys/signal.h"
 #include "sys/socket.h"
diff --git a/tests/libc/oracle/fc_libc.0.res.oracle b/tests/libc/oracle/fc_libc.0.res.oracle
index 483efb112ac3b086e079422c67dff159473513fe..42266a3a00f369cd9dfa692f7122427645010878 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:159: assertion got status valid.
 [eva] tests/libc/fc_libc.c:160: assertion got status valid.
 [eva] tests/libc/fc_libc.c:161: assertion got status valid.
 [eva] tests/libc/fc_libc.c:162: assertion got status valid.
+[eva] tests/libc/fc_libc.c:163: assertion got status valid.
 [eva] Recording results for main
 [eva] done for function main
 [eva] ====== VALUES COMPUTED ======
@@ -41,7 +41,7 @@
    wcscpy (0 call); wcsdup (0 call); wcslen (3 calls); wcsncat (0 call);
    wcsncpy (0 call); wmemcpy (1 call); wmemset (0 call); 
   
-  Specified-only functions (421)
+  Specified-only functions (422)
   ==============================
    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);
@@ -137,36 +137,37 @@
    recv (0 call); recvfrom (0 call); recvmsg (0 call); remove (0 call);
    rename (0 call); rewind (0 call); round (0 call); roundf (0 call);
    roundl (0 call); seed48 (0 call); select (0 call); send (0 call);
-   sendto (0 call); setbuf (0 call); setegid (0 call); seteuid (0 call);
-   setgid (0 call); sethostname (0 call); setitimer (0 call); setjmp (0 call);
-   setlogmask (0 call); setpgid (0 call); setpriority (0 call);
-   setregid (0 call); setresgid (0 call); setresuid (0 call);
-   setreuid (0 call); setrlimit (0 call); setsid (0 call); setsockopt (0 call);
-   settimeofday (0 call); setuid (0 call); setvbuf (0 call); shutdown (0 call);
-   sigaction (0 call); sigaddset (0 call); sigdelset (0 call);
-   sigemptyset (0 call); sigfillset (0 call); sigismember (0 call);
-   siglongjmp (0 call); signal (0 call); sigprocmask (0 call); sin (0 call);
-   sinf (0 call); sinl (0 call); sleep (0 call); socket (0 call);
-   socketpair (0 call); sqrt (0 call); sqrtf (0 call); sqrtl (0 call);
-   srand (0 call); srand48 (0 call); srandom (0 call); stat (0 call);
-   stpcpy (0 call); strcasestr (0 call); strchrnul (0 call); strcoll (0 call);
-   strcspn (0 call); strftime (0 call); strlcat (0 call); strlcpy (0 call);
-   strncasecmp (0 call); strpbrk (0 call); strsep (0 call); strspn (0 call);
-   strtod (0 call); strtof (0 call); strtoimax (0 call); strtok (0 call);
-   strtok_r (0 call); strtol (0 call); strtold (0 call); strtoll (0 call);
-   strtoul (0 call); strtoull (0 call); strxfrm (0 call); sync (0 call);
-   sysconf (0 call); syslog (0 call); system (0 call); tcflush (0 call);
-   tcgetattr (0 call); tcsetattr (0 call); time (0 call); times (0 call);
-   tmpfile (0 call); tmpnam (0 call); trunc (0 call); truncf (0 call);
-   truncl (0 call); ttyname (0 call); tzset (0 call); umask (0 call);
-   uname (0 call); ungetc (0 call); unlink (0 call); usleep (0 call);
-   utimes (0 call); vfprintf (0 call); vfscanf (0 call); vprintf (0 call);
-   vscanf (0 call); vsnprintf (0 call); vsprintf (0 call); vsyslog (0 call);
-   wait (0 call); waitpid (0 call); wcscasecmp (0 call); wcschr (0 call);
-   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); 
+   sendfile (0 call); sendto (0 call); setbuf (0 call); setegid (0 call);
+   seteuid (0 call); setgid (0 call); sethostname (0 call); setitimer (0 call);
+   setjmp (0 call); setlogmask (0 call); setpgid (0 call);
+   setpriority (0 call); setregid (0 call); setresgid (0 call);
+   setresuid (0 call); setreuid (0 call); setrlimit (0 call); setsid (0 call);
+   setsockopt (0 call); settimeofday (0 call); setuid (0 call);
+   setvbuf (0 call); shutdown (0 call); sigaction (0 call); sigaddset (0 call);
+   sigdelset (0 call); sigemptyset (0 call); sigfillset (0 call);
+   sigismember (0 call); siglongjmp (0 call); signal (0 call);
+   sigprocmask (0 call); sin (0 call); sinf (0 call); sinl (0 call);
+   sleep (0 call); socket (0 call); socketpair (0 call); sqrt (0 call);
+   sqrtf (0 call); sqrtl (0 call); srand (0 call); srand48 (0 call);
+   srandom (0 call); stat (0 call); stpcpy (0 call); strcasestr (0 call);
+   strchrnul (0 call); strcoll (0 call); strcspn (0 call); strftime (0 call);
+   strlcat (0 call); strlcpy (0 call); strncasecmp (0 call); strpbrk (0 call);
+   strsep (0 call); strspn (0 call); strtod (0 call); strtof (0 call);
+   strtoimax (0 call); strtok (0 call); strtok_r (0 call); strtol (0 call);
+   strtold (0 call); strtoll (0 call); strtoul (0 call); strtoull (0 call);
+   strxfrm (0 call); sync (0 call); sysconf (0 call); syslog (0 call);
+   system (0 call); tcflush (0 call); tcgetattr (0 call); tcsetattr (0 call);
+   time (0 call); times (0 call); tmpfile (0 call); tmpnam (0 call);
+   trunc (0 call); truncf (0 call); truncl (0 call); ttyname (0 call);
+   tzset (0 call); umask (0 call); uname (0 call); ungetc (0 call);
+   unlink (0 call); usleep (0 call); utimes (0 call); vfprintf (0 call);
+   vfscanf (0 call); vprintf (0 call); vscanf (0 call); vsnprintf (0 call);
+   vsprintf (0 call); vsyslog (0 call); wait (0 call); waitpid (0 call);
+   wcscasecmp (0 call); wcschr (0 call); 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); 
   
   Undefined and unspecified functions (1)
   =======================================
@@ -195,7 +196,7 @@
   Goto = 99
   Assignment = 466
   Exit point = 84
-  Function = 506
+  Function = 507
   Function call = 98
   Pointer dereferencing = 161
   Cyclomatic complexity = 299
@@ -252,6 +253,7 @@
 #include "stropts.h"
 #include "sys/file.h"
 #include "sys/resource.h"
+#include "sys/sendfile.h"
 #include "sys/socket.h"
 #include "sys/stat.h"
 #include "sys/time.h"
diff --git a/tests/libc/oracle/fc_libc.1.res.oracle b/tests/libc/oracle/fc_libc.1.res.oracle
index d1496ec153c6da59da7b3edd9387612b067730ce..c99ba102c79368d6a0891069a36e52ff359cfd10 100644
--- a/tests/libc/oracle/fc_libc.1.res.oracle
+++ b/tests/libc/oracle/fc_libc.1.res.oracle
@@ -8274,6 +8274,27 @@ extern int getrusage(int who, struct rusage *r_usage);
  */
 extern int setrlimit(int resource, struct rlimit const *rlp);
 
+/*@ requires valid_in_fd: 0 ≤ in_fd < 1024;
+    requires valid_out_fd: 0 ≤ out_fd < 1024;
+    requires valid_offset_or_null: offset ≡ \null ∨ \valid(offset);
+    requires
+      initialization: offset: offset ≡ \null ∨ \initialized(offset);
+    ensures
+      error_or_chars_sent: \result ≡ -1 ∨ (0 ≤ \result ≤ \old(count));
+    ensures initialization: offset: \initialized(\old(offset));
+    assigns __fc_errno, \result, *offset;
+    assigns __fc_errno
+      \from (indirect: out_fd), (indirect: in_fd), (indirect: offset),
+            (indirect: count);
+    assigns \result
+      \from (indirect: out_fd), (indirect: in_fd), (indirect: offset),
+            (indirect: count);
+    assigns *offset
+      \from (indirect: out_fd), (indirect: in_fd), (indirect: offset),
+            (indirect: count);
+ */
+ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
+
 /*@ requires valid_buffer: \valid(buffer);
     assigns \result, *buffer;
     assigns \result \from __fc_time;
diff --git a/tests/libc/oracle/fc_libc.2.res.oracle b/tests/libc/oracle/fc_libc.2.res.oracle
index ff8de64ff7b2a0c175e479d63f98a86db1289469..548b5555639845571c43ccce9622f06b69de87dd 100644
--- a/tests/libc/oracle/fc_libc.2.res.oracle
+++ b/tests/libc/oracle/fc_libc.2.res.oracle
@@ -105,6 +105,7 @@ skipping share/libc/complex.h
 [kernel] Parsing share/libc/sys/random.h (with preprocessing)
 [kernel] Parsing share/libc/sys/resource.h (with preprocessing)
 [kernel] Parsing share/libc/sys/select.h (with preprocessing)
+[kernel] Parsing share/libc/sys/sendfile.h (with preprocessing)
 [kernel] Parsing share/libc/sys/shm.h (with preprocessing)
 [kernel] Parsing share/libc/sys/signal.h (with preprocessing)
 [kernel] Parsing share/libc/sys/socket.h (with preprocessing)
diff --git a/tests/libc/oracle/sys_sendfile_h.res.oracle b/tests/libc/oracle/sys_sendfile_h.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..7cd2c9b5e2e868d3c4d187c0ba490cc914ca80a2
--- /dev/null
+++ b/tests/libc/oracle/sys_sendfile_h.res.oracle
@@ -0,0 +1,80 @@
+[kernel] Parsing tests/libc/sys_sendfile_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
+  
+[eva] computing for function __va_open_void <- main.
+  Called from tests/libc/sys_sendfile_h.c:7.
+[eva] using specification for function __va_open_void
+[eva] tests/libc/sys_sendfile_h.c:7: 
+  function __va_open_void: precondition 'valid_filename' got status valid.
+[eva] tests/libc/sys_sendfile_h.c:7: 
+  function __va_open_void: precondition 'flag_not_CREAT' got status valid.
+[eva] Done for function __va_open_void
+[eva] computing for function __va_open_mode_t <- main.
+  Called from tests/libc/sys_sendfile_h.c:9.
+[eva] using specification for function __va_open_mode_t
+[eva] tests/libc/sys_sendfile_h.c:9: 
+  function __va_open_mode_t: precondition 'valid_filename' got status valid.
+[eva] Done for function __va_open_mode_t
+[eva] computing for function sendfile <- main.
+  Called from tests/libc/sys_sendfile_h.c:13.
+[eva] using specification for function sendfile
+[eva] tests/libc/sys_sendfile_h.c:13: 
+  function sendfile: precondition 'valid_in_fd' got status valid.
+[eva] tests/libc/sys_sendfile_h.c:13: 
+  function sendfile: precondition 'valid_out_fd' got status valid.
+[eva] tests/libc/sys_sendfile_h.c:13: 
+  function sendfile: precondition 'valid_offset_or_null' got status valid.
+[eva] tests/libc/sys_sendfile_h.c:13: 
+  function sendfile: precondition 'initialization,offset' got status valid.
+[eva] Done for function sendfile
+[eva] tests/libc/sys_sendfile_h.c:14: assertion got status valid.
+[eva] computing for function close <- main.
+  Called from tests/libc/sys_sendfile_h.c:15.
+[eva] using specification for function close
+[eva] tests/libc/sys_sendfile_h.c:15: 
+  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_sendfile_h.c:17.
+[eva] tests/libc/sys_sendfile_h.c:17: 
+  function __va_open_mode_t: precondition 'valid_filename' got status valid.
+[eva] Done for function __va_open_mode_t
+[eva] computing for function sendfile <- main.
+  Called from tests/libc/sys_sendfile_h.c:19.
+[eva] tests/libc/sys_sendfile_h.c:19: 
+  function sendfile: precondition 'valid_in_fd' got status valid.
+[eva] tests/libc/sys_sendfile_h.c:19: 
+  function sendfile: precondition 'valid_out_fd' got status valid.
+[eva] tests/libc/sys_sendfile_h.c:19: 
+  function sendfile: precondition 'valid_offset_or_null' got status valid.
+[eva] tests/libc/sys_sendfile_h.c:19: 
+  function sendfile: precondition 'initialization,offset' got status valid.
+[eva:invalid-assigns] tests/libc/sys_sendfile_h.c:19: 
+  Completely invalid destination for assigns clause *offset. Ignoring.
+[eva] Done for function sendfile
+[eva] computing for function close <- main.
+  Called from tests/libc/sys_sendfile_h.c:20.
+[eva] tests/libc/sys_sendfile_h.c:20: 
+  function close: precondition 'valid_fd' got status valid.
+[eva] Done for function close
+[eva] computing for function close <- main.
+  Called from tests/libc/sys_sendfile_h.c:21.
+[eva] tests/libc/sys_sendfile_h.c:21: 
+  function close: precondition 'valid_fd' got status valid.
+[eva] Done for function close
+[eva] Recording results for main
+[eva] done for function main
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function main:
+  __fc_errno ∈ [--..--]
+  __fc_fds[0..1023] ∈ [--..--]
+  out_fd ∈ [-1..1023] or UNINITIALIZED
+  in_fd ∈ [-1..1023]
+  offset ∈ [--..--]
+  r1 ∈ [-1..42] or UNINITIALIZED
+  r3 ∈ [-1..42] or UNINITIALIZED
+  r ∈ {-1; 0}
+  __retres ∈ {0; 1}
diff --git a/tests/libc/sys_sendfile_h.c b/tests/libc/sys_sendfile_h.c
new file mode 100644
index 0000000000000000000000000000000000000000..fbb613b304999f3676735757c4be4d327fae576e
--- /dev/null
+++ b/tests/libc/sys_sendfile_h.c
@@ -0,0 +1,23 @@
+#include <sys/sendfile.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+int main() {
+  int out_fd, in_fd;
+  in_fd = open("/tmp/in.txt", O_RDONLY);
+  if (in_fd == -1) return 1;
+  out_fd = open("/tmp/out.txt", O_CREAT, O_WRONLY);
+  if (out_fd == -1) return 1;
+  off_t offset = 0;
+  ssize_t r1, r2, r3;
+  r1 = sendfile(out_fd, in_fd, &offset, 42);
+  //@ assert -1 <= r1 <= 42;
+  int r = close(out_fd);
+  if (r) return 1;
+  out_fd = open("/tmp/out.txt", O_CREAT, O_WRONLY);
+  if (out_fd == -1) return 1;
+  r3 = sendfile(out_fd, in_fd, 0, 42);
+  close(out_fd);
+  close(in_fd);
+  return 0;
+}