[v3,2/4] libio: Remove the usage of __libc_IO_vtables

Message ID 20221227211145.3765256-3-adhemerval.zanella@linaro.org
State Superseded
Headers
Series Remove --with-default-link option |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent

Commit Message

Adhemerval Zanella Netto Dec. 27, 2022, 9:11 p.m. UTC
  Instead of using a special ELF section along with a linker script
directive to put the IO vtables within the RELRO section, the libio
vtables are iall moved to an array marked as data.relro (so linker
will place in the RELRO segment without the need of extra directives).

To avoid static linking namespace issues and to pulling all vtables
referenced objects, all required function pointers are set to weak alias.

Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
---
 Makerules                             |  24 --
 elf/Makefile                          |  16 +-
 include/libc-symbols.h                |  18 +-
 libio/Makefile                        |   2 +
 libio/fileops.c                       |  81 +----
 libio/iofopncook.c                    |  60 +---
 libio/iopopen.c                       |  25 --
 libio/libio-macros.sym                |   7 +
 libio/libioP.h                        | 136 +++++--
 libio/memstream.c                     |  32 +-
 libio/oldfileops.c                    |  23 --
 libio/oldiopopen.c                    |  23 --
 libio/stdio.c                         |   3 +
 libio/strfile.h                       |   2 -
 libio/strops.c                        |  24 --
 libio/tst-vtables-interposed.c        |   5 +
 libio/vtables.c                       | 497 ++++++++++++++++++++++++++
 libio/wfileops.c                      |  79 +---
 libio/wmemstream.c                    |  32 +-
 libio/wstrops.c                       |  24 --
 stdio-common/printf_buffer_as_file.c  |  28 +-
 stdio-common/wprintf_buffer_as_file.c |  28 +-
 22 files changed, 656 insertions(+), 513 deletions(-)
 create mode 100644 libio/libio-macros.sym
  

Comments

Carlos O'Donell March 4, 2023, 5:37 p.m. UTC | #1
On 12/27/22 16:11, Adhemerval Zanella via Libc-alpha wrote:
> Instead of using a special ELF section along with a linker script
> directive to put the IO vtables within the RELRO section, the libio
> vtables are iall moved to an array marked as data.relro (so linker

s/iall/all/g

> will place in the RELRO segment without the need of extra directives).
> 
> To avoid static linking namespace issues and to pulling all vtables

s/to pulling/including/g
s/vtables/vtable/g

> referenced objects, all required function pointers are set to weak alias.
>

Have you tested this against legacy applications that interpose the vtables?

In the original design Florian wrote:
~~~
    To enable backwards compatibility, a special flag variable
    (_IO_accept_foreign_vtables), protected by the pointer guard, avoids
    process termination if libio stream object constructor functions have
    been called earlier.  Such constructor functions are called by the GCC
    2.95 libstdc++ library, and this mechanism ensures compatibility with
    old binaries.  Existing callers inside glibc of these functions are
    adjusted to call the original functions, not the wrappers which enable
    vtable compatiblity.
    
    The compatibility mechanism is used to enable passing FILE * objects
    across a static dlopen boundary, too.
~~~

> Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
> ---
>  Makerules                             |  24 --
>  elf/Makefile                          |  16 +-
>  include/libc-symbols.h                |  18 +-
>  libio/Makefile                        |   2 +
>  libio/fileops.c                       |  81 +----
>  libio/iofopncook.c                    |  60 +---
>  libio/iopopen.c                       |  25 --
>  libio/libio-macros.sym                |   7 +
>  libio/libioP.h                        | 136 +++++--
>  libio/memstream.c                     |  32 +-
>  libio/oldfileops.c                    |  23 --
>  libio/oldiopopen.c                    |  23 --
>  libio/stdio.c                         |   3 +
>  libio/strfile.h                       |   2 -
>  libio/strops.c                        |  24 --
>  libio/tst-vtables-interposed.c        |   5 +
>  libio/vtables.c                       | 497 ++++++++++++++++++++++++++
>  libio/wfileops.c                      |  79 +---
>  libio/wmemstream.c                    |  32 +-
>  libio/wstrops.c                       |  24 --
>  stdio-common/printf_buffer_as_file.c  |  28 +-
>  stdio-common/wprintf_buffer_as_file.c |  28 +-
>  22 files changed, 656 insertions(+), 513 deletions(-)
>  create mode 100644 libio/libio-macros.sym
> 
> diff --git a/Makerules b/Makerules
> index 962b2cd90c..41fc8db4ba 100644
> --- a/Makerules
> +++ b/Makerules
> @@ -544,34 +544,10 @@ $(LINK.o) -shared -static-libgcc -Wl,-O1 $(sysdep-LDFLAGS) \
>  	  -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link)
>  endef
>  
> -ifeq (yes,$(use-default-link))
>  # If the linker is good enough, we can let it use its default linker script.
>  # In the long term the custom linker script will be removed.
>  shlib-lds =
>  shlib-lds-flags =
> -else
> -# binutils only position loadable notes into the first page for binaries,
> -# not for shared objects
> -# lld --verbose does not dump a linker script.  Use -fuse-ld=bfd.
> -$(common-objpfx)shlib.lds: $(common-objpfx)config.make $(..)Makerules
> -	$(LINK.o) -shared -Wl,-O1 \
> -		  -nostdlib -nostartfiles -fuse-ld=bfd \
> -		  $(sysdep-LDFLAGS) $(rtld-LDFLAGS) $(LDFLAGS.so) \
> -		  -Wl,--verbose 2>/dev/null | \
> -	  sed > $@T \
> -	      -e '/^=========/,/^=========/!d;/^=========/d' \
> -	      -e 's@^.*\*(\.jcr).*$$@& \
> -		 PROVIDE(__start___libc_IO_vtables = .);\
> -		 __libc_IO_vtables : { *(__libc_IO_vtables) }\
> -		 PROVIDE(__stop___libc_IO_vtables = .);\
> -		 /DISCARD/ : { *(.gnu.glibc-stub.*) }@'
> -	test -s $@T
> -	mv -f $@T $@
> -common-generated += shlib.lds
> -
> -shlib-lds = $(common-objpfx)shlib.lds
> -shlib-lds-flags = -T $(shlib-lds)
> -endif

OK.

>  
>  define build-shlib
>  $(build-shlib-helper) -o $@ $(shlib-lds-flags) \
> diff --git a/elf/Makefile b/elf/Makefile
> index 0ecbcde962..f5157030c4 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -595,23 +595,9 @@ $(objpfx)tst-relro-ldso.out: tst-relro-symbols.py $(..)/scripts/glibcelf.py \
>  $(objpfx)tst-relro-libc.out: tst-relro-symbols.py $(..)/scripts/glibcelf.py \
>    $(common-objpfx)libc.so
>  	$(PYTHON) tst-relro-symbols.py $(common-objpfx)libc.so \
> -	    --required=_IO_cookie_jumps \
>  	    --required=_IO_file_jumps \
> -	    --required=_IO_file_jumps_maybe_mmap \
> -	    --required=_IO_file_jumps_mmap \
> -	    --required=_IO_mem_jumps \
> -	    --required=_IO_printf_buffer_as_file_jumps \
> -	    --required=_IO_proc_jumps \
> -	    --required=_IO_str_jumps \
>  	    --required=_IO_wfile_jumps \
> -	    --required=_IO_wfile_jumps_maybe_mmap \
> -	    --required=_IO_wfile_jumps_mmap \
> -	    --required=_IO_wmem_jumps \
> -	    --required=_IO_wprintf_buffer_as_file_jumps \
> -	    --required=_IO_wstr_jumps \
> -	    --optional=_IO_old_cookie_jumps \
> -	    --optional=_IO_old_file_jumps \
> -	    --optional=_IO_old_proc_jumps \
> +	    --required=__io_vtables \

OK.

>  	  > $@ 2>&1; $(evaluate-test)
>  
>  ifeq ($(run-built-tests),yes)
> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> index a1d422131f..02fbfe91f0 100644
> --- a/include/libc-symbols.h
> +++ b/include/libc-symbols.h
> @@ -243,20 +243,26 @@ for linking")
>     This is only necessary when defining something in assembly, or playing
>     funny alias games where the size should be other than what the compiler
>     thinks it is.  */
> -#ifdef __ASSEMBLER__
> -# define declare_object_symbol_alias(symbol, original, size) \
> +#define declare_object_symbol_alias(symbol, original, size) \
>    declare_object_symbol_alias_1 (symbol, original, size)
> +#ifdef __ASSEMBLER__
>  # define declare_object_symbol_alias_1(symbol, original, s_size) \
>     strong_alias (original, symbol) ASM_LINE_SEP \
>     .type C_SYMBOL_NAME (symbol), %object ASM_LINE_SEP \
>     .size C_SYMBOL_NAME (symbol), s_size ASM_LINE_SEP
>  #else /* Not __ASSEMBLER__.  */
>  # ifdef HAVE_ASM_SET_DIRECTIVE
> -#  define declare_symbol_alias_1_alias(symbol, original) \
> -     ".set " __SYMBOL_PREFIX #symbol ", " __SYMBOL_PREFIX #original
> +#  define declare_object_symbol_alias_1(symbol, original, size) \
> +     asm (".global " __SYMBOL_PREFIX # symbol "\n" \
> +	  ".type " __SYMBOL_PREFIX # symbol ", %object\n" \
> +	  ".set " __SYMBOL_PREFIX #symbol ", " __SYMBOL_PREFIX original "\n" \
> +	  ".size " __SYMBOL_PREFIX #symbol ", " #size "\n");
>  # else
> -#  define declare_symbol_alias_1_alias(symbol, original) \
> -     __SYMBOL_PREFIX #symbol " = " __SYMBOL_PREFIX #original
> +#  define declare_object_symbol_alias_1(symbol, original, size) \
> +     asm (".global " __SYMBOL_PREFIX # symbol "\n" \
> +	  ".type " __SYMBOL_PREFIX # symbol ", %object\n" \
> +	  __SYMBOL_PREFIX #symbol " = " __SYMBOL_PREFIX original "\n" \
> +	  ".size " __SYMBOL_PREFIX #symbol ", " #size "\n");
>  # endif /* HAVE_ASM_SET_DIRECTIVE */
>  #endif /* __ASSEMBLER__ */
>  
> diff --git a/libio/Makefile b/libio/Makefile
> index 64398ab1ee..fc67aea9e2 100644
> --- a/libio/Makefile
> +++ b/libio/Makefile
> @@ -51,6 +51,8 @@ routines	:=							      \
>  									      \
>  	libc_fatal fmemopen oldfmemopen vtables
>  
> +gen-as-const-headers += libio-macros.sym
> +
>  tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc   \
>  	tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-ext2 \
>  	tst-fgetws tst-ungetwc1 tst-ungetwc2 tst-swscanf tst-sscanf	      \
> diff --git a/libio/fileops.c b/libio/fileops.c
> index 41c18be789..87027d5adb 100644
> --- a/libio/fileops.c
> +++ b/libio/fileops.c
> @@ -815,7 +815,7 @@ _IO_new_file_sync (FILE *fp)
>  }
>  libc_hidden_ver (_IO_new_file_sync, _IO_file_sync)
>  
> -static int
> +int
>  _IO_file_sync_mmap (FILE *fp)
>  {
>    if (fp->_IO_read_ptr != fp->_IO_read_end)
> @@ -1109,7 +1109,7 @@ _IO_file_seekoff_mmap (FILE *fp, off64_t offset, int dir, int mode)
>    return offset;
>  }
>  
> -static off64_t
> +off64_t
>  _IO_file_seekoff_maybe_mmap (FILE *fp, off64_t offset, int dir,
>  			     int mode)
>  {
> @@ -1360,7 +1360,7 @@ _IO_file_xsgetn (FILE *fp, void *data, size_t n)
>  }
>  libc_hidden_def (_IO_file_xsgetn)
>  
> -static size_t
> +size_t
>  _IO_file_xsgetn_mmap (FILE *fp, void *data, size_t n)
>  {
>    size_t have;
> @@ -1405,7 +1405,7 @@ _IO_file_xsgetn_mmap (FILE *fp, void *data, size_t n)
>    return s - (char *) data;
>  }
>  
> -static size_t
> +size_t
>  _IO_file_xsgetn_maybe_mmap (FILE *fp, void *data, size_t n)
>  {
>    /* We only get here if this is the first attempt to read something.
> @@ -1428,76 +1428,3 @@ versioned_symbol (libc, _IO_new_file_seekoff, _IO_file_seekoff, GLIBC_2_1);
>  versioned_symbol (libc, _IO_new_file_underflow, _IO_file_underflow, GLIBC_2_1);
>  versioned_symbol (libc, _IO_new_file_write, _IO_file_write, GLIBC_2_1);
>  versioned_symbol (libc, _IO_new_file_xsputn, _IO_file_xsputn, GLIBC_2_1);
> -
> -const struct _IO_jump_t _IO_file_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_file_finish),
> -  JUMP_INIT(overflow, _IO_file_overflow),
> -  JUMP_INIT(underflow, _IO_file_underflow),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_default_pbackfail),
> -  JUMP_INIT(xsputn, _IO_file_xsputn),
> -  JUMP_INIT(xsgetn, _IO_file_xsgetn),
> -  JUMP_INIT(seekoff, _IO_new_file_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_new_file_setbuf),
> -  JUMP_INIT(sync, _IO_new_file_sync),
> -  JUMP_INIT(doallocate, _IO_file_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_new_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_file_close),
> -  JUMP_INIT(stat, _IO_file_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> -libc_hidden_data_def (_IO_file_jumps)
> -
> -const struct _IO_jump_t _IO_file_jumps_mmap libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_file_finish),
> -  JUMP_INIT(overflow, _IO_file_overflow),
> -  JUMP_INIT(underflow, _IO_file_underflow_mmap),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_default_pbackfail),
> -  JUMP_INIT(xsputn, _IO_new_file_xsputn),
> -  JUMP_INIT(xsgetn, _IO_file_xsgetn_mmap),
> -  JUMP_INIT(seekoff, _IO_file_seekoff_mmap),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
> -  JUMP_INIT(sync, _IO_file_sync_mmap),
> -  JUMP_INIT(doallocate, _IO_file_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_new_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_file_close_mmap),
> -  JUMP_INIT(stat, _IO_file_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> -
> -const struct _IO_jump_t _IO_file_jumps_maybe_mmap libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_file_finish),
> -  JUMP_INIT(overflow, _IO_file_overflow),
> -  JUMP_INIT(underflow, _IO_file_underflow_maybe_mmap),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_default_pbackfail),
> -  JUMP_INIT(xsputn, _IO_new_file_xsputn),
> -  JUMP_INIT(xsgetn, _IO_file_xsgetn_maybe_mmap),
> -  JUMP_INIT(seekoff, _IO_file_seekoff_maybe_mmap),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
> -  JUMP_INIT(sync, _IO_new_file_sync),
> -  JUMP_INIT(doallocate, _IO_file_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_new_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_file_close),
> -  JUMP_INIT(stat, _IO_file_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> diff --git a/libio/iofopncook.c b/libio/iofopncook.c
> index 6c27610319..338cb31c79 100644
> --- a/libio/iofopncook.c
> +++ b/libio/iofopncook.c
> @@ -30,7 +30,7 @@
>  #include <shlib-compat.h>
>  #include <pointer_guard.h>
>  
> -static ssize_t
> +ssize_t
>  _IO_cookie_read (FILE *fp, void *buf, ssize_t size)
>  {
>    struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
> @@ -43,7 +43,7 @@ _IO_cookie_read (FILE *fp, void *buf, ssize_t size)
>    return read_cb (cfile->__cookie, buf, size);
>  }
>  
> -static ssize_t
> +ssize_t
>  _IO_cookie_write (FILE *fp, const void *buf, ssize_t size)
>  {
>    struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
> @@ -63,7 +63,7 @@ _IO_cookie_write (FILE *fp, const void *buf, ssize_t size)
>    return n;
>  }
>  
> -static off64_t
> +off64_t
>  _IO_cookie_seek (FILE *fp, off64_t offset, int dir)
>  {
>    struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
> @@ -77,7 +77,7 @@ _IO_cookie_seek (FILE *fp, off64_t offset, int dir)
>  	  ? _IO_pos_BAD : offset);
>  }
>  
> -static int
> +int
>  _IO_cookie_close (FILE *fp)
>  {
>    struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
> @@ -91,7 +91,7 @@ _IO_cookie_close (FILE *fp)
>  }
>  
>  
> -static off64_t
> +off64_t
>  _IO_cookie_seekoff (FILE *fp, off64_t offset, int dir, int mode)
>  {
>    /* We must force the fileops code to always use seek to determine
> @@ -100,31 +100,6 @@ _IO_cookie_seekoff (FILE *fp, off64_t offset, int dir, int mode)
>    return _IO_file_seekoff (fp, offset, dir, mode);
>  }
>  
> -
> -static const struct _IO_jump_t _IO_cookie_jumps libio_vtable = {
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_file_finish),
> -  JUMP_INIT(overflow, _IO_file_overflow),
> -  JUMP_INIT(underflow, _IO_file_underflow),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_default_pbackfail),
> -  JUMP_INIT(xsputn, _IO_file_xsputn),
> -  JUMP_INIT(xsgetn, _IO_default_xsgetn),
> -  JUMP_INIT(seekoff, _IO_cookie_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_file_setbuf),
> -  JUMP_INIT(sync, _IO_file_sync),
> -  JUMP_INIT(doallocate, _IO_file_doallocate),
> -  JUMP_INIT(read, _IO_cookie_read),
> -  JUMP_INIT(write, _IO_cookie_write),
> -  JUMP_INIT(seek, _IO_cookie_seek),
> -  JUMP_INIT(close, _IO_cookie_close),
> -  JUMP_INIT(stat, _IO_default_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue),
> -};
> -
> -
>  /* Copy the callbacks from SOURCE to *TARGET, with pointer
>     mangling.  */
>  static void
> @@ -209,7 +184,7 @@ versioned_symbol (libc, _IO_fopencookie, fopencookie, GLIBC_2_2);
>  
>  #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
>  
> -static off64_t
> +off64_t
>  attribute_compat_text_section
>  _IO_old_cookie_seek (FILE *fp, off64_t offset, int dir)
>  {
> @@ -226,29 +201,6 @@ _IO_old_cookie_seek (FILE *fp, off64_t offset, int dir)
>    return (ret == -1) ? _IO_pos_BAD : ret;
>  }
>  
> -static const struct _IO_jump_t _IO_old_cookie_jumps libio_vtable = {
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_file_finish),
> -  JUMP_INIT(overflow, _IO_file_overflow),
> -  JUMP_INIT(underflow, _IO_file_underflow),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_default_pbackfail),
> -  JUMP_INIT(xsputn, _IO_file_xsputn),
> -  JUMP_INIT(xsgetn, _IO_default_xsgetn),
> -  JUMP_INIT(seekoff, _IO_cookie_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_file_setbuf),
> -  JUMP_INIT(sync, _IO_file_sync),
> -  JUMP_INIT(doallocate, _IO_file_doallocate),
> -  JUMP_INIT(read, _IO_cookie_read),
> -  JUMP_INIT(write, _IO_cookie_write),
> -  JUMP_INIT(seek, _IO_old_cookie_seek),
> -  JUMP_INIT(close, _IO_cookie_close),
> -  JUMP_INIT(stat, _IO_default_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue),
> -};
> -
>  FILE *
>  attribute_compat_text_section
>  _IO_old_fopencookie (void *cookie, const char *mode,
> diff --git a/libio/iopopen.c b/libio/iopopen.c
> index 06778cf110..5ed30a817b 100644
> --- a/libio/iopopen.c
> +++ b/libio/iopopen.c
> @@ -45,8 +45,6 @@ struct _IO_proc_file
>  };
>  typedef struct _IO_proc_file _IO_proc_file;
>  
> -static const struct _IO_jump_t _IO_proc_jumps;
> -
>  static struct _IO_proc_file *proc_file_chain;
>  
>  #ifdef _IO_MTSAFE_IO
> @@ -291,29 +289,6 @@ _IO_new_proc_close (FILE *fp)
>    return wstatus;
>  }
>  
> -static const struct _IO_jump_t _IO_proc_jumps libio_vtable = {
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_new_file_finish),
> -  JUMP_INIT(overflow, _IO_new_file_overflow),
> -  JUMP_INIT(underflow, _IO_new_file_underflow),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_default_pbackfail),
> -  JUMP_INIT(xsputn, _IO_new_file_xsputn),
> -  JUMP_INIT(xsgetn, _IO_default_xsgetn),
> -  JUMP_INIT(seekoff, _IO_new_file_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_new_file_setbuf),
> -  JUMP_INIT(sync, _IO_new_file_sync),
> -  JUMP_INIT(doallocate, _IO_file_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_new_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_new_proc_close),
> -  JUMP_INIT(stat, _IO_file_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> -
>  strong_alias (_IO_new_popen, __new_popen)
>  versioned_symbol (libc, _IO_new_popen, _IO_popen, GLIBC_2_1);
>  versioned_symbol (libc, __new_popen, popen, GLIBC_2_1);
> diff --git a/libio/libio-macros.sym b/libio/libio-macros.sym
> new file mode 100644
> index 0000000000..cfb5cf2841
> --- /dev/null
> +++ b/libio/libio-macros.sym
> @@ -0,0 +1,7 @@
> +#include <libioP.h>
> +
> +--
> +
> +IO_JUMP_T_SIZE		sizeof (struct _IO_jump_t)
> +IO_FILE_JUMPS_OFFSET	sizeof (struct _IO_jump_t) * IO_FILE_JUMPS
> +IO_WFILE_JUMPS_OFFSET	sizeof (struct _IO_jump_t) * IO_WFILE_JUMPS
> diff --git a/libio/libioP.h b/libio/libioP.h
> index 8500c75fa0..523bd577ae 100644
> --- a/libio/libioP.h
> +++ b/libio/libioP.h
> @@ -469,19 +469,68 @@ extern int _IO_default_sync (FILE *) __THROW;
>  extern int _IO_default_showmanyc (FILE *) __THROW;
>  extern void _IO_default_imbue (FILE *, void *) __THROW;
>  
> -extern const struct _IO_jump_t _IO_file_jumps;
> -libc_hidden_proto (_IO_file_jumps)
> -extern const struct _IO_jump_t _IO_file_jumps_mmap attribute_hidden;
> -extern const struct _IO_jump_t _IO_file_jumps_maybe_mmap attribute_hidden;
> -extern const struct _IO_jump_t _IO_wfile_jumps;
> -libc_hidden_proto (_IO_wfile_jumps)
> -extern const struct _IO_jump_t _IO_wfile_jumps_mmap attribute_hidden;
> -extern const struct _IO_jump_t _IO_wfile_jumps_maybe_mmap attribute_hidden;
> -extern const struct _IO_jump_t _IO_old_file_jumps attribute_hidden;
> -extern const struct _IO_jump_t _IO_streambuf_jumps;
> -extern const struct _IO_jump_t _IO_old_proc_jumps attribute_hidden;
> -extern const struct _IO_jump_t _IO_str_jumps attribute_hidden;
> -extern const struct _IO_jump_t _IO_wstr_jumps attribute_hidden;
> +extern int __printf_buffer_as_file_overflow (FILE *fp, int ch);
> +extern size_t __printf_buffer_as_file_xsputn (FILE *fp, const void *buf,
> +					      size_t len);
> +extern wint_t __wprintf_buffer_as_file_overflow (FILE *fp, int ch);
> +extern size_t __wprintf_buffer_as_file_xsputn (FILE *fp, const void *buf,
> +					       size_t len);
> +
> +enum
> +{
> +  IO_STR_JUMPS                    = 0,
> +  IO_WSTR_JUMPS                   = 1,
> +  IO_FILE_JUMPS                   = 2,
> +  IO_FILE_JUMPS_MMAP              = 3,
> +  IO_FILE_JUMPS_MAYBE_MMAP        = 4,
> +  IO_WFILE_JUMPS                  = 5,
> +  IO_WFILE_JUMPS_MMAP             = 6,
> +  IO_WFILE_JUMPS_MAYBE_MMAP       = 7,
> +  IO_COOKIE_JUMPS                 = 8,
> +  IO_PROC_JUMPS                   = 9,
> +  IO_MEM_JUMPS                    = 10,
> +  IO_WMEM_JUMPS                   = 11,
> +  IO_PRINTF_BUFFER_AS_FILE_JUMPS  = 12,
> +  IO_WPRINTF_BUFFER_AS_FILE_JUMPS = 13,
> +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
> +  IO_OLD_FILE_JUMPS               = 14,
> +  IO_OLD_PROC_JUMPS               = 15,
> +  IO_OLD_COOKIED_JUMPS            = 16,
> +  IO_VTABLES_NUM		  = IO_OLD_COOKIED_JUMPS + 1,
> +#elif SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
> +  IO_OLD_COOKIED_JUMPS            = 14,
> +  IO_VTABLES_NUM		  = IO_OLD_COOKIED_JUMPS + 1,
> +#else
> +  IO_VTABLES_NUM		  = IO_WPRINTF_BUFFER_AS_FILE_JUMPS + 1
> +#endif
> +};
> +#define IO_VTABLES_LEN (IO_VTABLES_NUM * sizeof (struct _IO_jump_t))
> +
> +extern const struct _IO_jump_t __io_vtables[] attribute_hidden;
> +#define _IO_str_jumps                    (__io_vtables[IO_STR_JUMPS])
> +#define _IO_wstr_jumps                   (__io_vtables[IO_WSTR_JUMPS])
> +#define _IO_file_jumps                   (__io_vtables[IO_FILE_JUMPS])
> +#define _IO_file_jumps_mmap              (__io_vtables[IO_FILE_JUMPS_MMAP])
> +#define _IO_file_jumps_maybe_mmap        (__io_vtables[IO_FILE_JUMPS_MAYBE_MMAP])
> +#define _IO_wfile_jumps                  (__io_vtables[IO_WFILE_JUMPS])
> +#define _IO_wfile_jumps_mmap             (__io_vtables[IO_WFILE_JUMPS_MMAP])
> +#define _IO_wfile_jumps_maybe_mmap       (__io_vtables[IO_WFILE_JUMPS_MAYBE_MMAP])
> +#define _IO_cookie_jumps                 (__io_vtables[IO_COOKIE_JUMPS])
> +#define _IO_proc_jumps                   (__io_vtables[IO_PROC_JUMPS])
> +#define _IO_mem_jumps                    (__io_vtables[IO_MEM_JUMPS])
> +#define _IO_wmem_jumps                   (__io_vtables[IO_WMEM_JUMPS])
> +#define _IO_printf_buffer_as_file_jumps  (__io_vtables[IO_PRINTF_BUFFER_AS_FILE_JUMPS])
> +#define _IO_wprintf_buffer_as_file_jumps (__io_vtables[IO_WPRINTF_BUFFER_AS_FILE_JUMPS])
> +#define _IO_old_file_jumps               (__io_vtables[IO_OLD_FILE_JUMPS])
> +#define _IO_old_proc_jumps               (__io_vtables[IO_OLD_PROC_JUMPS])
> +#define _IO_old_cookie_jumps             (__io_vtables[IO_OLD_COOKIED_JUMPS])
> +
> +#ifdef SHARED
> +# define libio_static_fn_required(name)
> +#else
> +# define libio_static_fn_required(name) __asm (".globl " #name);
> +#endif
> +
>  extern int _IO_do_write (FILE *, const char *, size_t);
>  libc_hidden_proto (_IO_do_write)
>  extern int _IO_new_do_write (FILE *, const char *, size_t);
> @@ -593,6 +642,14 @@ extern void _IO_new_file_init_internal (struct _IO_FILE_plus *)
>  extern FILE* _IO_new_file_setbuf (FILE *, char *, ssize_t);
>  extern FILE* _IO_file_setbuf_mmap (FILE *, char *, ssize_t);
>  extern int _IO_new_file_sync (FILE *);
> +extern int _IO_file_sync_mmap (FILE *) attribute_hidden;
> +extern size_t  _IO_file_xsgetn_maybe_mmap (FILE *fp, void *data, size_t n)
> +  attribute_hidden;
> +extern size_t _IO_file_xsgetn_mmap (FILE *fp, void *data, size_t n)
> +  attribute_hidden;
> +extern off64_t _IO_file_seekoff_maybe_mmap (FILE *fp, off64_t offset, int dir,
> +					    int mode)
> +     attribute_hidden;
>  extern int _IO_new_file_underflow (FILE *);
>  extern int _IO_new_file_overflow (FILE *, int);
>  extern off64_t _IO_new_file_seekoff (FILE *, off64_t, int, int);
> @@ -625,6 +682,10 @@ extern wint_t _IO_wfile_overflow (FILE *, wint_t);
>  libc_hidden_proto (_IO_wfile_overflow)
>  extern off64_t _IO_wfile_seekoff (FILE *, off64_t, int, int);
>  libc_hidden_proto (_IO_wfile_seekoff)
> +extern wint_t _IO_wfile_underflow_maybe_mmap (FILE *fp)
> +     attribute_hidden;
> +extern wint_t _IO_wfile_underflow_mmap (FILE *fp)
> +     attribute_hidden;
>  
>  /* Jumptable functions for proc_files. */
>  extern FILE* _IO_proc_open (FILE *, const char *, const char *)
> @@ -643,13 +704,41 @@ extern int _IO_str_overflow (FILE *, int) __THROW;
>  libc_hidden_proto (_IO_str_overflow)
>  extern int _IO_str_pbackfail (FILE *, int) __THROW;
>  libc_hidden_proto (_IO_str_pbackfail)
> -extern off64_t _IO_str_seekoff (FILE *, off64_t, int, int) __THROW;
> +extern off64_t _IO_str_seekoff (FILE *, off64_t, int, int) __THROW
> + ;
>  libc_hidden_proto (_IO_str_seekoff)
>  extern void _IO_str_finish (FILE *, int) __THROW;
> +extern int _IO_str_chk_overflow (FILE *fp, int c) __THROW
> +  attribute_hidden;
> +
> +/* Jumptable functions for fopencookie.  */
> +extern ssize_t _IO_cookie_read (FILE *fp, void *buf, ssize_t size)
> +  attribute_hidden;
> +extern ssize_t _IO_cookie_write (FILE *fp, const void *buf, ssize_t size)
> +  attribute_hidden;
> +extern off64_t _IO_cookie_seek (FILE *fp, off64_t offset, int dir)
> +  attribute_hidden;
> +extern int _IO_cookie_close (FILE *fp) attribute_hidden;
> +extern off64_t _IO_cookie_seekoff (FILE *fp, off64_t offset, int dir, int mode)
> +  attribute_hidden;
> +extern off64_t _IO_old_cookie_seek (FILE *fp, off64_t offset, int dir)
> +  attribute_hidden;
> +
> +/* Jumptable functions for obstack.  */
> +extern int __IO_obstack_overflow (FILE *fp, int c) attribute_hidden;
> +extern size_t __IO_obstack_xsputn (FILE *fp, const void *data, size_t n)
> +  attribute_hidden;
> +
> +/* Jumptable functions for open_{w}memstream.  */
> +extern int _IO_mem_sync (FILE* fp) __THROW attribute_hidden;
> +extern void _IO_mem_finish (FILE* fp, int) __THROW attribute_hidden;
> +extern int _IO_wmem_sync (FILE* fp) __THROW attribute_hidden;
> +extern void _IO_wmem_finish (FILE* fp, int) __THROW attribute_hidden;
>  
>  /* Other strfile functions */
>  struct _IO_strfile_;
>  extern ssize_t _IO_str_count (FILE *) __THROW;
> +extern int _IO_strn_overflow (FILE *fp, int c) __THROW attribute_hidden;
>  
>  /* And the wide character versions.  */
>  extern void _IO_wstr_init_static (FILE *, wchar_t *, size_t, wchar_t *)
> @@ -662,6 +751,10 @@ extern off64_t _IO_wstr_seekoff (FILE *, off64_t, int, int)
>  extern wint_t _IO_wstr_pbackfail (FILE *, wint_t) __THROW;
>  extern void _IO_wstr_finish (FILE *, int) __THROW;
>  
> +/* Helper functions.  */
> +int _IO_helper_overflow (FILE *s, int c);
> +int _IO_whelper_overflow (FILE *s, int c);
> +
>  /* Internal versions of v*printf that take an additional flags
>     parameter.  */
>  extern int __vfprintf_internal (FILE *fp, const char *format, va_list ap,
> @@ -891,14 +984,6 @@ _IO_acquire_lock_fct (FILE **p)
>    } while (0)
>  #endif
>  
> -/* Collect all vtables in a special section for vtable verification.
> -   These symbols cover the extent of this section.  */
> -symbol_set_declare (__libc_IO_vtables)
> -
> -/* libio vtables need to carry this attribute so that they pass
> -   validation.  */
> -#define libio_vtable __attribute__ ((section ("__libc_IO_vtables")))
> -
>  #ifdef SHARED
>  /* If equal to &_IO_vtable_check (with pointer guard protection),
>     unknown vtable pointers are valid.  This function pointer is solely
> @@ -933,12 +1018,9 @@ void _IO_vtable_check (void) attribute_hidden;
>  static inline const struct _IO_jump_t *
>  IO_validate_vtable (const struct _IO_jump_t *vtable)

OK.

>  {
> -  /* Fast path: The vtable pointer is within the __libc_IO_vtables
> -     section.  */
> -  uintptr_t section_length = __stop___libc_IO_vtables - __start___libc_IO_vtables;
>    uintptr_t ptr = (uintptr_t) vtable;
> -  uintptr_t offset = ptr - (uintptr_t) __start___libc_IO_vtables;
> -  if (__glibc_unlikely (offset >= section_length))
> +  uintptr_t offset = ptr - (uintptr_t) &__io_vtables;
> +  if (__glibc_unlikely (offset >= IO_VTABLES_LEN))
>      /* The vtable pointer is not in the expected section.  Use the
>         slow path, which will terminate the process if necessary.  */
>      _IO_vtable_check ();
> diff --git a/libio/memstream.c b/libio/memstream.c
> index 1ae8cd9544..b5b5254a34 100644
> --- a/libio/memstream.c
> +++ b/libio/memstream.c
> @@ -29,34 +29,6 @@ struct _IO_FILE_memstream
>  };
>  
>  
> -static int _IO_mem_sync (FILE* fp) __THROW;
> -static void _IO_mem_finish (FILE* fp, int) __THROW;
> -
> -
> -static const struct _IO_jump_t _IO_mem_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT (finish, _IO_mem_finish),
> -  JUMP_INIT (overflow, _IO_str_overflow),
> -  JUMP_INIT (underflow, _IO_str_underflow),
> -  JUMP_INIT (uflow, _IO_default_uflow),
> -  JUMP_INIT (pbackfail, _IO_str_pbackfail),
> -  JUMP_INIT (xsputn, _IO_default_xsputn),
> -  JUMP_INIT (xsgetn, _IO_default_xsgetn),
> -  JUMP_INIT (seekoff, _IO_str_seekoff),
> -  JUMP_INIT (seekpos, _IO_default_seekpos),
> -  JUMP_INIT (setbuf, _IO_default_setbuf),
> -  JUMP_INIT (sync, _IO_mem_sync),
> -  JUMP_INIT (doallocate, _IO_default_doallocate),
> -  JUMP_INIT (read, _IO_default_read),
> -  JUMP_INIT (write, _IO_default_write),
> -  JUMP_INIT (seek, _IO_default_seek),
> -  JUMP_INIT (close, _IO_default_close),
> -  JUMP_INIT (stat, _IO_default_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> -
>  /* Open a stream that writes into a malloc'd buffer that is expanded as
>     necessary.  *BUFLOC and *SIZELOC are updated with the buffer's location
>     and the number of characters written on fflush or fclose.  */
> @@ -105,7 +77,7 @@ libc_hidden_def (__open_memstream)
>  weak_alias (__open_memstream, open_memstream)
>  
>  
> -static int
> +int
>  _IO_mem_sync (FILE *fp)
>  {
>    struct _IO_FILE_memstream *mp = (struct _IO_FILE_memstream *) fp;
> @@ -123,7 +95,7 @@ _IO_mem_sync (FILE *fp)
>  }
>  
>  
> -static void
> +void
>  _IO_mem_finish (FILE *fp, int dummy)
>  {
>    struct _IO_FILE_memstream *mp = (struct _IO_FILE_memstream *) fp;
> diff --git a/libio/oldfileops.c b/libio/oldfileops.c
> index ea3b864447..371c7479c6 100644
> --- a/libio/oldfileops.c
> +++ b/libio/oldfileops.c
> @@ -716,29 +716,6 @@ _IO_old_file_xsputn (FILE *f, const void *data, size_t n)
>    return n - to_do;
>  }
>  
> -
> -const struct _IO_jump_t _IO_old_file_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_old_file_finish),
> -  JUMP_INIT(overflow, _IO_old_file_overflow),
> -  JUMP_INIT(underflow, _IO_old_file_underflow),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_default_pbackfail),
> -  JUMP_INIT(xsputn, _IO_old_file_xsputn),
> -  JUMP_INIT(xsgetn, _IO_default_xsgetn),
> -  JUMP_INIT(seekoff, _IO_old_file_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_old_file_setbuf),
> -  JUMP_INIT(sync, _IO_old_file_sync),
> -  JUMP_INIT(doallocate, _IO_file_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_old_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_file_close),
> -  JUMP_INIT(stat, _IO_file_stat)
> -};
> -
>  compat_symbol (libc, _IO_old_do_write, _IO_do_write, GLIBC_2_0);
>  compat_symbol (libc, _IO_old_file_attach, _IO_file_attach, GLIBC_2_0);
>  compat_symbol (libc, _IO_old_file_close_it, _IO_file_close_it, GLIBC_2_0);
> diff --git a/libio/oldiopopen.c b/libio/oldiopopen.c
> index f9149413e8..206a0f3858 100644
> --- a/libio/oldiopopen.c
> +++ b/libio/oldiopopen.c
> @@ -208,29 +208,6 @@ _IO_old_proc_close (FILE *fp)
>    return wstatus;
>  }
>  
> -const struct _IO_jump_t _IO_old_proc_jumps libio_vtable = {
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_old_file_finish),
> -  JUMP_INIT(overflow, _IO_old_file_overflow),
> -  JUMP_INIT(underflow, _IO_old_file_underflow),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_default_pbackfail),
> -  JUMP_INIT(xsputn, _IO_old_file_xsputn),
> -  JUMP_INIT(xsgetn, _IO_default_xsgetn),
> -  JUMP_INIT(seekoff, _IO_old_file_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_old_file_setbuf),
> -  JUMP_INIT(sync, _IO_old_file_sync),
> -  JUMP_INIT(doallocate, _IO_file_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_old_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_old_proc_close),
> -  JUMP_INIT(stat, _IO_file_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> -
>  strong_alias (_IO_old_popen, __old_popen)
>  compat_symbol (libc, _IO_old_popen, _IO_popen, GLIBC_2_0);
>  compat_symbol (libc, __old_popen, popen, GLIBC_2_0);
> diff --git a/libio/stdio.c b/libio/stdio.c
> index e65ee86b24..356d41d277 100644
> --- a/libio/stdio.c
> +++ b/libio/stdio.c
> @@ -33,3 +33,6 @@
>  FILE *stdin = (FILE *) &_IO_2_1_stdin_;
>  FILE *stdout = (FILE *) &_IO_2_1_stdout_;
>  FILE *stderr = (FILE *) &_IO_2_1_stderr_;
> +
> +libio_static_fn_required (_IO_file_open);
> +libio_static_fn_required (_IO_file_doallocate);
> diff --git a/libio/strfile.h b/libio/strfile.h
> index b7a57317d0..f2ce1ff6f3 100644
> --- a/libio/strfile.h
> +++ b/libio/strfile.h
> @@ -78,8 +78,6 @@ typedef struct
>    wchar_t overflow_buf[64];
>  } _IO_wstrnfile;
>  
> -extern const struct _IO_jump_t _IO_wstrn_jumps attribute_hidden;
> -
>  /* Initialize an _IO_strfile SF to read from narrow string STRING, and
>     return the corresponding FILE object.  It is not necessary to fclose
>     the FILE when it is no longer needed.  */
> diff --git a/libio/strops.c b/libio/strops.c
> index 1cd0bf6c3d..4e2243b8d9 100644
> --- a/libio/strops.c
> +++ b/libio/strops.c
> @@ -352,27 +352,3 @@ _IO_str_finish (FILE *fp, int dummy)
>  
>    _IO_default_finish (fp, 0);
>  }
> -
> -const struct _IO_jump_t _IO_str_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_str_finish),
> -  JUMP_INIT(overflow, _IO_str_overflow),
> -  JUMP_INIT(underflow, _IO_str_underflow),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_str_pbackfail),
> -  JUMP_INIT(xsputn, _IO_default_xsputn),
> -  JUMP_INIT(xsgetn, _IO_default_xsgetn),
> -  JUMP_INIT(seekoff, _IO_str_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_default_setbuf),
> -  JUMP_INIT(sync, _IO_default_sync),
> -  JUMP_INIT(doallocate, _IO_default_doallocate),
> -  JUMP_INIT(read, _IO_default_read),
> -  JUMP_INIT(write, _IO_default_write),
> -  JUMP_INIT(seek, _IO_default_seek),
> -  JUMP_INIT(close, _IO_default_close),
> -  JUMP_INIT(stat, _IO_default_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> diff --git a/libio/tst-vtables-interposed.c b/libio/tst-vtables-interposed.c
> index 9d03fa0ec2..66f79dddb5 100644
> --- a/libio/tst-vtables-interposed.c
> +++ b/libio/tst-vtables-interposed.c
> @@ -21,7 +21,12 @@
>  /* Provide an interposed definition of the standard file handles with
>     our own vtable.  stdout/stdin/stderr will not work as a result, but
>     a succesful test does not print anything, so this is fine.  */
> +#include "libioP.h"
> +#undef _IO_file_jumps
>  #define _IO_file_jumps jumps
> +#undef _IO_wfile_jumps
> +extern const struct _IO_jump_t _IO_wfile_jumps;
> +#define _IO_wfile_jumps _IO_wfile_jumps
>  #include "stdfiles.c"
>  
>  static int
> diff --git a/libio/vtables.c b/libio/vtables.c
> index e3809c28ce..2a652e0ba9 100644
> --- a/libio/vtables.c
> +++ b/libio/vtables.c
> @@ -21,6 +21,491 @@
>  #include <stdio.h>
>  #include <ldsodefs.h>
>  #include <pointer_guard.h>
> +#include <libio-macros.h>
> +
> +/* Bot _IO_str_* and _IO_new_file functiosn are pulled into every link (from
> +   stdio initialization).  */
> +#ifndef SHARED
> +# pragma weak _IO_default_close
> +# pragma weak _IO_default_doallocate
> +# pragma weak _IO_default_imbue
> +# pragma weak _IO_default_pbackfail
> +# pragma weak _IO_default_read
> +# pragma weak _IO_default_seek
> +# pragma weak _IO_default_seekpos
> +# pragma weak _IO_default_setbuf
> +# pragma weak _IO_default_showmanyc
> +# pragma weak _IO_default_stat
> +# pragma weak _IO_default_sync
> +# pragma weak _IO_default_uflow
> +# pragma weak _IO_default_write
> +# pragma weak _IO_default_xsgetn
> +# pragma weak _IO_default_xsputn
> +
> +# pragma weak _IO_wdefault_pbackfail
> +# pragma weak _IO_wdefault_uflow
> +# pragma weak _IO_wdefault_doallocate
> +# pragma weak _IO_wdefault_xsgetn
> +# pragma weak _IO_wdefault_xsputn
> +
> +# pragma weak _IO_wstr_finish
> +# pragma weak _IO_wstr_overflow
> +# pragma weak _IO_wstr_pbackfail
> +# pragma weak _IO_wstr_seekoff
> +# pragma weak _IO_wstr_underflow
> +
> +# pragma weak _IO_file_close
> +# pragma weak _IO_file_close_mmap
> +# pragma weak _IO_file_doallocate
> +# pragma weak _IO_file_finish
> +# pragma weak _IO_file_jumps_alia
> +# pragma weak _IO_file_overflow
> +# pragma weak _IO_file_read
> +# pragma weak _IO_file_seek
> +# pragma weak _IO_file_seekoff_maybe_mmap
> +# pragma weak _IO_file_seekoff_mmap
> +# pragma weak _IO_file_setbuf
> +# pragma weak _IO_file_setbuf_mmap
> +# pragma weak _IO_file_setbuf_mmap
> +# pragma weak _IO_file_stat
> +# pragma weak _IO_file_sync
> +# pragma weak _IO_file_sync_mmap
> +# pragma weak _IO_file_underflow
> +# pragma weak _IO_file_underflow_maybe_mmap
> +# pragma weak _IO_file_underflow_mmap
> +# pragma weak _IO_file_xsgetn
> +# pragma weak _IO_file_xsgetn_maybe_mmap
> +# pragma weak _IO_file_xsgetn_mmap
> +# pragma weak _IO_file_xsputn
> +
> +# pragma weak _IO_wfile_overflow
> +# pragma weak _IO_wfile_sync
> +# pragma weak _IO_wfile_underflow
> +# pragma weak _IO_wfile_underflow_maybe_mmap
> +# pragma weak _IO_wfile_underflow_mmap
> +# pragma weak _IO_wfile_doallocate
> +# pragma weak _IO_wfile_jumps_alia
> +# pragma weak _IO_wfile_seekoff
> +# pragma weak _IO_wfile_xsputn
> +
> +# pragma weak _IO_new_proc_close
> +
> +# pragma weak _IO_cookie_close
> +# pragma weak _IO_cookie_read
> +# pragma weak _IO_cookie_seek
> +# pragma weak _IO_cookie_seekoff
> +# pragma weak _IO_cookie_write
> +
> +# pragma weak _IO_mem_finish
> +# pragma weak _IO_mem_sync
> +
> +# pragma weak _IO_wmem_finish
> +# pragma weak _IO_wmem_sync
> +
> +# pragma weak __printf_buffer_as_file_overflow
> +# pragma weak __printf_buffer_as_file_xsputn
> +
> +# pragma weak __wprintf_buffer_as_file_overflow
> +# pragma weak __wprintf_buffer_as_file_xsputn
> +#endif
> +
> +const struct _IO_jump_t __io_vtables[IO_VTABLES_LEN] attribute_relro =
> +{
> +  /* _IO_str_jumps  */
> +  [IO_STR_JUMPS] =
> +  {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_str_finish),
> +    JUMP_INIT (overflow, _IO_str_overflow),
> +    JUMP_INIT (underflow, _IO_str_underflow),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_str_pbackfail),
> +    JUMP_INIT (xsputn, _IO_default_xsputn),
> +    JUMP_INIT (xsgetn, _IO_default_xsgetn),
> +    JUMP_INIT (seekoff, _IO_str_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_default_setbuf),
> +    JUMP_INIT (sync, _IO_default_sync),
> +    JUMP_INIT (doallocate, _IO_default_doallocate),
> +    JUMP_INIT (read, _IO_default_read),
> +    JUMP_INIT (write, _IO_default_write),
> +    JUMP_INIT (seek, _IO_default_seek),
> +    JUMP_INIT (close, _IO_default_close),
> +    JUMP_INIT (stat, _IO_default_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_wstr_jumps  */
> +  [IO_WSTR_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_wstr_finish),
> +    JUMP_INIT (overflow, (_IO_overflow_t) _IO_wstr_overflow),
> +    JUMP_INIT (underflow, (_IO_underflow_t) _IO_wstr_underflow),
> +    JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> +    JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
> +    JUMP_INIT (xsputn, _IO_wdefault_xsputn),
> +    JUMP_INIT (xsgetn, _IO_wdefault_xsgetn),
> +    JUMP_INIT (seekoff, _IO_wstr_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_default_setbuf),
> +    JUMP_INIT (sync, _IO_default_sync),
> +    JUMP_INIT (doallocate, _IO_wdefault_doallocate),
> +    JUMP_INIT (read, _IO_default_read),
> +    JUMP_INIT (write, _IO_default_write),
> +    JUMP_INIT (seek, _IO_default_seek),
> +    JUMP_INIT (close, _IO_default_close),
> +    JUMP_INIT (stat, _IO_default_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_file_jumps  */
> +  [IO_FILE_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_file_finish),
> +    JUMP_INIT (overflow, _IO_file_overflow),
> +    JUMP_INIT (underflow, _IO_file_underflow),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_default_pbackfail),
> +    JUMP_INIT (xsputn, _IO_file_xsputn),
> +    JUMP_INIT (xsgetn, _IO_file_xsgetn),
> +    JUMP_INIT (seekoff, _IO_new_file_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_new_file_setbuf),
> +    JUMP_INIT (sync, _IO_new_file_sync),
> +    JUMP_INIT (doallocate, _IO_file_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_new_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_file_close),
> +    JUMP_INIT (stat, _IO_file_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_file_jumps_mmap  */
> +  [IO_FILE_JUMPS_MMAP] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_file_finish),
> +    JUMP_INIT (overflow, _IO_file_overflow),
> +    JUMP_INIT (underflow, _IO_file_underflow_mmap),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_default_pbackfail),
> +    JUMP_INIT (xsputn, _IO_new_file_xsputn),
> +    JUMP_INIT (xsgetn, _IO_file_xsgetn_mmap),
> +    JUMP_INIT (seekoff, _IO_file_seekoff_mmap),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
> +    JUMP_INIT (sync, _IO_file_sync_mmap),
> +    JUMP_INIT (doallocate, _IO_file_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_new_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_file_close_mmap),
> +    JUMP_INIT (stat, _IO_file_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_file_jumps_maybe_mmap  */
> +  [IO_FILE_JUMPS_MAYBE_MMAP] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_file_finish),
> +    JUMP_INIT (overflow, _IO_file_overflow),
> +    JUMP_INIT (underflow, _IO_file_underflow_maybe_mmap),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_default_pbackfail),
> +    JUMP_INIT (xsputn, _IO_new_file_xsputn),
> +    JUMP_INIT (xsgetn, _IO_file_xsgetn_maybe_mmap),
> +    JUMP_INIT (seekoff, _IO_file_seekoff_maybe_mmap),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
> +    JUMP_INIT (sync, _IO_new_file_sync),
> +    JUMP_INIT (doallocate, _IO_file_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_new_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_file_close),
> +    JUMP_INIT (stat, _IO_file_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_wfile_jumps  */
> +  [IO_WFILE_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_new_file_finish),
> +    JUMP_INIT (overflow, (_IO_overflow_t) _IO_wfile_overflow),
> +    JUMP_INIT (underflow, (_IO_underflow_t) _IO_wfile_underflow),
> +    JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> +    JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
> +    JUMP_INIT (xsputn, _IO_wfile_xsputn),
> +    JUMP_INIT (xsgetn, _IO_file_xsgetn),
> +    JUMP_INIT (seekoff, _IO_wfile_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_new_file_setbuf),
> +    JUMP_INIT (sync, (_IO_sync_t) _IO_wfile_sync),
> +    JUMP_INIT (doallocate, _IO_wfile_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_new_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_file_close),
> +    JUMP_INIT (stat, _IO_file_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_wfile_jumps_mmap  */
> +  [IO_WFILE_JUMPS_MMAP] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_new_file_finish),
> +    JUMP_INIT (overflow, (_IO_overflow_t) _IO_wfile_overflow),
> +    JUMP_INIT (underflow, (_IO_underflow_t) _IO_wfile_underflow_mmap),
> +    JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> +    JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
> +    JUMP_INIT (xsputn, _IO_wfile_xsputn),
> +    JUMP_INIT (xsgetn, _IO_file_xsgetn),
> +    JUMP_INIT (seekoff, _IO_wfile_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_file_setbuf_mmap),
> +    JUMP_INIT (sync, (_IO_sync_t) _IO_wfile_sync),
> +    JUMP_INIT (doallocate, _IO_wfile_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_new_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_file_close_mmap),
> +    JUMP_INIT (stat, _IO_file_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_wfile_jumps_maybe_mmap  */
> +  [IO_WFILE_JUMPS_MAYBE_MMAP] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_new_file_finish),
> +    JUMP_INIT (overflow, (_IO_overflow_t) _IO_wfile_overflow),
> +    JUMP_INIT (underflow, (_IO_underflow_t) _IO_wfile_underflow_maybe_mmap),
> +    JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> +    JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
> +    JUMP_INIT (xsputn, _IO_wfile_xsputn),
> +    JUMP_INIT (xsgetn, _IO_file_xsgetn),
> +    JUMP_INIT (seekoff, _IO_wfile_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_file_setbuf_mmap),
> +    JUMP_INIT (sync, (_IO_sync_t) _IO_wfile_sync),
> +    JUMP_INIT (doallocate, _IO_wfile_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_new_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_file_close),
> +    JUMP_INIT (stat, _IO_file_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_cookie_jumps  */
> +  [IO_COOKIE_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_file_finish),
> +    JUMP_INIT (overflow, _IO_file_overflow),
> +    JUMP_INIT (underflow, _IO_file_underflow),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_default_pbackfail),
> +    JUMP_INIT (xsputn, _IO_file_xsputn),
> +    JUMP_INIT (xsgetn, _IO_default_xsgetn),
> +    JUMP_INIT (seekoff, _IO_cookie_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_file_setbuf),
> +    JUMP_INIT (sync, _IO_file_sync),
> +    JUMP_INIT (doallocate, _IO_file_doallocate),
> +    JUMP_INIT (read, _IO_cookie_read),
> +    JUMP_INIT (write, _IO_cookie_write),
> +    JUMP_INIT (seek, _IO_cookie_seek),
> +    JUMP_INIT (close, _IO_cookie_close),
> +    JUMP_INIT (stat, _IO_default_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue),
> +  },
> +  /* _IO_proc_jumps  */
> +  [IO_PROC_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_new_file_finish),
> +    JUMP_INIT (overflow, _IO_new_file_overflow),
> +    JUMP_INIT (underflow, _IO_new_file_underflow),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_default_pbackfail),
> +    JUMP_INIT (xsputn, _IO_new_file_xsputn),
> +    JUMP_INIT (xsgetn, _IO_default_xsgetn),
> +    JUMP_INIT (seekoff, _IO_new_file_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_new_file_setbuf),
> +    JUMP_INIT (sync, _IO_new_file_sync),
> +    JUMP_INIT (doallocate, _IO_file_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_new_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_new_proc_close),
> +    JUMP_INIT (stat, _IO_file_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_mem_jumps  */
> +  [IO_MEM_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_mem_finish),
> +    JUMP_INIT (overflow, _IO_str_overflow),
> +    JUMP_INIT (underflow, _IO_str_underflow),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_str_pbackfail),
> +    JUMP_INIT (xsputn, _IO_default_xsputn),
> +    JUMP_INIT (xsgetn, _IO_default_xsgetn),
> +    JUMP_INIT (seekoff, _IO_str_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_default_setbuf),
> +    JUMP_INIT (sync, _IO_mem_sync),
> +    JUMP_INIT (doallocate, _IO_default_doallocate),
> +    JUMP_INIT (read, _IO_default_read),
> +    JUMP_INIT (write, _IO_default_write),
> +    JUMP_INIT (seek, _IO_default_seek),
> +    JUMP_INIT (close, _IO_default_close),
> +    JUMP_INIT (stat, _IO_default_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_wmem_jumps  */
> +  [IO_WMEM_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_wmem_finish),
> +    JUMP_INIT (overflow, (_IO_overflow_t) _IO_wstr_overflow),
> +    JUMP_INIT (underflow, (_IO_underflow_t) _IO_wstr_underflow),
> +    JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> +    JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
> +    JUMP_INIT (xsputn, _IO_wdefault_xsputn),
> +    JUMP_INIT (xsgetn, _IO_wdefault_xsgetn),
> +    JUMP_INIT (seekoff, _IO_wstr_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_default_setbuf),
> +    JUMP_INIT (sync, _IO_wmem_sync),
> +    JUMP_INIT (doallocate, _IO_wdefault_doallocate),
> +    JUMP_INIT (read, _IO_default_read),
> +    JUMP_INIT (write, _IO_default_write),
> +    JUMP_INIT (seek, _IO_default_seek),
> +    JUMP_INIT (close, _IO_default_close),
> +    JUMP_INIT (stat, _IO_default_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  [IO_PRINTF_BUFFER_AS_FILE_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, NULL),
> +    JUMP_INIT (overflow, __printf_buffer_as_file_overflow),
> +    JUMP_INIT (underflow, NULL),
> +    JUMP_INIT (uflow, NULL),
> +    JUMP_INIT (pbackfail, NULL),
> +    JUMP_INIT (xsputn, __printf_buffer_as_file_xsputn),
> +    JUMP_INIT (xsgetn, NULL),
> +    JUMP_INIT (seekoff, NULL),
> +    JUMP_INIT (seekpos, NULL),
> +    JUMP_INIT (setbuf, NULL),
> +    JUMP_INIT (sync, NULL),
> +    JUMP_INIT (doallocate, NULL),
> +    JUMP_INIT (read, NULL),
> +    JUMP_INIT (write, NULL),
> +    JUMP_INIT (seek, NULL),
> +    JUMP_INIT (close, NULL),
> +    JUMP_INIT (stat, NULL),
> +    JUMP_INIT (showmanyc, NULL),
> +    JUMP_INIT (imbue, NULL)
> +  },
> +  [IO_WPRINTF_BUFFER_AS_FILE_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, NULL),
> +    JUMP_INIT (overflow, (_IO_overflow_t) __wprintf_buffer_as_file_overflow),
> +    JUMP_INIT (underflow, NULL),
> +    JUMP_INIT (uflow, NULL),
> +    JUMP_INIT (pbackfail, NULL),
> +    JUMP_INIT (xsputn, __wprintf_buffer_as_file_xsputn),
> +    JUMP_INIT (xsgetn, NULL),
> +    JUMP_INIT (seekoff, NULL),
> +    JUMP_INIT (seekpos, NULL),
> +    JUMP_INIT (setbuf, NULL),
> +    JUMP_INIT (sync, NULL),
> +    JUMP_INIT (doallocate, NULL),
> +    JUMP_INIT (read, NULL),
> +    JUMP_INIT (write, NULL),
> +    JUMP_INIT (seek, NULL),
> +    JUMP_INIT (close, NULL),
> +    JUMP_INIT (stat, NULL),
> +    JUMP_INIT (showmanyc, NULL),
> +    JUMP_INIT (imbue, NULL)
> +  },
> +
> +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
> +  /* _IO_old_file_jumps  */
> +  [IO_OLD_FILE_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_old_file_finish),
> +    JUMP_INIT (overflow, _IO_old_file_overflow),
> +    JUMP_INIT (underflow, _IO_old_file_underflow),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_default_pbackfail),
> +    JUMP_INIT (xsputn, _IO_old_file_xsputn),
> +    JUMP_INIT (xsgetn, _IO_default_xsgetn),
> +    JUMP_INIT (seekoff, _IO_old_file_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_old_file_setbuf),
> +    JUMP_INIT (sync, _IO_old_file_sync),
> +    JUMP_INIT (doallocate, _IO_file_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_old_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_file_close),
> +    JUMP_INIT (stat, _IO_file_stat)
> +  },
> +  /*  _IO_old_proc_jumps  */
> +  [IO_OLD_PROC_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_old_file_finish),
> +    JUMP_INIT (overflow, _IO_old_file_overflow),
> +    JUMP_INIT (underflow, _IO_old_file_underflow),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_default_pbackfail),
> +    JUMP_INIT (xsputn, _IO_old_file_xsputn),
> +    JUMP_INIT (xsgetn, _IO_default_xsgetn),
> +    JUMP_INIT (seekoff, _IO_old_file_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_old_file_setbuf),
> +    JUMP_INIT (sync, _IO_old_file_sync),
> +    JUMP_INIT (doallocate, _IO_file_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_old_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_old_proc_close),
> +    JUMP_INIT (stat, _IO_file_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +#endif
> +
> +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
> +  /* _IO_old_cookie_jumps  */
> +  [IO_OLD_COOKIED_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_file_finish),
> +    JUMP_INIT (overflow, _IO_file_overflow),
> +    JUMP_INIT (underflow, _IO_file_underflow),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_default_pbackfail),
> +    JUMP_INIT (xsputn, _IO_file_xsputn),
> +    JUMP_INIT (xsgetn, _IO_default_xsgetn),
> +    JUMP_INIT (seekoff, _IO_cookie_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_file_setbuf),
> +    JUMP_INIT (sync, _IO_file_sync),
> +    JUMP_INIT (doallocate, _IO_file_doallocate),
> +    JUMP_INIT (read, _IO_cookie_read),
> +    JUMP_INIT (write, _IO_cookie_write),
> +    JUMP_INIT (seek, _IO_old_cookie_seek),
> +    JUMP_INIT (close, _IO_cookie_close),
> +    JUMP_INIT (stat, _IO_default_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue),
> +  },
> +#endif
> +};
>  
>  #ifdef SHARED
>  
> @@ -82,3 +567,15 @@ check_stdfiles_vtables (void)
>      IO_set_accept_foreign_vtables (&_IO_vtable_check);
>  }
>  #endif
> +
> +#define STR(s)  XSTR(s)
> +#define XSTR(s) #s
> +
> +#undef _IO_file_jumps
> +#define _IO_file_jumps_alias  "__io_vtables + " STR(IO_FILE_JUMPS_OFFSET)
> +declare_object_symbol_alias (_IO_file_jumps, _IO_file_jumps_alias,
> +			     IO_JUMP_T_SIZE)
> +#undef _IO_wfile_jumps
> +#define _IO_wfile_jumps_alias  "__io_vtables + " STR(IO_WFILE_JUMPS_OFFSET)
> +declare_object_symbol_alias (_IO_wfile_jumps, _IO_wfile_jumps_alias,
> +			     IO_JUMP_T_SIZE)
> diff --git a/libio/wfileops.c b/libio/wfileops.c
> index b59a98881f..f92d9b42eb 100644
> --- a/libio/wfileops.c
> +++ b/libio/wfileops.c
> @@ -328,7 +328,7 @@ _IO_wfile_underflow (FILE *fp)
>  libc_hidden_def (_IO_wfile_underflow)
>  
>  
> -static wint_t
> +wint_t
>  _IO_wfile_underflow_mmap (FILE *fp)
>  {
>    struct _IO_codecvt *cd;
> @@ -389,7 +389,7 @@ _IO_wfile_underflow_mmap (FILE *fp)
>    return WEOF;
>  }
>  
> -static wint_t
> +wint_t
>  _IO_wfile_underflow_maybe_mmap (FILE *fp)
>  {
>    /* This is the first read attempt.  Doing the underflow will choose mmap
> @@ -1017,78 +1017,3 @@ _IO_wfile_xsputn (FILE *f, const void *data, size_t n)
>    return n - to_do;
>  }
>  libc_hidden_def (_IO_wfile_xsputn)
> -
> -
> -const struct _IO_jump_t _IO_wfile_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_new_file_finish),
> -  JUMP_INIT(overflow, (_IO_overflow_t) _IO_wfile_overflow),
> -  JUMP_INIT(underflow, (_IO_underflow_t) _IO_wfile_underflow),
> -  JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> -  JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
> -  JUMP_INIT(xsputn, _IO_wfile_xsputn),
> -  JUMP_INIT(xsgetn, _IO_file_xsgetn),
> -  JUMP_INIT(seekoff, _IO_wfile_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_new_file_setbuf),
> -  JUMP_INIT(sync, (_IO_sync_t) _IO_wfile_sync),
> -  JUMP_INIT(doallocate, _IO_wfile_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_new_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_file_close),
> -  JUMP_INIT(stat, _IO_file_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> -libc_hidden_data_def (_IO_wfile_jumps)
> -
> -
> -const struct _IO_jump_t _IO_wfile_jumps_mmap libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_new_file_finish),
> -  JUMP_INIT(overflow, (_IO_overflow_t) _IO_wfile_overflow),
> -  JUMP_INIT(underflow, (_IO_underflow_t) _IO_wfile_underflow_mmap),
> -  JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> -  JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
> -  JUMP_INIT(xsputn, _IO_wfile_xsputn),
> -  JUMP_INIT(xsgetn, _IO_file_xsgetn),
> -  JUMP_INIT(seekoff, _IO_wfile_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_file_setbuf_mmap),
> -  JUMP_INIT(sync, (_IO_sync_t) _IO_wfile_sync),
> -  JUMP_INIT(doallocate, _IO_wfile_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_new_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_file_close_mmap),
> -  JUMP_INIT(stat, _IO_file_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> -
> -const struct _IO_jump_t _IO_wfile_jumps_maybe_mmap libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_new_file_finish),
> -  JUMP_INIT(overflow, (_IO_overflow_t) _IO_wfile_overflow),
> -  JUMP_INIT(underflow, (_IO_underflow_t) _IO_wfile_underflow_maybe_mmap),
> -  JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> -  JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
> -  JUMP_INIT(xsputn, _IO_wfile_xsputn),
> -  JUMP_INIT(xsgetn, _IO_file_xsgetn),
> -  JUMP_INIT(seekoff, _IO_wfile_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_file_setbuf_mmap),
> -  JUMP_INIT(sync, (_IO_sync_t) _IO_wfile_sync),
> -  JUMP_INIT(doallocate, _IO_wfile_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_new_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_file_close),
> -  JUMP_INIT(stat, _IO_file_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> diff --git a/libio/wmemstream.c b/libio/wmemstream.c
> index e7f898c7fb..50ad1bdc86 100644
> --- a/libio/wmemstream.c
> +++ b/libio/wmemstream.c
> @@ -30,34 +30,6 @@ struct _IO_FILE_wmemstream
>  };
>  
>  
> -static int _IO_wmem_sync (FILE* fp) __THROW;
> -static void _IO_wmem_finish (FILE* fp, int) __THROW;
> -
> -
> -static const struct _IO_jump_t _IO_wmem_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT (finish, _IO_wmem_finish),
> -  JUMP_INIT (overflow, (_IO_overflow_t) _IO_wstr_overflow),
> -  JUMP_INIT (underflow, (_IO_underflow_t) _IO_wstr_underflow),
> -  JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> -  JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
> -  JUMP_INIT (xsputn, _IO_wdefault_xsputn),
> -  JUMP_INIT (xsgetn, _IO_wdefault_xsgetn),
> -  JUMP_INIT (seekoff, _IO_wstr_seekoff),
> -  JUMP_INIT (seekpos, _IO_default_seekpos),
> -  JUMP_INIT (setbuf, _IO_default_setbuf),
> -  JUMP_INIT (sync, _IO_wmem_sync),
> -  JUMP_INIT (doallocate, _IO_wdefault_doallocate),
> -  JUMP_INIT (read, _IO_default_read),
> -  JUMP_INIT (write, _IO_default_write),
> -  JUMP_INIT (seek, _IO_default_seek),
> -  JUMP_INIT (close, _IO_default_close),
> -  JUMP_INIT (stat, _IO_default_stat),
> -  JUMP_INIT (showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT (imbue, _IO_default_imbue)
> -};
> -
>  /* Open a stream that writes into a malloc'd buffer that is expanded as
>     necessary.  *BUFLOC and *SIZELOC are updated with the buffer's location
>     and the number of characters written on fflush or fclose.  */
> @@ -105,7 +77,7 @@ open_wmemstream (wchar_t **bufloc, size_t *sizeloc)
>  }
>  
>  
> -static int
> +int
>  _IO_wmem_sync (FILE *fp)
>  {
>    struct _IO_FILE_wmemstream *mp = (struct _IO_FILE_wmemstream *) fp;
> @@ -124,7 +96,7 @@ _IO_wmem_sync (FILE *fp)
>  }
>  
>  
> -static void
> +void
>  _IO_wmem_finish (FILE *fp, int dummy)
>  {
>    struct _IO_FILE_wmemstream *mp = (struct _IO_FILE_wmemstream *) fp;
> diff --git a/libio/wstrops.c b/libio/wstrops.c
> index 2aec314937..ac7efe9f65 100644
> --- a/libio/wstrops.c
> +++ b/libio/wstrops.c
> @@ -361,27 +361,3 @@ _IO_wstr_finish (FILE *fp, int dummy)
>  
>    _IO_wdefault_finish (fp, 0);
>  }
> -
> -const struct _IO_jump_t _IO_wstr_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_wstr_finish),
> -  JUMP_INIT(overflow, (_IO_overflow_t) _IO_wstr_overflow),
> -  JUMP_INIT(underflow, (_IO_underflow_t) _IO_wstr_underflow),
> -  JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> -  JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
> -  JUMP_INIT(xsputn, _IO_wdefault_xsputn),
> -  JUMP_INIT(xsgetn, _IO_wdefault_xsgetn),
> -  JUMP_INIT(seekoff, _IO_wstr_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_default_setbuf),
> -  JUMP_INIT(sync, _IO_default_sync),
> -  JUMP_INIT(doallocate, _IO_wdefault_doallocate),
> -  JUMP_INIT(read, _IO_default_read),
> -  JUMP_INIT(write, _IO_default_write),
> -  JUMP_INIT(seek, _IO_default_seek),
> -  JUMP_INIT(close, _IO_default_close),
> -  JUMP_INIT(stat, _IO_default_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> diff --git a/stdio-common/printf_buffer_as_file.c b/stdio-common/printf_buffer_as_file.c
> index f27b000d78..cd36fa77e4 100644
> --- a/stdio-common/printf_buffer_as_file.c
> +++ b/stdio-common/printf_buffer_as_file.c
> @@ -48,7 +48,7 @@ __printf_buffer_as_file_switch_to_buffer (struct __printf_buffer_as_file *file)
>  /* Only a small subset of the vtable functions is implemented here,
>     following _IO_obstack_jumps.  */
>  
> -static int
> +int
>  __printf_buffer_as_file_overflow (FILE *fp, int ch)
>  {
>    struct __printf_buffer_as_file *file = (struct __printf_buffer_as_file *) fp;
> @@ -72,7 +72,7 @@ __printf_buffer_as_file_overflow (FILE *fp, int ch)
>      return EOF;
>  }
>  
> -static size_t
> +size_t
>  __printf_buffer_as_file_xsputn (FILE *fp, const void *buf, size_t len)
>  {
>    struct __printf_buffer_as_file *file = (struct __printf_buffer_as_file *) fp;
> @@ -93,30 +93,6 @@ __printf_buffer_as_file_xsputn (FILE *fp, const void *buf, size_t len)
>      return 0;
>  }
>  
> -static const struct _IO_jump_t _IO_printf_buffer_as_file_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, NULL),
> -  JUMP_INIT(overflow, __printf_buffer_as_file_overflow),
> -  JUMP_INIT(underflow, NULL),
> -  JUMP_INIT(uflow, NULL),
> -  JUMP_INIT(pbackfail, NULL),
> -  JUMP_INIT(xsputn, __printf_buffer_as_file_xsputn),
> -  JUMP_INIT(xsgetn, NULL),
> -  JUMP_INIT(seekoff, NULL),
> -  JUMP_INIT(seekpos, NULL),
> -  JUMP_INIT(setbuf, NULL),
> -  JUMP_INIT(sync, NULL),
> -  JUMP_INIT(doallocate, NULL),
> -  JUMP_INIT(read, NULL),
> -  JUMP_INIT(write, NULL),
> -  JUMP_INIT(seek, NULL),
> -  JUMP_INIT(close, NULL),
> -  JUMP_INIT(stat, NULL),
> -  JUMP_INIT(showmanyc, NULL),
> -  JUMP_INIT(imbue, NULL)
> -};
> -
>  void
>  __printf_buffer_as_file_init (struct __printf_buffer_as_file *file,
>                                struct __printf_buffer *next)
> diff --git a/stdio-common/wprintf_buffer_as_file.c b/stdio-common/wprintf_buffer_as_file.c
> index cd48a7d42a..f0d05f8b4a 100644
> --- a/stdio-common/wprintf_buffer_as_file.c
> +++ b/stdio-common/wprintf_buffer_as_file.c
> @@ -48,7 +48,7 @@ __wprintf_buffer_as_file_switch_to_buffer (struct __wprintf_buffer_as_file *file
>  /* Only a small subset of the vtable functions is implemented here,
>     following _IO_obstack_jumps.  */
>  
> -static wint_t
> +wint_t
>  __wprintf_buffer_as_file_overflow (FILE *fp, int ch)
>  {
>    struct __wprintf_buffer_as_file *file
> @@ -75,7 +75,7 @@ __wprintf_buffer_as_file_overflow (FILE *fp, int ch)
>      return WEOF;
>  }
>  
> -static size_t
> +size_t
>  __wprintf_buffer_as_file_xsputn (FILE *fp, const void *buf, size_t len)
>  {
>    struct __wprintf_buffer_as_file *file
> @@ -97,30 +97,6 @@ __wprintf_buffer_as_file_xsputn (FILE *fp, const void *buf, size_t len)
>      return 0;
>  }
>  
> -static const struct _IO_jump_t _IO_wprintf_buffer_as_file_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, NULL),
> -  JUMP_INIT(overflow, (_IO_overflow_t) __wprintf_buffer_as_file_overflow),
> -  JUMP_INIT(underflow, NULL),
> -  JUMP_INIT(uflow, NULL),
> -  JUMP_INIT(pbackfail, NULL),
> -  JUMP_INIT(xsputn, __wprintf_buffer_as_file_xsputn),
> -  JUMP_INIT(xsgetn, NULL),
> -  JUMP_INIT(seekoff, NULL),
> -  JUMP_INIT(seekpos, NULL),
> -  JUMP_INIT(setbuf, NULL),
> -  JUMP_INIT(sync, NULL),
> -  JUMP_INIT(doallocate, NULL),
> -  JUMP_INIT(read, NULL),
> -  JUMP_INIT(write, NULL),
> -  JUMP_INIT(seek, NULL),
> -  JUMP_INIT(close, NULL),
> -  JUMP_INIT(stat, NULL),
> -  JUMP_INIT(showmanyc, NULL),
> -  JUMP_INIT(imbue, NULL)
> -};
> -
>  void
>  __wprintf_buffer_as_file_init (struct __wprintf_buffer_as_file *file,
>                                 struct __wprintf_buffer *next)
  
