Update.
* elf/rtld.c: Split _dl_start in two pieces to prevent GOT usage before the relocation happened. Patch by Franz Sirl <Franz.Sirl-kernel@lauterbach.com>.
This commit is contained in:
parent
56ad7b2cec
commit
6a1db4ffb6
|
@ -1,5 +1,9 @@
|
|||
1999-07-09 Ulrich Drepper <drepper@cygnus.com>
|
||||
|
||||
* elf/rtld.c: Split _dl_start in two pieces to prevent GOT usage
|
||||
before the relocation happened.
|
||||
Patch by Franz Sirl <Franz.Sirl-kernel@lauterbach.com>.
|
||||
|
||||
* Versions.def (libnsl): Add GLIBC_2.2.
|
||||
* nis/Versions (libnsl) [GLIBC_2.2]: Add xdr_ypall.
|
||||
|
||||
|
|
31
elf/rtld.c
31
elf/rtld.c
|
@ -129,6 +129,9 @@ static hp_timing_t relocate_time;
|
|||
static hp_timing_t load_time;
|
||||
extern unsigned long int _dl_num_relocations; /* in dl-lookup.c */
|
||||
|
||||
static ElfW(Addr) _dl_start_final (void *arg, struct link_map *bootstrap_map_p,
|
||||
hp_timing_t start_time);
|
||||
|
||||
#ifdef RTLD_START
|
||||
RTLD_START
|
||||
#else
|
||||
|
@ -140,7 +143,6 @@ _dl_start (void *arg)
|
|||
{
|
||||
struct link_map bootstrap_map;
|
||||
hp_timing_t start_time;
|
||||
ElfW(Addr) start_addr;
|
||||
|
||||
/* This #define produces dynamic linking inline functions for
|
||||
bootstrap relocation instead of general-purpose relocation. */
|
||||
|
@ -175,7 +177,22 @@ _dl_start (void *arg)
|
|||
/* Now life is sane; we can call functions and access global data.
|
||||
Set up to use the operating system facilities, and find out from
|
||||
the operating system's program loader where to find the program
|
||||
header table in core. */
|
||||
header table in core. Put the rest of _dl_start into a separate
|
||||
function, that way the compiler cannot put accesses to the GOT
|
||||
before ELF_DYNAMIC_RELOCATE. */
|
||||
return _dl_start_final (arg, &bootstrap_map, start_time);
|
||||
}
|
||||
|
||||
|
||||
static ElfW(Addr)
|
||||
_dl_start_final (void *arg, struct link_map *bootstrap_map_p,
|
||||
hp_timing_t start_time)
|
||||
{
|
||||
/* The use of `alloca' here looks ridiculous but it helps. The goal
|
||||
is to avoid the function from being inlined. There is no official
|
||||
way to do this so we use this trick. gcc never inlines functions
|
||||
which use `alloca'. */
|
||||
ElfW(Addr) *start_addr = alloca (sizeof (ElfW(Addr)));
|
||||
|
||||
if (HP_TIMING_AVAIL)
|
||||
{
|
||||
|
@ -188,10 +205,10 @@ _dl_start (void *arg)
|
|||
}
|
||||
|
||||
/* Transfer data about ourselves to the permanent link_map structure. */
|
||||
_dl_rtld_map.l_addr = bootstrap_map.l_addr;
|
||||
_dl_rtld_map.l_ld = bootstrap_map.l_ld;
|
||||
_dl_rtld_map.l_addr = bootstrap_map_p->l_addr;
|
||||
_dl_rtld_map.l_ld = bootstrap_map_p->l_ld;
|
||||
_dl_rtld_map.l_opencount = 1;
|
||||
memcpy (_dl_rtld_map.l_info, bootstrap_map.l_info,
|
||||
memcpy (_dl_rtld_map.l_info, bootstrap_map_p->l_info,
|
||||
sizeof _dl_rtld_map.l_info);
|
||||
_dl_setup_hash (&_dl_rtld_map);
|
||||
|
||||
|
@ -203,7 +220,7 @@ _dl_start (void *arg)
|
|||
file access. It will call `dl_main' (below) to do all the real work
|
||||
of the dynamic linker, and then unwind our frame and run the user
|
||||
entry point on the same stack we entered on. */
|
||||
start_addr = _dl_sysdep_start (arg, &dl_main);
|
||||
*start_addr = _dl_sysdep_start (arg, &dl_main);
|
||||
|
||||
if (HP_TIMING_AVAIL)
|
||||
{
|
||||
|
@ -219,7 +236,7 @@ _dl_start (void *arg)
|
|||
if (_dl_debug_statistics)
|
||||
print_statistics ();
|
||||
|
||||
return start_addr;
|
||||
return *start_addr;
|
||||
}
|
||||
|
||||
/* Now life is peachy; we can do all normal operations.
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
1999-06-23 Robey Pointer <robey@netscape.com>
|
||||
|
||||
* internals.h: Added p_nextlock entry to separate queueing for a
|
||||
lock from queueing for a CV (sometimes a thread queues on a lock
|
||||
to serialize removing itself from a CV queue).
|
||||
* pthread.c: Added p_nextlock to initializers.
|
||||
* spinlock.c: Changed to use p_nextlock instead of p_nextwaiting.
|
||||
|
||||
1999-07-09 Ulrich Drepper <drepper@cygnus.com>
|
||||
|
||||
* manager.c (pthread_handle_create): Free mmap region after stack
|
||||
|
|
|
@ -74,6 +74,7 @@ struct _pthread_descr_struct {
|
|||
pthread_descr p_nextlive, p_prevlive;
|
||||
/* Double chaining of active threads */
|
||||
pthread_descr p_nextwaiting; /* Next element in the queue holding the thr */
|
||||
pthread_descr p_nextlock; /* can be on a queue and waiting on a lock */
|
||||
pthread_t p_tid; /* Thread identifier */
|
||||
int p_pid; /* PID of Unix process */
|
||||
int p_priority; /* Thread priority (== 0 if not realtime) */
|
||||
|
|
|
@ -34,6 +34,7 @@ struct _pthread_descr_struct __pthread_initial_thread = {
|
|||
&__pthread_initial_thread, /* pthread_descr p_nextlive */
|
||||
&__pthread_initial_thread, /* pthread_descr p_prevlive */
|
||||
NULL, /* pthread_descr p_nextwaiting */
|
||||
NULL, /* pthread_descr p_nextlock */
|
||||
PTHREAD_THREADS_MAX, /* pthread_t p_tid */
|
||||
0, /* int p_pid */
|
||||
0, /* int p_priority */
|
||||
|
@ -75,6 +76,7 @@ struct _pthread_descr_struct __pthread_manager_thread = {
|
|||
NULL, /* pthread_descr p_nextlive */
|
||||
NULL, /* pthread_descr p_prevlive */
|
||||
NULL, /* pthread_descr p_nextwaiting */
|
||||
NULL, /* pthread_descr p_nextlock */
|
||||
0, /* int p_tid */
|
||||
0, /* int p_pid */
|
||||
0, /* int p_priority */
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
1: fastlock is taken, no thread is waiting on it
|
||||
ADDR: fastlock is taken, ADDR is address of thread descriptor for
|
||||
first waiting thread, other waiting threads are linked via
|
||||
their p_nextwaiting field.
|
||||
their p_nextlock field.
|
||||
The waiting list is not sorted by priority order.
|
||||
Actually, we always insert at top of list (sole insertion mode
|
||||
that can be performed without locking).
|
||||
|
@ -50,8 +50,10 @@ void internal_function __pthread_lock(struct _pthread_fastlock * lock,
|
|||
self = thread_self();
|
||||
newstatus = (long) self;
|
||||
}
|
||||
if (self != NULL)
|
||||
THREAD_SETMEM(self, p_nextwaiting, (pthread_descr) oldstatus);
|
||||
if (self != NULL) {
|
||||
ASSERT(self->p_nextlock == NULL);
|
||||
THREAD_SETMEM(self, p_nextlock, (pthread_descr) oldstatus);
|
||||
}
|
||||
} while(! compare_and_swap(&lock->__status, oldstatus, newstatus,
|
||||
&lock->__spinlock));
|
||||
if (oldstatus != 0) suspend(self);
|
||||
|
@ -83,7 +85,7 @@ again:
|
|||
maxptr = ptr;
|
||||
maxprio = thr->p_priority;
|
||||
}
|
||||
ptr = &(thr->p_nextwaiting);
|
||||
ptr = &(thr->p_nextlock);
|
||||
thr = *ptr;
|
||||
}
|
||||
/* Remove max prio thread from waiting list. */
|
||||
|
@ -92,16 +94,16 @@ again:
|
|||
to guard against concurrent lock operation */
|
||||
thr = (pthread_descr) oldstatus;
|
||||
if (! compare_and_swap(&lock->__status,
|
||||
oldstatus, (long)(thr->p_nextwaiting),
|
||||
oldstatus, (long)(thr->p_nextlock),
|
||||
&lock->__spinlock))
|
||||
goto again;
|
||||
} else {
|
||||
/* No risk of concurrent access, remove max prio thread normally */
|
||||
thr = *maxptr;
|
||||
*maxptr = thr->p_nextwaiting;
|
||||
*maxptr = thr->p_nextlock;
|
||||
}
|
||||
/* Wake up the selected waiting thread */
|
||||
thr->p_nextwaiting = NULL;
|
||||
thr->p_nextlock = NULL;
|
||||
restart(thr);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue