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