Adhemerval Zanella Netto March 6, 2023, 1:43 p.m. UTC | #2
On 04/03/23 14:37, Carlos O'Donell wrote:
> On 12/27/22 16:11, Adhemerval Zanella via Libc-alpha wrote:
>> Instead of using a special ELF section along with a linker script
>> directive to put the IO vtables within the RELRO section, the libio
>> vtables are iall moved to an array marked as data.relro (so linker
> 
> s/iall/all/g
> 
>> will place in the RELRO segment without the need of extra directives).
>>
>> To avoid static linking namespace issues and to pulling all vtables
> 
> s/to pulling/including/g
> s/vtables/vtable/g
> 
>> referenced objects, all required function pointers are set to weak alias.
>>
> 
> Have you tested this against legacy applications that interpose the vtables?
> 
> In the original design Florian wrote:
> ~~~
>     To enable backwards compatibility, a special flag variable
>     (_IO_accept_foreign_vtables), protected by the pointer guard, avoids
>     process termination if libio stream object constructor functions have
>     been called earlier.  Such constructor functions are called by the GCC
>     2.95 libstdc++ library, and this mechanism ensures compatibility with
>     old binaries.  Existing callers inside glibc of these functions are
>     adjusted to call the original functions, not the wrappers which enable
>     vtable compatiblity.
>     
>     The compatibility mechanism is used to enable passing FILE * objects
>     across a static dlopen boundary, too.
> ~~~

I have not, but we do have tests for these (which was added after the
vtable hardening with 29055464a03c72762969a2e8734d0d05d4d70e58).  My
understanding is it should cover the required interface for old binaries.
  
Arsen Arsenović March 6, 2023, 2:58 p.m. UTC | #3
Hi Adhemerval,

Adhemerval Zanella via Libc-alpha <libc-alpha@sourceware.org> writes:

