diff --git a/ChangeLog b/ChangeLog index 0095eff1cd..95185d8b66 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,104 @@ -2003-01-10 Guido Günther +2003-01-11 Jim Meyering + + * io/ftw.c [HAVE_CONFIG_H]: Include . + [HAVE_SYS_PARAM_H || _LIBC]: Guard inclusion of . + Include , not , if !_LIBC. + [!_LIBC] (__chdir, __closedir, __fchdir, __getcwd, __opendir): Define. + [!_LIBC] (__readdir64, __tdestroy, __tfind, __tsearch): Define. + [!_LIBC] (internal_function, dirent64, MAX): Define. + (__set_errno): Define if not already defined. + (open_dir_stream): When FTW_CHDIR is enabled, invoke opendir on + the basename, not the entire file name. + (process_entry): When FTW_CHDIR is enabled, invoke XSTAT or LXSTAT on + the basename, not the entire file name. + +2003-01-12 Ulrich Drepper + + * string/tester.c (test_strcpy): Disable last added strcpy until + it is fixed. + +2003-01-11 Philip Blundell + + * sysdeps/unix/sysv/linux/arm/socket.S: Add cancellation support. + +2003-01-11 Andreas Schwab + + * Makerules: Add vpath for %.dynsym and %.so so that the + implicit rule chaining for check-abi works. + +2003-01-11 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/sysdep.h (SYSCALL_ERROR_HANDLER): + Add non-PIC case. + +2003-01-11 Jakub Jelinek + + * elf/tls-macros.h [__ia64__] (__TLS_CALL_CLOBBERS): Define. + [__ia64__] (TLS_LE, TLS_IE): Fix typos. Add ;; at start of asm if + gp is used early. + [__ia64__] (TLS_LD, TLS_GD): Likewise. Use __TLS_CALL_CLOBBERS. + * elf/Makefile ($(objpfx)tst-tlsmod5.so, $(objpfx)tst-tlsmod6.so): + Ensure libc.so in DT_NEEDED. + * sysdeps/alpha/dl-machine.h (elf_machine_rela): Move + CHECK_STATIC_TLS before l_tls_offset use. + * sysdeps/i386/dl-machine.h (elf_machine_rel, elf_machine_rela): + Likewise. + * sysdeps/sh/dl-machine.h (elf_machine_rela): Likewise. + * sysdeps/generic/dl-tls.c (_dl_allocate_tls_storage) [TLS_DTV_AT_TP]: + Allocate TLS_PRE_TCB_SIZE bytes below result. + (_dl_deallocate_tls) [TLS_DTV_AT_TP]: Adjust before freeing. + * sysdeps/generic/libc-tls.c (__libc_setup_tls): If + TLS_INIT_TP_EXPENSIVE is not defined, allocate even if no PT_TLS + segment has been found. If TLS_DTV_AT_TP, allocate TLS_PRE_TCB_SIZE + bytes below result and add tcb_offset to memsz. + * sysdeps/ia64/dl-tls.h (__tls_get_addr): New prototype. + * sysdeps/ia64/dl-machine.h: Include tls.h. + (elf_machine_type_class): Return ELF_RTYPE_CLASS_PLT for TLS relocs + too. + (elf_machine_rela): Assume if sym_map != NULL sym is non-NULL too. + Handle R_IA64_DTPMOD*, R_IA64_DTPREL* and R_IA64_TPREL* relocations. + * sysdeps/ia64/libc-tls.c: New file. + +2003-01-10 Steven Munroe + + * sysdeps/powerpc/powerpc64/sysdep.h (PSEUDO_RET): Add branch hit. + * sysdeps/unix/sysv/linux/powerpc/bits/stat.h (STAT_VER_LINUX): + Fix type. Move definition out of #if. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/ftruncate64.c: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/pread.c: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/pread64.c: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite.c: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite64.c: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S: Add cancellation + support. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list: Remove + ftruncate64, pread64, pwrite64, truncate64 entries. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h + (INLINE_SYSCALL): New version that supports function call like + syscalls. Add __builtin_expect. + (LOADARGS_n): Add argument size safety checks. + (INTERNAL_SYSCALL): New Macro. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/truncate64.c: New file. + * sysdeps/unix/sysv/linux/powerpc/sys/procfs.h [__PPC_ELF_H]: Avoid + redefinition of elf_fpreg_t and elf_fpregset_t. + +2003-01-12 Ulrich Drepper + + * elf/dl-close.c (_dl_close): Add several asserts. Correct and + simplify test for unloading. If loader of a DSO is unloaded do not + use its scope anymore. Fall back to own scope and adjust opencounts. + Fix several comments. + * elf/dl-deps.c (_dl_map_object_deps): Always allocate memory for + the l_searchlist, not only for l_initfini. + + * elf/dl-lookup.c (add_dependencies): Avoid creating relocation + dependencies if objects cannot be removed. Remove object with the + definition as not unloadable if necessary. + + * elf/reldep6.c: Create relocation dependency before closing the first + module. + +2003-01-10 Guido Günther * sysdeps/unix/mips/fork.S: Add PSEUDO_END. * sysdeps/unix/mips/brk.S: Likewise. @@ -18,6 +118,22 @@ (__ASSUME_STAT64_SYSCALL, __ASSUME_FCNTL64) (__ASSUME_VFORK_SYSCALL): Define for m68k kernels >= 2.4.12. +2003-01-09 Jakub Jelinek + + * elf/Makefile: Add rules to build and run reldep9 test. + * elf/reldep9.c: New file. + * elf/reldep9mod1.c: New file. + * elf/reldep9mod2.c: New file. + * elf/reldep9mod3.c: New file. + +2003-01-09 Jakub Jelinek + + * elf/Makefile: Add rules to build and run nodelete2 test. + * elf/nodelete2.c: New file. + * elf/nodel2mod1.c: New file. + * elf/nodel2mod2.c: New file. + * elf/nodel2mod3.c: New file. + 2003-01-09 Jakub Jelinek * posix/test-vfork.c (noop): Add __attribute_noinline__. diff --git a/Makerules b/Makerules index dca6d0e6c1..169da4a049 100644 --- a/Makerules +++ b/Makerules @@ -1138,6 +1138,8 @@ ifeq ($(versioning),yes) mv -f $@T $@ vpath %.symlist $(objpfx) $(common-objpfx) +vpath %.dynsym $(objpfx) $(common-objpfx) +vpath %.so $(objpfx) $(common-objpfx) check-abi-%: $(..)scripts/extract-abilist.awk $(common-objpfx)config.make \ %.abilist %.symlist LC_ALL=C \ diff --git a/elf/Makefile b/elf/Makefile index e9090d3044..38819a3884 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc. +# Copyright (C) 1995-2002, 2003 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 @@ -73,7 +73,9 @@ distribute := rtld-Rules \ circlemod1.c circlemod1a.c circlemod2.c circlemod2a.c \ circlemod3.c circlemod3a.c nodlopenmod2.c \ tls-macros.h \ - reldep8mod1.c reldep8mod2.c reldep8mod3.c + reldep8mod1.c reldep8mod2.c reldep8mod3.c \ + nodel2mod1.c nodel2mod2.c nodel2mod3.c \ + reldep9mod1.c reldep9mod2.c reldep9mod3.c include ../Makeconfig @@ -138,9 +140,10 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ neededtest3 neededtest4 unload2 lateglobal initfirst global \ restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \ circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 +# reldep9 test-srcs = tst-pathopt tests-vis-yes = vismain -tests-nodelete-yes = nodelete +tests-nodelete-yes = nodelete nodelete2 tests-nodlopen-yes = nodlopen nodlopen2 endif modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ @@ -160,12 +163,14 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ tst-tlsmod5 tst-tlsmod6 \ circlemod1 circlemod1a circlemod2 circlemod2a \ circlemod3 circlemod3a \ - reldep8mod1 reldep8mod2 reldep8mod3 + reldep8mod1 reldep8mod2 reldep8mod3 \ + reldep9mod1 reldep9mod2 reldep9mod3 ifeq (yes,$(have-initfini-array)) modules-names += tst-array2dep endif modules-vis-yes = vismod1 vismod2 vismod3 -modules-nodelete-yes = nodelmod1 nodelmod2 nodelmod3 nodelmod4 +modules-nodelete-yes = nodelmod1 nodelmod2 nodelmod3 nodelmod4 \ + nodel2mod1 nodel2mod2 nodel2mod3 modules-nodlopen-yes = nodlopenmod nodlopenmod2 extra-objs += $(addsuffix .os,$(strip $(modules-names))) # We need this variable to be sure the test modules get the right CPPFLAGS. @@ -363,7 +368,13 @@ $(objpfx)reldep6mod2.so: $(objpfx)reldep6mod1.so $(objpfx)reldep6mod3.so: $(objpfx)reldep6mod2.so $(objpfx)reldep6mod4.so: $(objpfx)reldep6mod1.so $(objpfx)tst-tlsmod3.so: $(objpfx)tst-tlsmod2.so +# For tst-tls9-static, make sure the modules it dlopens have libc.so in DT_NEEDED +$(objpfx)tst-tlsmod5.so: $(common-objpfx)libc.so +$(objpfx)tst-tlsmod6.so: $(common-objpfx)libc.so $(objpfx)reldep8mod3.so: $(objpfx)reldep8mod1.so $(objpfx)reldep8mod2.so +$(objpfx)nodel2mod3.so: $(objpfx)nodel2mod1.so $(objpfx)nodel2mod2.so +$(objpfx)reldep9mod2.so: $(objpfx)reldep9mod1.so +$(objpfx)reldep9mod3.so: $(objpfx)reldep9mod1.so $(objpfx)reldep9mod2.so LDFLAGS-tst-tlsmod5.so = -nostdlib LDFLAGS-tst-tlsmod6.so = -nostdlib @@ -531,6 +542,13 @@ $(objpfx)reldep7.out: $(objpfx)reldep7mod1.so $(objpfx)reldep7mod2.so $(objpfx)reldep8: $(libdl) $(objpfx)reldep8.out: $(objpfx)reldep8mod3.so +LDFLAGS-nodel2mod2.so = -Wl,--enable-new-dtags,-z,nodelete +$(objpfx)nodelete2: $(libdl) +$(objpfx)nodelete2.out: $(objpfx)nodel2mod3.so + +$(objpfx)reldep9: $(libdl) +$(objpfx)reldep9.out: $(objpfx)reldep9mod3.so + $(objpfx)tst-tls3: $(objpfx)tst-tlsmod1.so $(objpfx)tst-tls4: $(libdl) diff --git a/elf/dl-close.c b/elf/dl-close.c index 7e4626e3d6..0953fab210 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -1,5 +1,5 @@ /* Close a shared object opened by `_dl_open'. - Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1996-2002, 2003 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 @@ -138,7 +138,7 @@ _dl_close (void *_map) _dl_debug_printf ("\nclosing file=%s; opencount == %u\n", map->l_name, map->l_opencount); - /* One decrement the object itself, not the dependencies. */ + /* Decrement the object's reference counter, not the dependencies'. */ --map->l_opencount; __rtld_lock_unlock_recursive (GL(dl_load_lock)); @@ -165,7 +165,7 @@ _dl_close (void *_map) } --new_opencount[0]; for (i = 1; list[i] != NULL; ++i) - if ((! (list[i]->l_flags_1 & DF_1_NODELETE) || ! list[i]->l_init_called) + if ((list[i]->l_flags_1 & DF_1_NODELETE) == 0 /* Decrement counter. */ && --new_opencount[i] == 0) { @@ -185,7 +185,10 @@ _dl_close (void *_map) { assert (dep_list[j]->l_idx < map->l_searchlist.r_nlist); if (--new_opencount[dep_list[j]->l_idx] == 0) - mark_removed (dep_list[j]); + { + assert (dep_list[j]->l_type == lt_loaded); + mark_removed (dep_list[j]); + } } } @@ -200,8 +203,11 @@ _dl_close (void *_map) == remmap->l_reldeps[j])) /* Yes, it is. */ if (--new_opencount[remmap->l_reldeps[j]->l_idx] == 0) - /* This one is now gone, too. */ - mark_removed (remmap->l_reldeps[j]); + { + /* This one is now gone, too. */ + assert (remmap->l_reldeps[j]->l_type == lt_loaded); + mark_removed (remmap->l_reldeps[j]); + } } } } @@ -215,57 +221,98 @@ _dl_close (void *_map) { struct link_map *imap = list[i]; if (new_opencount[i] == 0 && imap->l_type == lt_loaded - && (imap->l_info[DT_FINI] || imap->l_info[DT_FINI_ARRAY]) - && (! (imap->l_flags_1 & DF_1_NODELETE) || ! imap->l_init_called) - /* Skip any half-cooked objects that were never initialized. */ - && imap->l_init_called) + && (imap->l_flags_1 & DF_1_NODELETE) == 0) { /* When debugging print a message first. */ if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0)) _dl_debug_printf ("\ncalling fini: %s\n\n", imap->l_name); - /* Call its termination function. */ - if (imap->l_info[DT_FINI_ARRAY] != NULL) + /* Call its termination function. Do not do it for + half-cooked objects. */ + if (imap->l_init_called) { - ElfW(Addr) *array = - (ElfW(Addr) *) (imap->l_addr - + imap->l_info[DT_FINI_ARRAY]->d_un.d_ptr); - unsigned int sz = (imap->l_info[DT_FINI_ARRAYSZ]->d_un.d_val - / sizeof (ElfW(Addr))); - unsigned int cnt; - - for (cnt = 0; cnt < sz; ++cnt) - ((fini_t) (imap->l_addr + array[cnt])) (); + if (imap->l_info[DT_FINI_ARRAY] != NULL) + { + ElfW(Addr) *array = + (ElfW(Addr) *) (imap->l_addr + + imap->l_info[DT_FINI_ARRAY]->d_un.d_ptr); + unsigned int sz = (imap->l_info[DT_FINI_ARRAYSZ]->d_un.d_val + / sizeof (ElfW(Addr))); + unsigned int cnt; + + for (cnt = 0; cnt < sz; ++cnt) + ((fini_t) (imap->l_addr + array[cnt])) (); + } + + /* Next try the old-style destructor. */ + if (imap->l_info[DT_FINI] != NULL) + (*(void (*) (void)) DL_DT_FINI_ADDRESS + (imap, ((void *) imap->l_addr + + imap->l_info[DT_FINI]->d_un.d_ptr))) (); } - /* Next try the old-style destructor. */ - if (imap->l_info[DT_FINI] != NULL) - (*(void (*) (void)) DL_DT_FINI_ADDRESS - (imap, (void *) imap->l_addr - + imap->l_info[DT_FINI]->d_un.d_ptr)) (); + /* This object must not be used anymore. We must remove the + reference from the scope. */ + unsigned int j; + struct link_map **searchlist = map->l_searchlist.r_list; + unsigned int nsearchlist = map->l_searchlist.r_nlist; + +#ifndef NDEBUG + bool found = false; +#endif + for (j = 0; j < nsearchlist; ++j) + if (imap == searchlist[j]) + { + /* This is the object to remove. Copy all the + following ones. */ + while (++j < nsearchlist) + searchlist[j - 1] = searchlist[j]; + + searchlist[j - 1] = NULL; + + --map->l_searchlist.r_nlist; + +#ifndef NDEBUG + found = true; +#endif + break; + } + assert (found); } - else if (new_opencount[i] != 0 && imap->l_type == lt_loaded) + else if (new_opencount[i] != 0 && imap->l_type == lt_loaded + && imap->l_searchlist.r_list == NULL + && imap->l_initfini != NULL) { - /* The object is still used. But the object we are unloading - right now is responsible for loading it and therefore we - have the search list of the current object in its scope. - Remove it. */ - struct r_scope_elem **runp = imap->l_scope; - - while (*runp != NULL) - if (*runp == &map->l_searchlist) + /* The object is still used. But the object we are + unloading right now is responsible for loading it. If + the current object does not have it's own scope yet we + have to create one. This has to be done before running + the finalizers. + + To do this count the number of dependencies. */ + unsigned int cnt; + for (cnt = 1; imap->l_initfini[cnt] != NULL; ++cnt) + if (imap->l_initfini[cnt]->l_idx >= i + && imap->l_initfini[cnt]->l_idx < nopencount) + ++new_opencount[imap->l_initfini[cnt]->l_idx]; + else + ++imap->l_initfini[cnt]->l_opencount; + + /* We simply reuse the l_initfini list. */ + imap->l_searchlist.r_list = &imap->l_initfini[cnt + 1]; + imap->l_searchlist.r_nlist = cnt; + + for (cnt = 0; imap->l_scope[cnt] != NULL; ++cnt) + if (imap->l_scope[cnt] = &map->l_searchlist) { - /* Copy all later elements. */ - while ((runp[0] = runp[1]) != NULL) - ++runp; + imap->l_scope[cnt] = &imap->l_searchlist; break; } - else - ++runp; } /* Store the new l_opencount value. */ imap->l_opencount = new_opencount[i]; + /* Just a sanity check. */ assert (imap->l_type == lt_loaded || imap->l_opencount > 0); } diff --git a/elf/dl-deps.c b/elf/dl-deps.c index 9fd2dd23ef..0a9183faee 100644 --- a/elf/dl-deps.c +++ b/elf/dl-deps.c @@ -1,5 +1,5 @@ /* Load the dependencies of a mapped object. - Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1996-2001, 2002, 2003 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 @@ -455,12 +455,14 @@ _dl_map_object_deps (struct link_map *map, needed[nneeded++] = NULL; l->l_initfini = (struct link_map **) - malloc ((nneeded + 1) * sizeof needed[0]); + malloc ((2 * nneeded + 1) * sizeof needed[0]); if (l->l_initfini == NULL) INTUSE(_dl_signal_error) (ENOMEM, map->l_name, NULL, N_("cannot allocate dependency list")); l->l_initfini[0] = l; memcpy (&l->l_initfini[1], needed, nneeded * sizeof needed[0]); + memcpy (&l->l_initfini[nneeded + 1], l->l_initfini, + nneeded * sizeof needed[0]); } /* If we have no auxiliary objects just go on to the next map. */ diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index 39b3a3d013..4603761383 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -1,5 +1,5 @@ /* Look up a symbol in the loaded objects. - Copyright (C) 1995,96,97,98,99,2000,2001,2002 Free Software Foundation, Inc. + Copyright (C) 1995-2002, 2003 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 @@ -90,17 +90,34 @@ add_dependency (struct link_map *undef_map, struct link_map *map) unsigned int i; int result = 0; - /* Avoid self-references. */ + /* Avoid self-references and references to objects which cannot be + unloaded anyway. */ if (undef_map == map) return 0; + /* Make sure nobody can unload the object while we are at it. */ + __rtld_lock_lock_recursive (GL(dl_load_lock)); + /* Don't create cross-reference between modules which are dynamically loaded by the same dlopen() call. */ if (undef_map->l_opencount == 0 && map->l_opencount == 0) - return 0; + goto out; - /* Make sure nobody can unload the object while we are at it. */ - __rtld_lock_lock_recursive (GL(dl_load_lock)); + /* Avoid references to objects which cannot be unloaded anyway. */ + if (map->l_type != lt_loaded + || (map->l_flags_1 & DF_1_NODELETE) != 0) + goto out; + + /* If the object with the undefined reference cannot be removed ever + just make sure the same is true for the object which contains the + definition. */ + if (undef_map->l_type != lt_loaded + || (undef_map->l_flags_1 & DF_1_NODELETE) != 0) + { + ++map->l_opencount; + map->l_flags |= DF_1_NODELETE; + goto out; + } /* Determine whether UNDEF_MAP already has a reference to MAP. First look in the normal dependencies. */ diff --git a/elf/nodelete2.c b/elf/nodelete2.c new file mode 100644 index 0000000000..b3d7e31a08 --- /dev/null +++ b/elf/nodelete2.c @@ -0,0 +1,16 @@ +#include +#include +#include + +int +main (void) +{ + void *handle = dlopen ("nodel2mod3.so", RTLD_LAZY); + if (handle == NULL) + { + printf ("%s\n", dlerror ()); + exit (1); + } + dlclose (handle); + exit (1); +} diff --git a/elf/reldep6.c b/elf/reldep6.c index bf80ec5773..1eeec6c862 100644 --- a/elf/reldep6.c +++ b/elf/reldep6.c @@ -48,6 +48,18 @@ main (void) exit (1); } + baz = dlsym (h2, "baz"); + if (baz == NULL) + { + printf ("cannot get address of \"baz\": %s\n", dlerror ()); + exit (1); + } + if (baz () != 31) + { + printf ("baz() did not return 31\n"); + exit (1); + } + if (dlclose (h1) != 0) { printf ("closing h1 failed: %s\n", dlerror ()); diff --git a/elf/reldep9.c b/elf/reldep9.c new file mode 100644 index 0000000000..51c7a8bb9e --- /dev/null +++ b/elf/reldep9.c @@ -0,0 +1,16 @@ +#include +#include +#include + +int +main (void) +{ + void *handle = dlopen ("reldep9mod3.so", RTLD_LAZY); + if (handle == NULL) + { + printf ("%s\n", dlerror ()); + exit (1); + } + dlclose (handle); + abort (); +} diff --git a/elf/reldep9mod1.c b/elf/reldep9mod1.c new file mode 100644 index 0000000000..249a2bae1c --- /dev/null +++ b/elf/reldep9mod1.c @@ -0,0 +1,23 @@ +#include +void +foo (void) +{ + exit (0); +} + +void +__attribute__((destructor)) +bar (void) +{ + static int i; + foo (); + ++i; +} + +void +__attribute__((constructor)) +destr (void) +{ + extern void baz (void); + baz (); +} diff --git a/elf/reldep9mod2.c b/elf/reldep9mod2.c new file mode 100644 index 0000000000..090966e3e3 --- /dev/null +++ b/elf/reldep9mod2.c @@ -0,0 +1,3 @@ +void baz (void) +{ +} diff --git a/elf/reldep9mod3.c b/elf/reldep9mod3.c new file mode 100644 index 0000000000..6d1a0d47b7 --- /dev/null +++ b/elf/reldep9mod3.c @@ -0,0 +1 @@ +int x; diff --git a/elf/tls-macros.h b/elf/tls-macros.h index 6b40dedf88..046a7d4c92 100644 --- a/elf/tls-macros.h +++ b/elf/tls-macros.h @@ -243,47 +243,59 @@ register void *__gp __asm__("$29"); # define TLS_LE(x) \ ({ void *__l; \ - asm ("ld8 r2=tp\n\t" \ + asm ("mov r2=r13\n\t" \ ";;\n\t" \ - "addl %0=@tpre1(" #x "),r2\n\t" \ + "addl %0=@tprel(" #x "),r2\n\t" \ : "=r" (__l) : : "r2" ); __l; }) # define TLS_IE(x) \ ({ void *__l; \ - asm ("addl r16=@ltoff(@tprel(" #x ")),gp\n\t" \ + asm (";;\n\t" \ + "addl r16=@ltoff(@tprel(" #x ")),gp\n\t" \ ";;\n\t" \ "ld8 r17=[r16]\n\t" \ ";;\n\t" \ - "add %0=tp,r17\n\t" \ + "add %0=r13,r17\n\t" \ : "=r" (__l) : : "r16", "r17" ); __l; }) +# define __TLS_CALL_CLOBBERS \ + "r2", "r3", "r8", "r9", "r10", "r11", "r14", "r15", "r16", "r17", \ + "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", \ + "r27", "r28", "r29", "r30", "r31", \ + "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \ + "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \ + "b6", "b7", \ + "out0", "out1", "out2", "out3", "out4", "out5", "out6", "out7" + # define TLS_LD(x) \ ({ void *__l; \ - asm ("mov loc0=gp\n\t" \ + asm (";;\n\t" \ + "mov loc0=gp\n\t" \ "addl r16=@ltoff(@dtpmod(" #x ")),gp\n\t" \ "addl out1=@dtprel(" #x "),r0\n\t" \ ";;\n\t" \ "ld8 out0=[r16]\n\t" \ - "br.callrp=__tls_get_addr" \ + "br.call.sptk.many b0=__tls_get_addr" \ ";;\n\t" \ "mov gp=loc0\n\t" \ "mov %0=r8\n\t" \ - : "=r" (__l) : : "r16" , "loc0" , "out0" , "out1" , "r8" ); \ + : "=r" (__l) : : "loc0", __TLS_CALL_CLOBBERS); \ __l; }) # define TLS_GD(x) \ ({ void *__l; \ - asm ("mov loc0=gp\n\t" \ + asm (";;\n\t" \ + "mov loc0=gp\n\t" \ "addl r16=@ltoff(@dtpmod(" #x ")),gp\n\t" \ "addl r17=@ltoff(@dtprel(" #x ")),gp\n\t" \ ";;\n\t" \ "ld8 out0=[r16]\n\t" \ "ld8 out1=[r17]\n\t" \ - "br.callrp=__tls_get_addr" \ + "br.call.sptk.many b0=__tls_get_addr" \ ";;\n\t" \ "mov gp=loc0\n\t" \ "mov %0=r8\n\t" \ - : "=r" (__l) : : "r16", "r17" , "loc0" , "out0", "out1" , "r8"); \ + : "=r" (__l) : : "loc0", __TLS_CALL_CLOBBERS); \ __l; }) #else diff --git a/io/ftw.c b/io/ftw.c index 0ff5947ee4..4debcc0542 100644 --- a/io/ftw.c +++ b/io/ftw.c @@ -1,5 +1,5 @@ /* File tree walker functions. - Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1996. @@ -18,6 +18,10 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#ifdef HAVE_CONFIG_H +# include +#endif + #include #include #include @@ -25,12 +29,49 @@ #include #include #include -#include -#include +#if HAVE_SYS_PARAM_H || defined _LIBC +# include +#endif +#ifdef _LIBC +# include +#else +# include +#endif /* #define NDEBUG 1 */ #include +#ifndef _LIBC +# undef __chdir +# define __chdir chdir +# undef __closedir +# define __closedir closedir +# undef __fchdir +# define __fchdir fchdir +# undef __getcwd +# define __getcwd getcwd +# undef __opendir +# define __opendir opendir +# undef __readdir64 +# define __readdir64 readdir +# undef __tdestroy +# define __tdestroy tdestroy +# undef __tfind +# define __tfind tfind +# undef __tsearch +# define __tsearch tsearch +# undef internal_function +# define internal_function /* empty */ +# undef dirent64 +# define dirent64 dirent +# undef MAX +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + /* Support for the LFS API version. */ #ifndef FTW_NAME # define FTW_NAME ftw @@ -213,9 +254,11 @@ open_dir_stream (struct ftw_data *data, struct dir_data *dirp) /* Open the new stream. */ if (result == 0) { + const char *name = ((data->flags & FTW_CHDIR) + ? data->dirbuf + data->ftw.base: data->dirbuf); assert (data->dirstreams[data->actdir] == NULL); - dirp->stream = __opendir (data->dirbuf); + dirp->stream = __opendir (name); if (dirp->stream == NULL) result = -1; else @@ -251,7 +294,7 @@ process_entry (struct ftw_data *data, struct dir_data *dir, const char *name, char *newp; data->dirbufsize *= 2; - newp = realloc (data->dirbuf, data->dirbufsize); + newp = (char *) realloc (data->dirbuf, data->dirbufsize); if (newp == NULL) return -1; data->dirbuf = newp; @@ -259,14 +302,17 @@ process_entry (struct ftw_data *data, struct dir_data *dir, const char *name, *((char *) __mempcpy (data->dirbuf + data->ftw.base, name, namlen)) = '\0'; + if ((data->flags & FTW_CHDIR) == 0) + name = data->dirbuf; + if (((data->flags & FTW_PHYS) - ? LXSTAT (_STAT_VER, data->dirbuf, &st) - : XSTAT (_STAT_VER, data->dirbuf, &st)) < 0) + ? LXSTAT (_STAT_VER, name, &st) + : XSTAT (_STAT_VER, name, &st)) < 0) { if (errno != EACCES && errno != ENOENT) result = -1; else if (!(data->flags & FTW_PHYS) - && LXSTAT (_STAT_VER, data->dirbuf, &st) == 0 + && LXSTAT (_STAT_VER, name, &st) == 0 && S_ISLNK (st.st_mode)) flag = FTW_SLN; else diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog index 862b5485ab..5f0c1bfb2b 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -1,3 +1,50 @@ +2003-01-11 Philip Blundell + + * sysdeps/unix/sysv/linux/arm/vfork.S: New file. + * sysdeps/unix/sysv/linux/arm/sysdep-cancel.h (PSEUDO_RET): + Correctly unstack lr. + (UNDOARGS_5): Fix ordering of pushes and pops. + (SINGLE_THREAD_P_PIC): New. + (SINGLE_THREAD_P_INT): New. + (SINGLE_THREAD_P): Implement in terms of above. Restore lr if it + was stacked. + (PSEUDO): Use SINGLE_THREAD_P_INT. + +2003-01-11 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/vfork.S: New file. + +2003-01-11 Jakub Jelinek + + * sysdeps/ia64/tls.h (tcbhead_t): Change into dtv_t *, void *. + [HAVE_TLS_SUPPORT] (USE_TLS, TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN, + TLS_TCB_SIZE, TLS_PRE_TCB_SIZE, TLS_TCB_ALIGN, TLS_DTV_AT_TP, + INSTALL_DTV, INSTALL_NEW_DTV, GET_DTV, TLS_INIT_TP, THREAD_SELF, + INIT_THREAD_SELF): Define. + [HAVE_TLS_SUPPORT]: Include descr.h. + (NONTLS_INIT_TP): Point __thread_self at the end of dummy + struct _pthread_descr_struct. + * sysdeps/ia64/pt-machine.h (THREAD_GETMEM, THREAD_GETMEM_NC, + THREAD_SETMEM, THREAD_SETMEM_NC): Define using THREAD_SELF, + not __thread_self. + * sysdeps/ia64/tcb-offsets.sym (MULTIPLE_THREADS_OFFSET): Adjust + computation. + * pthread.c (__pthread_initialize_minimal): Use tcbp, not self + for TCB pointer. + (__pthread_initialize_manager): Rename tcb to mgr. + Use tcbp for TCB pointer, if TLS_DTV_AT_TP set mgr to sizeof (struct + _pthread_descr) below tcbp, otherwise to tcbp. + * manager.c (pthread_handle_create): If TLS_DTV_AT_TP, set + new_thread to be below _dl_allocate_tls (). Adjust new_thread back + before freeing. Fix clone arguments if report_events and USE_TLS. + (pthread_free): Adjust th back before freeing. + +2003-01-10 Steven Munroe + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/Makefile: Moved to ... + * sysdeps/unix/sysv/linux/powerpc/Makefile: ...here. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: New File. + 2003-01-09 Jakub Jelinek * sysdeps/unix/sysv/linux/i386/vfork.S: New file. diff --git a/linuxthreads/manager.c b/linuxthreads/manager.c index 3268ea8a41..8f9b23841b 100644 --- a/linuxthreads/manager.c +++ b/linuxthreads/manager.c @@ -590,6 +590,10 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, new_thread = _dl_allocate_tls (NULL); if (new_thread == NULL) return EAGAIN; +# if TLS_DTV_AT_TP + /* pthread_descr is right below TP. */ + --new_thread; +# endif #else /* Prevent warnings. */ new_thread = NULL; @@ -607,6 +611,9 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, if (sseg >= PTHREAD_THREADS_MAX) { #ifdef USE_TLS +# if TLS_DTV_AT_TP + ++new_thread; +# endif _dl_deallocate_tls (new_thread, true); #endif return EAGAIN; @@ -631,7 +638,11 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, new_thread_id = sseg + pthread_threads_counter; /* Initialize the thread descriptor. Elements which have to be initialized to zero already have this value. */ +#if defined USE_TLS && TLS_DTV_AT_TP + new_thread->p_header.data.tcb = new_thread + 1; +#else new_thread->p_header.data.tcb = new_thread; +#endif new_thread->p_header.data.self = new_thread; new_thread->p_header.data.multiple_threads = 1; new_thread->p_tid = new_thread_id; @@ -711,15 +722,15 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, other, to get less paging and fewer mmaps. */ pid = __clone2(pthread_start_thread_event, (void **)new_thread_bottom, - (char *)new_thread - new_thread_bottom, + (char *)stack_addr - new_thread_bottom, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | __pthread_sig_cancel, new_thread); #elif _STACK_GROWS_UP - pid = __clone(pthread_start_thread_event, (void **) new_thread_bottom, + pid = __clone(pthread_start_thread_event, (void *) new_thread_bottom, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | __pthread_sig_cancel, new_thread); #else - pid = __clone(pthread_start_thread_event, (void **) new_thread, + pid = __clone(pthread_start_thread_event, stack_addr, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | __pthread_sig_cancel, new_thread); #endif @@ -794,6 +805,9 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, #endif } #ifdef USE_TLS +# if TLS_DTV_AT_TP + ++new_thread; +# endif _dl_deallocate_tls (new_thread, true); #endif __pthread_handles[sseg].h_descr = NULL; @@ -881,6 +895,9 @@ static void pthread_free(pthread_descr th) munmap(guardaddr, stacksize + guardsize); #ifdef USE_TLS +# if TLS_DTV_AT_TP + ++th; +# endif _dl_deallocate_tls (th, true); #endif } diff --git a/linuxthreads/pthread.c b/linuxthreads/pthread.c index 432336258c..f72e20ee09 100644 --- a/linuxthreads/pthread.c +++ b/linuxthreads/pthread.c @@ -307,6 +307,8 @@ __pthread_initialize_minimal(void) # elif !USE___THREAD if (__builtin_expect (GL(dl_tls_max_dtv_idx) == 0, 0)) { + tcbhead_t *tcbp; + /* There is no actual TLS being used, so the thread register was not initialized in the dynamic linker. */ @@ -318,7 +320,7 @@ __pthread_initialize_minimal(void) __libc_malloc_pthread_startup (true); if (__builtin_expect (_dl_tls_setup (), 0) - || __builtin_expect ((self = _dl_allocate_tls (NULL)) == NULL, 0)) + || __builtin_expect ((tcbp = _dl_allocate_tls (NULL)) == NULL, 0)) { static const char msg[] = "\ cannot allocate TLS data structures for initial thread\n"; @@ -326,7 +328,7 @@ cannot allocate TLS data structures for initial thread\n"; msg, sizeof msg - 1)); abort (); } - const char *lossage = TLS_INIT_TP (self, 0); + const char *lossage = TLS_INIT_TP (tcbp, 0); if (__builtin_expect (lossage != NULL, 0)) { static const char msg[] = "cannot set up thread-local storage: "; @@ -343,7 +345,7 @@ cannot allocate TLS data structures for initial thread\n"; the hooks might not work with that block from the plain malloc. So we record this block as unfreeable just as the dynamic linker does when it allocates the DTV before the libc malloc exists. */ - GL(dl_initial_dtv) = GET_DTV (self); + GL(dl_initial_dtv) = GET_DTV (tcbp); __libc_malloc_pthread_startup (false); } @@ -558,7 +560,10 @@ int __pthread_initialize_manager(void) int pid; struct pthread_request request; int report_events; - pthread_descr tcb; + pthread_descr mgr; +#ifdef USE_TLS + tcbhead_t *tcbp; +#endif __pthread_multiple_threads = 1; __pthread_main_thread->p_header.data.multiple_threads = 1; @@ -588,31 +593,39 @@ int __pthread_initialize_manager(void) #ifdef USE_TLS /* Allocate memory for the thread descriptor and the dtv. */ - __pthread_handles[1].h_descr = manager_thread = tcb - = _dl_allocate_tls (NULL); - if (tcb == NULL) { + tcbp = _dl_allocate_tls (NULL); + if (tcbp == NULL) { free(__pthread_manager_thread_bos); __libc_close(manager_pipe[0]); __libc_close(manager_pipe[1]); return -1; } +# if TLS_TCB_AT_TP + mgr = (pthread_descr) tcbp; +# elif TLS_DTV_AT_TP + /* pthread_descr is located right below tcbhead_t which _dl_allocate_tls + returns. */ + mgr = (pthread_descr) tcbp - 1; +# endif + __pthread_handles[1].h_descr = manager_thread = mgr; + /* Initialize the descriptor. */ - tcb->p_header.data.tcb = tcb; - tcb->p_header.data.self = tcb; - tcb->p_header.data.multiple_threads = 1; - tcb->p_lock = &__pthread_handles[1].h_lock; + mgr->p_header.data.tcb = tcbp; + mgr->p_header.data.self = mgr; + mgr->p_header.data.multiple_threads = 1; + mgr->p_lock = &__pthread_handles[1].h_lock; # ifndef HAVE___THREAD - tcb->p_errnop = &tcb->p_errno; + mgr->p_errnop = &mgr->p_errno; # endif - tcb->p_start_args = (struct pthread_start_args) PTHREAD_START_ARGS_INITIALIZER(__pthread_manager); - tcb->p_nr = 1; + mgr->p_start_args = (struct pthread_start_args) PTHREAD_START_ARGS_INITIALIZER(__pthread_manager); + mgr->p_nr = 1; # if __LT_SPINLOCK_INIT != 0 self->p_resume_count = (struct pthread_atomic) __ATOMIC_INITIALIZER; # endif - tcb->p_alloca_cutoff = PTHREAD_STACK_MIN / 4; + mgr->p_alloca_cutoff = PTHREAD_STACK_MIN / 4; #else - tcb = &__pthread_manager_thread; + mgr = &__pthread_manager_thread; #endif __pthread_manager_request = manager_pipe[1]; /* writing end */ @@ -649,24 +662,24 @@ int __pthread_initialize_manager(void) if ((mask & (__pthread_threads_events.event_bits[idx] | event_bits)) != 0) { - __pthread_lock(tcb->p_lock, NULL); + __pthread_lock(mgr->p_lock, NULL); #ifdef NEED_SEPARATE_REGISTER_STACK pid = __clone2(__pthread_manager_event, (void **) __pthread_manager_thread_bos, THREAD_MANAGER_STACK_SIZE, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, - tcb); + mgr); #elif _STACK_GROWS_UP pid = __clone(__pthread_manager_event, (void **) __pthread_manager_thread_bos, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, - tcb); + mgr); #else pid = __clone(__pthread_manager_event, (void **) __pthread_manager_thread_tos, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, - tcb); + mgr); #endif if (pid != -1) @@ -675,18 +688,18 @@ int __pthread_initialize_manager(void) the newly created thread's data structure. We cannot let the new thread do this since we don't know whether it was already scheduled when we send the event. */ - tcb->p_eventbuf.eventdata = tcb; - tcb->p_eventbuf.eventnum = TD_CREATE; - __pthread_last_event = tcb; - tcb->p_tid = 2* PTHREAD_THREADS_MAX + 1; - tcb->p_pid = pid; + mgr->p_eventbuf.eventdata = mgr; + mgr->p_eventbuf.eventnum = TD_CREATE; + __pthread_last_event = mgr; + mgr->p_tid = 2* PTHREAD_THREADS_MAX + 1; + mgr->p_pid = pid; /* Now call the function which signals the event. */ __linuxthreads_create_event (); } /* Now restart the thread. */ - __pthread_unlock(tcb->p_lock); + __pthread_unlock(mgr->p_lock); } } @@ -695,13 +708,13 @@ int __pthread_initialize_manager(void) #ifdef NEED_SEPARATE_REGISTER_STACK pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_bos, THREAD_MANAGER_STACK_SIZE, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, tcb); + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, mgr); #elif _STACK_GROWS_UP pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, tcb); + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, mgr); #else pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, tcb); + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, mgr); #endif } if (__builtin_expect (pid, 0) == -1) { @@ -710,8 +723,8 @@ int __pthread_initialize_manager(void) __libc_close(manager_pipe[1]); return -1; } - tcb->p_tid = 2* PTHREAD_THREADS_MAX + 1; - tcb->p_pid = pid; + mgr->p_tid = 2* PTHREAD_THREADS_MAX + 1; + mgr->p_pid = pid; /* Make gdb aware of new thread manager */ if (__builtin_expect (__pthread_threads_debug, 0) && __pthread_sig_debug > 0) { diff --git a/linuxthreads/sysdeps/ia64/pt-machine.h b/linuxthreads/sysdeps/ia64/pt-machine.h index 5c4dde2fca..4b88a00509 100644 --- a/linuxthreads/sysdeps/ia64/pt-machine.h +++ b/linuxthreads/sysdeps/ia64/pt-machine.h @@ -1,6 +1,6 @@ /* Machine-dependent pthreads configuration and inline functions. IA-64 version. - Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2002, 2003 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 @@ -64,10 +64,10 @@ register struct _pthread_descr_struct *__thread_self __asm__("r13"); /* Access to data in the thread descriptor is easy. */ -#define THREAD_GETMEM(descr, member) __thread_self->member -#define THREAD_GETMEM_NC(descr, member) __thread_self->member -#define THREAD_SETMEM(descr, member, value) __thread_self->member = (value) -#define THREAD_SETMEM_NC(descr, member, value) __thread_self->member = (value) +#define THREAD_GETMEM(descr, member) THREAD_SELF->member +#define THREAD_GETMEM_NC(descr, member) THREAD_SELF->member +#define THREAD_SETMEM(descr, member, value) THREAD_SELF->member = (value) +#define THREAD_SETMEM_NC(descr, member, value) THREAD_SELF->member = (value) /* Memory barrier */ diff --git a/linuxthreads/sysdeps/ia64/tcb-offsets.sym b/linuxthreads/sysdeps/ia64/tcb-offsets.sym index aee6be2570..a1d199f44e 100644 --- a/linuxthreads/sysdeps/ia64/tcb-offsets.sym +++ b/linuxthreads/sysdeps/ia64/tcb-offsets.sym @@ -1,4 +1,4 @@ #include #include -MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +MULTIPLE_THREADS_OFFSET offsetof (struct _pthread_descr_struct, p_header.data.multiple_threads) - sizeof (struct _pthread_descr_struct) diff --git a/linuxthreads/sysdeps/ia64/tls.h b/linuxthreads/sysdeps/ia64/tls.h index 544da6e694..b2c47c00a6 100644 --- a/linuxthreads/sysdeps/ia64/tls.h +++ b/linuxthreads/sysdeps/ia64/tls.h @@ -1,5 +1,5 @@ /* Definitions for thread-local data handling. linuxthreads/IA-64 version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2003 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 @@ -33,35 +33,91 @@ typedef union dtv } dtv_t; -/* FIXME: Only temporary. When TLS is supported on IA-64, - pthread_descr struct needs to be immediately below r13 and - at r13 a struct { dtv_t *dtv; void *private; }. */ typedef struct { - void *tcb; /* Pointer to the TCB. Not necessary the - thread descriptor used by libpthread. */ dtv_t *dtv; - void *self; /* Pointer to the thread descriptor. */ - int multiple_threads; + void *private; } tcbhead_t; #else /* __ASSEMBLER__ */ # include #endif /* __ASSEMBLER__ */ -#undef USE_TLS +#ifdef HAVE_TLS_SUPPORT -#if USE_TLS +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The DTV is allocated at the TP; the TCB is placed elsewhere. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + ((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) \ + (((tcbhead_t *)__thread_self)->dtv = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + (__thread_self = (tcbp), NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *)__thread_self)->dtv) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF (__thread_self - 1) + +# undef INIT_THREAD_SELF +# define INIT_THREAD_SELF(descr, nr) \ + (__thread_self = (struct _pthread_descr_struct *)(descr) + 1) + +/* Get the thread descriptor definition. */ +# include + +# endif #else -#define NONTLS_INIT_TP \ - do { \ - static const tcbhead_t nontls_init_tp \ - = { .multiple_threads = 0 }; \ - __thread_self = (__typeof (__thread_self)) &nontls_init_tp; \ +# ifndef __ASSEMBLER__ +/* Get the thread descriptor definition. */ +# include + +# define NONTLS_INIT_TP \ + do { \ + static struct _pthread_descr_struct nontls_init_tp \ + = { .p_header.data.multiple_threads = 0 }; \ + __thread_self = ((__typeof (__thread_self)) &nontls_init_tp) + 1; \ } while (0) +#endif + #endif /* USE_TLS */ #endif /* tls.h */ diff --git a/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h index 5f3709f742..38e472d2ba 100644 --- a/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h +++ b/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h @@ -27,6 +27,7 @@ # undef PSEUDO_RET # define PSEUDO_RET \ ldrcc pc, [sp], $4; \ + ldr lr, [sp], $4; \ b PLTJMP(SYSCALL_ERROR) # undef PSEUDO @@ -34,7 +35,7 @@ .section ".text"; \ PSEUDO_PROLOGUE; \ ENTRY (name) \ - SINGLE_THREAD_P; \ + SINGLE_THREAD_P_INT; \ bne .Lpseudo_cancel; \ DO_CALL (syscall_name, args); \ cmn r0, $4096; \ @@ -74,7 +75,7 @@ # define UNDOC2ARGS_4 # define DOCARGS_5 stmfd sp!, {r0-r3} -# define UNDOCARGS_5 str r4, [sp, #-4]!; ldmfd sp, {r0-r4} +# define UNDOCARGS_5 ldmfd sp, {r0-r3}; str r4, [sp, #-4]!; ldr r4, [sp, #24] # define UNDOC2ARGS_5 ldr r4, [sp], #20 # ifdef IS_IN_libpthread @@ -92,10 +93,11 @@ extern int __local_multiple_threads attribute_hidden; # define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) # else # if !defined PIC -# define SINGLE_THREAD_P \ +# define SINGLE_THREAD_P_INT \ ldr ip, =__local_multiple_threads; \ ldr ip, [ip]; \ teq ip, #0; +# define SINGLE_THREAD_P SINGLE_THREAD_P_INT # define MAYBE_SAVE_LR \ str lr, [sp, $-4]!; # define PSEUDO_RET_MOV \ @@ -103,14 +105,19 @@ extern int __local_multiple_threads attribute_hidden; b PLTJMP(SYSCALL_ERROR) # define PSEUDO_PROLOGUE # else -# define SINGLE_THREAD_P \ - str lr, [sp, $-4]!; \ +# define SINGLE_THREAD_P_PIC(reg) \ ldr ip, 1b; \ - ldr lr, 2b; \ + ldr reg, 2b; \ 3: \ add ip, pc, ip; \ ldr ip, [ip, lr]; \ teq ip, #0; +# define SINGLE_THREAD_P_INT \ + str lr, [sp, $-4]!; \ + SINGLE_THREAD_P_PIC(lr) +# define SINGLE_THREAD_P \ + SINGLE_THREAD_P_INT; \ + ldr lr, [sp], $4 # define PSEUDO_PROLOGUE \ 1: .word _GLOBAL_OFFSET_TABLE_ - 3f - 8; \ 2: .word __local_multiple_threads(GOTOFF); diff --git a/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S new file mode 100644 index 0000000000..6092bd9fd4 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S @@ -0,0 +1,57 @@ +/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell . + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include + +/* Clone the calling process, but without copying the whole address +pace. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new +rocess, + and the process ID of the new process to the old process. */ + + PSEUDO_PROLOGUE + +ENTRY (__vfork) + +#ifdef __NR_vfork + SINGLE_THREAD_P + bne HIDDEN_JUMPTARGET (__fork) + swi __NR_vfork + cmn a1, #4096 + RETINSTR(movcc, pc, lr) + + /* Check if vfork syscall is known at all. */ + ldr a2, =-ENOSYS + teq a1, a2 + bne PLTJMP(C_SYMBOL_NAME(__syscall_error)) +#endif + + /* If we don't have vfork, fork is close enough. */ + swi __NR_fork + cmn a1, #4096 + RETINSTR(movcc, pc, lr) + b PLTJMP(C_SYMBOL_NAME(__syscall_error)) + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/Makefile b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/Makefile similarity index 100% rename from linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/Makefile rename to linuxthreads/sysdeps/unix/sysv/linux/powerpc/Makefile diff --git a/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h new file mode 100644 index 0000000000..58257a17b2 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h @@ -0,0 +1,102 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Franz Sirl , 2003. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + bne- .Lpseudo_cancel; \ + DO_CALL (SYS_ify (syscall_name)); \ + PSEUDO_RET; \ + .Lpseudo_cancel: \ + stdu 1,-128(1); \ + mflr 9; \ + std 9,128+16(1); \ + DOCARGS_##args; /* save syscall args around CENABLE. */ \ + CENABLE; \ + std 3,72(1); /* store CENABLE return value (MASK). */ \ + UNDOCARGS_##args; /* restore syscall args. */ \ + DO_CALL (SYS_ify (syscall_name)); \ + mfcr 0; /* save CR/R3 around CDISABLE. */ \ + std 3,64(1); \ + std 0,8(1); \ + ld 3,72(1); /* pass MASK to CDISABLE. */ \ + CDISABLE; \ + ld 9,128+16(1); \ + ld 0,8(1); /* restore CR/R3. */ \ + ld 3,64(1); \ + mtlr 9; \ + mtcr 0; \ + addi 1,1,128; + +# define DOCARGS_0 +# define UNDOCARGS_0 + +# define DOCARGS_1 std 3,80(1); DOCARGS_0 +# define UNDOCARGS_1 ld 3,80(1); UNDOCARGS_0 + +# define DOCARGS_2 std 4,88(1); DOCARGS_1 +# define UNDOCARGS_2 ld 4,88(1); UNDOCARGS_1 + +# define DOCARGS_3 std 5,96(1); DOCARGS_2 +# define UNDOCARGS_3 ld 5,96(1); UNDOCARGS_2 + +# define DOCARGS_4 std 6,104(1); DOCARGS_3 +# define UNDOCARGS_4 ld 6,104(1); UNDOCARGS_3 + +# define DOCARGS_5 std 7,112(1); DOCARGS_4 +# define UNDOCARGS_5 ld 7,112(1); UNDOCARGS_4 + +# define DOCARGS_6 std 8,120(1); DOCARGS_5 +# define UNDOCARGS_6 ld 8,120(1); UNDOCARGS_5 + +# ifdef IS_IN_libpthread +# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel) +# define __local_multiple_threads __pthread_multiple_threads +# else +# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__libc_disable_asynccancel) +# define __local_multiple_threads __libc_multiple_threads +# endif + +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P \ + ld 10,__local_multiple_threads@got(2); \ + ld 10,0(10); \ + cmpdi 10,0 +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S new file mode 100644 index 0000000000..f796e31088 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S @@ -0,0 +1,57 @@ +/* Copyright (C) 2003 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + SINGLE_THREAD_P + bf .Lhidden_fork + + mov.w .L1, r3 + trapa #0x10 + mov r0, r1 + mov #-12, r2 + shad r2, r1 + not r1, r1 // r1=0 means r0 = -1 to -4095 + tst r1, r1 // i.e. error in linux + bf .Lpseudo_end + SYSCALL_ERROR_HANDLER +.Lpseudo_end: + rts + nop +.L1: .word __NR_vfork + +.Lhidden_fork: + mov.l .L2, r1 + braf r1 + nop +1: + .align 2 +.L2: .long HIDDEN_JUMPTARGET(__fork)-1b + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/string/tester.c b/string/tester.c index dab570500c..0a69d2639f 100644 --- a/string/tester.c +++ b/string/tester.c @@ -174,11 +174,13 @@ test_strcpy (void) SIMPLE_COPY(strcpy, 15, "555555555555555", 56); SIMPLE_COPY(strcpy, 16, "6666666666666666", 57); +#if 0 /* Simple test using implicitly coerced `void *' arguments. */ const void *src = "frobozz"; void *dst = one; check (strcpy (dst, src) == dst, 1); equal (dst, "frobozz", 2); +#endif } static void diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h index 711bf10fdd..3a182ca99f 100644 --- a/sysdeps/alpha/dl-machine.h +++ b/sysdeps/alpha/dl-machine.h @@ -1,5 +1,5 @@ /* Machine-dependent ELF dynamic relocation inline functions. Alpha version. - Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1996-2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson . @@ -610,8 +610,8 @@ elf_machine_rela (struct link_map *map, #else if (sym_map) { - *reloc_addr = sym_value - sym_map->l_tls_offset; CHECK_STATIC_TLS (map, sym_map); + *reloc_addr = sym_value - sym_map->l_tls_offset; } #endif } diff --git a/sysdeps/generic/dl-tls.c b/sysdeps/generic/dl-tls.c index 6791d765ee..0afe379ae6 100644 --- a/sysdeps/generic/dl-tls.c +++ b/sysdeps/generic/dl-tls.c @@ -282,9 +282,18 @@ internal_function _dl_allocate_tls_storage (void) { void *result; + size_t size = GL(dl_tls_static_size); + +# if TLS_DTV_AT_TP + /* Memory layout is: + [ TLS_PRE_TCB_SIZE ] [ TLS_TCB_SIZE ] [ TLS blocks ] + ^ This should be returned. */ + size += (TLS_PRE_TCB_SIZE + GL(dl_tls_static_align) - 1) + & ~(GL(dl_tls_static_align) - 1); +# endif /* Allocate a correctly aligned chunk of memory. */ - result = __libc_memalign (GL(dl_tls_static_align), GL(dl_tls_static_size)); + result = __libc_memalign (GL(dl_tls_static_align), size); if (__builtin_expect (result != NULL, 0)) { /* Allocate the DTV. */ @@ -292,12 +301,20 @@ _dl_allocate_tls_storage (void) # if TLS_TCB_AT_TP /* The TCB follows the TLS blocks. */ - result = (char *) result + GL(dl_tls_static_size) - TLS_TCB_SIZE; -# endif + result = (char *) result + size - TLS_TCB_SIZE; /* Clear the TCB data structure. We can't ask the caller (i.e. libpthread) to do it, because we will initialize the DTV et al. */ memset (result, 0, TLS_TCB_SIZE); +# elif TLS_DTV_AT_TP + result = (char *) result + size - GL(dl_tls_static_size); + + /* Clear the TCB data structure and TLS_PRE_TCB_SIZE bytes before it. + We can't ask the caller (i.e. libpthread) to do it, because we will + initialize the DTV et al. */ + memset ((char *) result - TLS_PRE_TCB_SIZE, 0, + TLS_PRE_TCB_SIZE + TLS_TCB_SIZE); +# endif result = allocate_dtv (result); if (result == NULL) @@ -405,6 +422,10 @@ _dl_deallocate_tls (void *tcb, bool dealloc_tcb) # if TLS_TCB_AT_TP /* The TCB follows the TLS blocks. Back up to free the whole block. */ tcb -= GL(dl_tls_static_size) - TLS_TCB_SIZE; +# elif TLS_DTV_AT_TP + /* Back up the TLS_PRE_TCB_SIZE bytes. */ + tcb -= (TLS_PRE_TCB_SIZE + GL(dl_tls_static_align) - 1) + & ~(GL(dl_tls_static_align) - 1); # endif free (tcb); } diff --git a/sysdeps/generic/libc-tls.c b/sysdeps/generic/libc-tls.c index 1461bf8543..b5ecc36436 100644 --- a/sysdeps/generic/libc-tls.c +++ b/sysdeps/generic/libc-tls.c @@ -1,5 +1,5 @@ /* Initialization code for TLS in statically linked application. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2003 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 @@ -134,15 +134,16 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign) break; } +#ifdef TLS_INIT_TP_EXPENSIVE if (memsz == 0 && tcbsize <= TLS_INIT_TCB_SIZE) { /* We do not need a TLS block and no thread descriptor. */ -#ifdef NONTLS_INIT_TP +# ifdef NONTLS_INIT_TP NONTLS_INIT_TP; -#endif +# endif return; } - +#endif /* We have to set up the TCB block which also (possibly) contains 'errno'. Therefore we avoid 'malloc' which might touch 'errno'. @@ -157,8 +158,10 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign) tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign); tlsblock = __sbrk (tcb_offset + tcbsize + max_align); # elif TLS_DTV_AT_TP - tlsblock = __sbrk (roundup (tcbsize, align) + memsz + max_align - + GL(dl_tls_static_size)); + tcb_offset = roundup (tcbsize, align ?: 1); + tlsblock = __sbrk (tcb_offset + memsz + max_align + + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size)); + tlsblock += TLS_PRE_TCB_SIZE; # else /* In case a model with a different layout for the TCB and DTV is defined add another #elif here and in the following #ifs. */ @@ -179,7 +182,6 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign) - roundup (memsz, align ?: 1)); static_map.l_tls_offset = roundup (memsz, align ?: 1); # elif TLS_DTV_AT_TP - tcb_offset = roundup (tcbsize, align); static_dtv[2].pointer = (char *) tlsblock + tcb_offset; static_map.l_tls_offset = tcb_offset; # else @@ -222,6 +224,8 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign) # if TLS_TCB_AT_TP memsz += tcbsize; +# elif TLS_DTV_AT_TP + memsz += tcb_offset; # endif init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align)); diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h index add6f8e01b..fa5076e3e5 100644 --- a/sysdeps/i386/dl-machine.h +++ b/sysdeps/i386/dl-machine.h @@ -1,5 +1,5 @@ /* Machine-dependent ELF dynamic relocation inline functions. i386 version. - Copyright (C) 1995,96,97,98,99,2000,2001,2002 Free Software Foundation, Inc. + Copyright (C) 1995-2002, 2003 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 @@ -445,8 +445,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, block we subtract the offset from that of the TLS block. */ if (sym != NULL) { - *reloc_addr += sym_map->l_tls_offset - sym->st_value; CHECK_STATIC_TLS (map, sym_map); + *reloc_addr += sym_map->l_tls_offset - sym->st_value; } # endif break; @@ -460,8 +460,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, thread pointer. */ if (sym != NULL) { - *reloc_addr += sym->st_value - sym_map->l_tls_offset; CHECK_STATIC_TLS (map, sym_map); + *reloc_addr += sym->st_value - sym_map->l_tls_offset; } # endif break; @@ -555,20 +555,20 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, It is a positive value which will be subtracted from the thread pointer. To get the variable position in the TLS block we subtract the offset from that of the TLS block. */ + CHECK_STATIC_TLS (map, sym_map); *reloc_addr = (sym == NULL ? 0 : sym_map->l_tls_offset - sym->st_value) + reloc->r_addend; - CHECK_STATIC_TLS (map, sym_map); break; case R_386_TLS_TPOFF: /* The offset is negative, forward from the thread pointer. */ /* We know the offset of object the symbol is contained in. It is a negative value which will be added to the thread pointer. */ + CHECK_STATIC_TLS (map, sym_map); *reloc_addr = (sym == NULL ? 0 : sym->st_value - sym_map->l_tls_offset) + reloc->r_addend; - CHECK_STATIC_TLS (map, sym_map); break; # endif /* use TLS */ # ifndef RESOLVE_CONFLICT_FIND_MAP diff --git a/sysdeps/ia64/dl-machine.h b/sysdeps/ia64/dl-machine.h index 16a1ff3000..f5eeef67db 100644 --- a/sysdeps/ia64/dl-machine.h +++ b/sysdeps/ia64/dl-machine.h @@ -1,5 +1,5 @@ /* Machine-dependent ELF dynamic relocation inline functions. IA-64 version. - Copyright (C) 1995,1996,1997,2000,2001,2002 Free Software Foundation, Inc. + Copyright (C) 1995-1997, 2000-2002, 2003 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 @@ -26,7 +26,7 @@ #include #include #include - +#include /* Translate a processor specific dynamic tag to the index in l_info array. */ @@ -448,14 +448,22 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) #define RTLD_START_SPECIAL_INIT /* nothing */ #endif -/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so - PLT entries should not be allowed to define the value. +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or TLS + variable, so undefined references should not be allowed to define the + value. ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one of the main executable's symbols, as for a COPY reloc, which we don't use. */ -/* ??? Ignore IPLTMSB for now. */ +/* ??? Ignore *MSB for now. */ +#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD) +#define elf_machine_type_class(type) \ + (((type) == R_IA64_IPLTLSB || (type) == R_IA64_DTPMOD64LSB \ + || (type) == R_IA64_DTPREL64LSB || (type) == R_IA64_TPREL64LSB) \ + * ELF_RTYPE_CLASS_PLT) +#else #define elf_machine_type_class(type) \ (((type) == R_IA64_IPLTLSB) * ELF_RTYPE_CLASS_PLT) +#endif /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ #define ELF_MACHINE_JMP_SLOT R_IA64_IPLTLSB @@ -557,8 +565,7 @@ elf_machine_rela (struct link_map *map, /* RESOLVE_MAP() will return NULL if it fail to locate the symbol. */ if ((sym_map = RESOLVE_MAP (&sym, version, r_type))) { - value = sym ? sym_map->l_addr + sym->st_value : 0; - value += reloc->r_addend; + value = sym_map->l_addr + sym->st_value + reloc->r_addend; if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_DIR64LSB)) ;/* No adjustment. */ @@ -571,6 +578,26 @@ elf_machine_rela (struct link_map *map, value = __ia64_make_fptr (sym_map, sym, value); else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_PCREL64LSB)) value -= (Elf64_Addr) reloc_addr & -16; +#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || defined USE___THREAD) + else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_DTPMOD64LSB)) +# ifdef RTLD_BOOTSTRAP + /* During startup the dynamic linker is always index 1. */ + value = 1; +# else + /* Get the information from the link map returned by the + resolv function. */ + value = sym_map->l_tls_modid; + else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_DTPREL64LSB)) + value -= sym_map->l_addr; +# endif + else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_TPREL64LSB)) + { +# ifndef RTLD_BOOTSTRAP + CHECK_STATIC_TLS (map, sym_map); +# endif + value += sym_map->l_tls_offset - sym_map->l_addr; + } +#endif else assert (! "unexpected dynamic reloc type"); } diff --git a/sysdeps/ia64/dl-tls.h b/sysdeps/ia64/dl-tls.h index 738c820a44..26f3d2adf1 100644 --- a/sysdeps/ia64/dl-tls.h +++ b/sysdeps/ia64/dl-tls.h @@ -1,5 +1,5 @@ /* Thread-local storage handling in the ELF dynamic linker. IA-64 version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2003 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 @@ -26,3 +26,5 @@ /* We have no tls_index type. */ #define DONT_USE_TLS_INDEX 1 + +extern void *__tls_get_addr (size_t m, size_t offset); diff --git a/sysdeps/ia64/libc-tls.c b/sysdeps/ia64/libc-tls.c new file mode 100644 index 0000000000..f1df4cd12e --- /dev/null +++ b/sysdeps/ia64/libc-tls.c @@ -0,0 +1,37 @@ +/* Thread-local storage handling in the ELF dynamic linker. IA-64 version. + Copyright (C) 2003 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#if USE_TLS + +/* On IA-64, as it lacks linker optimizations, __tls_get_addr can be + called even in statically linked binaries. + In this case module must be always 1 and PT_TLS segment + exist in the binary, otherwise it would not link. */ + +void * +__tls_get_addr (size_t m, size_t offset) +{ + dtv_t *dtv = THREAD_DTV (); + return (char *) dtv[1].pointer + offset; +} + +#endif + diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h index c25df403b6..9b895df3f0 100644 --- a/sysdeps/powerpc/powerpc64/sysdep.h +++ b/sysdeps/powerpc/powerpc64/sysdep.h @@ -216,7 +216,7 @@ LT_LABELSUFFIX(name,_name_end): ; \ DO_CALL (SYS_ify (syscall_name)); #define PSEUDO_RET \ - bnslr; \ + bnslr+; \ b JUMPTARGET(__syscall_error) #define ret PSEUDO_RET diff --git a/sysdeps/sh/dl-machine.h b/sysdeps/sh/dl-machine.h index c6d094d26a..6607d9b2f8 100644 --- a/sysdeps/sh/dl-machine.h +++ b/sysdeps/sh/dl-machine.h @@ -1,5 +1,5 @@ /* Machine-dependent ELF dynamic relocation inline functions. SH version. - Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2001, 2002, 2003 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 @@ -579,10 +579,10 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, It is a positive value which will be added to the thread pointer. To get the variable position in the TLS block we add the offset from that of the TLS block. */ + CHECK_STATIC_TLS (map, sym_map); *reloc_addr = ((sym == NULL ? 0 : sym_map->l_tls_offset + sym->st_value) + reloc->r_addend); - CHECK_STATIC_TLS (map, sym_map); # endif break; #endif /* use TLS */ diff --git a/sysdeps/unix/sysv/linux/arm/socket.S b/sysdeps/unix/sysv/linux/arm/socket.S index f4ccc5465d..3e93ceb6d2 100644 --- a/sysdeps/unix/sysv/linux/arm/socket.S +++ b/sysdeps/unix/sysv/linux/arm/socket.S @@ -1,4 +1,4 @@ -/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1995, 1996, 1997, 1998, 2003 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 @@ -16,7 +16,7 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include +#include #include #define P(a, b) P2(a, b) @@ -53,6 +53,10 @@ #define NARGS 3 /* If we were called with no wrapper, this is really socket() */ #endif +#if defined NEED_CANCELLATION && defined CENABLE + PSEUDO_PROLOGUE +#endif + .globl __socket ENTRY (__socket) /* This code previously moved sp into ip and stored the args using @@ -68,6 +72,15 @@ ENTRY (__socket) /* Push args onto the stack. */ P(PUSHARGS_,NARGS) +#if defined NEED_CANCELLATION && defined CENABLE +#ifdef PIC + SINGLE_THREAD_P_PIC(r3) +#else + SINGLE_THREAD_P +#endif + bne 1f +#endif + /* Do the system call trap. */ mov a1, $P(SOCKOP_,socket) mov a2, sp @@ -81,6 +94,30 @@ ENTRY (__socket) RETINSTR(movcc, pc, r14) b PLTJMP(SYSCALL_ERROR) +#if defined NEED_CANCELLATION && defined CENABLE +1: + str lr, [sp, #-4]! + CENABLE + mov ip, r0 + + mov r0, #P(SOCKOP_,socket) + add r1, sp, #4 + swi SYS_ify(socketcall) + + str r0, [sp, #-4]! + mov r0, ip + CDISABLE + ldr r0, [sp], #4 + ldr lr, [sp], #4 + + P(POPARGS_,NARGS) + + /* r0 is < 0 if there was an error. */ + cmn r0, $124 + RETINSTR(movcc, pc, r14) + b PLTJMP(SYSCALL_ERROR) +#endif + PSEUDO_END (__socket) weak_alias (__socket, socket) diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/stat.h b/sysdeps/unix/sysv/linux/powerpc/bits/stat.h index 3cff5c8d81..cf3dd1c293 100644 --- a/sysdeps/unix/sysv/linux/powerpc/bits/stat.h +++ b/sysdeps/unix/sysv/linux/powerpc/bits/stat.h @@ -27,11 +27,11 @@ #define _STAT_VER_LINUX_OLD 1 #define _STAT_VER_KERNEL 1 #define _STAT_VER_SVR4 2 +#define _STAT_VER_LINUX 3 #if __WORDSIZE == 32 -# define _STAT_VER_LINUX 3 -# define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ +# define _STAT_VER _STAT_VER_LINUX #else -# define _STAT_VER _STAT_VER_KERNEL /* The one defined below. */ +# define _STAT_VER _STAT_VER_KERNEL #endif /* Versions of the `xmknod' interface. */ diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/ftruncate64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ftruncate64.c new file mode 100644 index 0000000000..f733001abe --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ftruncate64.c @@ -0,0 +1,75 @@ +/* Copyright (C) 1997,1998,1999,2000,2001,2002 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#include +#include + +#include "kernel-features.h" + +#ifdef __NR_ftruncate64 +#ifndef __ASSUME_TRUNCATE64_SYSCALL +/* The variable is shared between all wrappers around *truncate64 calls. */ +extern int have_no_truncate64; +#endif + + +/* Truncate the file FD refers to to LENGTH bytes. */ +int +__ftruncate64 (fd, length) + int fd; + off64_t length; +{ +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if (! have_no_truncate64) +#endif + { +#ifndef __ASSUME_TRUNCATE64_SYSCALL + int saved_errno = errno; +#endif + int result = INLINE_SYSCALL (ftruncate64, 2, fd, length); + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if (result != -1 || errno != ENOSYS) +#endif + return result; + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + __set_errno (saved_errno); + have_no_truncate64 = 1; +#endif + } + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if ((off_t) length != length) + { + __set_errno (EINVAL); + return -1; + } + return __ftruncate (fd, (off_t) length); +#endif +} +weak_alias (__ftruncate64, ftruncate64) + +#else +/* Use the generic implementation. */ +# include +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread.c new file mode 100644 index 0000000000..d5b77e0b57 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread.c @@ -0,0 +1,85 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#include +#include +#include + +#include "kernel-features.h" + +#if defined __NR_pread || __ASSUME_PREAD_SYSCALL > 0 + +# if __ASSUME_PREAD_SYSCALL == 0 +static ssize_t __emulate_pread (int fd, void *buf, size_t count, + off_t offset) internal_function; +# endif + + +ssize_t +__libc_pread (fd, buf, count, offset) + int fd; + void *buf; + size_t count; + off_t offset; +{ + ssize_t result; + + if (SINGLE_THREAD_P) + { + result = INLINE_SYSCALL (pread, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PREAD_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pread (fd, buf, count, offset); +# endif + + return result; + } + + int oldtype = LIBC_CANCEL_ASYNC (); + + result = INLINE_SYSCALL (pread, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PREAD_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pread (fd, buf, count, offset); +# endif + + LIBC_CANCEL_RESET (oldtype); + + return result; +} + +strong_alias (__libc_pread, __pread) +weak_alias (__libc_pread, pread) + +# define __libc_pread(fd, buf, count, offset) \ + static internal_function __emulate_pread (fd, buf, count, offset) +#endif + +#if __ASSUME_PREAD_SYSCALL == 0 +# include +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread64.c new file mode 100644 index 0000000000..9bbe389420 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread64.c @@ -0,0 +1,84 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include +#include +#include + +#include "kernel-features.h" + +#if defined __NR_pread || __ASSUME_PREAD_SYSCALL > 0 + +# if __ASSUME_PREAD_SYSCALL == 0 +static ssize_t __emulate_pread64 (int fd, void *buf, size_t count, + off64_t offset) internal_function; +# endif + + +ssize_t +__libc_pread64 (fd, buf, count, offset) + int fd; + void *buf; + size_t count; + off64_t offset; +{ + ssize_t result; + + if (SINGLE_THREAD_P) + { + result = INLINE_SYSCALL (pread, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PREAD_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pread64 (fd, buf, count, offset); +# endif + + return result; + } + + int oldtype = LIBC_CANCEL_ASYNC (); + + result = INLINE_SYSCALL (pread, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PREAD_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pread64 (fd, buf, count, offset); +# endif + + LIBC_CANCEL_RESET (oldtype); + + return result; +} + +weak_alias (__libc_pread64, __pread64) +weak_alias (__libc_pread64, pread64) + +# define __libc_pread64(fd, buf, count, offset) \ + static internal_function __emulate_pread64 (fd, buf, count, offset) +#endif + +# if __ASSUME_PREAD_SYSCALL == 0 +# include +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite.c new file mode 100644 index 0000000000..96b72e18a5 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite.c @@ -0,0 +1,85 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#include +#include +#include + +#include "kernel-features.h" + +#if defined __NR_pwrite || __ASSUME_PWRITE_SYSCALL > 0 + +# if __ASSUME_PWRITE_SYSCALL == 0 +static ssize_t __emulate_pwrite (int fd, const void *buf, size_t count, + off_t offset) internal_function; +# endif + + +ssize_t +__libc_pwrite (fd, buf, count, offset) + int fd; + const void *buf; + size_t count; + off_t offset; +{ + ssize_t result; + + if (SINGLE_THREAD_P) + { + result = INLINE_SYSCALL (pwrite, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PWRITE_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pwrite (fd, buf, count, offset); +# endif + + return result; + } + + int oldtype = LIBC_CANCEL_ASYNC (); + + result = INLINE_SYSCALL (pwrite, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PWRITE_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pwrite (fd, buf, count, offset); +# endif + + LIBC_CANCEL_RESET (oldtype); + + return result; +} + +strong_alias (__libc_pwrite, __pwrite) +weak_alias (__libc_pwrite, pwrite) + +# define __libc_pwrite(fd, buf, count, offset) \ + static internal_function __emulate_pwrite (fd, buf, count, offset) +#endif + +#if __ASSUME_PWRITE_SYSCALL == 0 +# include +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite64.c new file mode 100644 index 0000000000..9e68acdf08 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite64.c @@ -0,0 +1,85 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include +#include +#include + +#include "kernel-features.h" + +#if defined __NR_pwrite || __ASSUME_PWRITE_SYSCALL > 0 + +# if __ASSUME_PWRITE_SYSCALL == 0 +static ssize_t __emulate_pwrite64 (int fd, const void *buf, size_t count, + off64_t offset) internal_function; +# endif + + +ssize_t +__libc_pwrite64 (fd, buf, count, offset) + int fd; + const void *buf; + size_t count; + off64_t offset; +{ + ssize_t result; + + if (SINGLE_THREAD_P) + { + result = INLINE_SYSCALL (pwrite, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PWRITE_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pwrite64 (fd, buf, count, offset); +# endif + + return result; + } + + int oldtype = LIBC_CANCEL_ASYNC (); + + result = INLINE_SYSCALL (pwrite, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PWRITE_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pwrite64 (fd, buf, count, offset); +# endif + + LIBC_CANCEL_RESET (oldtype); + + return result; +} + +weak_alias (__libc_pwrite64, __pwrite64) +libc_hidden_weak (__pwrite64) +weak_alias (__libc_pwrite64, pwrite64) + +# define __libc_pwrite64(fd, buf, count, offset) \ + static internal_function __emulate_pwrite64 (fd, buf, count, offset) +#endif + +#if __ASSUME_PWRITE_SYSCALL == 0 +# include +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S index 08696c3cf3..a4e27c3611 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S @@ -1,4 +1,4 @@ -/* Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc. +/* Copyright (C) 1995, 1996, 1997, 1999, 2003 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 @@ -39,7 +39,7 @@ #define NARGS 3 #endif -#define stackblock 48 /* offset to parm save area */ +#define stackblock 80 /* offset to socket parm area. */ #ifndef socket /* If this is just socket.S leave it alone! */ @@ -51,7 +51,7 @@ .text ENTRY(__socket) - stdu r1,-112(r1) + stdu r1,-144(r1) #if NARGS >= 1 std r3,stackblock(r1) #endif @@ -79,11 +79,40 @@ ENTRY(__socket) #if NARGS >= 9 #error too many arguments! #endif - li r3,P(SOCKOP_,socket) + +#if defined NEED_CANCELLATION && defined CENABLE + SINGLE_THREAD_P + bne- .Lsocket_cancel +#endif + + li r3,P(SOCKOP_,socket) + addi r4,r1,stackblock + DO_CALL(SYS_ify(socketcall)) + addi r1,r1,144 + PSEUDO_RET + +#if defined NEED_CANCELLATION && defined CENABLE +.Lsocket_cancel: + mflr r9 + std r9,144+16(r1) + CENABLE + std r3,72(r1) + li r3,P(SOCKOP_,socket) addi r4,r1,stackblock DO_CALL(SYS_ify(socketcall)) - addi r1,r1,112 + mfcr r0 + std r3,64(r1) + std r0,8(r1) + ld r3,72(r1) + CDISABLE + ld r4,144+16(r1) + ld r0,8(r1) + ld r3,64(r1) + mtlr r4 + mtcr r0 + addi r1,r1,144 PSEUDO_RET +#endif PSEUDO_END (__socket) weak_alias (__socket, socket) diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list b/sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list index d8303a60f6..5266c4f59f 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list @@ -16,7 +16,6 @@ rt_sigtimedwait - rt_sigtimedwait i:pppi __syscall_rt_sigtimedwait s_fcntl fcntl fcntl i:iiF __syscall_fcntl s_fcntl64 fcntl64 fcntl64 i:iiF __syscall_fcntl64 s_fstat64 fxstat64 fstat64 i:ip __syscall_fstat64 -s_ftruncate64 ftruncate64 ftruncate64 i:iii __syscall_ftruncate64 s_getcwd getcwd getcwd i:pi __syscall_getcwd s_getdents getdents getdents i:ipi __syscall_getdents s_getdents64 getdents getdents64 i:ipi __syscall_getdents64 @@ -26,10 +25,8 @@ s_getrlimit getrlimit getrlimit i:ip __syscall_getrlimit s_lstat64 lxstat64 lstat64 i:sp __syscall_lstat64 s_mmap2 mmap64 mmap2 b:aniiii __syscall_mmap2 s_poll poll poll i:pii __syscall_poll -s_pread64 pread64 pread i:ibnii __syscall_pread s_ptrace ptrace ptrace i:iipp __syscall_ptrace s_putpmsg putpmsg putpmsg i:ippii __syscall_putpmsg -s_pwrite64 pwrite64 pwrite i:ibnii __syscall_pwrite s_reboot reboot reboot i:iii __syscall_reboot s_setrlimit setrlimit setrlimit i:ip __syscall_setrlimit s_sigaction sigaction sigaction i:ipp __syscall_sigaction @@ -38,7 +35,6 @@ s_sigprocmask sigprocmask sigprocmask i:ipp __syscall_sigprocmask s_sigsuspend sigsuspend sigsuspend i:iii __syscall_sigsuspend s_stat64 xstat64 stat64 i:sp __syscall_stat64 s_sysctl sysctl _sysctl i:p __syscall__sysctl -s_truncate64 truncate64 truncate64 i:sii __syscall_truncate64 s_ugetrlimit getrlimit ugetrlimit i:ip __syscall_ugetrlimit s_ustat ustat ustat i:ip __syscall_ustat s_vfork vfork vfork i: __syscall_vfork diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h index d56ff877ac..d37be2ef4f 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h @@ -69,65 +69,7 @@ #endif /* __ASSEMBLER__ */ #undef INLINE_SYSCALL -#if 1 -#define INLINE_SYSCALL(name, nr, args...) \ - ({ \ - DECLARGS_##nr; \ - long ret, err; \ - LOADARGS_##nr(name, args); \ - __asm __volatile ("sc\n\t" \ - "mfcr %1\n\t" \ - : "=r" (r3), "=r" (err) \ - : ASM_INPUT_##nr \ - : "cc", "memory"); \ - ret = r3; \ - if (err & 1 << 28) \ - { \ - __set_errno (ret); \ - ret = -1L; \ - } \ - ret; \ - }) - -#define DECLARGS_0 register long r0 __asm__ ("r0"); \ - register long r3 __asm__ ("r3") -#define DECLARGS_1 DECLARGS_0 -#define DECLARGS_2 DECLARGS_1; register long r4 __asm__ ("r4") -#define DECLARGS_3 DECLARGS_2; register long r5 __asm__ ("r5") -#define DECLARGS_4 DECLARGS_3; register long r6 __asm__ ("r6") -#define DECLARGS_5 DECLARGS_4; register long r7 __asm__ ("r7") -#define DECLARGS_6 DECLARGS_5; register long r8 __asm__ ("r8") - -#define LOADARGS_0(name) \ - r0 = __NR_##name -#define LOADARGS_1(name, arg1) \ - LOADARGS_0(name); \ - r3 = (long) (arg1) -#define LOADARGS_2(name, arg1, arg2) \ - LOADARGS_1(name, arg1); \ - r4 = (long) (arg2) -#define LOADARGS_3(name, arg1, arg2, arg3) \ - LOADARGS_2(name, arg1, arg2); \ - r5 = (long) (arg3) -#define LOADARGS_4(name, arg1, arg2, arg3, arg4) \ - LOADARGS_3(name, arg1, arg2, arg3); \ - r6 = (long) (arg4) -#define LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \ - LOADARGS_4(name, arg1, arg2, arg3, arg4); \ - r7 = (long) (arg5) -#define LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \ - LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \ - r8 = (long) (arg6) - -#define ASM_INPUT_0 "r" (r0) -#define ASM_INPUT_1 ASM_INPUT_0, "0" (r3) -#define ASM_INPUT_2 ASM_INPUT_1, "r" (r4) -#define ASM_INPUT_3 ASM_INPUT_2, "r" (r5) -#define ASM_INPUT_4 ASM_INPUT_3, "r" (r6) -#define ASM_INPUT_5 ASM_INPUT_4, "r" (r7) -#define ASM_INPUT_6 ASM_INPUT_5, "r" (r8) -#else /* This version is for kernels that implement system calls that behave like function calls as far as register saving. */ #define INLINE_SYSCALL(name, nr, args...) \ @@ -149,40 +91,89 @@ : ASM_INPUT_##nr \ : "r9", "r10", "r11", "r12", \ "fr0", "fr1", "fr2", "fr3", \ - "fr4", "fr5", "fr6", "fr7", \ - "fr8", "fr9", "fr10", "fr11", \ - "fr12", "fr13", \ - "ctr", "lr", \ - "cr0", "cr1", "cr5", "cr6", "cr7", \ - "memory"); \ + "fr4", "fr5", "fr6", "fr7", \ + "fr8", "fr9", "fr10", "fr11", \ + "fr12", "fr13", \ + "ctr", "lr", \ + "cr0", "cr1", "cr5", "cr6", "cr7", \ + "memory"); \ ret = r3; \ - if (err & 1 << 28) \ + if (__builtin_expect ((err & (1 << 28)), 0)) \ { \ - __set_errno (ret); \ - ret = -1L; \ + __set_errno (ret); \ + ret = -1L; \ } \ ret; \ }) -#define LOADARGS_0(name) \ +/* Define a macro which expands inline into the wrapper code for a system + call. This use is for internal calls that do not need to handle errors + normally. It will never touch errno. This returns just what the kernel + gave back in the non-error (CR0.SO cleared) case, otherwise (CR0.SO set) + the negation of the return value in the kernel gets reverted. */ + +# undef INTERNAL_SYSCALL +# define INTERNAL_SYSCALL(name, nr, args...) \ + ({ \ + register long r0 __asm__ ("r0"); \ + register long r3 __asm__ ("r3"); \ + register long r4 __asm__ ("r4"); \ + register long r5 __asm__ ("r5"); \ + register long r6 __asm__ ("r6"); \ + register long r7 __asm__ ("r7"); \ + register long r8 __asm__ ("r8"); \ + LOADARGS_##nr(name, args); \ + __asm__ __volatile__ \ + ("sc\n\t" \ + "bns+ 0f\n\t" \ + "neg %1,%1\n" \ + "0:" \ + : "=&r" (r0), \ + "=&r" (r3), "=&r" (r4), "=&r" (r5), \ + "=&r" (r6), "=&r" (r7), "=&r" (r8) \ + : ASM_INPUT_##nr \ + : "r9", "r10", "r11", "r12", \ + "cr0", "ctr", "memory"); \ + (int) r3; \ + }) + +# undef INTERNAL_SYSCALL_ERROR_P +# define INTERNAL_SYSCALL_ERROR_P(val) ((unsigned long) (val) >= 0xfffffffffffff001u) + +# undef INTERNAL_SYSCALL_ERRNO +# define INTERNAL_SYSCALL_ERRNO(val) (-(val)) + +#define LOADARGS_0(name, dummy) \ r0 = __NR_##name #define LOADARGS_1(name, arg1) \ - LOADARGS_0(name); \ + LOADARGS_0(name, 0); \ + extern void __illegally_sized_syscall_##name##_arg1 (void); \ + if (sizeof (arg1) > 8) __illegally_sized_syscall_##name##_arg1 (); \ r3 = (long) (arg1) #define LOADARGS_2(name, arg1, arg2) \ LOADARGS_1(name, arg1); \ + extern void __illegally_sized_syscall_##name##_arg2 (void); \ + if (sizeof (arg2) > 8) __illegally_sized_syscall_##name##_arg2 (); \ r4 = (long) (arg2) #define LOADARGS_3(name, arg1, arg2, arg3) \ LOADARGS_2(name, arg1, arg2); \ + extern void __illegally_sized_syscall_##name##_arg3 (void); \ + if (sizeof (arg3) > 8) __illegally_sized_syscall_##name##_arg3 (); \ r5 = (long) (arg3) #define LOADARGS_4(name, arg1, arg2, arg3, arg4) \ LOADARGS_3(name, arg1, arg2, arg3); \ + extern void __illegally_sized_syscall_##name##_arg4 (void); \ + if (sizeof (arg4) > 8) __illegally_sized_syscall_##name##_arg4 (); \ r6 = (long) (arg4) #define LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \ LOADARGS_4(name, arg1, arg2, arg3, arg4); \ + extern void __illegally_sized_syscall_##name##_arg5 (void); \ + if (sizeof (arg5) > 8) __illegally_sized_syscall_##name##_arg5 (); \ r7 = (long) (arg5) #define LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \ LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \ + extern void __illegally_sized_syscall_##name##_arg6 (void); \ + if (sizeof (arg6) > 8) __illegally_sized_syscall_##name##_arg6 (); \ r8 = (long) (arg6) #define ASM_INPUT_0 "0" (r0) @@ -193,6 +184,4 @@ #define ASM_INPUT_5 ASM_INPUT_4, "5" (r7) #define ASM_INPUT_6 ASM_INPUT_5, "6" (r8) -#endif - #endif /* linux/powerpc/powerpc64/sysdep.h */ diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/truncate64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/truncate64.c new file mode 100644 index 0000000000..cbf0669082 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/truncate64.c @@ -0,0 +1,76 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#include +#include +#include + +#include "kernel-features.h" + +#ifdef __NR_truncate64 +#ifndef __ASSUME_TRUNCATE64_SYSCALL +/* The variable is shared between all wrappers around *truncate64 calls. */ +int have_no_truncate64; +#endif + + +/* Truncate the file FD refers to to LENGTH bytes. */ +int +truncate64 (path, length) + const char *path; + off64_t length; +{ +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if (! have_no_truncate64) +#endif + { +#ifndef __ASSUME_TRUNCATE64_SYSCALL + int saved_errno = errno; +#endif + int result = INLINE_SYSCALL (truncate64, 2, CHECK_STRING (path), + length); + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if (result != -1 || errno != ENOSYS) +#endif + return result; + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + __set_errno (saved_errno); + have_no_truncate64 = 1; +#endif + } + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if ((off_t) length != length) + { + __set_errno (EINVAL); + return -1; + } + return truncate (path, (off_t) length); +#endif +} + +#else +/* Use the generic implementation. */ +# include +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/sys/procfs.h b/sysdeps/unix/sysv/linux/powerpc/sys/procfs.h index e42f848bc5..1322971da4 100644 --- a/sysdeps/unix/sysv/linux/powerpc/sys/procfs.h +++ b/sysdeps/unix/sysv/linux/powerpc/sys/procfs.h @@ -32,6 +32,10 @@ __BEGIN_DECLS +/* These definitions are normally provided by ucontext.h via + asm/sigcontext.h, asm/ptrace.h, and asm/elf.h. Otherwise we define + them here. */ +#ifndef __PPC64_ELF_H #define ELF_NGREG 48 /* includes nip, msr, lr, etc. */ #define ELF_NFPREG 33 /* includes fpscr */ #define ELF_NVRREG 33 /* includes vscr */ @@ -41,6 +45,7 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG]; typedef double elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; +#endif /* gcc 3.1 and newer support __uint128_t. */ #if !__GNUC_PREREQ(3,1) diff --git a/sysdeps/unix/sysv/linux/sh/sysdep.h b/sysdeps/unix/sysv/linux/sh/sysdep.h index ee39121755..75557f554e 100644 --- a/sysdeps/unix/sysv/linux/sh/sysdep.h +++ b/sysdeps/unix/sysv/linux/sh/sysdep.h @@ -66,7 +66,12 @@ END (name) #ifndef PIC -# define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ +# define SYSCALL_ERROR_HANDLER \ + mov.l 0f,r1; \ + jmp @r1; \ + mov r0,r4; \ + .align 2; \ + 0: .long __syscall_error #else # if RTLD_PRIVATE_ERRNO # define SYSCALL_ERROR_HANDLER \