diff options
Diffstat (limited to 'libexec')
-rw-r--r-- | libexec/rtld-elf/map_object.c | 3 | ||||
-rw-r--r-- | libexec/rtld-elf/rtld.c | 20 | ||||
-rw-r--r-- | libexec/rtld-elf/rtld.h | 1 |
3 files changed, 24 insertions, 0 deletions
diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c index 33fb9a6..2b1ef24 100644 --- a/libexec/rtld-elf/map_object.c +++ b/libexec/rtld-elf/map_object.c @@ -305,6 +305,9 @@ obj_free(Obj_Entry *obj) { Objlist_Entry *elm; + if (obj->tls_done) { + free_tls_offset(obj); + } free(obj->path); while (obj->needed != NULL) { Needed_Entry *needed = obj->needed; diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 6fc64dd..aec6e3d 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -2773,6 +2773,26 @@ allocate_tls_offset(Obj_Entry *obj) return true; } +void +free_tls_offset(Obj_Entry *obj) +{ +#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) || \ + defined(__arm__) + /* + * If we were the last thing to allocate out of the static TLS + * block, we give our space back to the 'allocator'. This is a + * simplistic workaround to allow libGL.so.1 to be loaded and + * unloaded multiple times. We only handle the Variant II + * mechanism for now - this really needs a proper allocator. + */ + if (calculate_tls_end(obj->tlsoffset, obj->tlssize) + == calculate_tls_end(tls_last_offset, tls_last_size)) { + tls_last_offset -= obj->tlssize; + tls_last_size = 0; + } +#endif +} + void * _rtld_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign) { diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index 69964d6..bee36af 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -238,6 +238,7 @@ void *allocate_tls(Obj_Entry *, void *, size_t, size_t); void free_tls(void *, size_t, size_t); void *allocate_module_tls(int index); bool allocate_tls_offset(Obj_Entry *obj); +void free_tls_offset(Obj_Entry *obj); /* * MD function declarations. |