PERFORCE change 57919 for review

Doug Rabson dfr at FreeBSD.org
Thu Jul 22 06:17:15 PDT 2004


http://perforce.freebsd.org/chv.cgi?CH=57919

Change 57919 by dfr at 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);
 }
 


More information about the p4-projects mailing list