> Instead of using a special ELF section along with a linker script
> directive to put the IO vtables within the RELRO section, the libio
> vtables are iall moved to an array marked as data.relro (so linker
> will place in the RELRO segment without the need of extra directives).
>
> To avoid static linking namespace issues and to pulling all vtables
> referenced objects, all required function pointers are set to weak alias.
>
> Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
> ---
>  Makerules                             |  24 --
>  elf/Makefile                          |  16 +-
>  include/libc-symbols.h                |  18 +-
>  libio/Makefile                        |   2 +
>  libio/fileops.c                       |  81 +----
>  libio/iofopncook.c                    |  60 +---
>  libio/iopopen.c                       |  25 --
>  libio/libio-macros.sym                |   7 +
>  libio/libioP.h                        | 136 +++++--
>  libio/memstream.c                     |  32 +-
>  libio/oldfileops.c                    |  23 --
>  libio/oldiopopen.c                    |  23 --
>  libio/stdio.c                         |   3 +
>  libio/strfile.h                       |   2 -
>  libio/strops.c                        |  24 --
>  libio/tst-vtables-interposed.c        |   5 +
>  libio/vtables.c                       | 497 ++++++++++++++++++++++++++
>  libio/wfileops.c                      |  79 +---
>  libio/wmemstream.c                    |  32 +-
>  libio/wstrops.c                       |  24 --
>  stdio-common/printf_buffer_as_file.c  |  28 +-
>  stdio-common/wprintf_buffer_as_file.c |  28 +-
>  22 files changed, 656 insertions(+), 513 deletions(-)
>  create mode 100644 libio/libio-macros.sym
>
> diff --git a/Makerules b/Makerules
> index 962b2cd90c..41fc8db4ba 100644
> --- a/Makerules
> +++ b/Makerules
> @@ -544,34 +544,10 @@ $(LINK.o) -shared -static-libgcc -Wl,-O1 $(sysdep-LDFLAGS) \
>  	  -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link)
>  endef
>  
> -ifeq (yes,$(use-default-link))
>  # If the linker is good enough, we can let it use its default linker script.
>  # In the long term the custom linker script will be removed.
>  shlib-lds =
>  shlib-lds-flags =
> -else
> -# binutils only position loadable notes into the first page for binaries,
> -# not for shared objects
> -# lld --verbose does not dump a linker script.  Use -fuse-ld=bfd.
> -$(common-objpfx)shlib.lds: $(common-objpfx)config.make $(..)Makerules
> -	$(LINK.o) -shared -Wl,-O1 \
> -		  -nostdlib -nostartfiles -fuse-ld=bfd \
> -		  $(sysdep-LDFLAGS) $(rtld-LDFLAGS) $(LDFLAGS.so) \
> -		  -Wl,--verbose 2>/dev/null | \
> -	  sed > $@T \
> -	      -e '/^=========/,/^=========/!d;/^=========/d' \
> -	      -e 's@^.*\*(\.jcr).*$$@& \
> -		 PROVIDE(__start___libc_IO_vtables = .);\
> -		 __libc_IO_vtables : { *(__libc_IO_vtables) }\
> -		 PROVIDE(__stop___libc_IO_vtables = .);\
> -		 /DISCARD/ : { *(.gnu.glibc-stub.*) }@'
> -	test -s $@T
> -	mv -f $@T $@
> -common-generated += shlib.lds
> -
> -shlib-lds = $(common-objpfx)shlib.lds
> -shlib-lds-flags = -T $(shlib-lds)
> -endif
>  
>  define build-shlib
>  $(build-shlib-helper) -o $@ $(shlib-lds-flags) \
> diff --git a/elf/Makefile b/elf/Makefile
> index 0ecbcde962..f5157030c4 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -595,23 +595,9 @@ $(objpfx)tst-relro-ldso.out: tst-relro-symbols.py $(..)/scripts/glibcelf.py \
>  $(objpfx)tst-relro-libc.out: tst-relro-symbols.py $(..)/scripts/glibcelf.py \
>    $(common-objpfx)libc.so
>  	$(PYTHON) tst-relro-symbols.py $(common-objpfx)libc.so \
> -	    --required=_IO_cookie_jumps \
>  	    --required=_IO_file_jumps \
> -	    --required=_IO_file_jumps_maybe_mmap \
> -	    --required=_IO_file_jumps_mmap \
> -	    --required=_IO_mem_jumps \
> -	    --required=_IO_printf_buffer_as_file_jumps \
> -	    --required=_IO_proc_jumps \
> -	    --required=_IO_str_jumps \
>  	    --required=_IO_wfile_jumps \
> -	    --required=_IO_wfile_jumps_maybe_mmap \
> -	    --required=_IO_wfile_jumps_mmap \
> -	    --required=_IO_wmem_jumps \
> -	    --required=_IO_wprintf_buffer_as_file_jumps \
> -	    --required=_IO_wstr_jumps \
> -	    --optional=_IO_old_cookie_jumps \
> -	    --optional=_IO_old_file_jumps \
> -	    --optional=_IO_old_proc_jumps \
> +	    --required=__io_vtables \
>  	  > $@ 2>&1; $(evaluate-test)
>  
>  ifeq ($(run-built-tests),yes)
> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> index a1d422131f..02fbfe91f0 100644
> --- a/include/libc-symbols.h
> +++ b/include/libc-symbols.h
> @@ -243,20 +243,26 @@ for linking")
>     This is only necessary when defining something in assembly, or playing
>     funny alias games where the size should be other than what the compiler
>     thinks it is.  */
> -#ifdef __ASSEMBLER__
> -# define declare_object_symbol_alias(symbol, original, size) \
> +#define declare_object_symbol_alias(symbol, original, size) \
>    declare_object_symbol_alias_1 (symbol, original, size)
> +#ifdef __ASSEMBLER__
>  # define declare_object_symbol_alias_1(symbol, original, s_size) \
>     strong_alias (original, symbol) ASM_LINE_SEP \
>     .type C_SYMBOL_NAME (symbol), %object ASM_LINE_SEP \
>     .size C_SYMBOL_NAME (symbol), s_size ASM_LINE_SEP
>  #else /* Not __ASSEMBLER__.  */
>  # ifdef HAVE_ASM_SET_DIRECTIVE
> -#  define declare_symbol_alias_1_alias(symbol, original) \
> -     ".set " __SYMBOL_PREFIX #symbol ", " __SYMBOL_PREFIX #original
> +#  define declare_object_symbol_alias_1(symbol, original, size) \
> +     asm (".global " __SYMBOL_PREFIX # symbol "\n" \
> +	  ".type " __SYMBOL_PREFIX # symbol ", %object\n" \
> +	  ".set " __SYMBOL_PREFIX #symbol ", " __SYMBOL_PREFIX original "\n" \
> +	  ".size " __SYMBOL_PREFIX #symbol ", " #size "\n");
>  # else
> -#  define declare_symbol_alias_1_alias(symbol, original) \
> -     __SYMBOL_PREFIX #symbol " = " __SYMBOL_PREFIX #original
> +#  define declare_object_symbol_alias_1(symbol, original, size) \
> +     asm (".global " __SYMBOL_PREFIX # symbol "\n" \
> +	  ".type " __SYMBOL_PREFIX # symbol ", %object\n" \
> +	  __SYMBOL_PREFIX #symbol " = " __SYMBOL_PREFIX original "\n" \
> +	  ".size " __SYMBOL_PREFIX #symbol ", " #size "\n");
>  # endif /* HAVE_ASM_SET_DIRECTIVE */
>  #endif /* __ASSEMBLER__ */
>  
> diff --git a/libio/Makefile b/libio/Makefile
> index 64398ab1ee..fc67aea9e2 100644
> --- a/libio/Makefile
> +++ b/libio/Makefile
> @@ -51,6 +51,8 @@ routines	:=							      \
>  									      \
>  	libc_fatal fmemopen oldfmemopen vtables
>  
> +gen-as-const-headers += libio-macros.sym
> +
>  tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc   \
>  	tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-ext2 \
>  	tst-fgetws tst-ungetwc1 tst-ungetwc2 tst-swscanf tst-sscanf	      \
> diff --git a/libio/fileops.c b/libio/fileops.c
> index 41c18be789..87027d5adb 100644
> --- a/libio/fileops.c
> +++ b/libio/fileops.c
> @@ -815,7 +815,7 @@ _IO_new_file_sync (FILE *fp)
>  }
>  libc_hidden_ver (_IO_new_file_sync, _IO_file_sync)
>  
> -static int
> +int
>  _IO_file_sync_mmap (FILE *fp)
>  {
>    if (fp->_IO_read_ptr != fp->_IO_read_end)
> @@ -1109,7 +1109,7 @@ _IO_file_seekoff_mmap (FILE *fp, off64_t offset, int dir, int mode)
>    return offset;
>  }
>  
> -static off64_t
> +off64_t
>  _IO_file_seekoff_maybe_mmap (FILE *fp, off64_t offset, int dir,
>  			     int mode)
>  {
> @@ -1360,7 +1360,7 @@ _IO_file_xsgetn (FILE *fp, void *data, size_t n)
>  }
>  libc_hidden_def (_IO_file_xsgetn)
>  
> -static size_t
> +size_t
>  _IO_file_xsgetn_mmap (FILE *fp, void *data, size_t n)
>  {
>    size_t have;
> @@ -1405,7 +1405,7 @@ _IO_file_xsgetn_mmap (FILE *fp, void *data, size_t n)
>    return s - (char *) data;
>  }
>  
> -static size_t
> +size_t
>  _IO_file_xsgetn_maybe_mmap (FILE *fp, void *data, size_t n)
>  {
>    /* We only get here if this is the first attempt to read something.
> @@ -1428,76 +1428,3 @@ versioned_symbol (libc, _IO_new_file_seekoff, _IO_file_seekoff, GLIBC_2_1);
>  versioned_symbol (libc, _IO_new_file_underflow, _IO_file_underflow, GLIBC_2_1);
>  versioned_symbol (libc, _IO_new_file_write, _IO_file_write, GLIBC_2_1);
>  versioned_symbol (libc, _IO_new_file_xsputn, _IO_file_xsputn, GLIBC_2_1);
> -
> -const struct _IO_jump_t _IO_file_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_file_finish),
> -  JUMP_INIT(overflow, _IO_file_overflow),
> -  JUMP_INIT(underflow, _IO_file_underflow),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_default_pbackfail),
> -  JUMP_INIT(xsputn, _IO_file_xsputn),
> -  JUMP_INIT(xsgetn, _IO_file_xsgetn),
> -  JUMP_INIT(seekoff, _IO_new_file_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_new_file_setbuf),
> -  JUMP_INIT(sync, _IO_new_file_sync),
> -  JUMP_INIT(doallocate, _IO_file_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_new_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_file_close),
> -  JUMP_INIT(stat, _IO_file_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> -libc_hidden_data_def (_IO_file_jumps)
> -
> -const struct _IO_jump_t _IO_file_jumps_mmap libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_file_finish),
> -  JUMP_INIT(overflow, _IO_file_overflow),
> -  JUMP_INIT(underflow, _IO_file_underflow_mmap),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_default_pbackfail),
> -  JUMP_INIT(xsputn, _IO_new_file_xsputn),
> -  JUMP_INIT(xsgetn, _IO_file_xsgetn_mmap),
> -  JUMP_INIT(seekoff, _IO_file_seekoff_mmap),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
> -  JUMP_INIT(sync, _IO_file_sync_mmap),
> -  JUMP_INIT(doallocate, _IO_file_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_new_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_file_close_mmap),
> -  JUMP_INIT(stat, _IO_file_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> -
> -const struct _IO_jump_t _IO_file_jumps_maybe_mmap libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_file_finish),
> -  JUMP_INIT(overflow, _IO_file_overflow),
> -  JUMP_INIT(underflow, _IO_file_underflow_maybe_mmap),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_default_pbackfail),
> -  JUMP_INIT(xsputn, _IO_new_file_xsputn),
> -  JUMP_INIT(xsgetn, _IO_file_xsgetn_maybe_mmap),
> -  JUMP_INIT(seekoff, _IO_file_seekoff_maybe_mmap),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
> -  JUMP_INIT(sync, _IO_new_file_sync),
> -  JUMP_INIT(doallocate, _IO_file_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_new_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_file_close),
> -  JUMP_INIT(stat, _IO_file_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> diff --git a/libio/iofopncook.c b/libio/iofopncook.c
> index 6c27610319..338cb31c79 100644
> --- a/libio/iofopncook.c
> +++ b/libio/iofopncook.c
> @@ -30,7 +30,7 @@
>  #include <shlib-compat.h>
>  #include <pointer_guard.h>
>  
> -static ssize_t
> +ssize_t
>  _IO_cookie_read (FILE *fp, void *buf, ssize_t size)
>  {
>    struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
> @@ -43,7 +43,7 @@ _IO_cookie_read (FILE *fp, void *buf, ssize_t size)
>    return read_cb (cfile->__cookie, buf, size);
>  }
>  
> -static ssize_t
> +ssize_t
>  _IO_cookie_write (FILE *fp, const void *buf, ssize_t size)
>  {
>    struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
> @@ -63,7 +63,7 @@ _IO_cookie_write (FILE *fp, const void *buf, ssize_t size)
>    return n;
>  }
>  
> -static off64_t
> +off64_t
>  _IO_cookie_seek (FILE *fp, off64_t offset, int dir)
>  {
>    struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
> @@ -77,7 +77,7 @@ _IO_cookie_seek (FILE *fp, off64_t offset, int dir)
>  	  ? _IO_pos_BAD : offset);
>  }
>  
> -static int
> +int
>  _IO_cookie_close (FILE *fp)
>  {
>    struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
> @@ -91,7 +91,7 @@ _IO_cookie_close (FILE *fp)
>  }
>  
>  
> -static off64_t
> +off64_t
>  _IO_cookie_seekoff (FILE *fp, off64_t offset, int dir, int mode)
>  {
>    /* We must force the fileops code to always use seek to determine
> @@ -100,31 +100,6 @@ _IO_cookie_seekoff (FILE *fp, off64_t offset, int dir, int mode)
>    return _IO_file_seekoff (fp, offset, dir, mode);
>  }
>  
> -
> -static const struct _IO_jump_t _IO_cookie_jumps libio_vtable = {
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_file_finish),
> -  JUMP_INIT(overflow, _IO_file_overflow),
> -  JUMP_INIT(underflow, _IO_file_underflow),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_default_pbackfail),
> -  JUMP_INIT(xsputn, _IO_file_xsputn),
> -  JUMP_INIT(xsgetn, _IO_default_xsgetn),
> -  JUMP_INIT(seekoff, _IO_cookie_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_file_setbuf),
> -  JUMP_INIT(sync, _IO_file_sync),
> -  JUMP_INIT(doallocate, _IO_file_doallocate),
> -  JUMP_INIT(read, _IO_cookie_read),
> -  JUMP_INIT(write, _IO_cookie_write),
> -  JUMP_INIT(seek, _IO_cookie_seek),
> -  JUMP_INIT(close, _IO_cookie_close),
> -  JUMP_INIT(stat, _IO_default_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue),
> -};
> -
> -
>  /* Copy the callbacks from SOURCE to *TARGET, with pointer
>     mangling.  */
>  static void
> @@ -209,7 +184,7 @@ versioned_symbol (libc, _IO_fopencookie, fopencookie, GLIBC_2_2);
>  
>  #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
>  
> -static off64_t
> +off64_t
>  attribute_compat_text_section
>  _IO_old_cookie_seek (FILE *fp, off64_t offset, int dir)
>  {
> @@ -226,29 +201,6 @@ _IO_old_cookie_seek (FILE *fp, off64_t offset, int dir)
>    return (ret == -1) ? _IO_pos_BAD : ret;
>  }
>  
> -static const struct _IO_jump_t _IO_old_cookie_jumps libio_vtable = {
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_file_finish),
> -  JUMP_INIT(overflow, _IO_file_overflow),
> -  JUMP_INIT(underflow, _IO_file_underflow),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_default_pbackfail),
> -  JUMP_INIT(xsputn, _IO_file_xsputn),
> -  JUMP_INIT(xsgetn, _IO_default_xsgetn),
> -  JUMP_INIT(seekoff, _IO_cookie_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_file_setbuf),
> -  JUMP_INIT(sync, _IO_file_sync),
> -  JUMP_INIT(doallocate, _IO_file_doallocate),
> -  JUMP_INIT(read, _IO_cookie_read),
> -  JUMP_INIT(write, _IO_cookie_write),
> -  JUMP_INIT(seek, _IO_old_cookie_seek),
> -  JUMP_INIT(close, _IO_cookie_close),
> -  JUMP_INIT(stat, _IO_default_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue),
> -};
> -
>  FILE *
>  attribute_compat_text_section
>  _IO_old_fopencookie (void *cookie, const char *mode,
> diff --git a/libio/iopopen.c b/libio/iopopen.c
> index 06778cf110..5ed30a817b 100644
> --- a/libio/iopopen.c
> +++ b/libio/iopopen.c
> @@ -45,8 +45,6 @@ struct _IO_proc_file
>  };
>  typedef struct _IO_proc_file _IO_proc_file;
>  
> -static const struct _IO_jump_t _IO_proc_jumps;
> -
>  static struct _IO_proc_file *proc_file_chain;
>  
>  #ifdef _IO_MTSAFE_IO
> @@ -291,29 +289,6 @@ _IO_new_proc_close (FILE *fp)
>    return wstatus;
>  }
>  
> -static const struct _IO_jump_t _IO_proc_jumps libio_vtable = {
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_new_file_finish),
> -  JUMP_INIT(overflow, _IO_new_file_overflow),
> -  JUMP_INIT(underflow, _IO_new_file_underflow),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_default_pbackfail),
> -  JUMP_INIT(xsputn, _IO_new_file_xsputn),
> -  JUMP_INIT(xsgetn, _IO_default_xsgetn),
> -  JUMP_INIT(seekoff, _IO_new_file_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_new_file_setbuf),
> -  JUMP_INIT(sync, _IO_new_file_sync),
> -  JUMP_INIT(doallocate, _IO_file_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_new_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_new_proc_close),
> -  JUMP_INIT(stat, _IO_file_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> -
>  strong_alias (_IO_new_popen, __new_popen)
>  versioned_symbol (libc, _IO_new_popen, _IO_popen, GLIBC_2_1);
>  versioned_symbol (libc, __new_popen, popen, GLIBC_2_1);
> diff --git a/libio/libio-macros.sym b/libio/libio-macros.sym
> new file mode 100644
> index 0000000000..cfb5cf2841
> --- /dev/null
> +++ b/libio/libio-macros.sym
> @@ -0,0 +1,7 @@
> +#include <libioP.h>
> +
> +--
> +
> +IO_JUMP_T_SIZE		sizeof (struct _IO_jump_t)
> +IO_FILE_JUMPS_OFFSET	sizeof (struct _IO_jump_t) * IO_FILE_JUMPS
> +IO_WFILE_JUMPS_OFFSET	sizeof (struct _IO_jump_t) * IO_WFILE_JUMPS
> diff --git a/libio/libioP.h b/libio/libioP.h
> index 8500c75fa0..523bd577ae 100644
> --- a/libio/libioP.h
> +++ b/libio/libioP.h
> @@ -469,19 +469,68 @@ extern int _IO_default_sync (FILE *) __THROW;
>  extern int _IO_default_showmanyc (FILE *) __THROW;
>  extern void _IO_default_imbue (FILE *, void *) __THROW;
>  
> -extern const struct _IO_jump_t _IO_file_jumps;
> -libc_hidden_proto (_IO_file_jumps)
> -extern const struct _IO_jump_t _IO_file_jumps_mmap attribute_hidden;
> -extern const struct _IO_jump_t _IO_file_jumps_maybe_mmap attribute_hidden;
> -extern const struct _IO_jump_t _IO_wfile_jumps;
> -libc_hidden_proto (_IO_wfile_jumps)
> -extern const struct _IO_jump_t _IO_wfile_jumps_mmap attribute_hidden;
> -extern const struct _IO_jump_t _IO_wfile_jumps_maybe_mmap attribute_hidden;
> -extern const struct _IO_jump_t _IO_old_file_jumps attribute_hidden;
> -extern const struct _IO_jump_t _IO_streambuf_jumps;
> -extern const struct _IO_jump_t _IO_old_proc_jumps attribute_hidden;
> -extern const struct _IO_jump_t _IO_str_jumps attribute_hidden;
> -extern const struct _IO_jump_t _IO_wstr_jumps attribute_hidden;
> +extern int __printf_buffer_as_file_overflow (FILE *fp, int ch);
> +extern size_t __printf_buffer_as_file_xsputn (FILE *fp, const void *buf,
> +					      size_t len);
> +extern wint_t __wprintf_buffer_as_file_overflow (FILE *fp, int ch);
> +extern size_t __wprintf_buffer_as_file_xsputn (FILE *fp, const void *buf,
> +					       size_t len);
> +
> +enum
> +{
> +  IO_STR_JUMPS                    = 0,
> +  IO_WSTR_JUMPS                   = 1,
> +  IO_FILE_JUMPS                   = 2,
> +  IO_FILE_JUMPS_MMAP              = 3,
> +  IO_FILE_JUMPS_MAYBE_MMAP        = 4,
> +  IO_WFILE_JUMPS                  = 5,
> +  IO_WFILE_JUMPS_MMAP             = 6,
> +  IO_WFILE_JUMPS_MAYBE_MMAP       = 7,
> +  IO_COOKIE_JUMPS                 = 8,
> +  IO_PROC_JUMPS                   = 9,
> +  IO_MEM_JUMPS                    = 10,
> +  IO_WMEM_JUMPS                   = 11,
> +  IO_PRINTF_BUFFER_AS_FILE_JUMPS  = 12,
> +  IO_WPRINTF_BUFFER_AS_FILE_JUMPS = 13,
> +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
> +  IO_OLD_FILE_JUMPS               = 14,
> +  IO_OLD_PROC_JUMPS               = 15,
> +  IO_OLD_COOKIED_JUMPS            = 16,
> +  IO_VTABLES_NUM		  = IO_OLD_COOKIED_JUMPS + 1,
> +#elif SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
> +  IO_OLD_COOKIED_JUMPS            = 14,
> +  IO_VTABLES_NUM		  = IO_OLD_COOKIED_JUMPS + 1,
> +#else
> +  IO_VTABLES_NUM		  = IO_WPRINTF_BUFFER_AS_FILE_JUMPS + 1
> +#endif
> +};
> +#define IO_VTABLES_LEN (IO_VTABLES_NUM * sizeof (struct _IO_jump_t))
> +
> +extern const struct _IO_jump_t __io_vtables[] attribute_hidden;
> +#define _IO_str_jumps                    (__io_vtables[IO_STR_JUMPS])
> +#define _IO_wstr_jumps                   (__io_vtables[IO_WSTR_JUMPS])
> +#define _IO_file_jumps                   (__io_vtables[IO_FILE_JUMPS])
> +#define _IO_file_jumps_mmap              (__io_vtables[IO_FILE_JUMPS_MMAP])
> +#define _IO_file_jumps_maybe_mmap        (__io_vtables[IO_FILE_JUMPS_MAYBE_MMAP])
> +#define _IO_wfile_jumps                  (__io_vtables[IO_WFILE_JUMPS])
> +#define _IO_wfile_jumps_mmap             (__io_vtables[IO_WFILE_JUMPS_MMAP])
> +#define _IO_wfile_jumps_maybe_mmap       (__io_vtables[IO_WFILE_JUMPS_MAYBE_MMAP])
> +#define _IO_cookie_jumps                 (__io_vtables[IO_COOKIE_JUMPS])
> +#define _IO_proc_jumps                   (__io_vtables[IO_PROC_JUMPS])
> +#define _IO_mem_jumps                    (__io_vtables[IO_MEM_JUMPS])
> +#define _IO_wmem_jumps                   (__io_vtables[IO_WMEM_JUMPS])
> +#define _IO_printf_buffer_as_file_jumps  (__io_vtables[IO_PRINTF_BUFFER_AS_FILE_JUMPS])
> +#define _IO_wprintf_buffer_as_file_jumps (__io_vtables[IO_WPRINTF_BUFFER_AS_FILE_JUMPS])
> +#define _IO_old_file_jumps               (__io_vtables[IO_OLD_FILE_JUMPS])
> +#define _IO_old_proc_jumps               (__io_vtables[IO_OLD_PROC_JUMPS])
> +#define _IO_old_cookie_jumps             (__io_vtables[IO_OLD_COOKIED_JUMPS])
> +
> +#ifdef SHARED
> +# define libio_static_fn_required(name)
> +#else
> +# define libio_static_fn_required(name) __asm (".globl " #name);
> +#endif
> +
>  extern int _IO_do_write (FILE *, const char *, size_t);
>  libc_hidden_proto (_IO_do_write)
>  extern int _IO_new_do_write (FILE *, const char *, size_t);
> @@ -593,6 +642,14 @@ extern void _IO_new_file_init_internal (struct _IO_FILE_plus *)
>  extern FILE* _IO_new_file_setbuf (FILE *, char *, ssize_t);
>  extern FILE* _IO_file_setbuf_mmap (FILE *, char *, ssize_t);
>  extern int _IO_new_file_sync (FILE *);
> +extern int _IO_file_sync_mmap (FILE *) attribute_hidden;
> +extern size_t  _IO_file_xsgetn_maybe_mmap (FILE *fp, void *data, size_t n)
> +  attribute_hidden;
> +extern size_t _IO_file_xsgetn_mmap (FILE *fp, void *data, size_t n)
> +  attribute_hidden;
> +extern off64_t _IO_file_seekoff_maybe_mmap (FILE *fp, off64_t offset, int dir,
> +					    int mode)
> +     attribute_hidden;
>  extern int _IO_new_file_underflow (FILE *);
>  extern int _IO_new_file_overflow (FILE *, int);
>  extern off64_t _IO_new_file_seekoff (FILE *, off64_t, int, int);
> @@ -625,6 +682,10 @@ extern wint_t _IO_wfile_overflow (FILE *, wint_t);
>  libc_hidden_proto (_IO_wfile_overflow)
>  extern off64_t _IO_wfile_seekoff (FILE *, off64_t, int, int);
>  libc_hidden_proto (_IO_wfile_seekoff)
> +extern wint_t _IO_wfile_underflow_maybe_mmap (FILE *fp)
> +     attribute_hidden;
> +extern wint_t _IO_wfile_underflow_mmap (FILE *fp)
> +     attribute_hidden;
>  
>  /* Jumptable functions for proc_files. */
>  extern FILE* _IO_proc_open (FILE *, const char *, const char *)
> @@ -643,13 +704,41 @@ extern int _IO_str_overflow (FILE *, int) __THROW;
>  libc_hidden_proto (_IO_str_overflow)
>  extern int _IO_str_pbackfail (FILE *, int) __THROW;
>  libc_hidden_proto (_IO_str_pbackfail)
> -extern off64_t _IO_str_seekoff (FILE *, off64_t, int, int) __THROW;
> +extern off64_t _IO_str_seekoff (FILE *, off64_t, int, int) __THROW
> + ;
>  libc_hidden_proto (_IO_str_seekoff)
>  extern void _IO_str_finish (FILE *, int) __THROW;
> +extern int _IO_str_chk_overflow (FILE *fp, int c) __THROW
> +  attribute_hidden;
> +
> +/* Jumptable functions for fopencookie.  */
> +extern ssize_t _IO_cookie_read (FILE *fp, void *buf, ssize_t size)
> +  attribute_hidden;
> +extern ssize_t _IO_cookie_write (FILE *fp, const void *buf, ssize_t size)
> +  attribute_hidden;
> +extern off64_t _IO_cookie_seek (FILE *fp, off64_t offset, int dir)
> +  attribute_hidden;
> +extern int _IO_cookie_close (FILE *fp) attribute_hidden;
> +extern off64_t _IO_cookie_seekoff (FILE *fp, off64_t offset, int dir, int mode)
> +  attribute_hidden;
> +extern off64_t _IO_old_cookie_seek (FILE *fp, off64_t offset, int dir)
> +  attribute_hidden;
> +
> +/* Jumptable functions for obstack.  */
> +extern int __IO_obstack_overflow (FILE *fp, int c) attribute_hidden;
> +extern size_t __IO_obstack_xsputn (FILE *fp, const void *data, size_t n)
> +  attribute_hidden;
> +
> +/* Jumptable functions for open_{w}memstream.  */
> +extern int _IO_mem_sync (FILE* fp) __THROW attribute_hidden;
> +extern void _IO_mem_finish (FILE* fp, int) __THROW attribute_hidden;
> +extern int _IO_wmem_sync (FILE* fp) __THROW attribute_hidden;
> +extern void _IO_wmem_finish (FILE* fp, int) __THROW attribute_hidden;
>  
>  /* Other strfile functions */
>  struct _IO_strfile_;
>  extern ssize_t _IO_str_count (FILE *) __THROW;
> +extern int _IO_strn_overflow (FILE *fp, int c) __THROW attribute_hidden;
>  
>  /* And the wide character versions.  */
>  extern void _IO_wstr_init_static (FILE *, wchar_t *, size_t, wchar_t *)
> @@ -662,6 +751,10 @@ extern off64_t _IO_wstr_seekoff (FILE *, off64_t, int, int)
>  extern wint_t _IO_wstr_pbackfail (FILE *, wint_t) __THROW;
>  extern void _IO_wstr_finish (FILE *, int) __THROW;
>  
> +/* Helper functions.  */
> +int _IO_helper_overflow (FILE *s, int c);
> +int _IO_whelper_overflow (FILE *s, int c);
> +
>  /* Internal versions of v*printf that take an additional flags
>     parameter.  */
>  extern int __vfprintf_internal (FILE *fp, const char *format, va_list ap,
> @@ -891,14 +984,6 @@ _IO_acquire_lock_fct (FILE **p)
>    } while (0)
>  #endif
>  
> -/* Collect all vtables in a special section for vtable verification.
> -   These symbols cover the extent of this section.  */
> -symbol_set_declare (__libc_IO_vtables)
> -
> -/* libio vtables need to carry this attribute so that they pass
> -   validation.  */
> -#define libio_vtable __attribute__ ((section ("__libc_IO_vtables")))
> -
>  #ifdef SHARED
>  /* If equal to &_IO_vtable_check (with pointer guard protection),
>     unknown vtable pointers are valid.  This function pointer is solely
> @@ -933,12 +1018,9 @@ void _IO_vtable_check (void) attribute_hidden;
>  static inline const struct _IO_jump_t *
>  IO_validate_vtable (const struct _IO_jump_t *vtable)
>  {
> -  /* Fast path: The vtable pointer is within the __libc_IO_vtables
> -     section.  */
> -  uintptr_t section_length = __stop___libc_IO_vtables - __start___libc_IO_vtables;
>    uintptr_t ptr = (uintptr_t) vtable;
> -  uintptr_t offset = ptr - (uintptr_t) __start___libc_IO_vtables;
> -  if (__glibc_unlikely (offset >= section_length))
> +  uintptr_t offset = ptr - (uintptr_t) &__io_vtables;
> +  if (__glibc_unlikely (offset >= IO_VTABLES_LEN))
>      /* The vtable pointer is not in the expected section.  Use the
>         slow path, which will terminate the process if necessary.  */
>      _IO_vtable_check ();
> diff --git a/libio/memstream.c b/libio/memstream.c
> index 1ae8cd9544..b5b5254a34 100644
> --- a/libio/memstream.c
> +++ b/libio/memstream.c
> @@ -29,34 +29,6 @@ struct _IO_FILE_memstream
>  };
>  
>  
> -static int _IO_mem_sync (FILE* fp) __THROW;
> -static void _IO_mem_finish (FILE* fp, int) __THROW;
> -
> -
> -static const struct _IO_jump_t _IO_mem_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT (finish, _IO_mem_finish),
> -  JUMP_INIT (overflow, _IO_str_overflow),
> -  JUMP_INIT (underflow, _IO_str_underflow),
> -  JUMP_INIT (uflow, _IO_default_uflow),
> -  JUMP_INIT (pbackfail, _IO_str_pbackfail),
> -  JUMP_INIT (xsputn, _IO_default_xsputn),
> -  JUMP_INIT (xsgetn, _IO_default_xsgetn),
> -  JUMP_INIT (seekoff, _IO_str_seekoff),
> -  JUMP_INIT (seekpos, _IO_default_seekpos),
> -  JUMP_INIT (setbuf, _IO_default_setbuf),
> -  JUMP_INIT (sync, _IO_mem_sync),
> -  JUMP_INIT (doallocate, _IO_default_doallocate),
> -  JUMP_INIT (read, _IO_default_read),
> -  JUMP_INIT (write, _IO_default_write),
> -  JUMP_INIT (seek, _IO_default_seek),
> -  JUMP_INIT (close, _IO_default_close),
> -  JUMP_INIT (stat, _IO_default_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> -
>  /* Open a stream that writes into a malloc'd buffer that is expanded as
>     necessary.  *BUFLOC and *SIZELOC are updated with the buffer's location
>     and the number of characters written on fflush or fclose.  */
> @@ -105,7 +77,7 @@ libc_hidden_def (__open_memstream)
>  weak_alias (__open_memstream, open_memstream)
>  
>  
> -static int
> +int
>  _IO_mem_sync (FILE *fp)
>  {
>    struct _IO_FILE_memstream *mp = (struct _IO_FILE_memstream *) fp;
> @@ -123,7 +95,7 @@ _IO_mem_sync (FILE *fp)
>  }
>  
>  
> -static void
> +void
>  _IO_mem_finish (FILE *fp, int dummy)
>  {
>    struct _IO_FILE_memstream *mp = (struct _IO_FILE_memstream *) fp;
> diff --git a/libio/oldfileops.c b/libio/oldfileops.c
> index ea3b864447..371c7479c6 100644
> --- a/libio/oldfileops.c
> +++ b/libio/oldfileops.c
> @@ -716,29 +716,6 @@ _IO_old_file_xsputn (FILE *f, const void *data, size_t n)
>    return n - to_do;
>  }
>  
> -
> -const struct _IO_jump_t _IO_old_file_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_old_file_finish),
> -  JUMP_INIT(overflow, _IO_old_file_overflow),
> -  JUMP_INIT(underflow, _IO_old_file_underflow),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_default_pbackfail),
> -  JUMP_INIT(xsputn, _IO_old_file_xsputn),
> -  JUMP_INIT(xsgetn, _IO_default_xsgetn),
> -  JUMP_INIT(seekoff, _IO_old_file_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_old_file_setbuf),
> -  JUMP_INIT(sync, _IO_old_file_sync),
> -  JUMP_INIT(doallocate, _IO_file_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_old_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_file_close),
> -  JUMP_INIT(stat, _IO_file_stat)
> -};
> -
>  compat_symbol (libc, _IO_old_do_write, _IO_do_write, GLIBC_2_0);
>  compat_symbol (libc, _IO_old_file_attach, _IO_file_attach, GLIBC_2_0);
>  compat_symbol (libc, _IO_old_file_close_it, _IO_file_close_it, GLIBC_2_0);
> diff --git a/libio/oldiopopen.c b/libio/oldiopopen.c
> index f9149413e8..206a0f3858 100644
> --- a/libio/oldiopopen.c
> +++ b/libio/oldiopopen.c
> @@ -208,29 +208,6 @@ _IO_old_proc_close (FILE *fp)
>    return wstatus;
>  }
>  
> -const struct _IO_jump_t _IO_old_proc_jumps libio_vtable = {
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_old_file_finish),
> -  JUMP_INIT(overflow, _IO_old_file_overflow),
> -  JUMP_INIT(underflow, _IO_old_file_underflow),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_default_pbackfail),
> -  JUMP_INIT(xsputn, _IO_old_file_xsputn),
> -  JUMP_INIT(xsgetn, _IO_default_xsgetn),
> -  JUMP_INIT(seekoff, _IO_old_file_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_old_file_setbuf),
> -  JUMP_INIT(sync, _IO_old_file_sync),
> -  JUMP_INIT(doallocate, _IO_file_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_old_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_old_proc_close),
> -  JUMP_INIT(stat, _IO_file_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> -
>  strong_alias (_IO_old_popen, __old_popen)
>  compat_symbol (libc, _IO_old_popen, _IO_popen, GLIBC_2_0);
>  compat_symbol (libc, __old_popen, popen, GLIBC_2_0);
> diff --git a/libio/stdio.c b/libio/stdio.c
> index e65ee86b24..356d41d277 100644
> --- a/libio/stdio.c
> +++ b/libio/stdio.c
> @@ -33,3 +33,6 @@
>  FILE *stdin = (FILE *) &_IO_2_1_stdin_;
>  FILE *stdout = (FILE *) &_IO_2_1_stdout_;
>  FILE *stderr = (FILE *) &_IO_2_1_stderr_;
> +
> +libio_static_fn_required (_IO_file_open);
> +libio_static_fn_required (_IO_file_doallocate);
> diff --git a/libio/strfile.h b/libio/strfile.h
> index b7a57317d0..f2ce1ff6f3 100644
> --- a/libio/strfile.h
> +++ b/libio/strfile.h
> @@ -78,8 +78,6 @@ typedef struct
>    wchar_t overflow_buf[64];
>  } _IO_wstrnfile;
>  
> -extern const struct _IO_jump_t _IO_wstrn_jumps attribute_hidden;
> -
>  /* Initialize an _IO_strfile SF to read from narrow string STRING, and
>     return the corresponding FILE object.  It is not necessary to fclose
>     the FILE when it is no longer needed.  */
> diff --git a/libio/strops.c b/libio/strops.c
> index 1cd0bf6c3d..4e2243b8d9 100644
> --- a/libio/strops.c
> +++ b/libio/strops.c
> @@ -352,27 +352,3 @@ _IO_str_finish (FILE *fp, int dummy)
>  
>    _IO_default_finish (fp, 0);
>  }
> -
> -const struct _IO_jump_t _IO_str_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_str_finish),
> -  JUMP_INIT(overflow, _IO_str_overflow),
> -  JUMP_INIT(underflow, _IO_str_underflow),
> -  JUMP_INIT(uflow, _IO_default_uflow),
> -  JUMP_INIT(pbackfail, _IO_str_pbackfail),
> -  JUMP_INIT(xsputn, _IO_default_xsputn),
> -  JUMP_INIT(xsgetn, _IO_default_xsgetn),
> -  JUMP_INIT(seekoff, _IO_str_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_default_setbuf),
> -  JUMP_INIT(sync, _IO_default_sync),
> -  JUMP_INIT(doallocate, _IO_default_doallocate),
> -  JUMP_INIT(read, _IO_default_read),
> -  JUMP_INIT(write, _IO_default_write),
> -  JUMP_INIT(seek, _IO_default_seek),
> -  JUMP_INIT(close, _IO_default_close),
> -  JUMP_INIT(stat, _IO_default_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> diff --git a/libio/tst-vtables-interposed.c b/libio/tst-vtables-interposed.c
> index 9d03fa0ec2..66f79dddb5 100644
> --- a/libio/tst-vtables-interposed.c
> +++ b/libio/tst-vtables-interposed.c
> @@ -21,7 +21,12 @@
>  /* Provide an interposed definition of the standard file handles with
>     our own vtable.  stdout/stdin/stderr will not work as a result, but
>     a succesful test does not print anything, so this is fine.  */
> +#include "libioP.h"
> +#undef _IO_file_jumps
>  #define _IO_file_jumps jumps
> +#undef _IO_wfile_jumps
> +extern const struct _IO_jump_t _IO_wfile_jumps;
> +#define _IO_wfile_jumps _IO_wfile_jumps
>  #include "stdfiles.c"
>  
>  static int
> diff --git a/libio/vtables.c b/libio/vtables.c
> index e3809c28ce..2a652e0ba9 100644
> --- a/libio/vtables.c
> +++ b/libio/vtables.c
> @@ -21,6 +21,491 @@
>  #include <stdio.h>
>  #include <ldsodefs.h>
>  #include <pointer_guard.h>
> +#include <libio-macros.h>
> +
> +/* Bot _IO_str_* and _IO_new_file functiosn are pulled into every link (from
> +   stdio initialization).  */
> +#ifndef SHARED
> +# pragma weak _IO_default_close
> +# pragma weak _IO_default_doallocate
> +# pragma weak _IO_default_imbue
> +# pragma weak _IO_default_pbackfail
> +# pragma weak _IO_default_read
> +# pragma weak _IO_default_seek
> +# pragma weak _IO_default_seekpos
> +# pragma weak _IO_default_setbuf
> +# pragma weak _IO_default_showmanyc
> +# pragma weak _IO_default_stat
> +# pragma weak _IO_default_sync
> +# pragma weak _IO_default_uflow
> +# pragma weak _IO_default_write
> +# pragma weak _IO_default_xsgetn
> +# pragma weak _IO_default_xsputn
> +
> +# pragma weak _IO_wdefault_pbackfail
> +# pragma weak _IO_wdefault_uflow
> +# pragma weak _IO_wdefault_doallocate
> +# pragma weak _IO_wdefault_xsgetn
> +# pragma weak _IO_wdefault_xsputn
> +
> +# pragma weak _IO_wstr_finish
> +# pragma weak _IO_wstr_overflow
> +# pragma weak _IO_wstr_pbackfail
> +# pragma weak _IO_wstr_seekoff
> +# pragma weak _IO_wstr_underflow
> +
> +# pragma weak _IO_file_close
> +# pragma weak _IO_file_close_mmap
> +# pragma weak _IO_file_doallocate
> +# pragma weak _IO_file_finish
> +# pragma weak _IO_file_jumps_alia
> +# pragma weak _IO_file_overflow
> +# pragma weak _IO_file_read
> +# pragma weak _IO_file_seek
> +# pragma weak _IO_file_seekoff_maybe_mmap
> +# pragma weak _IO_file_seekoff_mmap
> +# pragma weak _IO_file_setbuf
> +# pragma weak _IO_file_setbuf_mmap
> +# pragma weak _IO_file_setbuf_mmap
> +# pragma weak _IO_file_stat
> +# pragma weak _IO_file_sync
> +# pragma weak _IO_file_sync_mmap
> +# pragma weak _IO_file_underflow
> +# pragma weak _IO_file_underflow_maybe_mmap
> +# pragma weak _IO_file_underflow_mmap
> +# pragma weak _IO_file_xsgetn
> +# pragma weak _IO_file_xsgetn_maybe_mmap
> +# pragma weak _IO_file_xsgetn_mmap
> +# pragma weak _IO_file_xsputn
> +
> +# pragma weak _IO_wfile_overflow
> +# pragma weak _IO_wfile_sync
> +# pragma weak _IO_wfile_underflow
> +# pragma weak _IO_wfile_underflow_maybe_mmap
> +# pragma weak _IO_wfile_underflow_mmap
> +# pragma weak _IO_wfile_doallocate
> +# pragma weak _IO_wfile_jumps_alia
> +# pragma weak _IO_wfile_seekoff
> +# pragma weak _IO_wfile_xsputn
> +
> +# pragma weak _IO_new_proc_close
> +
> +# pragma weak _IO_cookie_close
> +# pragma weak _IO_cookie_read
> +# pragma weak _IO_cookie_seek
> +# pragma weak _IO_cookie_seekoff
> +# pragma weak _IO_cookie_write
> +
> +# pragma weak _IO_mem_finish
> +# pragma weak _IO_mem_sync
> +
> +# pragma weak _IO_wmem_finish
> +# pragma weak _IO_wmem_sync
> +
> +# pragma weak __printf_buffer_as_file_overflow
> +# pragma weak __printf_buffer_as_file_xsputn
> +
> +# pragma weak __wprintf_buffer_as_file_overflow
> +# pragma weak __wprintf_buffer_as_file_xsputn
> +#endif
> +
> +const struct _IO_jump_t __io_vtables[IO_VTABLES_LEN] attribute_relro =
> +{
> +  /* _IO_str_jumps  */
> +  [IO_STR_JUMPS] =
> +  {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_str_finish),
> +    JUMP_INIT (overflow, _IO_str_overflow),
> +    JUMP_INIT (underflow, _IO_str_underflow),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_str_pbackfail),
> +    JUMP_INIT (xsputn, _IO_default_xsputn),
> +    JUMP_INIT (xsgetn, _IO_default_xsgetn),
> +    JUMP_INIT (seekoff, _IO_str_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_default_setbuf),
> +    JUMP_INIT (sync, _IO_default_sync),
> +    JUMP_INIT (doallocate, _IO_default_doallocate),
> +    JUMP_INIT (read, _IO_default_read),
> +    JUMP_INIT (write, _IO_default_write),
> +    JUMP_INIT (seek, _IO_default_seek),
> +    JUMP_INIT (close, _IO_default_close),
> +    JUMP_INIT (stat, _IO_default_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_wstr_jumps  */
> +  [IO_WSTR_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_wstr_finish),
> +    JUMP_INIT (overflow, (_IO_overflow_t) _IO_wstr_overflow),
> +    JUMP_INIT (underflow, (_IO_underflow_t) _IO_wstr_underflow),
> +    JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> +    JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
> +    JUMP_INIT (xsputn, _IO_wdefault_xsputn),
> +    JUMP_INIT (xsgetn, _IO_wdefault_xsgetn),
> +    JUMP_INIT (seekoff, _IO_wstr_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_default_setbuf),
> +    JUMP_INIT (sync, _IO_default_sync),
> +    JUMP_INIT (doallocate, _IO_wdefault_doallocate),
> +    JUMP_INIT (read, _IO_default_read),
> +    JUMP_INIT (write, _IO_default_write),
> +    JUMP_INIT (seek, _IO_default_seek),
> +    JUMP_INIT (close, _IO_default_close),
> +    JUMP_INIT (stat, _IO_default_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_file_jumps  */
> +  [IO_FILE_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_file_finish),
> +    JUMP_INIT (overflow, _IO_file_overflow),
> +    JUMP_INIT (underflow, _IO_file_underflow),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_default_pbackfail),
> +    JUMP_INIT (xsputn, _IO_file_xsputn),
> +    JUMP_INIT (xsgetn, _IO_file_xsgetn),
> +    JUMP_INIT (seekoff, _IO_new_file_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_new_file_setbuf),
> +    JUMP_INIT (sync, _IO_new_file_sync),
> +    JUMP_INIT (doallocate, _IO_file_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_new_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_file_close),
> +    JUMP_INIT (stat, _IO_file_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_file_jumps_mmap  */
> +  [IO_FILE_JUMPS_MMAP] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_file_finish),
> +    JUMP_INIT (overflow, _IO_file_overflow),
> +    JUMP_INIT (underflow, _IO_file_underflow_mmap),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_default_pbackfail),
> +    JUMP_INIT (xsputn, _IO_new_file_xsputn),
> +    JUMP_INIT (xsgetn, _IO_file_xsgetn_mmap),
> +    JUMP_INIT (seekoff, _IO_file_seekoff_mmap),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
> +    JUMP_INIT (sync, _IO_file_sync_mmap),
> +    JUMP_INIT (doallocate, _IO_file_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_new_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_file_close_mmap),
> +    JUMP_INIT (stat, _IO_file_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_file_jumps_maybe_mmap  */
> +  [IO_FILE_JUMPS_MAYBE_MMAP] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_file_finish),
> +    JUMP_INIT (overflow, _IO_file_overflow),
> +    JUMP_INIT (underflow, _IO_file_underflow_maybe_mmap),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_default_pbackfail),
> +    JUMP_INIT (xsputn, _IO_new_file_xsputn),
> +    JUMP_INIT (xsgetn, _IO_file_xsgetn_maybe_mmap),
> +    JUMP_INIT (seekoff, _IO_file_seekoff_maybe_mmap),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
> +    JUMP_INIT (sync, _IO_new_file_sync),
> +    JUMP_INIT (doallocate, _IO_file_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_new_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_file_close),
> +    JUMP_INIT (stat, _IO_file_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_wfile_jumps  */
> +  [IO_WFILE_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_new_file_finish),
> +    JUMP_INIT (overflow, (_IO_overflow_t) _IO_wfile_overflow),
> +    JUMP_INIT (underflow, (_IO_underflow_t) _IO_wfile_underflow),
> +    JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> +    JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
> +    JUMP_INIT (xsputn, _IO_wfile_xsputn),
> +    JUMP_INIT (xsgetn, _IO_file_xsgetn),
> +    JUMP_INIT (seekoff, _IO_wfile_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_new_file_setbuf),
> +    JUMP_INIT (sync, (_IO_sync_t) _IO_wfile_sync),
> +    JUMP_INIT (doallocate, _IO_wfile_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_new_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_file_close),
> +    JUMP_INIT (stat, _IO_file_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_wfile_jumps_mmap  */
> +  [IO_WFILE_JUMPS_MMAP] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_new_file_finish),
> +    JUMP_INIT (overflow, (_IO_overflow_t) _IO_wfile_overflow),
> +    JUMP_INIT (underflow, (_IO_underflow_t) _IO_wfile_underflow_mmap),
> +    JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> +    JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
> +    JUMP_INIT (xsputn, _IO_wfile_xsputn),
> +    JUMP_INIT (xsgetn, _IO_file_xsgetn),
> +    JUMP_INIT (seekoff, _IO_wfile_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_file_setbuf_mmap),
> +    JUMP_INIT (sync, (_IO_sync_t) _IO_wfile_sync),
> +    JUMP_INIT (doallocate, _IO_wfile_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_new_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_file_close_mmap),
> +    JUMP_INIT (stat, _IO_file_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_wfile_jumps_maybe_mmap  */
> +  [IO_WFILE_JUMPS_MAYBE_MMAP] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_new_file_finish),
> +    JUMP_INIT (overflow, (_IO_overflow_t) _IO_wfile_overflow),
> +    JUMP_INIT (underflow, (_IO_underflow_t) _IO_wfile_underflow_maybe_mmap),
> +    JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> +    JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
> +    JUMP_INIT (xsputn, _IO_wfile_xsputn),
> +    JUMP_INIT (xsgetn, _IO_file_xsgetn),
> +    JUMP_INIT (seekoff, _IO_wfile_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_file_setbuf_mmap),
> +    JUMP_INIT (sync, (_IO_sync_t) _IO_wfile_sync),
> +    JUMP_INIT (doallocate, _IO_wfile_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_new_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_file_close),
> +    JUMP_INIT (stat, _IO_file_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_cookie_jumps  */
> +  [IO_COOKIE_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_file_finish),
> +    JUMP_INIT (overflow, _IO_file_overflow),
> +    JUMP_INIT (underflow, _IO_file_underflow),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_default_pbackfail),
> +    JUMP_INIT (xsputn, _IO_file_xsputn),
> +    JUMP_INIT (xsgetn, _IO_default_xsgetn),
> +    JUMP_INIT (seekoff, _IO_cookie_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_file_setbuf),
> +    JUMP_INIT (sync, _IO_file_sync),
> +    JUMP_INIT (doallocate, _IO_file_doallocate),
> +    JUMP_INIT (read, _IO_cookie_read),
> +    JUMP_INIT (write, _IO_cookie_write),
> +    JUMP_INIT (seek, _IO_cookie_seek),
> +    JUMP_INIT (close, _IO_cookie_close),
> +    JUMP_INIT (stat, _IO_default_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue),
> +  },
> +  /* _IO_proc_jumps  */
> +  [IO_PROC_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_new_file_finish),
> +    JUMP_INIT (overflow, _IO_new_file_overflow),
> +    JUMP_INIT (underflow, _IO_new_file_underflow),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_default_pbackfail),
> +    JUMP_INIT (xsputn, _IO_new_file_xsputn),
> +    JUMP_INIT (xsgetn, _IO_default_xsgetn),
> +    JUMP_INIT (seekoff, _IO_new_file_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_new_file_setbuf),
> +    JUMP_INIT (sync, _IO_new_file_sync),
> +    JUMP_INIT (doallocate, _IO_file_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_new_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_new_proc_close),
> +    JUMP_INIT (stat, _IO_file_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_mem_jumps  */
> +  [IO_MEM_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_mem_finish),
> +    JUMP_INIT (overflow, _IO_str_overflow),
> +    JUMP_INIT (underflow, _IO_str_underflow),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_str_pbackfail),
> +    JUMP_INIT (xsputn, _IO_default_xsputn),
> +    JUMP_INIT (xsgetn, _IO_default_xsgetn),
> +    JUMP_INIT (seekoff, _IO_str_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_default_setbuf),
> +    JUMP_INIT (sync, _IO_mem_sync),
> +    JUMP_INIT (doallocate, _IO_default_doallocate),
> +    JUMP_INIT (read, _IO_default_read),
> +    JUMP_INIT (write, _IO_default_write),
> +    JUMP_INIT (seek, _IO_default_seek),
> +    JUMP_INIT (close, _IO_default_close),
> +    JUMP_INIT (stat, _IO_default_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  /* _IO_wmem_jumps  */
> +  [IO_WMEM_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_wmem_finish),
> +    JUMP_INIT (overflow, (_IO_overflow_t) _IO_wstr_overflow),
> +    JUMP_INIT (underflow, (_IO_underflow_t) _IO_wstr_underflow),
> +    JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> +    JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
> +    JUMP_INIT (xsputn, _IO_wdefault_xsputn),
> +    JUMP_INIT (xsgetn, _IO_wdefault_xsgetn),
> +    JUMP_INIT (seekoff, _IO_wstr_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_default_setbuf),
> +    JUMP_INIT (sync, _IO_wmem_sync),
> +    JUMP_INIT (doallocate, _IO_wdefault_doallocate),
> +    JUMP_INIT (read, _IO_default_read),
> +    JUMP_INIT (write, _IO_default_write),
> +    JUMP_INIT (seek, _IO_default_seek),
> +    JUMP_INIT (close, _IO_default_close),
> +    JUMP_INIT (stat, _IO_default_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +  [IO_PRINTF_BUFFER_AS_FILE_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, NULL),
> +    JUMP_INIT (overflow, __printf_buffer_as_file_overflow),
> +    JUMP_INIT (underflow, NULL),
> +    JUMP_INIT (uflow, NULL),
> +    JUMP_INIT (pbackfail, NULL),
> +    JUMP_INIT (xsputn, __printf_buffer_as_file_xsputn),
> +    JUMP_INIT (xsgetn, NULL),
> +    JUMP_INIT (seekoff, NULL),
> +    JUMP_INIT (seekpos, NULL),
> +    JUMP_INIT (setbuf, NULL),
> +    JUMP_INIT (sync, NULL),
> +    JUMP_INIT (doallocate, NULL),
> +    JUMP_INIT (read, NULL),
> +    JUMP_INIT (write, NULL),
> +    JUMP_INIT (seek, NULL),
> +    JUMP_INIT (close, NULL),
> +    JUMP_INIT (stat, NULL),
> +    JUMP_INIT (showmanyc, NULL),
> +    JUMP_INIT (imbue, NULL)
> +  },
> +  [IO_WPRINTF_BUFFER_AS_FILE_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, NULL),
> +    JUMP_INIT (overflow, (_IO_overflow_t) __wprintf_buffer_as_file_overflow),
> +    JUMP_INIT (underflow, NULL),
> +    JUMP_INIT (uflow, NULL),
> +    JUMP_INIT (pbackfail, NULL),
> +    JUMP_INIT (xsputn, __wprintf_buffer_as_file_xsputn),
> +    JUMP_INIT (xsgetn, NULL),
> +    JUMP_INIT (seekoff, NULL),
> +    JUMP_INIT (seekpos, NULL),
> +    JUMP_INIT (setbuf, NULL),
> +    JUMP_INIT (sync, NULL),
> +    JUMP_INIT (doallocate, NULL),
> +    JUMP_INIT (read, NULL),
> +    JUMP_INIT (write, NULL),
> +    JUMP_INIT (seek, NULL),
> +    JUMP_INIT (close, NULL),
> +    JUMP_INIT (stat, NULL),
> +    JUMP_INIT (showmanyc, NULL),
> +    JUMP_INIT (imbue, NULL)
> +  },
> +
> +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
> +  /* _IO_old_file_jumps  */
> +  [IO_OLD_FILE_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_old_file_finish),
> +    JUMP_INIT (overflow, _IO_old_file_overflow),
> +    JUMP_INIT (underflow, _IO_old_file_underflow),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_default_pbackfail),
> +    JUMP_INIT (xsputn, _IO_old_file_xsputn),
> +    JUMP_INIT (xsgetn, _IO_default_xsgetn),
> +    JUMP_INIT (seekoff, _IO_old_file_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_old_file_setbuf),
> +    JUMP_INIT (sync, _IO_old_file_sync),
> +    JUMP_INIT (doallocate, _IO_file_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_old_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_file_close),
> +    JUMP_INIT (stat, _IO_file_stat)
> +  },
> +  /*  _IO_old_proc_jumps  */
> +  [IO_OLD_PROC_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_old_file_finish),
> +    JUMP_INIT (overflow, _IO_old_file_overflow),
> +    JUMP_INIT (underflow, _IO_old_file_underflow),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_default_pbackfail),
> +    JUMP_INIT (xsputn, _IO_old_file_xsputn),
> +    JUMP_INIT (xsgetn, _IO_default_xsgetn),
> +    JUMP_INIT (seekoff, _IO_old_file_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_old_file_setbuf),
> +    JUMP_INIT (sync, _IO_old_file_sync),
> +    JUMP_INIT (doallocate, _IO_file_doallocate),
> +    JUMP_INIT (read, _IO_file_read),
> +    JUMP_INIT (write, _IO_old_file_write),
> +    JUMP_INIT (seek, _IO_file_seek),
> +    JUMP_INIT (close, _IO_old_proc_close),
> +    JUMP_INIT (stat, _IO_file_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue)
> +  },
> +#endif
> +
> +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
> +  /* _IO_old_cookie_jumps  */
> +  [IO_OLD_COOKIED_JUMPS] = {
> +    JUMP_INIT_DUMMY,
> +    JUMP_INIT (finish, _IO_file_finish),
> +    JUMP_INIT (overflow, _IO_file_overflow),
> +    JUMP_INIT (underflow, _IO_file_underflow),
> +    JUMP_INIT (uflow, _IO_default_uflow),
> +    JUMP_INIT (pbackfail, _IO_default_pbackfail),
> +    JUMP_INIT (xsputn, _IO_file_xsputn),
> +    JUMP_INIT (xsgetn, _IO_default_xsgetn),
> +    JUMP_INIT (seekoff, _IO_cookie_seekoff),
> +    JUMP_INIT (seekpos, _IO_default_seekpos),
> +    JUMP_INIT (setbuf, _IO_file_setbuf),
> +    JUMP_INIT (sync, _IO_file_sync),
> +    JUMP_INIT (doallocate, _IO_file_doallocate),
> +    JUMP_INIT (read, _IO_cookie_read),
> +    JUMP_INIT (write, _IO_cookie_write),
> +    JUMP_INIT (seek, _IO_old_cookie_seek),
> +    JUMP_INIT (close, _IO_cookie_close),
> +    JUMP_INIT (stat, _IO_default_stat),
> +    JUMP_INIT (showmanyc, _IO_default_showmanyc),
> +    JUMP_INIT (imbue, _IO_default_imbue),
> +  },
> +#endif
> +};
>  
>  #ifdef SHARED
>  
> @@ -82,3 +567,15 @@ check_stdfiles_vtables (void)
>      IO_set_accept_foreign_vtables (&_IO_vtable_check);
>  }
>  #endif
> +
> +#define STR(s)  XSTR(s)
> +#define XSTR(s) #s
> +
> +#undef _IO_file_jumps
> +#define _IO_file_jumps_alias  "__io_vtables + " STR(IO_FILE_JUMPS_OFFSET)
> +declare_object_symbol_alias (_IO_file_jumps, _IO_file_jumps_alias,
> +			     IO_JUMP_T_SIZE)
> +#undef _IO_wfile_jumps
> +#define _IO_wfile_jumps_alias  "__io_vtables + " STR(IO_WFILE_JUMPS_OFFSET)
> +declare_object_symbol_alias (_IO_wfile_jumps, _IO_wfile_jumps_alias,
> +			     IO_JUMP_T_SIZE)
> diff --git a/libio/wfileops.c b/libio/wfileops.c
> index b59a98881f..f92d9b42eb 100644
> --- a/libio/wfileops.c
> +++ b/libio/wfileops.c
> @@ -328,7 +328,7 @@ _IO_wfile_underflow (FILE *fp)
>  libc_hidden_def (_IO_wfile_underflow)
>  
>  
> -static wint_t
> +wint_t
>  _IO_wfile_underflow_mmap (FILE *fp)
>  {
>    struct _IO_codecvt *cd;
> @@ -389,7 +389,7 @@ _IO_wfile_underflow_mmap (FILE *fp)
>    return WEOF;
>  }
>  
> -static wint_t
> +wint_t
>  _IO_wfile_underflow_maybe_mmap (FILE *fp)
>  {
>    /* This is the first read attempt.  Doing the underflow will choose mmap
> @@ -1017,78 +1017,3 @@ _IO_wfile_xsputn (FILE *f, const void *data, size_t n)
>    return n - to_do;
>  }
>  libc_hidden_def (_IO_wfile_xsputn)
> -
> -
> -const struct _IO_jump_t _IO_wfile_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_new_file_finish),
> -  JUMP_INIT(overflow, (_IO_overflow_t) _IO_wfile_overflow),
> -  JUMP_INIT(underflow, (_IO_underflow_t) _IO_wfile_underflow),
> -  JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> -  JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
> -  JUMP_INIT(xsputn, _IO_wfile_xsputn),
> -  JUMP_INIT(xsgetn, _IO_file_xsgetn),
> -  JUMP_INIT(seekoff, _IO_wfile_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_new_file_setbuf),
> -  JUMP_INIT(sync, (_IO_sync_t) _IO_wfile_sync),
> -  JUMP_INIT(doallocate, _IO_wfile_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_new_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_file_close),
> -  JUMP_INIT(stat, _IO_file_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> -libc_hidden_data_def (_IO_wfile_jumps)
> -
> -
> -const struct _IO_jump_t _IO_wfile_jumps_mmap libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_new_file_finish),
> -  JUMP_INIT(overflow, (_IO_overflow_t) _IO_wfile_overflow),
> -  JUMP_INIT(underflow, (_IO_underflow_t) _IO_wfile_underflow_mmap),
> -  JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> -  JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
> -  JUMP_INIT(xsputn, _IO_wfile_xsputn),
> -  JUMP_INIT(xsgetn, _IO_file_xsgetn),
> -  JUMP_INIT(seekoff, _IO_wfile_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_file_setbuf_mmap),
> -  JUMP_INIT(sync, (_IO_sync_t) _IO_wfile_sync),
> -  JUMP_INIT(doallocate, _IO_wfile_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_new_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_file_close_mmap),
> -  JUMP_INIT(stat, _IO_file_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> -
> -const struct _IO_jump_t _IO_wfile_jumps_maybe_mmap libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_new_file_finish),
> -  JUMP_INIT(overflow, (_IO_overflow_t) _IO_wfile_overflow),
> -  JUMP_INIT(underflow, (_IO_underflow_t) _IO_wfile_underflow_maybe_mmap),
> -  JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> -  JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
> -  JUMP_INIT(xsputn, _IO_wfile_xsputn),
> -  JUMP_INIT(xsgetn, _IO_file_xsgetn),
> -  JUMP_INIT(seekoff, _IO_wfile_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_file_setbuf_mmap),
> -  JUMP_INIT(sync, (_IO_sync_t) _IO_wfile_sync),
> -  JUMP_INIT(doallocate, _IO_wfile_doallocate),
> -  JUMP_INIT(read, _IO_file_read),
> -  JUMP_INIT(write, _IO_new_file_write),
> -  JUMP_INIT(seek, _IO_file_seek),
> -  JUMP_INIT(close, _IO_file_close),
> -  JUMP_INIT(stat, _IO_file_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> diff --git a/libio/wmemstream.c b/libio/wmemstream.c
> index e7f898c7fb..50ad1bdc86 100644
> --- a/libio/wmemstream.c
> +++ b/libio/wmemstream.c
> @@ -30,34 +30,6 @@ struct _IO_FILE_wmemstream
>  };
>  
>  
> -static int _IO_wmem_sync (FILE* fp) __THROW;
> -static void _IO_wmem_finish (FILE* fp, int) __THROW;
> -
> -
> -static const struct _IO_jump_t _IO_wmem_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT (finish, _IO_wmem_finish),
> -  JUMP_INIT (overflow, (_IO_overflow_t) _IO_wstr_overflow),
> -  JUMP_INIT (underflow, (_IO_underflow_t) _IO_wstr_underflow),
> -  JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> -  JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
> -  JUMP_INIT (xsputn, _IO_wdefault_xsputn),
> -  JUMP_INIT (xsgetn, _IO_wdefault_xsgetn),
> -  JUMP_INIT (seekoff, _IO_wstr_seekoff),
> -  JUMP_INIT (seekpos, _IO_default_seekpos),
> -  JUMP_INIT (setbuf, _IO_default_setbuf),
> -  JUMP_INIT (sync, _IO_wmem_sync),
> -  JUMP_INIT (doallocate, _IO_wdefault_doallocate),
> -  JUMP_INIT (read, _IO_default_read),
> -  JUMP_INIT (write, _IO_default_write),
> -  JUMP_INIT (seek, _IO_default_seek),
> -  JUMP_INIT (close, _IO_default_close),
> -  JUMP_INIT (stat, _IO_default_stat),
> -  JUMP_INIT (showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT (imbue, _IO_default_imbue)
> -};
> -
>  /* Open a stream that writes into a malloc'd buffer that is expanded as
>     necessary.  *BUFLOC and *SIZELOC are updated with the buffer's location
>     and the number of characters written on fflush or fclose.  */
> @@ -105,7 +77,7 @@ open_wmemstream (wchar_t **bufloc, size_t *sizeloc)
>  }
>  
>  
> -static int
> +int
>  _IO_wmem_sync (FILE *fp)
>  {
>    struct _IO_FILE_wmemstream *mp = (struct _IO_FILE_wmemstream *) fp;
> @@ -124,7 +96,7 @@ _IO_wmem_sync (FILE *fp)
>  }
>  
>  
> -static void
> +void
>  _IO_wmem_finish (FILE *fp, int dummy)
>  {
>    struct _IO_FILE_wmemstream *mp = (struct _IO_FILE_wmemstream *) fp;
> diff --git a/libio/wstrops.c b/libio/wstrops.c
> index 2aec314937..ac7efe9f65 100644
> --- a/libio/wstrops.c
> +++ b/libio/wstrops.c
> @@ -361,27 +361,3 @@ _IO_wstr_finish (FILE *fp, int dummy)
>  
>    _IO_wdefault_finish (fp, 0);
>  }
> -
> -const struct _IO_jump_t _IO_wstr_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, _IO_wstr_finish),
> -  JUMP_INIT(overflow, (_IO_overflow_t) _IO_wstr_overflow),
> -  JUMP_INIT(underflow, (_IO_underflow_t) _IO_wstr_underflow),
> -  JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
> -  JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
> -  JUMP_INIT(xsputn, _IO_wdefault_xsputn),
> -  JUMP_INIT(xsgetn, _IO_wdefault_xsgetn),
> -  JUMP_INIT(seekoff, _IO_wstr_seekoff),
> -  JUMP_INIT(seekpos, _IO_default_seekpos),
> -  JUMP_INIT(setbuf, _IO_default_setbuf),
> -  JUMP_INIT(sync, _IO_default_sync),
> -  JUMP_INIT(doallocate, _IO_wdefault_doallocate),
> -  JUMP_INIT(read, _IO_default_read),
> -  JUMP_INIT(write, _IO_default_write),
> -  JUMP_INIT(seek, _IO_default_seek),
> -  JUMP_INIT(close, _IO_default_close),
> -  JUMP_INIT(stat, _IO_default_stat),
> -  JUMP_INIT(showmanyc, _IO_default_showmanyc),
> -  JUMP_INIT(imbue, _IO_default_imbue)
> -};
> diff --git a/stdio-common/printf_buffer_as_file.c b/stdio-common/printf_buffer_as_file.c
> index f27b000d78..cd36fa77e4 100644
> --- a/stdio-common/printf_buffer_as_file.c
> +++ b/stdio-common/printf_buffer_as_file.c
> @@ -48,7 +48,7 @@ __printf_buffer_as_file_switch_to_buffer (struct __printf_buffer_as_file *file)
>  /* Only a small subset of the vtable functions is implemented here,
>     following _IO_obstack_jumps.  */
>  
> -static int
> +int
>  __printf_buffer_as_file_overflow (FILE *fp, int ch)
>  {
>    struct __printf_buffer_as_file *file = (struct __printf_buffer_as_file *) fp;
> @@ -72,7 +72,7 @@ __printf_buffer_as_file_overflow (FILE *fp, int ch)
>      return EOF;
>  }
>  
> -static size_t
> +size_t
>  __printf_buffer_as_file_xsputn (FILE *fp, const void *buf, size_t len)
>  {
>    struct __printf_buffer_as_file *file = (struct __printf_buffer_as_file *) fp;
> @@ -93,30 +93,6 @@ __printf_buffer_as_file_xsputn (FILE *fp, const void *buf, size_t len)
>      return 0;
>  }
>  
> -static const struct _IO_jump_t _IO_printf_buffer_as_file_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, NULL),
> -  JUMP_INIT(overflow, __printf_buffer_as_file_overflow),
> -  JUMP_INIT(underflow, NULL),
> -  JUMP_INIT(uflow, NULL),
> -  JUMP_INIT(pbackfail, NULL),
> -  JUMP_INIT(xsputn, __printf_buffer_as_file_xsputn),
> -  JUMP_INIT(xsgetn, NULL),
> -  JUMP_INIT(seekoff, NULL),
> -  JUMP_INIT(seekpos, NULL),
> -  JUMP_INIT(setbuf, NULL),
> -  JUMP_INIT(sync, NULL),
> -  JUMP_INIT(doallocate, NULL),
> -  JUMP_INIT(read, NULL),
> -  JUMP_INIT(write, NULL),
> -  JUMP_INIT(seek, NULL),
> -  JUMP_INIT(close, NULL),
> -  JUMP_INIT(stat, NULL),
> -  JUMP_INIT(showmanyc, NULL),
> -  JUMP_INIT(imbue, NULL)
> -};
> -
>  void
>  __printf_buffer_as_file_init (struct __printf_buffer_as_file *file,
>                                struct __printf_buffer *next)
> diff --git a/stdio-common/wprintf_buffer_as_file.c b/stdio-common/wprintf_buffer_as_file.c
> index cd48a7d42a..f0d05f8b4a 100644
> --- a/stdio-common/wprintf_buffer_as_file.c
> +++ b/stdio-common/wprintf_buffer_as_file.c
> @@ -48,7 +48,7 @@ __wprintf_buffer_as_file_switch_to_buffer (struct __wprintf_buffer_as_file *file
>  /* Only a small subset of the vtable functions is implemented here,
>     following _IO_obstack_jumps.  */
>  
> -static wint_t
> +wint_t
>  __wprintf_buffer_as_file_overflow (FILE *fp, int ch)
>  {
>    struct __wprintf_buffer_as_file *file
> @@ -75,7 +75,7 @@ __wprintf_buffer_as_file_overflow (FILE *fp, int ch)
>      return WEOF;
>  }
>  
> -static size_t
> +size_t
>  __wprintf_buffer_as_file_xsputn (FILE *fp, const void *buf, size_t len)
>  {
>    struct __wprintf_buffer_as_file *file
> @@ -97,30 +97,6 @@ __wprintf_buffer_as_file_xsputn (FILE *fp, const void *buf, size_t len)
>      return 0;
>  }
>  
> -static const struct _IO_jump_t _IO_wprintf_buffer_as_file_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT(finish, NULL),
> -  JUMP_INIT(overflow, (_IO_overflow_t) __wprintf_buffer_as_file_overflow),
> -  JUMP_INIT(underflow, NULL),
> -  JUMP_INIT(uflow, NULL),
> -  JUMP_INIT(pbackfail, NULL),
> -  JUMP_INIT(xsputn, __wprintf_buffer_as_file_xsputn),
> -  JUMP_INIT(xsgetn, NULL),
> -  JUMP_INIT(seekoff, NULL),
> -  JUMP_INIT(seekpos, NULL),
> -  JUMP_INIT(setbuf, NULL),
> -  JUMP_INIT(sync, NULL),
> -  JUMP_INIT(doallocate, NULL),
> -  JUMP_INIT(read, NULL),
> -  JUMP_INIT(write, NULL),
> -  JUMP_INIT(seek, NULL),
> -  JUMP_INIT(close, NULL),
> -  JUMP_INIT(stat, NULL),
> -  JUMP_INIT(showmanyc, NULL),
> -  JUMP_INIT(imbue, NULL)
> -};
> -
>  void
>  __wprintf_buffer_as_file_init (struct __wprintf_buffer_as_file *file,
>                                 struct __wprintf_buffer *next)

