This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [HURD, PATCH] Fix stack switching at initialization time
- From: ludo at gnu dot org (Ludovic Courtès)
- To: Thomas Schwinge <thomas at schwinge dot name>
- Cc: bug-hurd at gnu dot org, libc-alpha at sourceware dot org
- Date: Fri, 22 Jul 2011 16:31:00 +0200
- Subject: Re: [HURD, PATCH] Fix stack switching at initialization time
- References: <87livqctoy.fsf@gnu.org><87r55ih0fs.fsf@kepler.schwinge.homeip.net>
Hi!
Thomas Schwinge <thomas@schwinge.name> skribis:
> This patch is to be put on top of our TopGit t/init-first.c branch, I
> guess, which itself is not yet in the sourceware repository, I think?
Right, other changes in t/init-first.c arenât in the Sourceware repo.
Hereâs the diff between the Savannah + this patch and Sourceware repo:
diff -ubB --show-c-function /data/src/glibc/sysdeps/mach/hurd/i386/init-first.c /data/src/hurd/glibc/sysdeps/mach/hurd/i386/init-first.c
--- /data/src/glibc/sysdeps/mach/hurd/i386/init-first.c 2011-07-22 16:26:37.000000000 +0200
+++ /data/src/hurd/glibc/sysdeps/mach/hurd/i386/init-first.c 2011-07-22 15:45:58.000000000 +0200
@@ -1,6 +1,7 @@
/* Initialization code run first thing by the ELF startup code. For i386/Hurd.
- Copyright (C) 1995,96,97,98,99,2000,01,02,03,04,05
- Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2007 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
@@ -92,7 +93,7 @@ posixland_init (int argc, char **argv, c
__getopt_clean_environment (envp);
#endif
-#if defined SHARED && !defined NO_CTORS_DTORS_SECTIONS
+#ifdef SHARED
__libc_global_ctors ();
#endif
}
@@ -104,10 +105,6 @@ init1 (int argc, char *arg0, ...)
char **argv = &arg0;
char **envp = &argv[argc + 1];
struct hurd_startup_data *d;
-#ifndef SHARED
- extern ElfW(Phdr) *_dl_phdr;
- extern size_t _dl_phnum;
-#endif
while (*envp)
++envp;
@@ -118,27 +115,9 @@ init1 (int argc, char *arg0, ...)
data block; the argument strings start there. */
if ((void *) d == argv[0])
{
-#ifndef SHARED
- /* We may need to see our own phdrs, e.g. for TLS setup.
- Try the usual kludge to find the headers without help from
- the exec server. */
- extern const void _start;
- const ElfW(Ehdr) *const ehdr = &_start;
- _dl_phdr = (ElfW(Phdr) *) ((const void *) ehdr + ehdr->e_phoff);
- _dl_phnum = ehdr->e_phnum;
- assert (ehdr->e_phentsize == sizeof (ElfW(Phdr)));
-#endif
return;
}
-#ifndef SHARED
- __libc_enable_secure = d->flags & EXEC_SECURE;
-
- _dl_phdr = (ElfW(Phdr) *) d->phdr;
- _dl_phnum = d->phdrsz / sizeof (ElfW(Phdr));
- assert (d->phdrsz % sizeof (ElfW(Phdr)) == 0);
-#endif
-
_hurd_init_dtable = d->dtable;
_hurd_init_dtablesize = d->dtablesize;
@@ -172,13 +151,16 @@ init (int *data)
char **envp = &argv[argc + 1];
struct hurd_startup_data *d;
unsigned long int threadvars[_HURD_THREADVAR_MAX];
+#ifndef SHARED
+ extern ElfW(Phdr) *_dl_phdr;
+ extern size_t _dl_phnum;
+#endif
/* Provide temporary storage for thread-specific variables on the
startup stack so the cthreads initialization code can use them
for malloc et al, or so we can use malloc below for the real
threadvars array. */
memset (threadvars, 0, sizeof threadvars);
- threadvars[_HURD_THREADVAR_LOCALE] = (unsigned long int) &_nl_global_locale;
__hurd_threadvar_stack_offset = (unsigned long int) threadvars;
/* Since the cthreads initialization code uses malloc, and the
@@ -192,6 +174,39 @@ init (int *data)
++envp;
d = (void *) ++envp;
+ /* If we are the bootstrap task started by the kernel,
+ then after the environment pointers there is no Hurd
+ data block; the argument strings start there. */
+ if ((void *) d == argv[0])
+ {
+#ifndef SHARED
+ /* We may need to see our own phdrs, e.g. for TLS setup.
+ Try the usual kludge to find the headers without help from
+ the exec server. */
+ extern const void __executable_start;
+ const ElfW(Ehdr) *const ehdr = &__executable_start;
+ _dl_phdr = (ElfW(Phdr) *) ((const void *) ehdr + ehdr->e_phoff);
+ _dl_phnum = ehdr->e_phnum;
+ assert (ehdr->e_phentsize == sizeof (ElfW(Phdr)));
+#endif
+ }
+ else
+ {
+#ifndef SHARED
+ __libc_enable_secure = d->flags & EXEC_SECURE;
+
+ _dl_phdr = (ElfW(Phdr) *) d->phdr;
+ _dl_phnum = d->phdrsz / sizeof (ElfW(Phdr));
+ assert (d->phdrsz % sizeof (ElfW(Phdr)) == 0);
+#endif
+ }
+
+#ifndef SHARED
+ /* We need to setup TLS before starting sigthread */
+ extern void __pthread_initialize_minimal(void);
+ __pthread_initialize_minimal();
+#endif
+
/* The user might have defined a value for this, to get more variables.
Otherwise it will be zero on startup. We must make sure it is set
properly before before cthreads initialization, so cthreads can know
@@ -242,9 +257,9 @@ init (int *data)
/* Push the user code address on the top of the new stack. It will
be the return address for `init1'; we will jump there with NEWSP
as the stack pointer. */
- *--newsp = data[-1];
- ((void **) data)[-1] = switch_stacks;
- /* Force NEWSP into %ecx and &init1 into %eax, which are not restored
+ *--newsp = __builtin_return_address (0);
+ * ((void **) __builtin_frame_address (0) + 1) = &switch_stacks;
+ /* Force NEWSP into %eax and &init1 into %ecx, which are not restored
by function return. */
asm volatile ("# a %0 c %1" : : "a" (newsp), "c" (&init1));
}
@@ -320,11 +335,11 @@ first_init (void)
stack set up just as the user will see it, so it can switch stacks. */
void
-_dl_init_first (void)
+_dl_init_first (int argc, ...)
{
first_init ();
- init ((int *) __builtin_frame_address (0) + 2);
+ init (&argc);
}
#endif
@@ -351,23 +366,23 @@ strong_alias (posixland_init, __libc_ini
This poorly-named function is called by static-start.S,
which should not exist at all. */
void
-_hurd_stack_setup (void)
+_hurd_stack_setup (void *arg, ...)
{
- intptr_t caller = (intptr_t) __builtin_return_address (0);
+ void *caller = (&arg)[-1];
void doinit (intptr_t *data)
{
/* This function gets called with the argument data at TOS. */
- void doinit1 (void)
+ void doinit1 (volatile int argc, ...)
{
- init ((int *) __builtin_frame_address (0) + 2);
+ init ((int *) &argc);
}
/* Push the user return address after the argument data, and then
jump to `doinit1' (above), so it is as if __libc_init_first's
caller had called `doinit1' with the argument data already on the
stack. */
- *--data = caller;
+ *--data = (intptr_t) caller;
asm volatile ("movl %0, %%esp\n" /* Switch to new outermost stack. */
"movl $0, %%ebp\n" /* Clear outermost frame pointer. */
"jmp *%1" : : "r" (data), "r" (&doinit1) : "sp");
@@ -376,7 +391,7 @@ _hurd_stack_setup (void)
first_init ();
- _hurd_startup ((void **) __builtin_frame_address (0) + 2, &doinit);
+ _hurd_startup (&arg, &doinit);
}
#endif
So Iâll commit it to t/init-first.c, OK?
Thanks!
Ludoâ.