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