diff options
-rw-r--r-- | abi-tags | 2 | ||||
-rw-r--r-- | sysdeps/arm/nacl/Makefile | 23 | ||||
-rw-r--r-- | sysdeps/arm/nacl/dl-machine.h | 17 | ||||
-rw-r--r-- | sysdeps/nacl/Makefile | 38 | ||||
-rw-r--r-- | sysdeps/nacl/Versions | 2 | ||||
-rw-r--r-- | sysdeps/nacl/____longjmp_chk.c | 28 | ||||
-rw-r--r-- | sysdeps/nacl/_exit.c | 3 | ||||
-rw-r--r-- | sysdeps/nacl/bits/dirent.h | 2 | ||||
-rw-r--r-- | sysdeps/nacl/dl-map-segments.h | 320 | ||||
-rw-r--r-- | sysdeps/nacl/dl-sysdep.c | 15 | ||||
-rw-r--r-- | sysdeps/nacl/errnos.awk | 21 | ||||
-rw-r--r-- | sysdeps/nacl/glob.c | 26 | ||||
-rw-r--r-- | sysdeps/nacl/isatty.c | 11 | ||||
-rw-r--r-- | sysdeps/nacl/ldsodefs.h | 2 | ||||
-rwxr-xr-x | sysdeps/nacl/nacl-after-link.sh | 69 | ||||
-rw-r--r-- | sysdeps/nacl/nacl-interface-list.h | 48 | ||||
-rw-r--r-- | sysdeps/nacl/nacl-interfaces.c | 11 | ||||
-rw-r--r-- | sysdeps/nacl/rename.c | 2 | ||||
-rw-r--r-- | sysdeps/nacl/shlib-versions | 6 |
19 files changed, 398 insertions, 248 deletions
diff --git a/abi-tags b/abi-tags index 9eaf23e083..930a88942d 100644 --- a/abi-tags +++ b/abi-tags @@ -1,4 +1,4 @@ # Configuration ABI OS ABI version # ------------- ------ ----------- -.*-.*-nacl.* 6 22.0.0 +.*-.*-nacl.* 6 42.0.0 diff --git a/sysdeps/arm/nacl/Makefile b/sysdeps/arm/nacl/Makefile index 5e56895cbd..c9226595e6 100644 --- a/sysdeps/arm/nacl/Makefile +++ b/sysdeps/arm/nacl/Makefile @@ -1,3 +1,26 @@ +# Makefile fragment for ARM/NaCl configurations. + +# 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 +# <http://www.gnu.org/licenses/>. + +# sysdeps/nacl/Makefile needs this set to the architecture suffix used in +# the NaCl SDK. +nacl-sdk-arch = arm + # We don't really support TLSDESC, even though the compiler thinks it does. have-arm-tls-desc = no diff --git a/sysdeps/arm/nacl/dl-machine.h b/sysdeps/arm/nacl/dl-machine.h index b48517bcc0..81f3755b3b 100644 --- a/sysdeps/arm/nacl/dl-machine.h +++ b/sysdeps/arm/nacl/dl-machine.h @@ -39,14 +39,15 @@ .text\n\ .globl _start\n\ .type _start, %function\n\ +.p2align 4\n\ _start:\n\ - @ r0 has the pointer to the info block (see nacl_startup.h)\n\ - mov r1, sp @ Save stack base for __libc_stack_end.\n\ - push {r0-r3} @ Push those, maintaining alignment to 16.\n\ - mov r0, sp @ Pointer to {info, sp} is argument.\n\ - sfi_bl _dl_start\n\ - pop {r1-r4} @ Restore stack, getting info block into r1.\n\ - mov lr, #0 @ Return address for noreturn call.\n\ - b _dl_start_user"); + @ r0 has the pointer to the info block (see nacl_startup.h)\n\ + mov r1, sp @ Save stack base for __libc_stack_end.\n\ + push {r0-r3} @ Push those, maintaining alignment to 16.\n\ + mov r0, sp @ Pointer to {info, sp} is argument.\n\ + sfi_bl _dl_start\n\ + pop {r1-r4} @ Restore stack, getting info block into r1.\n\ + mov lr, #0 @ Return address for noreturn call.\n\ + b _dl_start_user"); #endif diff --git a/sysdeps/nacl/Makefile b/sysdeps/nacl/Makefile index 7a26b7f50d..e4c03020c8 100644 --- a/sysdeps/nacl/Makefile +++ b/sysdeps/nacl/Makefile @@ -1,3 +1,5 @@ +# Makefile fragment for NaCl configurations. + # Copyright (C) 2015 Free Software Foundation, Inc. # This file is part of the GNU C Library. @@ -46,6 +48,8 @@ $(common-objpfx)stamp-errnos: $(nacl)/errnos.awk $(..)manual/errno.texi \ common-generated += stamp-errnos bits/errno.h before-compile += $(bits-errno) +# Massage NaCl's irt.h (and irt_dev.h) into something we can use. +# See irt.sed for details. nacl-irt.h = $(common-objpfx)nacl-irt.h $(nacl-irt.h): $(nacl)/irt.sed \ $(naclsrc)/untrusted/irt/irt.h \ @@ -55,21 +59,6 @@ $(nacl-irt.h): $(nacl)/irt.sed \ common-generated += nacl-irt.h before-compile += $(nacl-irt.h) -ifeq ($(subdir),misc) - -# We reuse the Linux file since the bits match. The file lives in the -# top-level source tree so we can use it without reference to any -# sysdeps/.../linux/ directories, but it's still a sysdeps decision to -# install it. -sysdep_headers += bits/mman-linux.h - -# XXX temp test -others += hello hellow -others-static += hello - -endif - - $(common-objpfx)nacl-interfaces.v.i: $(nacl)/nacl-interfaces.mk.in \ $(nacl)/nacl-interface-list.h -include $(common-objpfx)nacl-interfaces.v @@ -102,6 +91,17 @@ $(nacl-optional-interfaces:%=$(nacl-interface-pattern)): \ nacl-routines-of = $(filter nacl-interface-$1-%,$(nacl-interface-routines)) + +# Run the NaCl code validator on binaries after we link them, so the +# build does not succeed with any binary that won't pass validation. +# Moving the file around makes sure that we don't leave a target +# appearing complete after it fails validation. +define after-link +mv -f $1 $1.prevalidation +$(nacl)/nacl-after-link.sh '${READELF}' $1.prevalidation +mv -f $1.prevalidation $1 +endef + ifeq ($(subdir),csu) sysdep_routines += nacl_interface_query \ nacl-interfaces $(call nacl-routines-of,libc) @@ -120,3 +120,11 @@ ifeq ($(subdir),nptl) # XXX temporary hack libpthread-routines := $(filter-out ptw-%,$(libpthread-routines)) endif + +ifeq ($(subdir),misc) +# We reuse the Linux file since the bits match. The file lives in the +# top-level source tree so we can use it without reference to any +# sysdeps/.../linux/ directories, but it's still a sysdeps decision to +# install it. +sysdep_headers += bits/mman-linux.h +endif diff --git a/sysdeps/nacl/Versions b/sysdeps/nacl/Versions index 32eb77241a..4ac56c2a28 100644 --- a/sysdeps/nacl/Versions +++ b/sysdeps/nacl/Versions @@ -5,7 +5,7 @@ ld { } libc { - GLIBC_2.17 { + GLIBC_2.22 { nacl_interface_query; } diff --git a/sysdeps/nacl/____longjmp_chk.c b/sysdeps/nacl/____longjmp_chk.c deleted file mode 100644 index 05ad655559..0000000000 --- a/sysdeps/nacl/____longjmp_chk.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Fortified longjmp. Stub version. - 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 - <http://www.gnu.org/licenses/>. */ - -#include <setjmp.h> - -/* We don't have any way to validate the stack pointer. - So we just do a vanilla longjmp. */ -void -__attribute__ ((__noreturn__)) -____longjmp_chk (__jmp_buf env, int val) -{ - __longjmp (env, val); -} diff --git a/sysdeps/nacl/_exit.c b/sysdeps/nacl/_exit.c index 0ec902f9ea..6006e26e55 100644 --- a/sysdeps/nacl/_exit.c +++ b/sysdeps/nacl/_exit.c @@ -24,6 +24,9 @@ void _exit (int status) { __nacl_irt_basic.exit (status); + + /* That never returns unless something is severely and unrecoverably wrong. + If it ever does, try to make sure we crash. */ while (1) __builtin_trap (); } diff --git a/sysdeps/nacl/bits/dirent.h b/sysdeps/nacl/bits/dirent.h index 3fb19c3eab..571ac0c67b 100644 --- a/sysdeps/nacl/bits/dirent.h +++ b/sysdeps/nacl/bits/dirent.h @@ -1,5 +1,5 @@ /* Directory entry structure `struct dirent'. NaCl version. - Copyright (C) 2012 Free Software Foundation, Inc. + 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 diff --git a/sysdeps/nacl/dl-map-segments.h b/sysdeps/nacl/dl-map-segments.h index d93badf1d3..f305da304a 100644 --- a/sysdeps/nacl/dl-map-segments.h +++ b/sysdeps/nacl/dl-map-segments.h @@ -34,12 +34,12 @@ read_in_data (int fd, void *data, size_t len, off_t pos) { ssize_t n = __read (fd, data, len); if (__glibc_unlikely (n < 0)) - return true; + return true; if (__glibc_unlikely (n == 0)) - { - errno = EFTYPE; - return true; - } + { + errno = EFTYPE; + return true; + } data += n; len -= n; } @@ -48,59 +48,63 @@ read_in_data (int fd, void *data, size_t len, off_t pos) static const char * _dl_map_segments (struct link_map *l, int fd, - const ElfW(Ehdr) *header, int type, - const struct loadcmd loadcmds[], size_t nloadcmds, - const size_t maplength, bool has_holes, - struct link_map *loader) + const ElfW(Ehdr) *header, int type, + const struct loadcmd loadcmds[], size_t nloadcmds, + const size_t maplength, bool has_holes, + struct link_map *loader) { if (__builtin_expect (type, ET_DYN) == ET_DYN) { /* This is a position-independent shared object. Let the system - choose where to place it. + choose where to place it. - As a refinement, sometimes we have an address that we would - prefer to map such objects at; but this is only a preference, - the OS can do whatever it likes. */ + As a refinement, sometimes we have an address that we would + prefer to map such objects at; but this is only a preference, + the OS can do whatever it likes. */ ElfW(Addr) mappref - = (ELF_PREFERRED_ADDRESS (loader, maplength, - loadcmds[0].mapstart & GLRO(dl_use_load_bias)) - - MAP_BASE_ADDR (l)); + = (ELF_PREFERRED_ADDRESS (loader, maplength, + loadcmds[0].mapstart & GLRO(dl_use_load_bias)) + - MAP_BASE_ADDR (l)); uintptr_t mapstart; if (__glibc_likely (loadcmds[0].prot & PROT_EXEC)) - { - uintptr_t code_size = loadcmds[0].allocend - loadcmds[0].mapstart; - uintptr_t data_offset; - size_t data_size; - - if (__glibc_likely (nloadcmds > 1)) - { - data_offset = loadcmds[1].mapstart - loadcmds[0].mapstart; - data_size = ALIGN_UP (maplength - data_offset, - GLRO(dl_pagesize)); - } - else - { - data_offset = 0; - data_size = 0; - } - - int error = __nacl_irt_code_data_alloc.allocate_code_data - (mappref, code_size, data_offset, data_size, &mapstart); - if (__glibc_unlikely (error)) - { - errno = error; - return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; - } - } + { + /* When there is a code segment, we must use the + allocate_code_data interface to choose a location. */ + + uintptr_t code_size = loadcmds[0].allocend - loadcmds[0].mapstart; + uintptr_t data_offset; + size_t data_size; + + if (__glibc_likely (nloadcmds > 1)) + { + data_offset = loadcmds[1].mapstart - loadcmds[0].mapstart; + data_size = ALIGN_UP (maplength - data_offset, + GLRO(dl_pagesize)); + } + else + { + data_offset = 0; + data_size = 0; + } + + int error = __nacl_irt_code_data_alloc.allocate_code_data + (mappref, code_size, data_offset, data_size, &mapstart); + if (__glibc_unlikely (error)) + { + errno = error; + return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; + } + } else - { - void *mapped = __mmap ((void *) mappref, maplength, - PROT_NONE, MAP_ANON, -1, 0); - if (__glibc_unlikely (mapped == MAP_FAILED)) - return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; - mapstart = (uintptr_t) mapped; - } + { + /* With no code pages involved, plain mmap works fine. */ + void *mapped = __mmap ((void *) mappref, maplength, + PROT_NONE, MAP_ANON, -1, 0); + if (__glibc_unlikely (mapped == MAP_FAILED)) + return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; + mapstart = (uintptr_t) mapped; + } l->l_addr = mapstart - loadcmds[0].mapstart; } @@ -110,118 +114,120 @@ _dl_map_segments (struct link_map *l, int fd, l->l_map_end = l->l_map_start + maplength; l->l_contiguous = !has_holes; + /* Now actually map (or read) in each segment. */ for (const struct loadcmd *c = loadcmds; c < &loadcmds[nloadcmds]; ++c) if (__glibc_likely (c->mapend > c->mapstart)) { - /* Unlike POSIX mmap, NaCl's mmap does not reliably handle COW - faults in the remainder of the final partial page. So to get - the expected behavior for the unaligned boundary between data - and bss, it's necessary to allocate the final partial page of - data as anonymous memory rather than mapping it from the file. */ - - size_t maplen = c->mapend - c->mapstart; - if (c->mapend > c->dataend && c->allocend > c->dataend) - maplen = (c->dataend & -GLRO(dl_pagesize)) - c->mapstart; - - /* Map the segment contents from the file. */ - if (__glibc_unlikely (__mmap ((void *) (l->l_addr + c->mapstart), - maplen, c->prot, - MAP_FIXED|MAP_COPY|MAP_FILE, - fd, c->mapoff) - == MAP_FAILED)) - { - switch (errno) - { - case EINVAL: - case ENOTSUP: - case ENOSYS: - break; - default: - return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; - } - - /* No mmap support for this file. */ - if (c->prot & PROT_EXEC) - { - /* Read the data into a temporary buffer. */ - const size_t len = c->mapend - c->mapstart; - void *data = __mmap (NULL, len, PROT_READ | PROT_WRITE, - MAP_ANON|MAP_PRIVATE, -1, 0); - if (__glibc_unlikely (data == MAP_FAILED)) - return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL; - if (read_in_data (fd, data, len, c->mapoff)) - return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; - int error = __nacl_irt_dyncode.dyncode_create - ((void *) (l->l_addr + c->mapstart), data, len); - __munmap (data, len); - if (__glibc_unlikely (error)) - { - errno = error; - return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; - } - } - else - { - /* Allocate the pages. */ - if (__mmap ((void *) (l->l_addr + c->mapstart), - c->mapend - c->mapstart, c->prot | PROT_WRITE, - MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0) - == MAP_FAILED) - return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL; - /* Now read in the data. */ - if (read_in_data (fd, (void *) (l->l_addr + c->mapstart), - c->dataend - c->mapstart, c->mapoff)) - return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; - /* Now that we've filled the pages, reset the page - protections to what they should be. */ - if (!(c->prot & PROT_WRITE) - && __mprotect ((void *) (l->l_addr + c->mapstart), - c->mapend - c->mapstart, c->prot) < 0) - return DL_MAP_SEGMENTS_ERROR_MPROTECT; - } - } - else if (c->allocend > c->dataend) - { - /* Extra zero pages should appear at the end of this segment, - after the data mapped from the file. */ - - uintptr_t allocend = c->mapend; - if (c->mapend > c->dataend) - { - /* The final data page was partial. So we didn't map it in. - Instead, we must allocate an anonymous page to fill. */ - if (c->prot & PROT_WRITE) - /* Do the whole allocation right here. */ - allocend = c->allocend; - if (__mmap ((void *) (l->l_addr + c->mapstart + maplen), - allocend - (c->mapstart + maplen), c->prot, - MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0) - == MAP_FAILED) - return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL; - if (read_in_data (fd, - (void *) (l->l_addr + c->mapstart + maplen), - c->dataend & (GLRO(dl_pagesize) - 1), - c->mapoff + maplen)) - return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; - /* Now that we've filled the page, reset its - protections to what they should be. */ - if (!(c->prot & PROT_WRITE) - && __mprotect ((void *) (l->l_addr + c->mapstart + maplen), - c->mapend - (c->mapstart + maplen), - c->prot) < 0) - return DL_MAP_SEGMENTS_ERROR_MPROTECT; - } - - /* Now allocate the pure zero-fill pages. */ - if (allocend < c->allocend - && (__mmap ((void *) (l->l_addr + c->mapstart + allocend), - c->allocend - (c->mapstart + allocend), c->prot, - MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0) - == MAP_FAILED)) - return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL; - } - - _dl_postprocess_loadcmd (l, header, c); + /* Unlike POSIX mmap, NaCl's mmap does not reliably handle COW + faults in the remainder of the final partial page. So to get + the expected behavior for the unaligned boundary between data + and bss, it's necessary to allocate the final partial page of + data as anonymous memory rather than mapping it from the file. */ + + size_t maplen = c->mapend - c->mapstart; + if (c->mapend > c->dataend && c->allocend > c->dataend) + maplen = (c->dataend & -GLRO(dl_pagesize)) - c->mapstart; + + /* Map the segment contents from the file. */ + if (__glibc_unlikely (__mmap ((void *) (l->l_addr + c->mapstart), + maplen, c->prot, + MAP_FIXED|MAP_COPY|MAP_FILE, + fd, c->mapoff) + == MAP_FAILED)) + { + switch (errno) + { + case EINVAL: + case ENOTSUP: + case ENOSYS: + break; + default: + return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; + } + + /* No mmap support for this file. */ + if (c->prot & PROT_EXEC) + { + /* Read the data into a temporary buffer. */ + const size_t len = c->mapend - c->mapstart; + void *data = __mmap (NULL, len, PROT_READ | PROT_WRITE, + MAP_ANON|MAP_PRIVATE, -1, 0); + if (__glibc_unlikely (data == MAP_FAILED)) + return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL; + if (read_in_data (fd, data, len, c->mapoff)) + return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; + /* Now validate and install the code. */ + int error = __nacl_irt_dyncode.dyncode_create + ((void *) (l->l_addr + c->mapstart), data, len); + __munmap (data, len); + if (__glibc_unlikely (error)) + { + errno = error; + return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; + } + } + else + { + /* Allocate the pages. */ + if (__mmap ((void *) (l->l_addr + c->mapstart), + c->mapend - c->mapstart, c->prot | PROT_WRITE, + MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0) + == MAP_FAILED) + return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL; + /* Now read in the data. */ + if (read_in_data (fd, (void *) (l->l_addr + c->mapstart), + c->dataend - c->mapstart, c->mapoff)) + return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; + /* Now that we've filled the pages, reset the page + protections to what they should be. */ + if (!(c->prot & PROT_WRITE) + && __mprotect ((void *) (l->l_addr + c->mapstart), + c->mapend - c->mapstart, c->prot) < 0) + return DL_MAP_SEGMENTS_ERROR_MPROTECT; + } + } + else if (c->allocend > c->dataend) + { + /* Extra zero pages should appear at the end of this segment, + after the data mapped from the file. */ + + uintptr_t allocend = c->mapend; + if (c->mapend > c->dataend) + { + /* The final data page was partial. So we didn't map it in. + Instead, we must allocate an anonymous page to fill. */ + if (c->prot & PROT_WRITE) + /* Do the whole allocation right here. */ + allocend = c->allocend; + if (__mmap ((void *) (l->l_addr + c->mapstart + maplen), + allocend - (c->mapstart + maplen), c->prot, + MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0) + == MAP_FAILED) + return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL; + if (read_in_data (fd, + (void *) (l->l_addr + c->mapstart + maplen), + c->dataend & (GLRO(dl_pagesize) - 1), + c->mapoff + maplen)) + return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; + /* Now that we've filled the page, reset its + protections to what they should be. */ + if (!(c->prot & PROT_WRITE) + && __mprotect ((void *) (l->l_addr + c->mapstart + maplen), + c->mapend - (c->mapstart + maplen), + c->prot) < 0) + return DL_MAP_SEGMENTS_ERROR_MPROTECT; + } + + /* Now allocate the pure zero-fill pages. */ + if (allocend < c->allocend + && (__mmap ((void *) (l->l_addr + c->mapstart + allocend), + c->allocend - (c->mapstart + allocend), c->prot, + MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0) + == MAP_FAILED)) + return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL; + } + + _dl_postprocess_loadcmd (l, header, c); } /* Notify ELF_PREFERRED_ADDRESS that we have to load this one diff --git a/sysdeps/nacl/dl-sysdep.c b/sysdeps/nacl/dl-sysdep.c index f9af5a3acb..3e902c2cae 100644 --- a/sysdeps/nacl/dl-sysdep.c +++ b/sysdeps/nacl/dl-sysdep.c @@ -48,15 +48,15 @@ macro in the machine-specific dl-machine.h file. At this point, dynamic linking has been completed and the first argument is the application's entry point. */ -attribute_hidden internal_function +attribute_hidden internal_function __attribute__ ((noreturn)) void _dl_start_user (void (*user_entry) (uint32_t info[]), uint32_t info[]) { if (_dl_skip_args > 0) { /* There are some arguments that the user program should not see. - Just slide up the INFO pointer so its NACL_STARTUP_ARGV points - to what should now be argv[0], and copy back the earlier fields. */ + Just slide up the INFO pointer so its NACL_STARTUP_ARGV points + to what should now be argv[0], and copy back the earlier fields. */ assert (nacl_startup_argc (info) >= _dl_skip_args); assert (NACL_STARTUP_ARGV == 3); uint32_t envc = info[NACL_STARTUP_ENVC]; @@ -71,12 +71,15 @@ _dl_start_user (void (*user_entry) (uint32_t info[]), uint32_t info[]) /* Run initializers. */ _dl_init (GL(dl_ns)[0]._ns_loaded, - nacl_startup_argc (info), - nacl_startup_argv (info), - nacl_startup_envp (info)); + nacl_startup_argc (info), + nacl_startup_argv (info), + nacl_startup_envp (info)); /* Call the user's entry point. This should never return. */ (*user_entry) (info); + + /* Fail clearly just in case it did return. */ + __builtin_trap (); } # define DL_SYSDEP_INIT __nacl_initialize_interfaces () diff --git a/sysdeps/nacl/errnos.awk b/sysdeps/nacl/errnos.awk index 35f29719ea..65fa19bd06 100644 --- a/sysdeps/nacl/errnos.awk +++ b/sysdeps/nacl/errnos.awk @@ -1,3 +1,22 @@ +# Script to produce bits/errno.h for NaCl. + +# 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 +# <http://www.gnu.org/licenses/>. + BEGIN { maxerrno = 0 } $1 == "#define" && $2 ~ /NACL_ABI_E[A-Z0-9_]+/ && $3 ~ /[0-9]+/ { @@ -61,7 +80,7 @@ END { #define EWOULDBLOCK EAGAIN\n\ #define ENOTSUP EOPNOTSUPP\n\ \n\ -extern __thread int errno;\n\ +extern __thread int errno __attribute__ ((__tls_model__ (\"initial-exec\")));\n\ #define errno errno\n\ \n\ #endif"; diff --git a/sysdeps/nacl/glob.c b/sysdeps/nacl/glob.c index 147bc10132..36d62e807d 100644 --- a/sysdeps/nacl/glob.c +++ b/sysdeps/nacl/glob.c @@ -1,6 +1,26 @@ -/* XXX temporary? hack */ -#include <unistd.h> -#define getlogin_r(name, len) (ENOSYS) +/* Do glob searching. NaCl version. + 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 + <http://www.gnu.org/licenses/>. */ + +#include <unistd.h> /* Declares getlogin_r. */ + +/* We do not have getlogin_r in the library at all for NaCl. + Define it away so the glob code does not try to use it. */ +#define getlogin_r(name, len) (ENOSYS) /* Fetch the version that defines glob64 as an alias. */ #include <sysdeps/wordsize-64/glob.c> diff --git a/sysdeps/nacl/isatty.c b/sysdeps/nacl/isatty.c index 6e2b01ad94..fc1a686bae 100644 --- a/sysdeps/nacl/isatty.c +++ b/sysdeps/nacl/isatty.c @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <errno.h> #include <unistd.h> #include <nacl-interfaces.h> @@ -24,6 +25,14 @@ int __isatty (int fd) { int result; - return NACL_CALL (__nacl_irt_dev_fdio.isatty (fd, &result), result); + int error = __nacl_irt_dev_fdio.isatty (fd, &result); + if (error == 0) + { + if (result) + return 1; + error = ENOTTY; + } + errno = error; + return 0; } weak_alias (__isatty, isatty) diff --git a/sysdeps/nacl/ldsodefs.h b/sysdeps/nacl/ldsodefs.h index c1cfd12c99..383ced5612 100644 --- a/sysdeps/nacl/ldsodefs.h +++ b/sysdeps/nacl/ldsodefs.h @@ -24,7 +24,7 @@ /* Now define our stuff. */ /* We have the auxiliary vector. */ -#define HAVE_AUX_VECTOR +#define HAVE_AUX_VECTOR 1 /* Used by static binaries to check the auxiliary vector. */ extern void _dl_aux_init (ElfW(auxv_t) *av) internal_function; diff --git a/sysdeps/nacl/nacl-after-link.sh b/sysdeps/nacl/nacl-after-link.sh new file mode 100755 index 0000000000..199f1b89ac --- /dev/null +++ b/sysdeps/nacl/nacl-after-link.sh @@ -0,0 +1,69 @@ +#!/bin/sh +# Script to validate NaCl binaries after linking. + +# 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 +# <http://www.gnu.org/licenses/>. + +# See sysdeps/nacl/Makefile for how this script is invoked. +READELF="$1" +binary="$2" + +if [ -z "$NACL_SDK_ROOT" ]; then + echo >&2 "$0: NACL_SDK_ROOT must be set in the environment" + exit 77 +fi + +ncval="${NACL_SDK_ROOT}/tools/ncval" + +if [ ! -x "$ncval" ]; then + echo >&2 "$0: No ncval binary in $ncval" + exit 77 +fi + +"${READELF}" -Wl "$binary" | awk ' +BEGIN { saw_load = saw_text = 0 } +$1 == "LOAD" { + saw_load = 1; + if (/ R.E /) saw_code = 1; +} +END { + exit (saw_code ? 11 : saw_load ? 22 : 1); +} +' +case $? in +11) + # We saw a code segment, so we can try ncval. + ;; +22) + # We saw LOAD segments but none of them were code. + echo >&2 "+++ No code: $binary" + exit 0 + ;; +*) + # Something funny going on. + echo >&2 "*** Failed to analyze: $binary" + exit 2 + ;; +esac + +if "$ncval" "$binary"; then + echo >&2 "+++ Validated: $binary" + exit 0 +else + echo >&2 "*** Validation failed: $binary" + exit 2 +fi diff --git a/sysdeps/nacl/nacl-interface-list.h b/sysdeps/nacl/nacl-interface-list.h index 11ad69ac16..d09814739a 100644 --- a/sysdeps/nacl/nacl-interface-list.h +++ b/sysdeps/nacl/nacl-interface-list.h @@ -1,29 +1,47 @@ +/* List of NaCl interface tables used in libraries. + 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 + <http://www.gnu.org/licenses/>. */ + NACL_MANDATORY_INTERFACE (rtld, - NACL_IRT_BASIC_v0_1, nacl_irt_basic) + NACL_IRT_BASIC_v0_1, nacl_irt_basic) NACL_MANDATORY_INTERFACE (rtld, - NACL_IRT_FDIO_v0_1, nacl_irt_fdio) + NACL_IRT_FDIO_v0_1, nacl_irt_fdio) NACL_MANDATORY_INTERFACE (rtld, - NACL_IRT_FILENAME_v0_1, nacl_irt_filename) + NACL_IRT_FILENAME_v0_1, nacl_irt_filename) NACL_MANDATORY_INTERFACE (rtld, - NACL_IRT_MEMORY_v0_3, nacl_irt_memory) + NACL_IRT_MEMORY_v0_3, nacl_irt_memory) NACL_MANDATORY_INTERFACE (libc, - NACL_IRT_THREAD_v0_1, nacl_irt_thread) + NACL_IRT_THREAD_v0_1, nacl_irt_thread) NACL_MANDATORY_INTERFACE (rtld, - NACL_IRT_FUTEX_v0_1, nacl_irt_futex) + NACL_IRT_FUTEX_v0_1, nacl_irt_futex) NACL_MANDATORY_INTERFACE (rtld, - NACL_IRT_TLS_v0_1, nacl_irt_tls) + NACL_IRT_TLS_v0_1, nacl_irt_tls) NACL_MANDATORY_INTERFACE (libc, - NACL_IRT_RESOURCE_OPEN_v0_1, nacl_irt_resource_open) + NACL_IRT_RESOURCE_OPEN_v0_1, nacl_irt_resource_open) NACL_MANDATORY_INTERFACE (rtld, - NACL_IRT_CODE_DATA_ALLOC_v0_1, - nacl_irt_code_data_alloc) + NACL_IRT_CODE_DATA_ALLOC_v0_1, + nacl_irt_code_data_alloc) NACL_OPTIONAL_INTERFACE (libc, - NACL_IRT_CLOCK_v0_1, nacl_irt_clock) + NACL_IRT_CLOCK_v0_1, nacl_irt_clock) NACL_OPTIONAL_INTERFACE (rtld, - NACL_IRT_DYNCODE_v0_1, nacl_irt_dyncode) + NACL_IRT_DYNCODE_v0_1, nacl_irt_dyncode) NACL_OPTIONAL_INTERFACE (rtld, - NACL_IRT_DEV_GETPID_v0_1, nacl_irt_dev_getpid) + NACL_IRT_DEV_GETPID_v0_1, nacl_irt_dev_getpid) NACL_OPTIONAL_INTERFACE (rtld, - NACL_IRT_DEV_FILENAME_v0_3, nacl_irt_dev_filename) + NACL_IRT_DEV_FILENAME_v0_3, nacl_irt_dev_filename) NACL_OPTIONAL_INTERFACE (libc, - NACL_IRT_DEV_FDIO_v0_3, nacl_irt_dev_fdio) + NACL_IRT_DEV_FDIO_v0_3, nacl_irt_dev_fdio) diff --git a/sysdeps/nacl/nacl-interfaces.c b/sysdeps/nacl/nacl-interfaces.c index 469ee6581b..cb0dcd0bc8 100644 --- a/sysdeps/nacl/nacl-interfaces.c +++ b/sysdeps/nacl/nacl-interfaces.c @@ -48,8 +48,7 @@ extern uintptr_t __stop_nacl_optional_interface_tables[] attribute_hidden __attribute__ ((weak)); static uintptr_t * -next_nacl_table (uintptr_t *t, - const struct nacl_interface *i) +next_nacl_table (uintptr_t *t, const struct nacl_interface *i) { return (void *) t + i->table_size; } @@ -84,7 +83,7 @@ initialize_mandatory_interfaces (void) while (i < __stop_nacl_mandatory_interface_names) { if (__nacl_irt_query (i->name, t, i->table_size) != i->table_size) - missing_mandatory_interface (i); + missing_mandatory_interface (i); t = next_nacl_table (t, i); i = next_nacl_interface (i); @@ -106,9 +105,9 @@ initialize_optional_interfaces (void) while (i < __stop_nacl_optional_interface_names) { size_t filled = __nacl_irt_query (i->name, t, i->table_size); - if (filled == 0) - for (size_t slot = 0; slot < i->table_size / sizeof *t; ++slot) - t[slot] = (uintptr_t) &nacl_missing_optional_interface; + if (filled != i->table_size) + for (size_t slot = 0; slot < i->table_size / sizeof *t; ++slot) + t[slot] = (uintptr_t) &nacl_missing_optional_interface; t = next_nacl_table (t, i); i = next_nacl_interface (i); diff --git a/sysdeps/nacl/rename.c b/sysdeps/nacl/rename.c index a968eaf969..8cf1b2f218 100644 --- a/sysdeps/nacl/rename.c +++ b/sysdeps/nacl/rename.c @@ -1,4 +1,4 @@ -/* Make a hard link. NaCl version. +/* Rename a file. NaCl version. Copyright (C) 2015 Free Software Foundation, Inc. This file is part of the GNU C Library. diff --git a/sysdeps/nacl/shlib-versions b/sysdeps/nacl/shlib-versions index 2658047209..c146d31b96 100644 --- a/sysdeps/nacl/shlib-versions +++ b/sysdeps/nacl/shlib-versions @@ -1,9 +1,9 @@ # DEFAULT Earliest symbol set # ------- ------------------- -DEFAULT GLIBC_2.21 +DEFAULT GLIBC_2.22 # Library=version Earliest symbol set (optional) # --------------- ------------------------------ -libc=1 -libm=1 +libc=0.1 +libm=0.1 |