From da7f049cad943629f16cd6e533214955edfd511d Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Wed, 3 Jun 2015 13:51:11 -0700 Subject: [PATCH] NaCl: Implement nacl_interface_ext_supply entry point. --- ChangeLog | 12 +++++++ sysdeps/nacl/Makefile | 2 +- sysdeps/nacl/Versions | 2 ++ sysdeps/nacl/nacl-interfaces.c | 42 ++++++++++++++++++++++++ sysdeps/nacl/nacl-interfaces.h | 9 ++++- sysdeps/nacl/nacl_interface_ext_supply.c | 42 ++++++++++++++++++++++++ 6 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 sysdeps/nacl/nacl_interface_ext_supply.c diff --git a/ChangeLog b/ChangeLog index 33d9f66142..e0e6d6b210 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2015-06-03 Roland McGrath + + * sysdeps/nacl/nacl-interfaces.c (try_supply): New static function. + (PASTE_NAME (__nacl_supply_interface_, MODULE_NAME)): New function. + * sysdeps/nacl/nacl-interfaces.h: Declare __nacl_supply_interface_libc + and __nacl_supply_interface_rtld. + * sysdeps/nacl/nacl_interface_ext_supply.c: New file. + * sysdeps/nacl/Makefile [$(subdir) = csu] (sysdep_routines): Add it. + * sysdeps/nacl/Versions (ld: GLIBC_PRIVATE): + Add __nacl_supply_interface_rtld. + (libc: GLIBC_2.22): Add nacl_interface_ext_supply. + 2015-06-03 Wilco Dijkstra * sysdeps/ieee754/ldbl-128ibm/s_fmal.c (__fmal): Replace finite with diff --git a/sysdeps/nacl/Makefile b/sysdeps/nacl/Makefile index b51156b5ad..6749a44c53 100644 --- a/sysdeps/nacl/Makefile +++ b/sysdeps/nacl/Makefile @@ -108,7 +108,7 @@ test-wrapper-env = $(test-wrapper-env-only) test-wrapper = $(test-wrapper-env) -- ifeq ($(subdir),csu) -sysdep_routines += nacl_interface_query \ +sysdep_routines += nacl_interface_query nacl_interface_ext_supply \ nacl-interfaces $(call nacl-routines-of,libc) endif diff --git a/sysdeps/nacl/Versions b/sysdeps/nacl/Versions index 4ac56c2a28..cfc4a08c40 100644 --- a/sysdeps/nacl/Versions +++ b/sysdeps/nacl/Versions @@ -1,12 +1,14 @@ ld { GLIBC_PRIVATE { __nacl_irt_*; + __nacl_supply_interface_rtld; } } libc { GLIBC_2.22 { nacl_interface_query; + nacl_interface_ext_supply; } GLIBC_PRIVATE { diff --git a/sysdeps/nacl/nacl-interfaces.c b/sysdeps/nacl/nacl-interfaces.c index cb0dcd0bc8..5dbfadd7f1 100644 --- a/sysdeps/nacl/nacl-interfaces.c +++ b/sysdeps/nacl/nacl-interfaces.c @@ -121,3 +121,45 @@ __nacl_initialize_interfaces (void) initialize_mandatory_interfaces (); initialize_optional_interfaces (); } + + +static bool +try_supply (const struct nacl_interface *const start, + const struct nacl_interface *const stop, + uintptr_t *all_tables, + const char *ident, size_t ident_len, + const void *table, size_t tablesize) +{ + const struct nacl_interface *i = start; + uintptr_t *t = all_tables; + while (i < stop) + { + if (i->table_size == tablesize + && i->namelen == ident_len + && !memcmp (i->name, ident, ident_len)) + { + memcpy (t, table, tablesize); + return true; + } + + t = next_nacl_table (t, i); + i = next_nacl_interface (i); + } + + return false; +} + +internal_function +bool +PASTE_NAME (__nacl_supply_interface_, MODULE_NAME) + (const char *ident, size_t ident_len, const void *table, size_t tablesize) +{ + return (try_supply (__start_nacl_mandatory_interface_names, + __stop_nacl_mandatory_interface_names, + __start_nacl_mandatory_interface_tables, + ident, ident_len, table, tablesize) + || try_supply (__start_nacl_optional_interface_names, + __stop_nacl_optional_interface_names, + __start_nacl_optional_interface_tables, + ident, ident_len, table, tablesize)); +} diff --git a/sysdeps/nacl/nacl-interfaces.h b/sysdeps/nacl/nacl-interfaces.h index 0c886a5bd7..36f380886c 100644 --- a/sysdeps/nacl/nacl-interfaces.h +++ b/sysdeps/nacl/nacl-interfaces.h @@ -20,6 +20,7 @@ #define _NACL_INTERFACES_H 1 #include +#include #include #include #include @@ -73,7 +74,7 @@ next_nacl_interface (const struct nacl_interface *i) { uintptr_t align = __alignof (*i); return (const void *) (((uintptr_t) &i->name[i->namelen] + align - 1) - & -align); + & -align); } #if IS_IN (libpthread) @@ -94,6 +95,12 @@ next_nacl_interface (const struct nacl_interface *i) #undef NACL_OPTIONAL_INTERFACE extern void __nacl_initialize_interfaces (void) attribute_hidden; +extern bool __nacl_supply_interface_libc (const char *ident, size_t ident_len, + const void *table, size_t tablesize) + internal_function attribute_hidden; +extern bool __nacl_supply_interface_rtld (const char *ident, size_t ident_len, + const void *table, size_t tablesize); + internal_function; /* Convenience function for handling IRT call return values. */ static inline int diff --git a/sysdeps/nacl/nacl_interface_ext_supply.c b/sysdeps/nacl/nacl_interface_ext_supply.c new file mode 100644 index 0000000000..a1525be58c --- /dev/null +++ b/sysdeps/nacl/nacl_interface_ext_supply.c @@ -0,0 +1,42 @@ +/* Interface for the user to replace NaCl IRT interface functions. + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include + +size_t +nacl_interface_ext_supply (const char *interface_ident, + const void *table, size_t tablesize) +{ + const size_t ident_len = strlen (interface_ident) + 1; + + /* Most interfaces are in rtld, so try there first. If other + libraries ever get their own tables not used in libc, then we + will need some dynamic registration mechanism here to iterate + over all libraries' __nacl_supply_interface_libfoo calls. */ + if (0 +#ifdef SHARED + || __nacl_supply_interface_rtld (interface_ident, ident_len, + table, tablesize) +#endif + || __nacl_supply_interface_libc (interface_ident, ident_len, + table, tablesize)) + return tablesize; + + return 0; +}