This patch seems to confuse GNU make 4.4+ in the libio subdirectory (for
me, it just spins forever).  4.3 seems unaffected.

  make  subdir=libio -C libio ..=../ subdir_lib
  make[3]: Entering directory '/home/arsen/gnu/glibc/glibc/libio'
  ^Cmake[2]: *** [Makefile:484: libio/subdir_lib] Interrupt

I'll investigate later today, but I'm letting you know so that it's not
forgotten.

I'm decently sure this is a bug in GNU make from how it behaves.

Have a lovely day.
  
Adhemerval Zanella Netto March 6, 2023, 4:01 p.m. UTC | #4
On 06/03/23 11:58, Arsen Arsenović wrote:
> 
> This patch seems to confuse GNU make 4.4+ in the libio subdirectory (for
> me, it just spins forever).  4.3 seems unaffected.
> 
>   make  subdir=libio -C libio ..=../ subdir_lib
>   make[3]: Entering directory '/home/arsen/gnu/glibc/glibc/libio'
>   ^Cmake[2]: *** [Makefile:484: libio/subdir_lib] Interrupt
> 
> I'll investigate later today, but I'm letting you know so that it's not
> forgotten.
> 
> I'm decently sure this is a bug in GNU make from how it behaves.
> 
> Have a lovely day.

I recall Andreas saying he also found some issues with make 4.4, which
makes me believe it is a gnumake issue indeed.
  
Andreas Schwab March 6, 2023, 4:23 p.m. UTC | #5
On Mär 06 2023, Arsen Arsenović via Libc-alpha wrote:

> This patch seems to confuse GNU make 4.4+ in the libio subdirectory (for
> me, it just spins forever).  4.3 seems unaffected.
>
>   make  subdir=libio -C libio ..=../ subdir_lib
>   make[3]: Entering directory '/home/arsen/gnu/glibc/glibc/libio'
>   ^Cmake[2]: *** [Makefile:484: libio/subdir_lib] Interrupt

It is constantly rereading makefiles do to these conditions:

  Prerequisite '../../test/versions.stmp' is newer than target '../../test/sysd-versions'.
   Prerequisite '../../test/libc-modules.stmp' is newer than target '../../test/libc-modules.h'.
  Must remake target '../../test/libc-modules.h'.
  Successfully remade target file '../../test/libc-modules.h'.
   Prerequisite '../../test/bits/stdio_lim.st' is newer than target '../../test/bits/stdio_lim.h'.
  Must remake target '../../test/bits/stdio_lim.h'.
  Successfully remade target file '../../test/bits/stdio_lim.h'.

That appears to be related to the way libio-macros.h is generated or its
dependencies, because if I remove that file and rerun make, it
progresses forward over libio (and hangs there again in the others
pass).
  
Andreas Schwab March 6, 2023, 4:31 p.m. UTC | #6
On Mär 06 2023, Adhemerval Zanella Netto wrote:

> I recall Andreas saying he also found some issues with make 4.4, which
> makes me believe it is a gnumake issue indeed.

It also happens with 4.4.1 which has this issue fixed.
  
Adhemerval Zanella Netto March 6, 2023, 4:39 p.m. UTC | #7
On 06/03/23 13:31, Andreas Schwab wrote:
> On Mär 06 2023, Adhemerval Zanella Netto wrote:
> 
>> I recall Andreas saying he also found some issues with make 4.4, which
>> makes me believe it is a gnumake issue indeed.
> 
> It also happens with 4.4.1 which has this issue fixed.
> 

So could be an issue with my patch then? I did not added any new
dependency or rule with this patchset.
  
Andreas Schwab March 6, 2023, 4:53 p.m. UTC | #8
On Mär 06 2023, Adhemerval Zanella Netto wrote:

> So could be an issue with my patch then? I did not added any new
> dependency or rule with this patchset.

The new dependency is gen-as-const-headers.

I think it adds a cycle because libio-macros.h depends on
$(common-objpfx)bits/stdio_lim.h, whereas other gen-as-const-headers
don't depend on it.
  
Adhemerval Zanella Netto March 6, 2023, 5:24 p.m. UTC | #9
On 06/03/23 13:53, Andreas Schwab wrote:
> On Mär 06 2023, Adhemerval Zanella Netto wrote:
> 
>> So could be an issue with my patch then? I did not added any new
>> dependency or rule with this patchset.
> 
> The new dependency is gen-as-const-headers.
> 
> I think it adds a cycle because libio-macros.h depends on
> $(common-objpfx)bits/stdio_lim.h, whereas other gen-as-const-headers
> don't depend on it.

Right, do we really have to autogenerate stdio_lim.h? It seems that no 
target currently requires to the overrides its values.  It would be way 
simpler if we can assume the sysdeps/posix/Makefile values instead.
  
Adhemerval Zanella Netto March 6, 2023, 6:17 p.m. UTC | #10
On 06/03/23 14:24, Adhemerval Zanella Netto wrote:
> 
> 
> On 06/03/23 13:53, Andreas Schwab wrote:
>> On Mär 06 2023, Adhemerval Zanella Netto wrote:
>>
>>> So could be an issue with my patch then? I did not added any new
>>> dependency or rule with this patchset.
>>
>> The new dependency is gen-as-const-headers.
>>
>> I think it adds a cycle because libio-macros.h depends on
>> $(common-objpfx)bits/stdio_lim.h, whereas other gen-as-const-headers
>> don't depend on it.
> 
> Right, do we really have to autogenerate stdio_lim.h? It seems that no 
> target currently requires to the overrides its values.  It would be way 
> simpler if we can assume the sysdeps/posix/Makefile values instead.

Alright, I could reproduce it and I am not sure how to fix it.  This fix
requires libio-macros.sym to correctly setup _IO_file_jumps and 
_IO_wfile_jumps alias symbol, and the libio/libio-macros.sym requires to 
know the size ofstruct _IO_jump_t (which in turn uses function pointer 
that uses FILE *).

So libio-macros.sym does require stdio_lim.h in the end.  Best solution
I can think of is to just remove stdio_lim.h autogeneration, the only
real system dependent definition is FILENAME_MAX, obtained from kernel
limits.h.  I think it should be feasible to just define is a 1024 for
hurd and 4096 for Linux (these should not change in near future and
change it might incur in some compatibility issues).
  
Arsen Arsenović March 6, 2023, 6:47 p.m. UTC | #11
Adhemerval Zanella Netto via Libc-alpha <libc-alpha@sourceware.org> writes:

> On 06/03/23 14:24, Adhemerval Zanella Netto wrote:
>> 
>> 
>> On 06/03/23 13:53, Andreas Schwab wrote:
>>> On Mär 06 2023, Adhemerval Zanella Netto wrote:
>>>
>>>> So could be an issue with my patch then? I did not added any new
>>>> dependency or rule with this patchset.
>>>
>>> The new dependency is gen-as-const-headers.
>>>
>>> I think it adds a cycle because libio-macros.h depends on
>>> $(common-objpfx)bits/stdio_lim.h, whereas other gen-as-const-headers
>>> don't depend on it.
>> 
>> Right, do we really have to autogenerate stdio_lim.h? It seems that no 
>> target currently requires to the overrides its values.  It would be way 
>> simpler if we can assume the sysdeps/posix/Makefile values instead.
>
> Alright, I could reproduce it and I am not sure how to fix it.  This fix
> requires libio-macros.sym to correctly setup _IO_file_jumps and 
> _IO_wfile_jumps alias symbol, and the libio/libio-macros.sym requires to 
> know the size ofstruct _IO_jump_t (which in turn uses function pointer 
> that uses FILE *).
>
> So libio-macros.sym does require stdio_lim.h in the end.  Best solution
> I can think of is to just remove stdio_lim.h autogeneration, the only
> real system dependent definition is FILENAME_MAX, obtained from kernel
> limits.h.  I think it should be feasible to just define is a 1024 for
> hurd and 4096 for Linux (these should not change in near future and
> change it might incur in some compatibility issues).

FWIW, I have an interest in making a new port (as time permits...), so
please also add an...

  #else
  # error "Update the port!"

... or such, if you choose to do that.

TIA, have a lovely night.
  
Adhemerval Zanella Netto March 6, 2023, 6:53 p.m. UTC | #12
On 06/03/23 15:47, Arsen Arsenović wrote:
> 
> Adhemerval Zanella Netto via Libc-alpha <libc-alpha@sourceware.org> writes:
> 
>> On 06/03/23 14:24, Adhemerval Zanella Netto wrote:
>>>
>>>
>>> On 06/03/23 13:53, Andreas Schwab wrote:
>>>> On Mär 06 2023, Adhemerval Zanella Netto wrote:
>>>>
>>>>> So could be an issue with my patch then? I did not added any new
>>>>> dependency or rule with this patchset.
>>>>
>>>> The new dependency is gen-as-const-headers.
>>>>
>>>> I think it adds a cycle because libio-macros.h depends on
>>>> $(common-objpfx)bits/stdio_lim.h, whereas other gen-as-const-headers
>>>> don't depend on it.
>>>
>>> Right, do we really have to autogenerate stdio_lim.h? It seems that no 
>>> target currently requires to the overrides its values.  It would be way 
>>> simpler if we can assume the sysdeps/posix/Makefile values instead.
>>
>> Alright, I could reproduce it and I am not sure how to fix it.  This fix
>> requires libio-macros.sym to correctly setup _IO_file_jumps and 
>> _IO_wfile_jumps alias symbol, and the libio/libio-macros.sym requires to 
>> know the size ofstruct _IO_jump_t (which in turn uses function pointer 
>> that uses FILE *).
>>
>> So libio-macros.sym does require stdio_lim.h in the end.  Best solution
>> I can think of is to just remove stdio_lim.h autogeneration, the only
>> real system dependent definition is FILENAME_MAX, obtained from kernel
>> limits.h.  I think it should be feasible to just define is a 1024 for
>> hurd and 4096 for Linux (these should not change in near future and
>> change it might incur in some compatibility issues).
> 
> FWIW, I have an interest in making a new port (as time permits...), so
> please also add an...
> 
>   #else
>   # error "Update the port!"
> 
> ... or such, if you choose to do that.
> 

The usual way now is to provide arch specific files through sysdep, so
if a new target does not provide it either build will fail (if it
includes direct or indirectly it) or by running the testsuite (which
run install on a temporary file at build directory).
  
Arsen Arsenović March 6, 2023, 7:10 p.m. UTC | #13
Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> writes:

>> FWIW, I have an interest in making a new port (as time permits...), so
>> please also add an...
>> 
>>   #else
>>   # error "Update the port!"
>> 
>> ... or such, if you choose to do that.
>> 
>
> The usual way now is to provide arch specific files through sysdep, so
> if a new target does not provide it either build will fail (if it
> includes direct or indirectly it) or by running the testsuite (which
> run install on a temporary file at build directory).

I meant a kernel port (i.e. a third contender besides Hurd and Linux).
I might've misunderstood you, though, and this might not be moving
something OS-specific out of sysdeps/ - if so, disregard.
  
Adhemerval Zanella Netto March 6, 2023, 7:20 p.m. UTC | #14
On 06/03/23 16:10, Arsen Arsenović wrote:
> 
> Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> writes:
> 
>>> FWIW, I have an interest in making a new port (as time permits...), so
>>> please also add an...
>>>
>>>   #else
>>>   # error "Update the port!"
>>>
>>> ... or such, if you choose to do that.
>>>
>>
>> The usual way now is to provide arch specific files through sysdep, so
>> if a new target does not provide it either build will fail (if it
>> includes direct or indirectly it) or by running the testsuite (which
>> run install on a temporary file at build directory).
> 
> I meant a kernel port (i.e. a third contender besides Hurd and Linux).
> I might've misunderstood you, though, and this might not be moving
> something OS-specific out of sysdeps/ - if so, disregard.

Check the patch I just submit [1]: the idea would be to just add a
new sysdep/<system>/bits/stdio_lim.h as similar to what Hurd and
Linux does.

https://patchwork.sourceware.org/project/glibc/patch/20230306191642.347001-3-adhemerval.zanella@linaro.org/
  
Arsen Arsenović March 6, 2023, 7:26 p.m. UTC | #15
Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> writes:

> Check the patch I just submit [1]: the idea would be to just add a
> new sysdep/<system>/bits/stdio_lim.h as similar to what Hurd and
> Linux does.
>
> https://patchwork.sourceware.org/project/glibc/patch/20230306191642.347001-3-adhemerval.zanella@linaro.org/

Ah!  Yes - I misunderstood you indeed.  This seems perfect.

Thanks, sorry about the fuss; have a wonderful day.
  
Carlos O'Donell March 27, 2023, 12:53 p.m. UTC | #16
On 3/6/23 08:43, Adhemerval Zanella Netto wrote:
> 
> 
> On 04/03/23 14:37, Carlos O'Donell wrote:
>> On 12/27/22 16:11, Adhemerval Zanella via Libc-alpha wrote:
>>> Instead of using a special ELF section along with a linker script
>>> directive to put the IO vtables within the RELRO section, the libio
>>> vtables are iall moved to an array marked as data.relro (so linker
>>
>> s/iall/all/g
>>
>>> will place in the RELRO segment without the need of extra directives).
>>>
>>> To avoid static linking namespace issues and to pulling all vtables
>>
>> s/to pulling/including/g
>> s/vtables/vtable/g
>>
>>> referenced objects, all required function pointers are set to weak alias.
>>>
>>
>> Have you tested this against legacy applications that interpose the vtables?
>>
>> In the original design Florian wrote:
>> ~~~
>>     To enable backwards compatibility, a special flag variable
>>     (_IO_accept_foreign_vtables), protected by the pointer guard, avoids
>>     process termination if libio stream object constructor functions have
>>     been called earlier.  Such constructor functions are called by the GCC
>>     2.95 libstdc++ library, and this mechanism ensures compatibility with
>>     old binaries.  Existing callers inside glibc of these functions are
>>     adjusted to call the original functions, not the wrappers which enable
>>     vtable compatiblity.
>>     
>>     The compatibility mechanism is used to enable passing FILE * objects
>>     across a static dlopen boundary, too.
>> ~~~
> 
> I have not, but we do have tests for these (which was added after the
> vtable hardening with 29055464a03c72762969a2e8734d0d05d4d70e58).  My
> understanding is it should cover the required interface for old binaries.

Agreed, that should cover the testing requirements, thanks for reviewing the existing
tests and seeing which apply to my request. That's something I should have done in more
detail as reviewer. Thank you for that.

It also meant I re-read the whole thread on "adding compat symbols requires testing old
behaviour" which was an interesting consensus discussion. I think we have achieved that
with Florian's new tests that were part of the bug 23313 fixes.
  

Patch

diff --git a/Makerules b/Makerules
index 962b2cd90c..41fc8db4ba 100644
--- a/Makerules
+++ b/Makerules
@@ -544,34 +544,10 @@  $(LINK.o) -shared -static-libgcc -Wl,-O1 $(sysdep-LDFLAGS) \
 	  -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link)
 endef
 
-ifeq (yes,$(use-default-link))
 # If the linker is good enough, we can let it use its default linker script.
 # In the long term the custom linker script will be removed.
 shlib-lds =
 shlib-lds-flags =
-else
-# binutils only position loadable notes into the first page for binaries,
-# not for shared objects
-# lld --verbose does not dump a linker script.  Use -fuse-ld=bfd.
-$(common-objpfx)shlib.lds: $(common-objpfx)config.make $(..)Makerules
-	$(LINK.o) -shared -Wl,-O1 \
-		  -nostdlib -nostartfiles -fuse-ld=bfd \
-		  $(sysdep-LDFLAGS) $(rtld-LDFLAGS) $(LDFLAGS.so) \
-		  -Wl,--verbose 2>/dev/null | \
-	  sed > $@T \
-	      -e '/^=========/,/^=========/!d;/^=========/d' \
-	      -e 's@^.*\*(\.jcr).*$$@& \
-		 PROVIDE(__start___libc_IO_vtables = .);\
-		 __libc_IO_vtables : { *(__libc_IO_vtables) }\
-		 PROVIDE(__stop___libc_IO_vtables = .);\
-		 /DISCARD/ : { *(.gnu.glibc-stub.*) }@'
-	test -s $@T
-	mv -f $@T $@
-common-generated += shlib.lds
-
-shlib-lds = $(common-objpfx)shlib.lds
-shlib-lds-flags = -T $(shlib-lds)
-endif
 
 define build-shlib
 $(build-shlib-helper) -o $@ $(shlib-lds-flags) \
diff --git a/elf/Makefile b/elf/Makefile
index 0ecbcde962..f5157030c4 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -595,23 +595,9 @@  $(objpfx)tst-relro-ldso.out: tst-relro-symbols.py $(..)/scripts/glibcelf.py \
 $(objpfx)tst-relro-libc.out: tst-relro-symbols.py $(..)/scripts/glibcelf.py \
   $(common-objpfx)libc.so
 	$(PYTHON) tst-relro-symbols.py $(common-objpfx)libc.so \
-	    --required=_IO_cookie_jumps \
 	    --required=_IO_file_jumps \
-	    --required=_IO_file_jumps_maybe_mmap \
-	    --required=_IO_file_jumps_mmap \
-	    --required=_IO_mem_jumps \
-	    --required=_IO_printf_buffer_as_file_jumps \
-	    --required=_IO_proc_jumps \
-	    --required=_IO_str_jumps \
 	    --required=_IO_wfile_jumps \
-	    --required=_IO_wfile_jumps_maybe_mmap \
-	    --required=_IO_wfile_jumps_mmap \
-	    --required=_IO_wmem_jumps \
-	    --required=_IO_wprintf_buffer_as_file_jumps \
-	    --required=_IO_wstr_jumps \
-	    --optional=_IO_old_cookie_jumps \
-	    --optional=_IO_old_file_jumps \
-	    --optional=_IO_old_proc_jumps \
+	    --required=__io_vtables \
 	  > $@ 2>&1; $(evaluate-test)
 
 ifeq ($(run-built-tests),yes)
diff --git a/include/libc-symbols.h b/include/libc-symbols.h
index a1d422131f..02fbfe91f0 100644
--- a/include/libc-symbols.h
+++ b/include/libc-symbols.h
@@ -243,20 +243,26 @@  for linking")
    This is only necessary when defining something in assembly, or playing
    funny alias games where the size should be other than what the compiler
    thinks it is.  */
-#ifdef __ASSEMBLER__
-# define declare_object_symbol_alias(symbol, original, size) \
+#define declare_object_symbol_alias(symbol, original, size) \
   declare_object_symbol_alias_1 (symbol, original, size)
+#ifdef __ASSEMBLER__
 # define declare_object_symbol_alias_1(symbol, original, s_size) \
    strong_alias (original, symbol) ASM_LINE_SEP \
    .type C_SYMBOL_NAME (symbol), %object ASM_LINE_SEP \
    .size C_SYMBOL_NAME (symbol), s_size ASM_LINE_SEP
 #else /* Not __ASSEMBLER__.  */
 # ifdef HAVE_ASM_SET_DIRECTIVE
-#  define declare_symbol_alias_1_alias(symbol, original) \
-     ".set " __SYMBOL_PREFIX #symbol ", " __SYMBOL_PREFIX #original
+#  define declare_object_symbol_alias_1(symbol, original, size) \
+     asm (".global " __SYMBOL_PREFIX # symbol "\n" \
+	  ".type " __SYMBOL_PREFIX # symbol ", %object\n" \
+	  ".set " __SYMBOL_PREFIX #symbol ", " __SYMBOL_PREFIX original "\n" \
+	  ".size " __SYMBOL_PREFIX #symbol ", " #size "\n");
 # else
-#  define declare_symbol_alias_1_alias(symbol, original) \
-     __SYMBOL_PREFIX #symbol " = " __SYMBOL_PREFIX #original
+#  define declare_object_symbol_alias_1(symbol, original, size) \
+     asm (".global " __SYMBOL_PREFIX # symbol "\n" \
+	  ".type " __SYMBOL_PREFIX # symbol ", %object\n" \
+	  __SYMBOL_PREFIX #symbol " = " __SYMBOL_PREFIX original "\n" \
+	  ".size " __SYMBOL_PREFIX #symbol ", " #size "\n");
 # endif /* HAVE_ASM_SET_DIRECTIVE */
 #endif /* __ASSEMBLER__ */
 
diff --git a/libio/Makefile b/libio/Makefile
index 64398ab1ee..fc67aea9e2 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -51,6 +51,8 @@  routines	:=							      \
 									      \
 	libc_fatal fmemopen oldfmemopen vtables
 
+gen-as-const-headers += libio-macros.sym
+
 tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc   \
 	tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-ext2 \
 	tst-fgetws tst-ungetwc1 tst-ungetwc2 tst-swscanf tst-sscanf	      \
diff --git a/libio/fileops.c b/libio/fileops.c
index 41c18be789..87027d5adb 100644
--- a/libio/fileops.c
+++ b/libio/fileops.c
@@ -815,7 +815,7 @@  _IO_new_file_sync (FILE *fp)
 }
 libc_hidden_ver (_IO_new_file_sync, _IO_file_sync)
 
-static int
+int
 _IO_file_sync_mmap (FILE *fp)
 {
   if (fp->_IO_read_ptr != fp->_IO_read_end)
@@ -1109,7 +1109,7 @@  _IO_file_seekoff_mmap (FILE *fp, off64_t offset, int dir, int mode)
   return offset;
 }
 
-static off64_t
+off64_t
 _IO_file_seekoff_maybe_mmap (FILE *fp, off64_t offset, int dir,
 			     int mode)
 {
@@ -1360,7 +1360,7 @@  _IO_file_xsgetn (FILE *fp, void *data, size_t n)
 }
 libc_hidden_def (_IO_file_xsgetn)
 
-static size_t
+size_t
 _IO_file_xsgetn_mmap (FILE *fp, void *data, size_t n)
 {
   size_t have;
@@ -1405,7 +1405,7 @@  _IO_file_xsgetn_mmap (FILE *fp, void *data, size_t n)
   return s - (char *) data;
 }
 
-static size_t
+size_t
 _IO_file_xsgetn_maybe_mmap (FILE *fp, void *data, size_t n)
 {
   /* We only get here if this is the first attempt to read something.
@@ -1428,76 +1428,3 @@  versioned_symbol (libc, _IO_new_file_seekoff, _IO_file_seekoff, GLIBC_2_1);
 versioned_symbol (libc, _IO_new_file_underflow, _IO_file_underflow, GLIBC_2_1);
 versioned_symbol (libc, _IO_new_file_write, _IO_file_write, GLIBC_2_1);
 versioned_symbol (libc, _IO_new_file_xsputn, _IO_file_xsputn, GLIBC_2_1);
-
-const struct _IO_jump_t _IO_file_jumps libio_vtable =
-{
-  JUMP_INIT_DUMMY,
-  JUMP_INIT(finish, _IO_file_finish),
-  JUMP_INIT(overflow, _IO_file_overflow),
-  JUMP_INIT(underflow, _IO_file_underflow),
-  JUMP_INIT(uflow, _IO_default_uflow),
-  JUMP_INIT(pbackfail, _IO_default_pbackfail),
-  JUMP_INIT(xsputn, _IO_file_xsputn),
-  JUMP_INIT(xsgetn, _IO_file_xsgetn),
-  JUMP_INIT(seekoff, _IO_new_file_seekoff),
-  JUMP_INIT(seekpos, _IO_default_seekpos),
-  JUMP_INIT(setbuf, _IO_new_file_setbuf),
-  JUMP_INIT(sync, _IO_new_file_sync),
-  JUMP_INIT(doallocate, _IO_file_doallocate),
-  JUMP_INIT(read, _IO_file_read),
-  JUMP_INIT(write, _IO_new_file_write),
-  JUMP_INIT(seek, _IO_file_seek),
-  JUMP_INIT(close, _IO_file_close),
-  JUMP_INIT(stat, _IO_file_stat),
-  JUMP_INIT(showmanyc, _IO_default_showmanyc),
-  JUMP_INIT(imbue, _IO_default_imbue)
-};
-libc_hidden_data_def (_IO_file_jumps)
-
-const struct _IO_jump_t _IO_file_jumps_mmap libio_vtable =
-{
-  JUMP_INIT_DUMMY,
-  JUMP_INIT(finish, _IO_file_finish),
-  JUMP_INIT(overflow, _IO_file_overflow),
-  JUMP_INIT(underflow, _IO_file_underflow_mmap),
-  JUMP_INIT(uflow, _IO_default_uflow),
-  JUMP_INIT(pbackfail, _IO_default_pbackfail),
-  JUMP_INIT(xsputn, _IO_new_file_xsputn),
-  JUMP_INIT(xsgetn, _IO_file_xsgetn_mmap),
-  JUMP_INIT(seekoff, _IO_file_seekoff_mmap),
-  JUMP_INIT(seekpos, _IO_default_seekpos),
-  JUMP_INIT(setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
-  JUMP_INIT(sync, _IO_file_sync_mmap),
-  JUMP_INIT(doallocate, _IO_file_doallocate),
-  JUMP_INIT(read, _IO_file_read),
-  JUMP_INIT(write, _IO_new_file_write),
-  JUMP_INIT(seek, _IO_file_seek),
-  JUMP_INIT(close, _IO_file_close_mmap),
-  JUMP_INIT(stat, _IO_file_stat),
-  JUMP_INIT(showmanyc, _IO_default_showmanyc),
-  JUMP_INIT(imbue, _IO_default_imbue)
-};
-
-const struct _IO_jump_t _IO_file_jumps_maybe_mmap libio_vtable =
-{
-  JUMP_INIT_DUMMY,
-  JUMP_INIT(finish, _IO_file_finish),
-  JUMP_INIT(overflow, _IO_file_overflow),
-  JUMP_INIT(underflow, _IO_file_underflow_maybe_mmap),
-  JUMP_INIT(uflow, _IO_default_uflow),
-  JUMP_INIT(pbackfail, _IO_default_pbackfail),
-  JUMP_INIT(xsputn, _IO_new_file_xsputn),
-  JUMP_INIT(xsgetn, _IO_file_xsgetn_maybe_mmap),
-  JUMP_INIT(seekoff, _IO_file_seekoff_maybe_mmap),
-  JUMP_INIT(seekpos, _IO_default_seekpos),
-  JUMP_INIT(setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
-  JUMP_INIT(sync, _IO_new_file_sync),
-  JUMP_INIT(doallocate, _IO_file_doallocate),
-  JUMP_INIT(read, _IO_file_read),
-  JUMP_INIT(write, _IO_new_file_write),
-  JUMP_INIT(seek, _IO_file_seek),
-  JUMP_INIT(close, _IO_file_close),
-  JUMP_INIT(stat, _IO_file_stat),
-  JUMP_INIT(showmanyc, _IO_default_showmanyc),
-  JUMP_INIT(imbue, _IO_default_imbue)
-};
diff --git a/libio/iofopncook.c b/libio/iofopncook.c
index 6c27610319..338cb31c79 100644
--- a/libio/iofopncook.c
+++ b/libio/iofopncook.c
@@ -30,7 +30,7 @@ 
 #include <shlib-compat.h>
 #include <pointer_guard.h>
 
-static ssize_t
+ssize_t
 _IO_cookie_read (FILE *fp, void *buf, ssize_t size)
 {
   struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
@@ -43,7 +43,7 @@  _IO_cookie_read (FILE *fp, void *buf, ssize_t size)
   return read_cb (cfile->__cookie, buf, size);
 }
 
-static ssize_t
+ssize_t
 _IO_cookie_write (FILE *fp, const void *buf, ssize_t size)
 {
   struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
@@ -63,7 +63,7 @@  _IO_cookie_write (FILE *fp, const void *buf, ssize_t size)
   return n;
 }
 
-static off64_t
+off64_t
 _IO_cookie_seek (FILE *fp, off64_t offset, int dir)
 {
   struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
@@ -77,7 +77,7 @@  _IO_cookie_seek (FILE *fp, off64_t offset, int dir)
 	  ? _IO_pos_BAD : offset);
 }
 
-static int
+int
 _IO_cookie_close (FILE *fp)
 {
   struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
@@ -91,7 +91,7 @@  _IO_cookie_close (FILE *fp)
 }
 
 
-static off64_t
+off64_t
 _IO_cookie_seekoff (FILE *fp, off64_t offset, int dir, int mode)
 {
   /* We must force the fileops code to always use seek to determine
@@ -100,31 +100,6 @@  _IO_cookie_seekoff (FILE *fp, off64_t offset, int dir, int mode)
   return _IO_file_seekoff (fp, offset, dir, mode);
 }
 
-
-static const struct _IO_jump_t _IO_cookie_jumps libio_vtable = {
-  JUMP_INIT_DUMMY,
-  JUMP_INIT(finish, _IO_file_finish),
-  JUMP_INIT(overflow, _IO_file_overflow),
-  JUMP_INIT(underflow, _IO_file_underflow),
-  JUMP_INIT(uflow, _IO_default_uflow),
-  JUMP_INIT(pbackfail, _IO_default_pbackfail),
-  JUMP_INIT(xsputn, _IO_file_xsputn),
-  JUMP_INIT(xsgetn, _IO_default_xsgetn),
-  JUMP_INIT(seekoff, _IO_cookie_seekoff),
-  JUMP_INIT(seekpos, _IO_default_seekpos),
-  JUMP_INIT(setbuf, _IO_file_setbuf),
-  JUMP_INIT(sync, _IO_file_sync),
-  JUMP_INIT(doallocate, _IO_file_doallocate),
-  JUMP_INIT(read, _IO_cookie_read),
-  JUMP_INIT(write, _IO_cookie_write),
-  JUMP_INIT(seek, _IO_cookie_seek),
-  JUMP_INIT(close, _IO_cookie_close),
-  JUMP_INIT(stat, _IO_default_stat),
-  JUMP_INIT(showmanyc, _IO_default_showmanyc),
-  JUMP_INIT(imbue, _IO_default_imbue),
-};
-
-
 /* Copy the callbacks from SOURCE to *TARGET, with pointer
    mangling.  */
 static void
@@ -209,7 +184,7 @@  versioned_symbol (libc, _IO_fopencookie, fopencookie, GLIBC_2_2);
 
 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
 
-static off64_t
+off64_t
 attribute_compat_text_section
 _IO_old_cookie_seek (FILE *fp, off64_t offset, int dir)
 {
@@ -226,29 +201,6 @@  _IO_old_cookie_seek (FILE *fp, off64_t offset, int dir)
   return (ret == -1) ? _IO_pos_BAD : ret;
 }
 
-static const struct _IO_jump_t _IO_old_cookie_jumps libio_vtable = {
-  JUMP_INIT_DUMMY,
-  JUMP_INIT(finish, _IO_file_finish),
-  JUMP_INIT(overflow, _IO_file_overflow),
-  JUMP_INIT(underflow, _IO_file_underflow),
-  JUMP_INIT(uflow, _IO_default_uflow),
-  JUMP_INIT(pbackfail, _IO_default_pbackfail),
-  JUMP_INIT(xsputn, _IO_file_xsputn),
-  JUMP_INIT(xsgetn, _IO_default_xsgetn),
-  JUMP_INIT(seekoff, _IO_cookie_seekoff),
-  JUMP_INIT(seekpos, _IO_default_seekpos),
-  JUMP_INIT(setbuf, _IO_file_setbuf),
-  JUMP_INIT(sync, _IO_file_sync),
-  JUMP_INIT(doallocate, _IO_file_doallocate),
-  JUMP_INIT(read, _IO_cookie_read),
-  JUMP_INIT(write, _IO_cookie_write),
-  JUMP_INIT(seek, _IO_old_cookie_seek),
-  JUMP_INIT(close, _IO_cookie_close),
-  JUMP_INIT(stat, _IO_default_stat),
-  JUMP_INIT(showmanyc, _IO_default_showmanyc),
-  JUMP_INIT(imbue, _IO_default_imbue),
-};
-
 FILE *
 attribute_compat_text_section
 _IO_old_fopencookie (void *cookie, const char *mode,
diff --git a/libio/iopopen.c b/libio/iopopen.c
index 06778cf110..5ed30a817b 100644
--- a/libio/iopopen.c
+++ b/libio/iopopen.c
@@ -45,8 +45,6 @@  struct _IO_proc_file
 };
 typedef struct _IO_proc_file _IO_proc_file;
 
-static const struct _IO_jump_t _IO_proc_jumps;
-
 static struct _IO_proc_file *proc_file_chain;
 
 #ifdef _IO_MTSAFE_IO
@@ -291,29 +289,6 @@  _IO_new_proc_close (FILE *fp)
   return wstatus;
 }
 
-static const struct _IO_jump_t _IO_proc_jumps libio_vtable = {
-  JUMP_INIT_DUMMY,
-  JUMP_INIT(finish, _IO_new_file_finish),
-  JUMP_INIT(overflow, _IO_new_file_overflow),
-  JUMP_INIT(underflow, _IO_new_file_underflow),
-  JUMP_INIT(uflow, _IO_default_uflow),
-  JUMP_INIT(pbackfail, _IO_default_pbackfail),
-  JUMP_INIT(xsputn, _IO_new_file_xsputn),
-  JUMP_INIT(xsgetn, _IO_default_xsgetn),
-  JUMP_INIT(seekoff, _IO_new_file_seekoff),
-  JUMP_INIT(seekpos, _IO_default_seekpos),
-  JUMP_INIT(setbuf, _IO_new_file_setbuf),
-  JUMP_INIT(sync, _IO_new_file_sync),
-  JUMP_INIT(doallocate, _IO_file_doallocate),
-  JUMP_INIT(read, _IO_file_read),
-  JUMP_INIT(write, _IO_new_file_write),
-  JUMP_INIT(seek, _IO_file_seek),
-  JUMP_INIT(close, _IO_new_proc_close),
-  JUMP_INIT(stat, _IO_file_stat),
-  JUMP_INIT(showmanyc, _IO_default_showmanyc),
-  JUMP_INIT(imbue, _IO_default_imbue)
-};
-
 strong_alias (_IO_new_popen, __new_popen)
 versioned_symbol (libc, _IO_new_popen, _IO_popen, GLIBC_2_1);
 versioned_symbol (libc, __new_popen, popen, GLIBC_2_1);
diff --git a/libio/libio-macros.sym b/libio/libio-macros.sym
new file mode 100644
index 0000000000..cfb5cf2841
--- /dev/null
+++ b/libio/libio-macros.sym
@@ -0,0 +1,7 @@ 
+#include <libioP.h>
+
+--
+
+IO_JUMP_T_SIZE		sizeof (struct _IO_jump_t)
+IO_FILE_JUMPS_OFFSET	sizeof (struct _IO_jump_t) * IO_FILE_JUMPS
+IO_WFILE_JUMPS_OFFSET	sizeof (struct _IO_jump_t) * IO_WFILE_JUMPS
diff --git a/libio/libioP.h b/libio/libioP.h
index 8500c75fa0..523bd577ae 100644
--- a/libio/libioP.h
+++ b/libio/libioP.h
@@ -469,19 +469,68 @@  extern int _IO_default_sync (FILE *) __THROW;
 extern int _IO_default_showmanyc (FILE *) __THROW;
 extern void _IO_default_imbue (FILE *, void *) __THROW;
 
-extern const struct _IO_jump_t _IO_file_jumps;
-libc_hidden_proto (_IO_file_jumps)
-extern const struct _IO_jump_t _IO_file_jumps_mmap attribute_hidden;
-extern const struct _IO_jump_t _IO_file_jumps_maybe_mmap attribute_hidden;
-extern const struct _IO_jump_t _IO_wfile_jumps;
-libc_hidden_proto (_IO_wfile_jumps)
-extern const struct _IO_jump_t _IO_wfile_jumps_mmap attribute_hidden;
-extern const struct _IO_jump_t _IO_wfile_jumps_maybe_mmap attribute_hidden;
-extern const struct _IO_jump_t _IO_old_file_jumps attribute_hidden;
-extern const struct _IO_jump_t _IO_streambuf_jumps;
-extern const struct _IO_jump_t _IO_old_proc_jumps attribute_hidden;
-extern const struct _IO_jump_t _IO_str_jumps attribute_hidden;
-extern const struct _IO_jump_t _IO_wstr_jumps attribute_hidden;
+extern int __printf_buffer_as_file_overflow (FILE *fp, int ch);
+extern size_t __printf_buffer_as_file_xsputn (FILE *fp, const void *buf,
+					      size_t len);
+extern wint_t __wprintf_buffer_as_file_overflow (FILE *fp, int ch);
+extern size_t __wprintf_buffer_as_file_xsputn (FILE *fp, const void *buf,
+					       size_t len);
+
+enum
+{
+  IO_STR_JUMPS                    = 0,
+  IO_WSTR_JUMPS                   = 1,
+  IO_FILE_JUMPS                   = 2,
+  IO_FILE_JUMPS_MMAP              = 3,
+  IO_FILE_JUMPS_MAYBE_MMAP        = 4,
+  IO_WFILE_JUMPS                  = 5,
+  IO_WFILE_JUMPS_MMAP             = 6,
+  IO_WFILE_JUMPS_MAYBE_MMAP       = 7,
+  IO_COOKIE_JUMPS                 = 8,
+  IO_PROC_JUMPS                   = 9,
+  IO_MEM_JUMPS                    = 10,
+  IO_WMEM_JUMPS                   = 11,
+  IO_PRINTF_BUFFER_AS_FILE_JUMPS  = 12,
+  IO_WPRINTF_BUFFER_AS_FILE_JUMPS = 13,
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+  IO_OLD_FILE_JUMPS               = 14,
+  IO_OLD_PROC_JUMPS               = 15,
+  IO_OLD_COOKIED_JUMPS            = 16,
+  IO_VTABLES_NUM		  = IO_OLD_COOKIED_JUMPS + 1,
+#elif SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
+  IO_OLD_COOKIED_JUMPS            = 14,
+  IO_VTABLES_NUM		  = IO_OLD_COOKIED_JUMPS + 1,
+#else
+  IO_VTABLES_NUM		  = IO_WPRINTF_BUFFER_AS_FILE_JUMPS + 1
+#endif
+};
+#define IO_VTABLES_LEN (IO_VTABLES_NUM * sizeof (struct _IO_jump_t))
+
+extern const struct _IO_jump_t __io_vtables[] attribute_hidden;
+#define _IO_str_jumps                    (__io_vtables[IO_STR_JUMPS])
+#define _IO_wstr_jumps                   (__io_vtables[IO_WSTR_JUMPS])
+#define _IO_file_jumps                   (__io_vtables[IO_FILE_JUMPS])
+#define _IO_file_jumps_mmap              (__io_vtables[IO_FILE_JUMPS_MMAP])
+#define _IO_file_jumps_maybe_mmap        (__io_vtables[IO_FILE_JUMPS_MAYBE_MMAP])
+#define _IO_wfile_jumps                  (__io_vtables[IO_WFILE_JUMPS])
+#define _IO_wfile_jumps_mmap             (__io_vtables[IO_WFILE_JUMPS_MMAP])
+#define _IO_wfile_jumps_maybe_mmap       (__io_vtables[IO_WFILE_JUMPS_MAYBE_MMAP])
+#define _IO_cookie_jumps                 (__io_vtables[IO_COOKIE_JUMPS])
+#define _IO_proc_jumps                   (__io_vtables[IO_PROC_JUMPS])
+#define _IO_mem_jumps                    (__io_vtables[IO_MEM_JUMPS])
+#define _IO_wmem_jumps                   (__io_vtables[IO_WMEM_JUMPS])
+#define _IO_printf_buffer_as_file_jumps  (__io_vtables[IO_PRINTF_BUFFER_AS_FILE_JUMPS])
+#define _IO_wprintf_buffer_as_file_jumps (__io_vtables[IO_WPRINTF_BUFFER_AS_FILE_JUMPS])
+#define _IO_old_file_jumps               (__io_vtables[IO_OLD_FILE_JUMPS])
+#define _IO_old_proc_jumps               (__io_vtables[IO_OLD_PROC_JUMPS])
+#define _IO_old_cookie_jumps             (__io_vtables[IO_OLD_COOKIED_JUMPS])
+
+#ifdef SHARED
+# define libio_static_fn_required(name)
+#else
+# define libio_static_fn_required(name) __asm (".globl " #name);
+#endif
+
 extern int _IO_do_write (FILE *, const char *, size_t);
 libc_hidden_proto (_IO_do_write)
 extern int _IO_new_do_write (FILE *, const char *, size_t);
@@ -593,6 +642,14 @@  extern void _IO_new_file_init_internal (struct _IO_FILE_plus *)
 extern FILE* _IO_new_file_setbuf (FILE *, char *, ssize_t);
 extern FILE* _IO_file_setbuf_mmap (FILE *, char *, ssize_t);
 extern int _IO_new_file_sync (FILE *);
+extern int _IO_file_sync_mmap (FILE *) attribute_hidden;
+extern size_t  _IO_file_xsgetn_maybe_mmap (FILE *fp, void *data, size_t n)
+  attribute_hidden;
+extern size_t _IO_file_xsgetn_mmap (FILE *fp, void *data, size_t n)
+  attribute_hidden;
+extern off64_t _IO_file_seekoff_maybe_mmap (FILE *fp, off64_t offset, int dir,
+					    int mode)
+     attribute_hidden;
 extern int _IO_new_file_underflow (FILE *);
 extern int _IO_new_file_overflow (FILE *, int);
 extern off64_t _IO_new_file_seekoff (FILE *, off64_t, int, int);
@@ -625,6 +682,10 @@  extern wint_t _IO_wfile_overflow (FILE *, wint_t);
 libc_hidden_proto (_IO_wfile_overflow)
 extern off64_t _IO_wfile_seekoff (FILE *, off64_t, int, int);
 libc_hidden_proto (_IO_wfile_seekoff)
+extern wint_t _IO_wfile_underflow_maybe_mmap (FILE *fp)
+     attribute_hidden;
+extern wint_t _IO_wfile_underflow_mmap (FILE *fp)
+     attribute_hidden;
 
 /* Jumptable functions for proc_files. */
 extern FILE* _IO_proc_open (FILE *, const char *, const char *)
@@ -643,13 +704,41 @@  extern int _IO_str_overflow (FILE *, int) __THROW;
 libc_hidden_proto (_IO_str_overflow)
 extern int _IO_str_pbackfail (FILE *, int) __THROW;
 libc_hidden_proto (_IO_str_pbackfail)
-extern off64_t _IO_str_seekoff (FILE *, off64_t, int, int) __THROW;
+extern off64_t _IO_str_seekoff (FILE *, off64_t, int, int) __THROW
+ ;
 libc_hidden_proto (_IO_str_seekoff)
 extern void _IO_str_finish (FILE *, int) __THROW;
+extern int _IO_str_chk_overflow (FILE *fp, int c) __THROW
+  attribute_hidden;
+
+/* Jumptable functions for fopencookie.  */
+extern ssize_t _IO_cookie_read (FILE *fp, void *buf, ssize_t size)
+  attribute_hidden;
+extern ssize_t _IO_cookie_write (FILE *fp, const void *buf, ssize_t size)
+  attribute_hidden;
+extern off64_t _IO_cookie_seek (FILE *fp, off64_t offset, int dir)
+  attribute_hidden;
+extern int _IO_cookie_close (FILE *fp) attribute_hidden;
+extern off64_t _IO_cookie_seekoff (FILE *fp, off64_t offset, int dir, int mode)
+  attribute_hidden;
+extern off64_t _IO_old_cookie_seek (FILE *fp, off64_t offset, int dir)
+  attribute_hidden;
+
+/* Jumptable functions for obstack.  */
+extern int __IO_obstack_overflow (FILE *fp, int c) attribute_hidden;
+extern size_t __IO_obstack_xsputn (FILE *fp, const void *data, size_t n)
+  attribute_hidden;
+
+/* Jumptable functions for open_{w}memstream.  */
+extern int _IO_mem_sync (FILE* fp) __THROW attribute_hidden;
+extern void _IO_mem_finish (FILE* fp, int) __THROW attribute_hidden;
+extern int _IO_wmem_sync (FILE* fp) __THROW attribute_hidden;
+extern void _IO_wmem_finish (FILE* fp, int) __THROW attribute_hidden;
 
 /* Other strfile functions */
 struct _IO_strfile_;
 extern ssize_t _IO_str_count (FILE *) __THROW;
+extern int _IO_strn_overflow (FILE *fp, int c) __THROW attribute_hidden;
 
 /* And the wide character versions.  */
 extern void _IO_wstr_init_static (FILE *, wchar_t *, size_t, wchar_t *)
@@ -662,6 +751,10 @@  extern off64_t _IO_wstr_seekoff (FILE *, off64_t, int, int)
 extern wint_t _IO_wstr_pbackfail (FILE *, wint_t) __THROW;
 extern void _IO_wstr_finish (FILE *, int) __THROW;
 
+/* Helper functions.  */
+int _IO_helper_overflow (FILE *s, int c);
+int _IO_whelper_overflow (FILE *s, int c);
+
 /* Internal versions of v*printf that take an additional flags
    parameter.  */
 extern int __vfprintf_internal (FILE *fp, const char *format, va_list ap,
@@ -891,14 +984,6 @@  _IO_acquire_lock_fct (FILE **p)
   } while (0)
 #endif
 
-/* Collect all vtables in a special section for vtable verification.
-   These symbols cover the extent of this section.  */
-symbol_set_declare (__libc_IO_vtables)
-
-/* libio vtables need to carry this attribute so that they pass
-   validation.  */
-#define libio_vtable __attribute__ ((section ("__libc_IO_vtables")))
-
 #ifdef SHARED
 /* If equal to &_IO_vtable_check (with pointer guard protection),
    unknown vtable pointers are valid.  This function pointer is solely
@@ -933,12 +1018,9 @@  void _IO_vtable_check (void) attribute_hidden;
 static inline const struct _IO_jump_t *
 IO_validate_vtable (const struct _IO_jump_t *vtable)
 {
-  /* Fast path: The vtable pointer is within the __libc_IO_vtables
-     section.  */
-  uintptr_t section_length = __stop___libc_IO_vtables - __start___libc_IO_vtables;
   uintptr_t ptr = (uintptr_t) vtable;
-  uintptr_t offset = ptr - (uintptr_t) __start___libc_IO_vtables;
-  if (__glibc_unlikely (offset >= section_length))
+  uintptr_t offset = ptr - (uintptr_t) &__io_vtables;
+  if (__glibc_unlikely (offset >= IO_VTABLES_LEN))
     /* The vtable pointer is not in the expected section.  Use the
        slow path, which will terminate the process if necessary.  */
     _IO_vtable_check ();
diff --git a/libio/memstream.c b/libio/memstream.c
index 1ae8cd9544..b5b5254a34 100644
--- a/libio/memstream.c
+++ b/libio/memstream.c
@@ -29,34 +29,6 @@  struct _IO_FILE_memstream
 };
 
 
