PERFORCE change 57928 for review

Doug Rabson dfr at FreeBSD.org
Thu Jul 22 09:03:39 PDT 2004


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

Change 57928 by dfr at dfr_home on 2004/07/22 16:03:00

	Add some defines for non-i386 arches and flesh out the amd64
	support (untested).

Affected files ...

.. //depot/projects/kse/libexec/rtld-elf/alpha/rtld_machdep.h#3 edit
.. //depot/projects/kse/libexec/rtld-elf/amd64/reloc.c#3 edit
.. //depot/projects/kse/libexec/rtld-elf/amd64/rtld_machdep.h#3 edit
.. //depot/projects/kse/libexec/rtld-elf/sparc64/reloc.c#3 edit
.. //depot/projects/kse/libexec/rtld-elf/sparc64/rtld_machdep.h#4 edit

Differences ...

==== //depot/projects/kse/libexec/rtld-elf/alpha/rtld_machdep.h#3 (text+ko) ====

@@ -66,6 +66,7 @@
 	round(16, align)
 #define calculate_tls_offset(prev_offset, prev_size, size, align) \
 	round(prev_offset + prev_size, align)
+#define calculate_tls_end(off, size) 	((off) + (size))
 
 typedef struct {
     unsigned long ti_module;

==== //depot/projects/kse/libexec/rtld-elf/amd64/reloc.c#3 (text+ko) ====

@@ -48,6 +48,15 @@
 #include "debug.h"
 #include "rtld.h"
 
+#define R_X86_64_DTPMOD64	16 /* ID of module containing symbol */
+#define R_X86_64_DTPOFF64	17 /* Offset in TLS block */
+#define R_X86_64_TPOFF64	18 /* Offset in static TLS block */
+#define R_X86_64_TLSGD		19 /* PC relative offset to GD GOT entry */
+#define R_X86_64_TLSLD		20 /* PC relative offset to LD GOT entry */
+#define R_X86_64_DTPOFF32	21 /* Offset in TLS block */
+#define R_X86_64_GOTTPOFF	22 /* PC relative offset to IE GOT entry */
+#define R_X86_64_TPOFF32	23 /* Offset in static TLS block */
+
 /*
  * Process the special R_X86_64_COPY relocations in the main program.  These
  * copy data from a shared object into a region in the main program's BSS
@@ -200,6 +209,108 @@
 		}
 		break;
 
+	    case R_X86_64_TPOFF64:
+		{
+		    const Elf_Sym *def;
+		    const Obj_Entry *defobj;
+
+		    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
+		      false, cache);
+		    if (def == NULL)
+			goto done;
+
+		    /*
+		     * 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);
+			    goto done;
+			}
+		    }
+
+		    *where = (Elf_Addr) (def->st_value - defobj->tlsoffset);
+		}
+		break;
+
+	    case R_X86_64_TPOFF32:
+		{
+		    const Elf_Sym *def;
+		    const Obj_Entry *defobj;
+
+		    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
+		      false, cache);
+		    if (def == NULL)
+			goto done;
+
+		    /*
+		     * 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);
+			    goto done;
+			}
+		    }
+
+		    *where32 = (Elf32_Addr) (def->st_value - defobj->tlsoffset);
+		}
+		break;
+
+	    case R_X86_64_DTPMOD64:
+		{
+		    const Elf_Sym *def;
+		    const Obj_Entry *defobj;
+
+		    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
+		      false, cache);
+		    if (def == NULL)
+			goto done;
+
+		    *where += (Elf_Addr) defobj->tlsindex;
+		}
+		break;
+
+	    case R_X86_64_DTPOFF64:
+		{
+		    const Elf_Sym *def;
+		    const Obj_Entry *defobj;
+
+		    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
+		      false, cache);
+		    if (def == NULL)
+			goto done;
+
+		    *where += (Elf_Addr) def->st_value;
+		}
+		break;
+
+	    case R_X86_64_DTPOFF32:
+		{
+		    const Elf_Sym *def;
+		    const Obj_Entry *defobj;
+
+		    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
+		      false, cache);
+		    if (def == NULL)
+			goto done;
+
+		    *where32 += (Elf32_Addr) def->st_value;
+		}
+		break;
+
 	    case R_X86_64_RELATIVE:
 		*where = (Elf_Addr)(obj->relocbase + rela->r_addend);
 		break;
@@ -267,24 +378,20 @@
     return 0;
 }
 
-void
-allocate_initial_tls(Obj_Entry *list)
+void *
+allocate_tls(Objlist* list, size_t tcbsize, size_t tcbalign)
 {
+    Objlist_Entry *entry;
     Obj_Entry *obj;
     size_t size;
     char *tls;
     Elf_Addr *dtv;
-    union descriptor ldt;
-    Elf_Addr segbase;
-    int sel;
+    Elf_Addr segbase, addr;
 
-    size = 0;
-    for (obj = list; obj; obj = obj->next) {
-        if (obj->tlsoffset > size)
-            size = obj->tlsoffset;
-    }
+    size = round(tls_static_space, tcbalign);
 
-    tls = malloc(size + 2*sizeof(Elf_Addr));
+    assert(tcbsize >= 2*sizeof(Elf_Addr));
+    tls = malloc(size + tcbsize);
     dtv = malloc((tls_max_index + 2) * sizeof(Elf_Addr));
 
     segbase = (Elf_Addr)(tls + size);
@@ -293,16 +400,60 @@
 
     dtv[0] = tls_dtv_generation;
     dtv[1] = tls_max_index;
-    for (obj = list; obj; obj = obj->next) {
-	Elf_Addr addr = segbase - 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 = segbase - 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 (void*) segbase;
+}
+
+void
+free_tls(Objlist *list, void *tls, size_t tcbsize, size_t tcbalign)
+{
+    size_t size;
+    Elf_Addr* dtv;
+    int dtvsize, i;
+    Elf_Addr tlsstart, tlsend;
+
+    /*
+     * Figure out the size of the initial TLS block so that we can
+     * find stuff which ___tls_get_addr() allocated dynamically.
+     */
+    size = round(tls_static_space, tcbalign);
+
+    dtv = ((Elf_Addr**)tls)[1];
+    dtvsize = dtv[1];
+    tlsend = (Elf_Addr) tls;
+    tlsstart = tlsend - size;
+    for (i = 0; i < dtvsize; i++) {
+	if (dtv[i+2] < tlsstart || dtv[i+2] > tlsend) {
+	    free((void*) dtv[i+2]);
+	}
     }
 
-    amd64_set_fsbase(segbase);
+    free((void*) tlsstart);
+}
+
+void
+allocate_initial_tls(Obj_Entry *list)
+{
+    /*
+     * 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 + 64;
+    amd64_set_fsbase(allocate_tls(list, 2*sizeof(Elf_Addr), 4));
 }
 
 void *__tls_get_addr(tls_index *ti)

==== //depot/projects/kse/libexec/rtld-elf/amd64/rtld_machdep.h#3 (text+ko) ====

@@ -64,6 +64,7 @@
 	round(size, align)
 #define calculate_tls_offset(prev_offset, prev_size, size, align) \
 	round((prev_offset) + (size), align)
+#define calculate_tls_end(off, size) 	(off)
 
 typedef struct {
     unsigned long ti_module;

==== //depot/projects/kse/libexec/rtld-elf/sparc64/reloc.c#3 (text+ko) ====


==== //depot/projects/kse/libexec/rtld-elf/sparc64/rtld_machdep.h#4 (text+ko) ====

@@ -58,6 +58,7 @@
 	round(size, align)
 #define calculate_tls_offset(prev_offset, prev_size, size, align) \
 	round((prev_offset) + (size), align)
+#define calculate_tls_end(off, size) 	((off) + (size))
 
 typedef struct {
     unsigned long ti_module;


More information about the p4-projects mailing list