diff options
-rw-r--r-- | csu/initfini.c | 5 | ||||
-rw-r--r-- | elf/dl-open.c | 15 | ||||
-rw-r--r-- | elf/rtld.c | 12 | ||||
-rw-r--r-- | err.h | 1 | ||||
-rw-r--r-- | login/pututline_r.c | 20 | ||||
-rw-r--r-- | sysdeps/generic/sbrk.c | 9 | ||||
-rw-r--r-- | sysdeps/i386/dl-machine.h | 4 | ||||
-rw-r--r-- | sysdeps/m68k/dl-machine.h | 4 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/Makefile | 4 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/alpha/Makefile | 2 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/alpha/ioperm.c | 4 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/init-first.c | 54 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/sys/io.h | 4 |
13 files changed, 72 insertions, 66 deletions
diff --git a/csu/initfini.c b/csu/initfini.c index bc412622bc..f816e08169 100644 --- a/csu/initfini.c +++ b/csu/initfini.c @@ -111,11 +111,6 @@ asm ("\nEOF.crtn.init\ \n\ cat >> crti.s-new <<\\EOF.crti.fini"); -/* Global variable which says whether we have a statically or dynamically - linked program. If > 0, static, for < 0 dynamic, == 0 means yet to - be determined (see init-first.c). */ -int __libc_is_static = 0; - SECTION (".fini") void _fini (void) diff --git a/elf/dl-open.c b/elf/dl-open.c index 9dda31e761..40b5224725 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -22,6 +22,11 @@ Cambridge, MA 02139, USA. */ #include <stdlib.h> #include <errno.h> + +extern void _dl_start (void); weak_extern (_dl_start) + +extern int __libc_multiple_libcs; /* Defined in init-first.c. */ + size_t _dl_global_scope_alloc; struct link_map * @@ -30,7 +35,9 @@ _dl_open (const char *file, int mode) struct link_map *new, *l; ElfW(Addr) init; struct r_debug *r; - + /* To decide whether we are the static libc or not. We must use + this variable since gcc would otherwise optimize the test away. */ + void (*dl_start_ptr) (void) = &_dl_start; /* Load the named object. */ new = _dl_map_object (NULL, file, lt_loaded); @@ -131,5 +138,11 @@ _dl_open (const char *file, int mode) while (init = _dl_init_next (new)) (*(void (*) (void)) init) (); + if (dl_start_ptr == NULL) + /* We must be the static _dl_open in libc.a because ld.so.1 is not + in scope. A static program that has loaded a dynamic object + now has competition. */ + __libc_multiple_libcs = 1; + return new; } diff --git a/elf/rtld.c b/elf/rtld.c index b8aa7311ab..9f13124207 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -42,6 +42,15 @@ int _dl_argc; char **_dl_argv; const char *_dl_rpath; +/* Set nonzero during loading and initialization of executable and + libraries, cleared before the executable's entry point runs. This + must not be initialized to nonzero, because the unused dynamic + linker loaded in for libc.so's "ld.so.1" dep will provide the + definition seen by libc.so's initializer; that value must be zero, + and will be since that dynamic linker's _dl_start and dl_main will + never be called. */ +int _dl_starting_up; + static void dl_main (const ElfW(Phdr) *phdr, ElfW(Half) phent, ElfW(Addr) *user_entry); @@ -486,6 +495,9 @@ of this helper program; chances are you did not intend to run this program.\n", _dl_rtld_map.l_info[DT_INIT] = NULL; } + /* We finished the intialization and will start up. */ + _dl_starting_up = 1; + /* Once we return, _dl_sysdep_start will invoke the DT_INIT functions and then *USER_ENTRY. */ } diff --git a/err.h b/err.h new file mode 100644 index 0000000000..915720aa4c --- /dev/null +++ b/err.h @@ -0,0 +1 @@ +#include <misc/err.h> diff --git a/login/pututline_r.c b/login/pututline_r.c index 0b819000d1..55436bf2b8 100644 --- a/login/pututline_r.c +++ b/login/pututline_r.c @@ -64,7 +64,8 @@ __pututline_r (const struct utmp *id, struct utmp_data *utmp_data) match: */ if (id->ut_id[0] && (utmp_data->loc_utmp < (off_t) sizeof (struct utmp) - || strncmp(utmp_data->ubuf.ut_id, id->ut_id, sizeof (id->ut_id)) != 0)) + || strncmp (utmp_data->ubuf.ut_id, id->ut_id, + sizeof (id->ut_id)) != 0)) { /* We must not overwrite the data in UTMP_DATA since ID may be aliasing it. */ @@ -74,16 +75,8 @@ __pututline_r (const struct utmp *id, struct utmp_data *utmp_data) *data_tmp = *utmp_data; utmp_data = data_tmp; - if (getutid_r (id, &dummy, utmp_data) < 0) - { - if (errno != ESRCH) - /* Some error occured. If no entry was found, the position - pointer now is at the end of the file. */ - return -1; - - /* Set position pointer to position behind the record. */ - utmp_data->loc_utmp += sizeof (struct utmp); - } + if (getutid_r (id, &dummy, utmp_data) < 0 && errno != ESRCH) + return -1; } #endif @@ -102,7 +95,8 @@ __pututline_r (const struct utmp *id, struct utmp_data *utmp_data) if (result >= 0) /* Position file correctly. */ - if (utmp_data->loc_utmp < (off_t) sizeof (struct utmp)) + if (utmp_data->loc_utmp < (off_t) sizeof (struct utmp) + || utmp_data->loc_utmp - sizeof (struct utmp) > st.st_size) /* Not located at any valid entry. Add at the end. */ { result = lseek (utmp_data->ut_fd, 0L, SEEK_END); @@ -110,7 +104,7 @@ __pututline_r (const struct utmp *id, struct utmp_data *utmp_data) /* Where we'll be if the write succeeds. */ utmp_data->loc_utmp = st.st_size + sizeof (struct utmp); } - else if (utmp_data->loc_utmp <= st.st_size) + else result = lseek (utmp_data->ut_fd, utmp_data->loc_utmp - sizeof (struct utmp), SEEK_SET); diff --git a/sysdeps/generic/sbrk.c b/sysdeps/generic/sbrk.c index 92ad8c4102..f63195adb3 100644 --- a/sysdeps/generic/sbrk.c +++ b/sysdeps/generic/sbrk.c @@ -22,10 +22,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ extern void *__curbrk; extern int __brk (void *addr); -#ifdef PIC -extern int __libc_is_static; -weak_extern (__libc_is_static) -#endif +extern int __libc_multiple_libcs; /* Defined in init-first.c. */ /* Extend the process's data space by INCREMENT. If INCREMENT is negative, shrink data space by - INCREMENT. @@ -40,9 +37,7 @@ __sbrk (ptrdiff_t increment) __curbrk from the kernel's brk value. That way two separate instances of __brk and __sbrk can share the heap, returning interleaved pieces of it. */ -#ifdef PIC - if (__curbrk == NULL || &__libc_is_static == NULL) -#endif + if (__curbrk == NULL || __libc_multiple_libcs) if (__brk (0) < 0) return (void *) -1; diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h index d616bf4db8..83b6f8d165 100644 --- a/sysdeps/i386/dl-machine.h +++ b/sysdeps/i386/dl-machine.h @@ -163,7 +163,9 @@ _dl_start_user:\n\ call *%eax\n\ # Loop to call _dl_init_next for the next initializer.\n\ jmp 0b\n\ -1: # Pass our finalizer function to the user in %edx, as per ELF ABI.\n\ +1: # Clear the startup flag.\n\ + movl $0, _dl_starting_up@GOT(%ebx)\n\ + # Pass our finalizer function to the user in %edx, as per ELF ABI.\n\ movl _dl_fini@GOT(%ebx), %edx\n\ # Jump to the user's entry point.\n\ jmp *%edi\n\ diff --git a/sysdeps/m68k/dl-machine.h b/sysdeps/m68k/dl-machine.h index 15aa5325fc..f36b9ce2f4 100644 --- a/sysdeps/m68k/dl-machine.h +++ b/sysdeps/m68k/dl-machine.h @@ -174,7 +174,9 @@ _dl_start_user: jsr (%a0) | Loop to call _dl_init_next for the next initializer. jra 0b -1: | Pass our finalizer function to the user in %a1. +1: | Clear the startup flag. + move.l #0, _dl_starting_up@GOT(%a5) + | Pass our finalizer function to the user in %a1. move.l _dl_fini@GOT(%a5), %a1 | Initialize %fp with the stack pointer. move.l %sp, %fp diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 7d83718e5c..02b44a8fc5 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -1,3 +1,7 @@ +ifeq ($(subdir), csu) +CFLAGS-init-first.c = -fkeep-inline-functions +endif + ifeq ($(subdir), misc) sysdep_routines += sysctl clone diff --git a/sysdeps/unix/sysv/linux/alpha/Makefile b/sysdeps/unix/sysv/linux/alpha/Makefile index 9d596719da..3908b5703c 100644 --- a/sysdeps/unix/sysv/linux/alpha/Makefile +++ b/sysdeps/unix/sysv/linux/alpha/Makefile @@ -2,5 +2,5 @@ ifeq ($(subdir), misc) sysdep_headers += alpha/ptrace.h alpha/regdef.h sysdep_routines += ieee_get_fp_control ieee_set_fp_control \ - sethae ioperm osf_sigprocmask fstatfs statfs + sethae ioperm osf_sigprocmask fstatfs statfs llseek endif diff --git a/sysdeps/unix/sysv/linux/alpha/ioperm.c b/sysdeps/unix/sysv/linux/alpha/ioperm.c index d24eabe473..a91608ff24 100644 --- a/sysdeps/unix/sysv/linux/alpha/ioperm.c +++ b/sysdeps/unix/sysv/linux/alpha/ioperm.c @@ -52,7 +52,7 @@ I/O address space that's 512MB large!). */ #define vuip volatile unsigned int * #define JENSEN_IO_BASE (0xfffffc0300000000UL) -#define JENSEN_MEM (0xfffffc0200000000UL) /* sparse!! */ +#define JENSEN_SPARSE_MEM (0xfffffc0200000000UL) /* * With respect to the I/O architecture, APECS and LCA are identical, @@ -94,7 +94,7 @@ static struct platform { {"EB64+", IOSYS_APECS, APECS_DENSE_MEM, APECS_SPARSE_MEM}, {"EB66", IOSYS_APECS, APECS_DENSE_MEM, APECS_SPARSE_MEM}, {"EB66P", IOSYS_APECS, APECS_DENSE_MEM, APECS_SPARSE_MEM}, - {"Jensen", IOSYS_JENSEN, JENSEN_MEM, JENSEN_MEM}, + {"Jensen", IOSYS_JENSEN, 0, JENSEN_SPARSE_MEM}, {"Mikasa", IOSYS_APECS, APECS_DENSE_MEM, APECS_SPARSE_MEM}, {"Mustang", IOSYS_APECS, APECS_DENSE_MEM, APECS_SPARSE_MEM}, {"Noname", IOSYS_APECS, APECS_DENSE_MEM, APECS_SPARSE_MEM}, diff --git a/sysdeps/unix/sysv/linux/init-first.c b/sysdeps/unix/sysv/linux/init-first.c index 267c01afc8..feff028a28 100644 --- a/sysdeps/unix/sysv/linux/init-first.c +++ b/sysdeps/unix/sysv/linux/init-first.c @@ -29,10 +29,12 @@ extern void __libc_global_ctors (void); /* The function is called from assembly stubs the compiler can't see. */ static void init (void *) __attribute__ ((unused)); -extern int __libc_is_static; -#ifdef PIC -weak_extern (__libc_is_static) -#endif +extern int _dl_starting_up; +weak_extern (_dl_starting_up) + +/* Set nonzero if we have to be prepared for more then one libc being + used in the process. Safe assumption if initializer never runs. */ +int __libc_multiple_libcs = 1; static void init (void *data) @@ -43,39 +45,21 @@ init (void *data) char **argv = (char **)data + 1; char **envp = &argv[argc + 1]; - /* XXX Another gcc bug. We marked the function as `unused' but it - is still optimized away. */ - volatile void *foo __attribute__ ((unused)) = &init; -#ifdef PIC - if (&__libc_is_static != NULL) -#endif + __libc_multiple_libcs = &_dl_starting_up && ! _dl_starting_up; + + /* We must not call `personality' twice. */ + if (!__libc_multiple_libcs) { -#ifdef PIC - /* We must not call `personality' twice. */ - if (__libc_is_static == 0) -#endif - { - /* The `personality' system call takes one argument that - chooses the "personality", i.e. the set of system calls - and such. We must make this call first thing to disable - emulation of some other system that might have been - enabled by default based on the executable format. */ - __personality (PER_LINUX); - - /* Set the FPU control word to the proper default value. */ - __setfpucw (__fpu_control); - } - - /* We set LIBC_IS_STATIC to a value > 0 for the static library - and < 0 for the shared library. This information might be - useful for the running program but it is mainly necessary for - the above `if' statement. */ -#ifdef PIC - __libc_is_static = -1; -#else - __libc_is_static = 1; -#endif + /* The `personality' system call takes one argument that chooses + the "personality", i.e. the set of system calls and such. We + must make this call first thing to disable emulation of some + other system that might have been enabled by default based on + the executable format. */ + __personality (PER_LINUX); + + /* Set the FPU control word to the proper default value. */ + __setfpucw (__fpu_control); } __environ = envp; diff --git a/sysdeps/unix/sysv/linux/sys/io.h b/sysdeps/unix/sysv/linux/sys/io.h index 6f0b9aba14..6b4de65c9c 100644 --- a/sysdeps/unix/sysv/linux/sys/io.h +++ b/sysdeps/unix/sysv/linux/sys/io.h @@ -21,6 +21,8 @@ Cambridge, MA 02139, USA. */ #define _SYS_IO_H 1 #include <features.h> +__BEGIN_DECLS + /* Get constants from kernel header files. */ #include <asm/io.h> @@ -39,4 +41,6 @@ extern int ioperm __P ((unsigned long int __from, unsigned long int __num, privileges. */ extern int iopl __P ((int __level)); +__END_DECLS + #endif /* _SYS_IO_H */ |