-static int _IO_mem_sync (FILE* fp) __THROW;
-static void _IO_mem_finish (FILE* fp, int) __THROW;
-
-
-static const struct _IO_jump_t _IO_mem_jumps libio_vtable =
-{
-  JUMP_INIT_DUMMY,
-  JUMP_INIT (finish, _IO_mem_finish),
-  JUMP_INIT (overflow, _IO_str_overflow),
-  JUMP_INIT (underflow, _IO_str_underflow),
-  JUMP_INIT (uflow, _IO_default_uflow),
-  JUMP_INIT (pbackfail, _IO_str_pbackfail),
-  JUMP_INIT (xsputn, _IO_default_xsputn),
-  JUMP_INIT (xsgetn, _IO_default_xsgetn),
-  JUMP_INIT (seekoff, _IO_str_seekoff),
-  JUMP_INIT (seekpos, _IO_default_seekpos),
-  JUMP_INIT (setbuf, _IO_default_setbuf),
-  JUMP_INIT (sync, _IO_mem_sync),
-  JUMP_INIT (doallocate, _IO_default_doallocate),
-  JUMP_INIT (read, _IO_default_read),
-  JUMP_INIT (write, _IO_default_write),
-  JUMP_INIT (seek, _IO_default_seek),
-  JUMP_INIT (close, _IO_default_close),
-  JUMP_INIT (stat, _IO_default_stat),
-  JUMP_INIT(showmanyc, _IO_default_showmanyc),
-  JUMP_INIT(imbue, _IO_default_imbue)
-};
-
 /* Open a stream that writes into a malloc'd buffer that is expanded as
    necessary.  *BUFLOC and *SIZELOC are updated with the buffer's location
    and the number of characters written on fflush or fclose.  */
@@ -105,7 +77,7 @@  libc_hidden_def (__open_memstream)
 weak_alias (__open_memstream, open_memstream)
 
 
-static int
+int
 _IO_mem_sync (FILE *fp)
 {
   struct _IO_FILE_memstream *mp = (struct _IO_FILE_memstream *) fp;
@@ -123,7 +95,7 @@  _IO_mem_sync (FILE *fp)
 }
 
 
-static void
+void
 _IO_mem_finish (FILE *fp, int dummy)
 {
   struct _IO_FILE_memstream *mp = (struct _IO_FILE_memstream *) fp;
diff --git a/libio/oldfileops.c b/libio/oldfileops.c
index ea3b864447..371c7479c6 100644
--- a/libio/oldfileops.c
+++ b/libio/oldfileops.c
@@ -716,29 +716,6 @@  _IO_old_file_xsputn (FILE *f, const void *data, size_t n)
   return n - to_do;
 }
 
-
-const struct _IO_jump_t _IO_old_file_jumps libio_vtable =
-{
-  JUMP_INIT_DUMMY,
-  JUMP_INIT(finish, _IO_old_file_finish),
-  JUMP_INIT(overflow, _IO_old_file_overflow),
-  JUMP_INIT(underflow, _IO_old_file_underflow),
-  JUMP_INIT(uflow, _IO_default_uflow),
-  JUMP_INIT(pbackfail, _IO_default_pbackfail),
-  JUMP_INIT(xsputn, _IO_old_file_xsputn),
-  JUMP_INIT(xsgetn, _IO_default_xsgetn),
-  JUMP_INIT(seekoff, _IO_old_file_seekoff),
-  JUMP_INIT(seekpos, _IO_default_seekpos),
-  JUMP_INIT(setbuf, _IO_old_file_setbuf),
-  JUMP_INIT(sync, _IO_old_file_sync),
-  JUMP_INIT(doallocate, _IO_file_doallocate),
-  JUMP_INIT(read, _IO_file_read),
-  JUMP_INIT(write, _IO_old_file_write),
-  JUMP_INIT(seek, _IO_file_seek),
-  JUMP_INIT(close, _IO_file_close),
-  JUMP_INIT(stat, _IO_file_stat)
-};
-
 compat_symbol (libc, _IO_old_do_write, _IO_do_write, GLIBC_2_0);
 compat_symbol (libc, _IO_old_file_attach, _IO_file_attach, GLIBC_2_0);
 compat_symbol (libc, _IO_old_file_close_it, _IO_file_close_it, GLIBC_2_0);
diff --git a/libio/oldiopopen.c b/libio/oldiopopen.c
index f9149413e8..206a0f3858 100644
--- a/libio/oldiopopen.c
+++ b/libio/oldiopopen.c
@@ -208,29 +208,6 @@  _IO_old_proc_close (FILE *fp)
   return wstatus;
 }
 
-const struct _IO_jump_t _IO_old_proc_jumps libio_vtable = {
-  JUMP_INIT_DUMMY,
-  JUMP_INIT(finish, _IO_old_file_finish),
-  JUMP_INIT(overflow, _IO_old_file_overflow),
-  JUMP_INIT(underflow, _IO_old_file_underflow),
-  JUMP_INIT(uflow, _IO_default_uflow),
-  JUMP_INIT(pbackfail, _IO_default_pbackfail),
-  JUMP_INIT(xsputn, _IO_old_file_xsputn),
-  JUMP_INIT(xsgetn, _IO_default_xsgetn),
-  JUMP_INIT(seekoff, _IO_old_file_seekoff),
-  JUMP_INIT(seekpos, _IO_default_seekpos),
-  JUMP_INIT(setbuf, _IO_old_file_setbuf),
-  JUMP_INIT(sync, _IO_old_file_sync),
-  JUMP_INIT(doallocate, _IO_file_doallocate),
-  JUMP_INIT(read, _IO_file_read),
-  JUMP_INIT(write, _IO_old_file_write),
-  JUMP_INIT(seek, _IO_file_seek),
-  JUMP_INIT(close, _IO_old_proc_close),
-  JUMP_INIT(stat, _IO_file_stat),
-  JUMP_INIT(showmanyc, _IO_default_showmanyc),
-  JUMP_INIT(imbue, _IO_default_imbue)
-};
-
 strong_alias (_IO_old_popen, __old_popen)
 compat_symbol (libc, _IO_old_popen, _IO_popen, GLIBC_2_0);
 compat_symbol (libc, __old_popen, popen, GLIBC_2_0);
diff --git a/libio/stdio.c b/libio/stdio.c
index e65ee86b24..356d41d277 100644
--- a/libio/stdio.c
+++ b/libio/stdio.c
@@ -33,3 +33,6 @@ 
 FILE *stdin = (FILE *) &_IO_2_1_stdin_;
 FILE *stdout = (FILE *) &_IO_2_1_stdout_;
 FILE *stderr = (FILE *) &_IO_2_1_stderr_;
+
+libio_static_fn_required (_IO_file_open);
+libio_static_fn_required (_IO_file_doallocate);
diff --git a/libio/strfile.h b/libio/strfile.h
index b7a57317d0..f2ce1ff6f3 100644
--- a/libio/strfile.h
+++ b/libio/strfile.h
@@ -78,8 +78,6 @@  typedef struct
   wchar_t overflow_buf[64];
 } _IO_wstrnfile;
 
-extern const struct _IO_jump_t _IO_wstrn_jumps attribute_hidden;
-
 /* Initialize an _IO_strfile SF to read from narrow string STRING, and
    return the corresponding FILE object.  It is not necessary to fclose
    the FILE when it is no longer needed.  */
diff --git a/libio/strops.c b/libio/strops.c
index 1cd0bf6c3d..4e2243b8d9 100644
--- a/libio/strops.c
+++ b/libio/strops.c
@@ -352,27 +352,3 @@  _IO_str_finish (FILE *fp, int dummy)
 
   _IO_default_finish (fp, 0);
 }
-
-const struct _IO_jump_t _IO_str_jumps libio_vtable =
-{
-  JUMP_INIT_DUMMY,
-  JUMP_INIT(finish, _IO_str_finish),
-  JUMP_INIT(overflow, _IO_str_overflow),
-  JUMP_INIT(underflow, _IO_str_underflow),
-  JUMP_INIT(uflow, _IO_default_uflow),
-  JUMP_INIT(pbackfail, _IO_str_pbackfail),
-  JUMP_INIT(xsputn, _IO_default_xsputn),
-  JUMP_INIT(xsgetn, _IO_default_xsgetn),
-  JUMP_INIT(seekoff, _IO_str_seekoff),
-  JUMP_INIT(seekpos, _IO_default_seekpos),
-  JUMP_INIT(setbuf, _IO_default_setbuf),
-  JUMP_INIT(sync, _IO_default_sync),
-  JUMP_INIT(doallocate, _IO_default_doallocate),
-  JUMP_INIT(read, _IO_default_read),
-  JUMP_INIT(write, _IO_default_write),
-  JUMP_INIT(seek, _IO_default_seek),
-  JUMP_INIT(close, _IO_default_close),
-  JUMP_INIT(stat, _IO_default_stat),
-  JUMP_INIT(showmanyc, _IO_default_showmanyc),
-  JUMP_INIT(imbue, _IO_default_imbue)
-};
diff --git a/libio/tst-vtables-interposed.c b/libio/tst-vtables-interposed.c
index 9d03fa0ec2..66f79dddb5 100644
--- a/libio/tst-vtables-interposed.c
+++ b/libio/tst-vtables-interposed.c
@@ -21,7 +21,12 @@ 
 /* Provide an interposed definition of the standard file handles with
    our own vtable.  stdout/stdin/stderr will not work as a result, but
    a succesful test does not print anything, so this is fine.  */
+#include "libioP.h"
+#undef _IO_file_jumps
 #define _IO_file_jumps jumps
+#undef _IO_wfile_jumps
+extern const struct _IO_jump_t _IO_wfile_jumps;
+#define _IO_wfile_jumps _IO_wfile_jumps
 #include "stdfiles.c"
 
 static int
diff --git a/libio/vtables.c b/libio/vtables.c
index e3809c28ce..2a652e0ba9 100644
--- a/libio/vtables.c
+++ b/libio/vtables.c
@@ -21,6 +21,491 @@ 
 #include <stdio.h>
 #include <ldsodefs.h>
 #include <pointer_guard.h>
+#include <libio-macros.h>
+
+/* Bot _IO_str_* and _IO_new_file functiosn are pulled into every link (from
+   stdio initialization).  */
+#ifndef SHARED
+# pragma weak _IO_default_close
+# pragma weak _IO_default_doallocate
+# pragma weak _IO_default_imbue
+# pragma weak _IO_default_pbackfail
+# pragma weak _IO_default_read
+# pragma weak _IO_default_seek
+# pragma weak _IO_default_seekpos
+# pragma weak _IO_default_setbuf
+# pragma weak _IO_default_showmanyc
+# pragma weak _IO_default_stat
+# pragma weak _IO_default_sync
+# pragma weak _IO_default_uflow
+# pragma weak _IO_default_write
+# pragma weak _IO_default_xsgetn
+# pragma weak _IO_default_xsputn
+
+# pragma weak _IO_wdefault_pbackfail
+# pragma weak _IO_wdefault_uflow
+# pragma weak _IO_wdefault_doallocate
+# pragma weak _IO_wdefault_xsgetn
+# pragma weak _IO_wdefault_xsputn
+
+# pragma weak _IO_wstr_finish
+# pragma weak _IO_wstr_overflow
+# pragma weak _IO_wstr_pbackfail
+# pragma weak _IO_wstr_seekoff
+# pragma weak _IO_wstr_underflow
+
+# pragma weak _IO_file_close
+# pragma weak _IO_file_close_mmap
+# pragma weak _IO_file_doallocate
+# pragma weak _IO_file_finish
+# pragma weak _IO_file_jumps_alia
+# pragma weak _IO_file_overflow
+# pragma weak _IO_file_read
+# pragma weak _IO_file_seek
+# pragma weak _IO_file_seekoff_maybe_mmap
+# pragma weak _IO_file_seekoff_mmap
+# pragma weak _IO_file_setbuf
+# pragma weak _IO_file_setbuf_mmap
+# pragma weak _IO_file_setbuf_mmap
+# pragma weak _IO_file_stat
+# pragma weak _IO_file_sync
+# pragma weak _IO_file_sync_mmap
+# pragma weak _IO_file_underflow
+# pragma weak _IO_file_underflow_maybe_mmap
+# pragma weak _IO_file_underflow_mmap
+# pragma weak _IO_file_xsgetn
+# pragma weak _IO_file_xsgetn_maybe_mmap
+# pragma weak _IO_file_xsgetn_mmap
+# pragma weak _IO_file_xsputn
+
+# pragma weak _IO_wfile_overflow
+# pragma weak _IO_wfile_sync
+# pragma weak _IO_wfile_underflow
+# pragma weak _IO_wfile_underflow_maybe_mmap
+# pragma weak _IO_wfile_underflow_mmap
+# pragma weak _IO_wfile_doallocate
+# pragma weak _IO_wfile_jumps_alia
+# pragma weak _IO_wfile_seekoff
+# pragma weak _IO_wfile_xsputn
+
+# pragma weak _IO_new_proc_close
+
+# pragma weak _IO_cookie_close
+# pragma weak _IO_cookie_read
+# pragma weak _IO_cookie_seek
+# pragma weak _IO_cookie_seekoff
+# pragma weak _IO_cookie_write
+
+# pragma weak _IO_mem_finish
+# pragma weak _IO_mem_sync
+
+# pragma weak _IO_wmem_finish
+# pragma weak _IO_wmem_sync
+
+# pragma weak __printf_buffer_as_file_overflow
+# pragma weak __printf_buffer_as_file_xsputn
+
+# pragma weak __wprintf_buffer_as_file_overflow
+# pragma weak __wprintf_buffer_as_file_xsputn
+#endif
+
+const struct _IO_jump_t __io_vtables[IO_VTABLES_LEN] attribute_relro =
+{
+  /* _IO_str_jumps  */
+  [IO_STR_JUMPS] =
+  {
+    JUMP_INIT_DUMMY,
+    JUMP_INIT (finish, _IO_str_finish),
+    JUMP_INIT (overflow, _IO_str_overflow),
+    JUMP_INIT (underflow, _IO_str_underflow),
+    JUMP_INIT (uflow, _IO_default_uflow),
+    JUMP_INIT (pbackfail, _IO_str_pbackfail),
+    JUMP_INIT (xsputn, _IO_default_xsputn),
+    JUMP_INIT (xsgetn, _IO_default_xsgetn),
+    JUMP_INIT (seekoff, _IO_str_seekoff),
+    JUMP_INIT (seekpos, _IO_default_seekpos),
+    JUMP_INIT (setbuf, _IO_default_setbuf),
+    JUMP_INIT (sync, _IO_default_sync),
+    JUMP_INIT (doallocate, _IO_default_doallocate),
+    JUMP_INIT (read, _IO_default_read),
+    JUMP_INIT (write, _IO_default_write),
+    JUMP_INIT (seek, _IO_default_seek),
+    JUMP_INIT (close, _IO_default_close),
+    JUMP_INIT (stat, _IO_default_stat),
+    JUMP_INIT (showmanyc, _IO_default_showmanyc),
+    JUMP_INIT (imbue, _IO_default_imbue)
+  },
+  /* _IO_wstr_jumps  */
+  [IO_WSTR_JUMPS] = {
+    JUMP_INIT_DUMMY,
+    JUMP_INIT (finish, _IO_wstr_finish),
+    JUMP_INIT (overflow, (_IO_overflow_t) _IO_wstr_overflow),
+    JUMP_INIT (underflow, (_IO_underflow_t) _IO_wstr_underflow),
+    JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
+    JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
+    JUMP_INIT (xsputn, _IO_wdefault_xsputn),
+    JUMP_INIT (xsgetn, _IO_wdefault_xsgetn),
+    JUMP_INIT (seekoff, _IO_wstr_seekoff),
+    JUMP_INIT (seekpos, _IO_default_seekpos),
+    JUMP_INIT (setbuf, _IO_default_setbuf),
+    JUMP_INIT (sync, _IO_default_sync),
+    JUMP_INIT (doallocate, _IO_wdefault_doallocate),
+    JUMP_INIT (read, _IO_default_read),
+    JUMP_INIT (write, _IO_default_write),
+    JUMP_INIT (seek, _IO_default_seek),
+    JUMP_INIT (close, _IO_default_close),
+    JUMP_INIT (stat, _IO_default_stat),
+    JUMP_INIT (showmanyc, _IO_default_showmanyc),
+    JUMP_INIT (imbue, _IO_default_imbue)
+  },
+  /* _IO_file_jumps  */
+  [IO_FILE_JUMPS] = {
+    JUMP_INIT_DUMMY,
+    JUMP_INIT (finish, _IO_file_finish),
+    JUMP_INIT (overflow, _IO_file_overflow),
+    JUMP_INIT (underflow, _IO_file_underflow),
+    JUMP_INIT (uflow, _IO_default_uflow),
+    JUMP_INIT (pbackfail, _IO_default_pbackfail),
+    JUMP_INIT (xsputn, _IO_file_xsputn),
+    JUMP_INIT (xsgetn, _IO_file_xsgetn),
+    JUMP_INIT (seekoff, _IO_new_file_seekoff),
+    JUMP_INIT (seekpos, _IO_default_seekpos),
+    JUMP_INIT (setbuf, _IO_new_file_setbuf),
+    JUMP_INIT (sync, _IO_new_file_sync),
+    JUMP_INIT (doallocate, _IO_file_doallocate),
+    JUMP_INIT (read, _IO_file_read),
+    JUMP_INIT (write, _IO_new_file_write),
+    JUMP_INIT (seek, _IO_file_seek),
+    JUMP_INIT (close, _IO_file_close),
+    JUMP_INIT (stat, _IO_file_stat),
+    JUMP_INIT (showmanyc, _IO_default_showmanyc),
+    JUMP_INIT (imbue, _IO_default_imbue)
+  },
+  /* _IO_file_jumps_mmap  */
+  [IO_FILE_JUMPS_MMAP] = {
+    JUMP_INIT_DUMMY,
+    JUMP_INIT (finish, _IO_file_finish),
+    JUMP_INIT (overflow, _IO_file_overflow),
+    JUMP_INIT (underflow, _IO_file_underflow_mmap),
+    JUMP_INIT (uflow, _IO_default_uflow),
+    JUMP_INIT (pbackfail, _IO_default_pbackfail),
+    JUMP_INIT (xsputn, _IO_new_file_xsputn),
+    JUMP_INIT (xsgetn, _IO_file_xsgetn_mmap),
+    JUMP_INIT (seekoff, _IO_file_seekoff_mmap),
+    JUMP_INIT (seekpos, _IO_default_seekpos),
+    JUMP_INIT (setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
+    JUMP_INIT (sync, _IO_file_sync_mmap),
+    JUMP_INIT (doallocate, _IO_file_doallocate),
+    JUMP_INIT (read, _IO_file_read),
+    JUMP_INIT (write, _IO_new_file_write),
+    JUMP_INIT (seek, _IO_file_seek),
+    JUMP_INIT (close, _IO_file_close_mmap),
+    JUMP_INIT (stat, _IO_file_stat),
+    JUMP_INIT (showmanyc, _IO_default_showmanyc),
+    JUMP_INIT (imbue, _IO_default_imbue)
+  },
+  /* _IO_file_jumps_maybe_mmap  */
+  [IO_FILE_JUMPS_MAYBE_MMAP] = {
+    JUMP_INIT_DUMMY,
+    JUMP_INIT (finish, _IO_file_finish),
+    JUMP_INIT (overflow, _IO_file_overflow),
+    JUMP_INIT (underflow, _IO_file_underflow_maybe_mmap),
+    JUMP_INIT (uflow, _IO_default_uflow),
+    JUMP_INIT (pbackfail, _IO_default_pbackfail),
+    JUMP_INIT (xsputn, _IO_new_file_xsputn),
+    JUMP_INIT (xsgetn, _IO_file_xsgetn_maybe_mmap),
+    JUMP_INIT (seekoff, _IO_file_seekoff_maybe_mmap),
+    JUMP_INIT (seekpos, _IO_default_seekpos),
+    JUMP_INIT (setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
+    JUMP_INIT (sync, _IO_new_file_sync),
+    JUMP_INIT (doallocate, _IO_file_doallocate),
+    JUMP_INIT (read, _IO_file_read),
+    JUMP_INIT (write, _IO_new_file_write),
+    JUMP_INIT (seek, _IO_file_seek),
+    JUMP_INIT (close, _IO_file_close),
+    JUMP_INIT (stat, _IO_file_stat),
+    JUMP_INIT (showmanyc, _IO_default_showmanyc),
+    JUMP_INIT (imbue, _IO_default_imbue)
+  },
+  /* _IO_wfile_jumps  */
+  [IO_WFILE_JUMPS] = {
+    JUMP_INIT_DUMMY,
+    JUMP_INIT (finish, _IO_new_file_finish),
+    JUMP_INIT (overflow, (_IO_overflow_t) _IO_wfile_overflow),
+    JUMP_INIT (underflow, (_IO_underflow_t) _IO_wfile_underflow),
+    JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
+    JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
+    JUMP_INIT (xsputn, _IO_wfile_xsputn),
+    JUMP_INIT (xsgetn, _IO_file_xsgetn),
+    JUMP_INIT (seekoff, _IO_wfile_seekoff),
+    JUMP_INIT (seekpos, _IO_default_seekpos),
+    JUMP_INIT (setbuf, _IO_new_file_setbuf),
+    JUMP_INIT (sync, (_IO_sync_t) _IO_wfile_sync),
+    JUMP_INIT (doallocate, _IO_wfile_doallocate),
+    JUMP_INIT (read, _IO_file_read),
+    JUMP_INIT (write, _IO_new_file_write),
+    JUMP_INIT (seek, _IO_file_seek),
+    JUMP_INIT (close, _IO_file_close),
+    JUMP_INIT (stat, _IO_file_stat),
+    JUMP_INIT (showmanyc, _IO_default_showmanyc),
+    JUMP_INIT (imbue, _IO_default_imbue)
+  },
+  /* _IO_wfile_jumps_mmap  */
+  [IO_WFILE_JUMPS_MMAP] = {
+    JUMP_INIT_DUMMY,
+    JUMP_INIT (finish, _IO_new_file_finish),
+    JUMP_INIT (overflow, (_IO_overflow_t) _IO_wfile_overflow),
+    JUMP_INIT (underflow, (_IO_underflow_t) _IO_wfile_underflow_mmap),
+    JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
+    JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
+    JUMP_INIT (xsputn, _IO_wfile_xsputn),
+    JUMP_INIT (xsgetn, _IO_file_xsgetn),
+    JUMP_INIT (seekoff, _IO_wfile_seekoff),
+    JUMP_INIT (seekpos, _IO_default_seekpos),
+    JUMP_INIT (setbuf, _IO_file_setbuf_mmap),
+    JUMP_INIT (sync, (_IO_sync_t) _IO_wfile_sync),
+    JUMP_INIT (doallocate, _IO_wfile_doallocate),
+    JUMP_INIT (read, _IO_file_read),
+    JUMP_INIT (write, _IO_new_file_write),
+    JUMP_INIT (seek, _IO_file_seek),
+    JUMP_INIT (close, _IO_file_close_mmap),
+    JUMP_INIT (stat, _IO_file_stat),
+    JUMP_INIT (showmanyc, _IO_default_showmanyc),
+    JUMP_INIT (imbue, _IO_default_imbue)
+  },
+  /* _IO_wfile_jumps_maybe_mmap  */
+  [IO_WFILE_JUMPS_MAYBE_MMAP] = {
+    JUMP_INIT_DUMMY,
+    JUMP_INIT (finish, _IO_new_file_finish),
+    JUMP_INIT (overflow, (_IO_overflow_t) _IO_wfile_overflow),
+    JUMP_INIT (underflow, (_IO_underflow_t) _IO_wfile_underflow_maybe_mmap),
+    JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
+    JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
+    JUMP_INIT (xsputn, _IO_wfile_xsputn),
+    JUMP_INIT (xsgetn, _IO_file_xsgetn),
+    JUMP_INIT (seekoff, _IO_wfile_seekoff),
+    JUMP_INIT (seekpos, _IO_default_seekpos),
+    JUMP_INIT (setbuf, _IO_file_setbuf_mmap),
+    JUMP_INIT (sync, (_IO_sync_t) _IO_wfile_sync),
+    JUMP_INIT (doallocate, _IO_wfile_doallocate),
+    JUMP_INIT (read, _IO_file_read),
+    JUMP_INIT (write, _IO_new_file_write),
+    JUMP_INIT (seek, _IO_file_seek),
+    JUMP_INIT (close, _IO_file_close),
+    JUMP_INIT (stat, _IO_file_stat),
+    JUMP_INIT (showmanyc, _IO_default_showmanyc),
+    JUMP_INIT (imbue, _IO_default_imbue)
+  },
+  /* _IO_cookie_jumps  */
+  [IO_COOKIE_JUMPS] = {
+    JUMP_INIT_DUMMY,
+    JUMP_INIT (finish, _IO_file_finish),
+    JUMP_INIT (overflow, _IO_file_overflow),
+    JUMP_INIT (underflow, _IO_file_underflow),
+    JUMP_INIT (uflow, _IO_default_uflow),
+    JUMP_INIT (pbackfail, _IO_default_pbackfail),
+    JUMP_INIT (xsputn, _IO_file_xsputn),
+    JUMP_INIT (xsgetn, _IO_default_xsgetn),
+    JUMP_INIT (seekoff, _IO_cookie_seekoff),
+    JUMP_INIT (seekpos, _IO_default_seekpos),
+    JUMP_INIT (setbuf, _IO_file_setbuf),
+    JUMP_INIT (sync, _IO_file_sync),
+    JUMP_INIT (doallocate, _IO_file_doallocate),
+    JUMP_INIT (read, _IO_cookie_read),
+    JUMP_INIT (write, _IO_cookie_write),
+    JUMP_INIT (seek, _IO_cookie_seek),
+    JUMP_INIT (close, _IO_cookie_close),
+    JUMP_INIT (stat, _IO_default_stat),
+    JUMP_INIT (showmanyc, _IO_default_showmanyc),
+    JUMP_INIT (imbue, _IO_default_imbue),
+  },
+  /* _IO_proc_jumps  */
+  [IO_PROC_JUMPS] = {
+    JUMP_INIT_DUMMY,
+    JUMP_INIT (finish, _IO_new_file_finish),
+    JUMP_INIT (overflow, _IO_new_file_overflow),
+    JUMP_INIT (underflow, _IO_new_file_underflow),
+    JUMP_INIT (uflow, _IO_default_uflow),
+    JUMP_INIT (pbackfail, _IO_default_pbackfail),
+    JUMP_INIT (xsputn, _IO_new_file_xsputn),
+    JUMP_INIT (xsgetn, _IO_default_xsgetn),
+    JUMP_INIT (seekoff, _IO_new_file_seekoff),
+    JUMP_INIT (seekpos, _IO_default_seekpos),
+    JUMP_INIT (setbuf, _IO_new_file_setbuf),
+    JUMP_INIT (sync, _IO_new_file_sync),
+    JUMP_INIT (doallocate, _IO_file_doallocate),
+    JUMP_INIT (read, _IO_file_read),
+    JUMP_INIT (write, _IO_new_file_write),
+    JUMP_INIT (seek, _IO_file_seek),
+    JUMP_INIT (close, _IO_new_proc_close),
+    JUMP_INIT (stat, _IO_file_stat),
+    JUMP_INIT (showmanyc, _IO_default_showmanyc),
+    JUMP_INIT (imbue, _IO_default_imbue)
+  },
+  /* _IO_mem_jumps  */
+  [IO_MEM_JUMPS] = {
+    JUMP_INIT_DUMMY,
+    JUMP_INIT (finish, _IO_mem_finish),
+    JUMP_INIT (overflow, _IO_str_overflow),
+    JUMP_INIT (underflow, _IO_str_underflow),
+    JUMP_INIT (uflow, _IO_default_uflow),
+    JUMP_INIT (pbackfail, _IO_str_pbackfail),
+    JUMP_INIT (xsputn, _IO_default_xsputn),
+    JUMP_INIT (xsgetn, _IO_default_xsgetn),
+    JUMP_INIT (seekoff, _IO_str_seekoff),
+    JUMP_INIT (seekpos, _IO_default_seekpos),
+    JUMP_INIT (setbuf, _IO_default_setbuf),
+    JUMP_INIT (sync, _IO_mem_sync),
+    JUMP_INIT (doallocate, _IO_default_doallocate),
+    JUMP_INIT (read, _IO_default_read),
+    JUMP_INIT (write, _IO_default_write),
+    JUMP_INIT (seek, _IO_default_seek),
+    JUMP_INIT (close, _IO_default_close),
+    JUMP_INIT (stat, _IO_default_stat),
+    JUMP_INIT (showmanyc, _IO_default_showmanyc),
+    JUMP_INIT (imbue, _IO_default_imbue)
+  },
+  /* _IO_wmem_jumps  */
+  [IO_WMEM_JUMPS] = {
+    JUMP_INIT_DUMMY,
+    JUMP_INIT (finish, _IO_wmem_finish),
+    JUMP_INIT (overflow, (_IO_overflow_t) _IO_wstr_overflow),
+    JUMP_INIT (underflow, (_IO_underflow_t) _IO_wstr_underflow),
+    JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
+    JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
+    JUMP_INIT (xsputn, _IO_wdefault_xsputn),
+    JUMP_INIT (xsgetn, _IO_wdefault_xsgetn),
+    JUMP_INIT (seekoff, _IO_wstr_seekoff),
+    JUMP_INIT (seekpos, _IO_default_seekpos),
+    JUMP_INIT (setbuf, _IO_default_setbuf),
+    JUMP_INIT (sync, _IO_wmem_sync),
+    JUMP_INIT (doallocate, _IO_wdefault_doallocate),
+    JUMP_INIT (read, _IO_default_read),
+    JUMP_INIT (write, _IO_default_write),
+    JUMP_INIT (seek, _IO_default_seek),
+    JUMP_INIT (close, _IO_default_close),
+    JUMP_INIT (stat, _IO_default_stat),
+    JUMP_INIT (showmanyc, _IO_default_showmanyc),
+    JUMP_INIT (imbue, _IO_default_imbue)
+  },
+  [IO_PRINTF_BUFFER_AS_FILE_JUMPS] = {
+    JUMP_INIT_DUMMY,
+    JUMP_INIT (finish, NULL),
+    JUMP_INIT (overflow, __printf_buffer_as_file_overflow),
+    JUMP_INIT (underflow, NULL),
+    JUMP_INIT (uflow, NULL),
+    JUMP_INIT (pbackfail, NULL),
+    JUMP_INIT (xsputn, __printf_buffer_as_file_xsputn),
+    JUMP_INIT (xsgetn, NULL),
+    JUMP_INIT (seekoff, NULL),
+    JUMP_INIT (seekpos, NULL),
+    JUMP_INIT (setbuf, NULL),
+    JUMP_INIT (sync, NULL),
+    JUMP_INIT (doallocate, NULL),
+    JUMP_INIT (read, NULL),
+    JUMP_INIT (write, NULL),
+    JUMP_INIT (seek, NULL),
+    JUMP_INIT (close, NULL),
+    JUMP_INIT (stat, NULL),
+    JUMP_INIT (showmanyc, NULL),
+    JUMP_INIT (imbue, NULL)
+  },
+  [IO_WPRINTF_BUFFER_AS_FILE_JUMPS] = {
+    JUMP_INIT_DUMMY,
+    JUMP_INIT (finish, NULL),
+    JUMP_INIT (overflow, (_IO_overflow_t) __wprintf_buffer_as_file_overflow),
+    JUMP_INIT (underflow, NULL),
+    JUMP_INIT (uflow, NULL),
+    JUMP_INIT (pbackfail, NULL),
+    JUMP_INIT (xsputn, __wprintf_buffer_as_file_xsputn),
+    JUMP_INIT (xsgetn, NULL),
+    JUMP_INIT (seekoff, NULL),
+    JUMP_INIT (seekpos, NULL),
+    JUMP_INIT (setbuf, NULL),
+    JUMP_INIT (sync, NULL),
+    JUMP_INIT (doallocate, NULL),
+    JUMP_INIT (read, NULL),
+    JUMP_INIT (write, NULL),
+    JUMP_INIT (seek, NULL),
+    JUMP_INIT (close, NULL),
+    JUMP_INIT (stat, NULL),
+    JUMP_INIT (showmanyc, NULL),
+    JUMP_INIT (imbue, NULL)
+  },
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+  /* _IO_old_file_jumps  */
+  [IO_OLD_FILE_JUMPS] = {
+    JUMP_INIT_DUMMY,
+    JUMP_INIT (finish, _IO_old_file_finish),
+    JUMP_INIT (overflow, _IO_old_file_overflow),
+    JUMP_INIT (underflow, _IO_old_file_underflow),
+    JUMP_INIT (uflow, _IO_default_uflow),
+    JUMP_INIT (pbackfail, _IO_default_pbackfail),
+    JUMP_INIT (xsputn, _IO_old_file_xsputn),
+    JUMP_INIT (xsgetn, _IO_default_xsgetn),
+    JUMP_INIT (seekoff, _IO_old_file_seekoff),
+    JUMP_INIT (seekpos, _IO_default_seekpos),
+    JUMP_INIT (setbuf, _IO_old_file_setbuf),
+    JUMP_INIT (sync, _IO_old_file_sync),
+    JUMP_INIT (doallocate, _IO_file_doallocate),
+    JUMP_INIT (read, _IO_file_read),
+    JUMP_INIT (write, _IO_old_file_write),
+    JUMP_INIT (seek, _IO_file_seek),
+    JUMP_INIT (close, _IO_file_close),
+    JUMP_INIT (stat, _IO_file_stat)
+  },
+  /*  _IO_old_proc_jumps  */
+  [IO_OLD_PROC_JUMPS] = {
+    JUMP_INIT_DUMMY,
+    JUMP_INIT (finish, _IO_old_file_finish),
+    JUMP_INIT (overflow, _IO_old_file_overflow),
+    JUMP_INIT (underflow, _IO_old_file_underflow),
+    JUMP_INIT (uflow, _IO_default_uflow),
+    JUMP_INIT (pbackfail, _IO_default_pbackfail),
+    JUMP_INIT (xsputn, _IO_old_file_xsputn),
+    JUMP_INIT (xsgetn, _IO_default_xsgetn),
+    JUMP_INIT (seekoff, _IO_old_file_seekoff),
+    JUMP_INIT (seekpos, _IO_default_seekpos),
+    JUMP_INIT (setbuf, _IO_old_file_setbuf),
+    JUMP_INIT (sync, _IO_old_file_sync),
+    JUMP_INIT (doallocate, _IO_file_doallocate),
+    JUMP_INIT (read, _IO_file_read),
+    JUMP_INIT (write, _IO_old_file_write),
+    JUMP_INIT (seek, _IO_file_seek),
+    JUMP_INIT (close, _IO_old_proc_close),
+    JUMP_INIT (stat, _IO_file_stat),
+    JUMP_INIT (showmanyc, _IO_default_showmanyc),
+    JUMP_INIT (imbue, _IO_default_imbue)
+  },
+#endif
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
+  /* _IO_old_cookie_jumps  */
+  [IO_OLD_COOKIED_JUMPS] = {
+    JUMP_INIT_DUMMY,
+    JUMP_INIT (finish, _IO_file_finish),
+    JUMP_INIT (overflow, _IO_file_overflow),
+    JUMP_INIT (underflow, _IO_file_underflow),
+    JUMP_INIT (uflow, _IO_default_uflow),
+    JUMP_INIT (pbackfail, _IO_default_pbackfail),
+    JUMP_INIT (xsputn, _IO_file_xsputn),
+    JUMP_INIT (xsgetn, _IO_default_xsgetn),
+    JUMP_INIT (seekoff, _IO_cookie_seekoff),
+    JUMP_INIT (seekpos, _IO_default_seekpos),
+    JUMP_INIT (setbuf, _IO_file_setbuf),
+    JUMP_INIT (sync, _IO_file_sync),
+    JUMP_INIT (doallocate, _IO_file_doallocate),
+    JUMP_INIT (read, _IO_cookie_read),
+    JUMP_INIT (write, _IO_cookie_write),
+    JUMP_INIT (seek, _IO_old_cookie_seek),
+    JUMP_INIT (close, _IO_cookie_close),
+    JUMP_INIT (stat, _IO_default_stat),
+    JUMP_INIT (showmanyc, _IO_default_showmanyc),
+    JUMP_INIT (imbue, _IO_default_imbue),
+  },
+#endif
+};
 
 #ifdef SHARED
 
@@ -82,3 +567,15 @@  check_stdfiles_vtables (void)
     IO_set_accept_foreign_vtables (&_IO_vtable_check);
 }
 #endif
+
+#define STR(s)  XSTR(s)
+#define XSTR(s) #s
+
+#undef _IO_file_jumps
+#define _IO_file_jumps_alias  "__io_vtables + " STR(IO_FILE_JUMPS_OFFSET)
+declare_object_symbol_alias (_IO_file_jumps, _IO_file_jumps_alias,
+			     IO_JUMP_T_SIZE)
+#undef _IO_wfile_jumps
+#define _IO_wfile_jumps_alias  "__io_vtables + " STR(IO_WFILE_JUMPS_OFFSET)
+declare_object_symbol_alias (_IO_wfile_jumps, _IO_wfile_jumps_alias,
+			     IO_JUMP_T_SIZE)
diff --git a/libio/wfileops.c b/libio/wfileops.c
index b59a98881f..f92d9b42eb 100644
--- a/libio/wfileops.c
+++ b/libio/wfileops.c
@@ -328,7 +328,7 @@  _IO_wfile_underflow (FILE *fp)
 libc_hidden_def (_IO_wfile_underflow)
 
 
-static wint_t
+wint_t
 _IO_wfile_underflow_mmap (FILE *fp)
 {
   struct _IO_codecvt *cd;
@@ -389,7 +389,7 @@  _IO_wfile_underflow_mmap (FILE *fp)
   return WEOF;
 }
 
-static wint_t
+wint_t
 _IO_wfile_underflow_maybe_mmap (FILE *fp)
 {
   /* This is the first read attempt.  Doing the underflow will choose mmap
@@ -1017,78 +1017,3 @@  _IO_wfile_xsputn (FILE *f, const void *data, size_t n)
   return n - to_do;
 }
 libc_hidden_def (_IO_wfile_xsputn)
-
-
-const struct _IO_jump_t _IO_wfile_jumps libio_vtable =
-{
-  JUMP_INIT_DUMMY,
-  JUMP_INIT(finish, _IO_new_file_finish),
-  JUMP_INIT(overflow, (_IO_overflow_t) _IO_wfile_overflow),
-  JUMP_INIT(underflow, (_IO_underflow_t) _IO_wfile_underflow),
-  JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
-  JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
-  JUMP_INIT(xsputn, _IO_wfile_xsputn),
-  JUMP_INIT(xsgetn, _IO_file_xsgetn),
-  JUMP_INIT(seekoff, _IO_wfile_seekoff),
-  JUMP_INIT(seekpos, _IO_default_seekpos),
-  JUMP_INIT(setbuf, _IO_new_file_setbuf),
-  JUMP_INIT(sync, (_IO_sync_t) _IO_wfile_sync),
-  JUMP_INIT(doallocate, _IO_wfile_doallocate),
-  JUMP_INIT(read, _IO_file_read),
-  JUMP_INIT(write, _IO_new_file_write),
-  JUMP_INIT(seek, _IO_file_seek),
-  JUMP_INIT(close, _IO_file_close),
-  JUMP_INIT(stat, _IO_file_stat),
-  JUMP_INIT(showmanyc, _IO_default_showmanyc),
-  JUMP_INIT(imbue, _IO_default_imbue)
-};
-libc_hidden_data_def (_IO_wfile_jumps)
-
-
-const struct _IO_jump_t _IO_wfile_jumps_mmap libio_vtable =
-{
-  JUMP_INIT_DUMMY,
-  JUMP_INIT(finish, _IO_new_file_finish),
-  JUMP_INIT(overflow, (_IO_overflow_t) _IO_wfile_overflow),
-  JUMP_INIT(underflow, (_IO_underflow_t) _IO_wfile_underflow_mmap),
-  JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
-  JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
-  JUMP_INIT(xsputn, _IO_wfile_xsputn),
-  JUMP_INIT(xsgetn, _IO_file_xsgetn),
-  JUMP_INIT(seekoff, _IO_wfile_seekoff),
-  JUMP_INIT(seekpos, _IO_default_seekpos),
-  JUMP_INIT(setbuf, _IO_file_setbuf_mmap),
-  JUMP_INIT(sync, (_IO_sync_t) _IO_wfile_sync),
-  JUMP_INIT(doallocate, _IO_wfile_doallocate),
-  JUMP_INIT(read, _IO_file_read),
-  JUMP_INIT(write, _IO_new_file_write),
-  JUMP_INIT(seek, _IO_file_seek),
-  JUMP_INIT(close, _IO_file_close_mmap),
-  JUMP_INIT(stat, _IO_file_stat),
-  JUMP_INIT(showmanyc, _IO_default_showmanyc),
-  JUMP_INIT(imbue, _IO_default_imbue)
-};
-
-const struct _IO_jump_t _IO_wfile_jumps_maybe_mmap libio_vtable =
-{
-  JUMP_INIT_DUMMY,
-  JUMP_INIT(finish, _IO_new_file_finish),
-  JUMP_INIT(overflow, (_IO_overflow_t) _IO_wfile_overflow),
-  JUMP_INIT(underflow, (_IO_underflow_t) _IO_wfile_underflow_maybe_mmap),
-  JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
-  JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
-  JUMP_INIT(xsputn, _IO_wfile_xsputn),
-  JUMP_INIT(xsgetn, _IO_file_xsgetn),
-  JUMP_INIT(seekoff, _IO_wfile_seekoff),
-  JUMP_INIT(seekpos, _IO_default_seekpos),
-  JUMP_INIT(setbuf, _IO_file_setbuf_mmap),
-  JUMP_INIT(sync, (_IO_sync_t) _IO_wfile_sync),
-  JUMP_INIT(doallocate, _IO_wfile_doallocate),
-  JUMP_INIT(read, _IO_file_read),
-  JUMP_INIT(write, _IO_new_file_write),
-  JUMP_INIT(seek, _IO_file_seek),
-  JUMP_INIT(close, _IO_file_close),
-  JUMP_INIT(stat, _IO_file_stat),
-  JUMP_INIT(showmanyc, _IO_default_showmanyc),
-  JUMP_INIT(imbue, _IO_default_imbue)
-};
diff --git a/libio/wmemstream.c b/libio/wmemstream.c
index e7f898c7fb..50ad1bdc86 100644
--- a/libio/wmemstream.c
+++ b/libio/wmemstream.c
@@ -30,34 +30,6 @@  struct _IO_FILE_wmemstream
 };
 
 
-static int _IO_wmem_sync (FILE* fp) __THROW;
-static void _IO_wmem_finish (FILE* fp, int) __THROW;
-
-
-static const struct _IO_jump_t _IO_wmem_jumps libio_vtable =
-{
-  JUMP_INIT_DUMMY,
-  JUMP_INIT (finish, _IO_wmem_finish),
-  JUMP_INIT (overflow, (_IO_overflow_t) _IO_wstr_overflow),
-  JUMP_INIT (underflow, (_IO_underflow_t) _IO_wstr_underflow),
-  JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
-  JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
-  JUMP_INIT (xsputn, _IO_wdefault_xsputn),
-  JUMP_INIT (xsgetn, _IO_wdefault_xsgetn),
-  JUMP_INIT (seekoff, _IO_wstr_seekoff),
-  JUMP_INIT (seekpos, _IO_default_seekpos),
-  JUMP_INIT (setbuf, _IO_default_setbuf),
-  JUMP_INIT (sync, _IO_wmem_sync),
-  JUMP_INIT (doallocate, _IO_wdefault_doallocate),
-  JUMP_INIT (read, _IO_default_read),
-  JUMP_INIT (write, _IO_default_write),
-  JUMP_INIT (seek, _IO_default_seek),
-  JUMP_INIT (close, _IO_default_close),
-  JUMP_INIT (stat, _IO_default_stat),
-  JUMP_INIT (showmanyc, _IO_default_showmanyc),
-  JUMP_INIT (imbue, _IO_default_imbue)
-};
-
 /* Open a stream that writes into a malloc'd buffer that is expanded as
    necessary.  *BUFLOC and *SIZELOC are updated with the buffer's location
    and the number of characters written on fflush or fclose.  */
@@ -105,7 +77,7 @@  open_wmemstream (wchar_t **bufloc, size_t *sizeloc)
 }
 
 
-static int
+int
 _IO_wmem_sync (FILE *fp)
 {
   struct _IO_FILE_wmemstream *mp = (struct _IO_FILE_wmemstream *) fp;
@@ -124,7 +96,7 @@  _IO_wmem_sync (FILE *fp)
 }
 
 
-static void
+void
 _IO_wmem_finish (FILE *fp, int dummy)
 {
   struct _IO_FILE_wmemstream *mp = (struct _IO_FILE_wmemstream *) fp;
diff --git a/libio/wstrops.c b/libio/wstrops.c
index 2aec314937..ac7efe9f65 100644
--- a/libio/wstrops.c
+++ b/libio/wstrops.c
@@ -361,27 +361,3 @@  _IO_wstr_finish (FILE *fp, int dummy)
 
   _IO_wdefault_finish (fp, 0);
 }
-
-const struct _IO_jump_t _IO_wstr_jumps libio_vtable =
-{
-  JUMP_INIT_DUMMY,
-  JUMP_INIT(finish, _IO_wstr_finish),
-  JUMP_INIT(overflow, (_IO_overflow_t) _IO_wstr_overflow),
-  JUMP_INIT(underflow, (_IO_underflow_t) _IO_wstr_underflow),
-  JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
-  JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
-  JUMP_INIT(xsputn, _IO_wdefault_xsputn),
-  JUMP_INIT(xsgetn, _IO_wdefault_xsgetn),
-  JUMP_INIT(seekoff, _IO_wstr_seekoff),
-  JUMP_INIT(seekpos, _IO_default_seekpos),
-  JUMP_INIT(setbuf, _IO_default_setbuf),
-  JUMP_INIT(sync, _IO_default_sync),
-  JUMP_INIT(doallocate, _IO_wdefault_doallocate),
-  JUMP_INIT(read, _IO_default_read),
-  JUMP_INIT(write, _IO_default_write),
-  JUMP_INIT(seek, _IO_default_seek),
-  JUMP_INIT(close, _IO_default_close),
-  JUMP_INIT(stat, _IO_default_stat),
-  JUMP_INIT(showmanyc, _IO_default_showmanyc),
-  JUMP_INIT(imbue, _IO_default_imbue)
-};
diff --git a/stdio-common/printf_buffer_as_file.c b/stdio-common/printf_buffer_as_file.c
index f27b000d78..cd36fa77e4 100644
--- a/stdio-common/printf_buffer_as_file.c
+++ b/stdio-common/printf_buffer_as_file.c
@@ -48,7 +48,7 @@  __printf_buffer_as_file_switch_to_buffer (struct __printf_buffer_as_file *file)
 /* Only a small subset of the vtable functions is implemented here,
    following _IO_obstack_jumps.  */
 
-static int
+int
 __printf_buffer_as_file_overflow (FILE *fp, int ch)
 {
   struct __printf_buffer_as_file *file = (struct __printf_buffer_as_file *) fp;
@@ -72,7 +72,7 @@  __printf_buffer_as_file_overflow (FILE *fp, int ch)
     return EOF;
 }
 
-static size_t
+size_t
 __printf_buffer_as_file_xsputn (FILE *fp, const void *buf, size_t len)
 {
   struct __printf_buffer_as_file *file = (struct __printf_buffer_as_file *) fp;
@@ -93,30 +93,6 @@  __printf_buffer_as_file_xsputn (FILE *fp, const void *buf, size_t len)
     return 0;
 }
 
-static const struct _IO_jump_t _IO_printf_buffer_as_file_jumps libio_vtable =
-{
-  JUMP_INIT_DUMMY,
-  JUMP_INIT(finish, NULL),
-  JUMP_INIT(overflow, __printf_buffer_as_file_overflow),
-  JUMP_INIT(underflow, NULL),
-  JUMP_INIT(uflow, NULL),
-  JUMP_INIT(pbackfail, NULL),
-  JUMP_INIT(xsputn, __printf_buffer_as_file_xsputn),
-  JUMP_INIT(xsgetn, NULL),
-  JUMP_INIT(seekoff, NULL),
-  JUMP_INIT(seekpos, NULL),
-  JUMP_INIT(setbuf, NULL),
-  JUMP_INIT(sync, NULL),
-  JUMP_INIT(doallocate, NULL),
-  JUMP_INIT(read, NULL),
-  JUMP_INIT(write, NULL),
-  JUMP_INIT(seek, NULL),
-  JUMP_INIT(close, NULL),
-  JUMP_INIT(stat, NULL),
-  JUMP_INIT(showmanyc, NULL),
-  JUMP_INIT(imbue, NULL)
-};
-
 void
 __printf_buffer_as_file_init (struct __printf_buffer_as_file *file,
                               struct __printf_buffer *next)
diff --git a/stdio-common/wprintf_buffer_as_file.c b/stdio-common/wprintf_buffer_as_file.c
index cd48a7d42a..f0d05f8b4a 100644
--- a/stdio-common/wprintf_buffer_as_file.c
+++ b/stdio-common/wprintf_buffer_as_file.c
@@ -48,7 +48,7 @@  __wprintf_buffer_as_file_switch_to_buffer (struct __wprintf_buffer_as_file *file
 /* Only a small subset of the vtable functions is implemented here,
    following _IO_obstack_jumps.  */
 
-static wint_t
+wint_t
 __wprintf_buffer_as_file_overflow (FILE *fp, int ch)
 {
   struct __wprintf_buffer_as_file *file
@@ -75,7 +75,7 @@  __wprintf_buffer_as_file_overflow (FILE *fp, int ch)
     return WEOF;
 }
 
-static size_t
+size_t
 __wprintf_buffer_as_file_xsputn (FILE *fp, const void *buf, size_t len)
 {
   struct __wprintf_buffer_as_file *file
@@ -97,30 +97,6 @@  __wprintf_buffer_as_file_xsputn (FILE *fp, const void *buf, size_t len)
     return 0;
 }
 
-static const struct _IO_jump_t _IO_wprintf_buffer_as_file_jumps libio_vtable =
-{
-  JUMP_INIT_DUMMY,
-  JUMP_INIT(finish, NULL),
-  JUMP_INIT(overflow, (_IO_overflow_t) __wprintf_buffer_as_file_overflow),
-  JUMP_INIT(underflow, NULL),
-  JUMP_INIT(uflow, NULL),
-  JUMP_INIT(pbackfail, NULL),
-  JUMP_INIT(xsputn, __wprintf_buffer_as_file_xsputn),
-  JUMP_INIT(xsgetn, NULL),
-  JUMP_INIT(seekoff, NULL),
-  JUMP_INIT(seekpos, NULL),
-  JUMP_INIT(setbuf, NULL),
-  JUMP_INIT(sync, NULL),
-  JUMP_INIT(doallocate, NULL),
-  JUMP_INIT(read, NULL),
-  JUMP_INIT(write, NULL),
-  JUMP_INIT(seek, NULL),
-  JUMP_INIT(close, NULL),
-  JUMP_INIT(stat, NULL),
-  JUMP_INIT(showmanyc, NULL),
-  JUMP_INIT(imbue, NULL)
-};
-
 void
 __wprintf_buffer_as_file_init (struct __wprintf_buffer_as_file *file,
                                struct __wprintf_buffer *next)