From owner-p4-projects@FreeBSD.ORG Thu Jul 22 13:17:15 2004 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id D8F8816A4D0; Thu, 22 Jul 2004 13:17:14 +0000 (GMT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 7ACD216A4CE for ; Thu, 22 Jul 2004 13:17:14 +0000 (GMT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 60C2F43D4C for ; Thu, 22 Jul 2004 13:17:14 +0000 (GMT) (envelope-from dfr@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.11/8.12.11) with ESMTP id i6MDHE0M001718 for ; Thu, 22 Jul 2004 13:17:14 GMT (envelope-from dfr@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.11/8.12.11/Submit) id i6MDHDpg001715 for perforce@freebsd.org; Thu, 22 Jul 2004 13:17:13 GMT (envelope-from dfr@freebsd.org) Date: Thu, 22 Jul 2004 13:17:13 GMT Message-Id: <200407221317.i6MDHDpg001715@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to dfr@freebsd.org using -f From: Doug Rabson To: Perforce Change Reviews Subject: PERFORCE change 57919 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Jul 2004 13:17:15 -0000 http://perforce.freebsd.org/chv.cgi?CH=57919 Change 57919 by dfr@dfr_home on 2004/07/22 13:16:57 Add dynamic static TLS support for ia64 (untested). Affected files ... .. //depot/projects/kse/libexec/rtld-elf/ia64/reloc.c#4 edit Differences ... ==== //depot/projects/kse/libexec/rtld-elf/ia64/reloc.c#4 (text+ko) ==== @@ -319,6 +319,22 @@ if (def == NULL) return -1; + /* + * We lazily allocate offsets for static TLS as we + * see the first relocation that references the + * TLS block. This allows us to support (small + * amounts of) static TLS in dynamically loaded + * modules. If we run out of space, we generate an + * error. + */ + if (!defobj->tls_done) { + if (!allocate_tls_offset((Obj_Entry*) defobj)) { + _rtld_error("%s: No space available for static " + "Thread Local Storage", obj->path); + return -1; + } + } + store64(where, defobj->tlsoffset + def->st_value + rela->r_addend); break; } @@ -600,6 +616,35 @@ pltres[2] = FPTR_GP(_rtld_bind_start); } +bool +allocate_tls_offset(Obj_Entry *obj) +{ + size_t off; + + if (obj->tlsindex == 1) + off = calculate_first_tls_offset(obj->tlssize, obj->tlsalign); + else + off = calculate_tls_offset(tls_last_offset, tls_last_size, + obj->tlssize, obj->tlsalign); + + /* + * If we have already fixed the size of the static TLS block, we + * must stay within that size. When allocating the static TLS, we + * leave a small amount of space spare to be used for dynamically + * loading modules which use static TLS. + */ + if (tls_static_space) { + if (calculate_tls_end(off, obj->tlssize) > tls_static_space) + return false; + } + + tls_last_offset = obj->tlsoffset = off; + tls_last_size = obj->tlssize; + obj->tls_done = true; + + return true; +} + void allocate_tls(Objlist *list, size_t tcbsize, size_t tcbalign) { @@ -609,18 +654,13 @@ char *tls; Elf_Addr *dtv; union descriptor ldt; - Elf_Addr segbase; + Elf_Addr segbase, addr; int sel; assert(tcbsize == 16); assert(tcbalign == 16); - size = 0; - STAILQ_FOREACH(entry, list, link) { - obj = entry->obj; - if (obj->tlsoffset + obj->tlssize > size) - size = obj->tlsoffset + obj->tlssize; - } + size = tls_static_space; tls = malloc(size); dtv = malloc((tls_max_index + 2) * sizeof(Elf_Addr)); @@ -629,13 +669,18 @@ dtv[0] = tls_dtv_generation; dtv[1] = tls_max_index; - for (obj = list; obj; obj = obj->next) { - Elf_Addr addr = tls + obj->tlsoffset; - memset((void*) (addr + obj->tlsinitsize), - 0, obj->tlssize - obj->tlsinitsize); - if (obj->tlsinit) - memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize); - dtv[obj->tlsindex] = addr; + STAILQ_FOREACH(entry, list, link) { + obj = entry->obj; + if (obj->tlsoffset) { + addr = tls + obj->tlsoffset; + memset((void*) (addr + obj->tlsinitsize), + 0, obj->tlssize - obj->tlsinitsize); + if (obj->tlsinit) + memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize); + dtv[obj->tlsindex + 1] = addr; + } else if (obj->tlsindex) { + dtv[obj->tlsindex + 1] = 0; + } } return tls; @@ -644,8 +689,6 @@ void free_tls(Objlist *list, void *tls, size_t tcbsize, size_t tcbalign) { - Objlist_Entry *entry; - Obj_Entry *obj; size_t size; Elf_Addr* dtv; int dtvsize, i; @@ -655,12 +698,7 @@ * Figure out the size of the initial TLS block so that we can * find stuff which __tls_get_addr() allocated dynamically. */ - size = 0; - STAILQ_FOREACH(entry, list, link) { - obj = entry->obj; - if (obj->tlsoffset + obj->tlssize > size) - size = obj->tlsoffset + obj->tlssize; - } + size = tls_static_space; dtv = ((Elf_Addr**)tls)[0]; dtvsize = dtv[1]; @@ -680,6 +718,13 @@ { register struct Elf_Addr** tp __asm__("r13"); + /* + * Fix the size of the static TLS block by using the maximum + * offset allocated so far and adding a bit for dynamic modules to + * use. + */ + tls_static_space = tls_last_offset + tls_last_size + 64; + tp = allocate_tls(list, 16, 16); }