aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--csu/initfini.c5
-rw-r--r--elf/dl-open.c15
-rw-r--r--elf/rtld.c12
-rw-r--r--err.h1
-rw-r--r--login/pututline_r.c20
-rw-r--r--sysdeps/generic/sbrk.c9
-rw-r--r--sysdeps/i386/dl-machine.h4
-rw-r--r--sysdeps/m68k/dl-machine.h4
-rw-r--r--sysdeps/unix/sysv/linux/Makefile4
-rw-r--r--sysdeps/unix/sysv/linux/alpha/Makefile2
-rw-r--r--sysdeps/unix/sysv/linux/alpha/ioperm.c4
-rw-r--r--sysdeps/unix/sysv/linux/init-first.c54
-rw-r--r--sysdeps/unix/sysv/linux/sys/io.h4
13 files changed, 72 insertions, 66 deletions
diff --git a/csu/initfini.c b/csu/initfini.c
index bc41262..f816e08 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 9dda31e..40b5224 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 b8aa731..9f13124 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 0000000..915720a
--- /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 0b81900..55436bf 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 92ad8c4..f63195a 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 d616bf4..83b6f8d 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 15aa532..f36b9ce 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 7d83718..02b44a8 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 9d59671..3908b57 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 d24eabe..a91608f 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 267c01a..feff028 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 6f0b9ab..6b4de65 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 */