FreeBSD/libexec/rtld-elf/rtld.c
/*
 * Allocate Static TLS using the Variant I method.
 */
Allocate Static TLS using the Variant I method.
Allocate Static TLS using the Variant I method .
void *
allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign)
{
    Obj_Entry *obj;
    char *tcb;
    Elf_Addr **tls;
    Elf_Addr *dtv;
    Elf_Addr addr;
    int i;
    if (oldtcb != NULL && tcbsize == TLS_TCB_SIZE)
	return (oldtcb);
    assert(tcbsize >= TLS_TCB_SIZE);
    tcb = xcalloc(1, tls_static_space - TLS_TCB_SIZE + tcbsize);
    tls = (Elf_Addr **)(tcb + tcbsize - TLS_TCB_SIZE);
    if (oldtcb != NULL) {
	memcpy(tls, oldtcb, tls_static_space);
	free(oldtcb);
	dtv = tls[0];
	for (i = 0; i < dtv[1]; i++) {
	    if (dtv[i+2] >= (Elf_Addr)oldtcb &&
		dtv[i+2] < (Elf_Addr)oldtcb + tls_static_space) {
		dtv[i+2] = dtv[i+2] - (Elf_Addr)oldtcb + (Elf_Addr)tls;
	    }
	}
    } else {
	dtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr));
	tls[0] = dtv;
	dtv[0] = tls_dtv_generation;
	dtv[1] = tls_max_index;
	for (obj = globallist_curr(objs); obj != NULL;
	  obj = globallist_next(obj)) {
	    if (obj->tlsoffset > 0) {
		addr = (Elf_Addr)tls + obj->tlsoffset;
		if (obj->tlsinitsize > 0)
		    memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize);
		if (obj->tlssize > obj->tlsinitsize)
		    memset((void*) (addr + obj->tlsinitsize), 0,
			   obj->tlssize - obj->tlsinitsize);
		dtv[obj->tlsindex + 1] = addr;
	    }
	}
    }
    return (tcb);
}
void * allocate_tls ( Obj_Entry * objs , void * oldtcb , size_t tcbsize , size_t tcbalign ) { Obj_Entry * obj ; char * tcb ; Elf_Addr * * tls ; Elf_Addr * dtv ; Elf_Addr addr ; int i ; if ( oldtcb != NULL && tcbsize == TLS_TCB_SIZE ) return ( oldtcb ) ; assert ( tcbsize >= TLS_TCB_SIZE ) ; tcb = xcalloc ( 1 , tls_static_space - TLS_TCB_SIZE + tcbsize ) ; tls = ( Elf_Addr * * ) ( tcb + tcbsize - TLS_TCB_SIZE ) ; if ( oldtcb != NULL ) { memcpy ( tls , oldtcb , tls_static_space ) ; free ( oldtcb ) ; dtv = tls [ 0 ] ; for ( i = 0 ; i < dtv [ 1 ] ; i ++ ) { if ( dtv [ i + 2 ] >= ( Elf_Addr ) oldtcb && dtv [ i + 2 ] < ( Elf_Addr ) oldtcb + tls_static_space ) { dtv [ i + 2 ] = dtv [ i + 2 ] - ( Elf_Addr ) oldtcb + ( Elf_Addr ) tls ; } } } else { dtv = xcalloc ( tls_max_index + 2 , sizeof ( Elf_Addr ) ) ; tls [ 0 ] = dtv ; dtv [ 0 ] = tls_dtv_generation ; dtv [ 1 ] = tls_max_index ; for ( obj = globallist_curr ( objs ) ; obj != NULL ; obj = globallist_next ( obj ) ) { if ( obj -> tlsoffset > 0 ) { addr = ( Elf_Addr ) tls + obj -> tlsoffset ; if ( obj -> tlsinitsize > 0 ) memcpy ( ( void * ) addr , obj -> tlsinit , obj -> tlsinitsize ) ; if ( obj -> tlssize > obj -> tlsinitsize ) memset ( ( void * ) ( addr + obj -> tlsinitsize ) , 0 , obj -> tlssize - obj -> tlsinitsize ) ; dtv [ obj -> tlsindex + 1 ] = addr ; } } } return ( tcb ) ; }
Allocate Static TLS using the Variant I method.
Allocate Static TLS using the Variant I method .
/* Adjust the DTV. */