Index: abi/include/abi/elf.h
===================================================================
--- abi/include/abi/elf.h	(revision bab0f42542f9964d547692bfd310e99993b1003f)
+++ abi/include/abi/elf.h	(revision e2f260026920f1d43bed8d2b775564b1f64a6f6a)
@@ -157,4 +157,5 @@
 #define STT_SECTION  3
 #define STT_FILE     4
+#define STT_TLS      6
 #define STT_LOPROC   13
 #define STT_HIPROC   15
Index: uspace/app/dltest/dltest.c
===================================================================
--- uspace/app/dltest/dltest.c	(revision bab0f42542f9964d547692bfd310e99993b1003f)
+++ uspace/app/dltest/dltest.c	(revision e2f260026920f1d43bed8d2b775564b1f64a6f6a)
@@ -581,5 +581,5 @@
 
 	printf("Got %d, expected %d... ", val, dl_private_fib_var_val);
-	if (val != dl_private_var_val) {
+	if (val != dl_private_fib_var_val) {
 		printf("FAILED\n");
 		return false;
Index: uspace/lib/c/arch/ia32/src/tls.c
===================================================================
--- uspace/lib/c/arch/ia32/src/tls.c	(revision bab0f42542f9964d547692bfd310e99993b1003f)
+++ uspace/lib/c/arch/ia32/src/tls.c	(revision e2f260026920f1d43bed8d2b775564b1f64a6f6a)
@@ -69,19 +69,14 @@
     *___tls_get_addr(tls_index *ti)
 {
-	size_t tls_size;
 	uint8_t *tls;
-
-	/* Calculate size of TLS block */
-	tls_size = tls_get_size();
-
-	/* The TLS block is just before TCB */
-	tls = (uint8_t *)__tcb_get() - tls_size;
 
 #ifdef CONFIG_RTLD
 	if (runtime_env != NULL) {
-		return rtld_tls_get_addr(runtime_env, tls, ti->ti_module,
+		return rtld_tls_get_addr(runtime_env, ti->ti_module,
 		    ti->ti_offset);
 	}
 #endif
+	/* Get address of static TLS block */
+	tls = tls_get();
 	return tls + ti->ti_offset;
 }
Index: uspace/lib/c/generic/rtld/rtld.c
===================================================================
--- uspace/lib/c/generic/rtld/rtld.c	(revision bab0f42542f9964d547692bfd310e99993b1003f)
+++ uspace/lib/c/generic/rtld/rtld.c	(revision e2f260026920f1d43bed8d2b775564b1f64a6f6a)
@@ -187,12 +187,20 @@
 }
 
-void *rtld_tls_get_addr(rtld_t *rtld, void *tls, unsigned long mod_id,
+void *rtld_tls_get_addr(rtld_t *rtld, unsigned long mod_id,
     unsigned long offset)
 {
 	module_t *m;
+	uint8_t *tls;
 
 	m = module_by_id(rtld, mod_id);
 	assert(m != NULL);
 
+	if (!link_used(&m->imodules_link)) {
+		printf("module '%s' is not initial. aborting.\n",
+		    m->dyn.soname);
+		abort();
+	}
+
+	tls = tls_get();
 	return tls + m->ioffs + offset;
 }
Index: uspace/lib/c/generic/rtld/symbol.c
===================================================================
--- uspace/lib/c/generic/rtld/symbol.c	(revision bab0f42542f9964d547692bfd310e99993b1003f)
+++ uspace/lib/c/generic/rtld/symbol.c	(revision e2f260026920f1d43bed8d2b775564b1f64a6f6a)
@@ -251,5 +251,7 @@
 void *symbol_get_addr(elf_symbol_t *sym, module_t *m)
 {
-	if (sym->st_shndx == SHN_ABS) {
+	if (ELF_ST_TYPE(sym->st_info) == STT_TLS) {
+		return rtld_tls_get_addr(m->rtld, m->id, sym->st_value);
+	} else if (sym->st_shndx == SHN_ABS) {
 		/* Do not add bias to absolute symbols */
 		return (void *) sym->st_value;
Index: uspace/lib/c/generic/tls.c
===================================================================
--- uspace/lib/c/generic/tls.c	(revision bab0f42542f9964d547692bfd310e99993b1003f)
+++ uspace/lib/c/generic/tls.c	(revision e2f260026920f1d43bed8d2b775564b1f64a6f6a)
@@ -52,4 +52,14 @@
 #endif
 	return &_tbss_end - &_tdata_start;
+}
+
+/** Get address of static TLS block */
+void *tls_get(void)
+{
+#ifdef CONFIG_TLS_VARIANT_1
+	return (uint8_t *)__tcb_get() + sizeof(tcb_t);
+#else /* CONFIG_TLS_VARIANT_2 */
+	return (uint8_t *)__tcb_get() - tls_get_size();
+#endif
 }
 
Index: uspace/lib/c/include/rtld/rtld.h
===================================================================
--- uspace/lib/c/include/rtld/rtld.h	(revision bab0f42542f9964d547692bfd310e99993b1003f)
+++ uspace/lib/c/include/rtld/rtld.h	(revision e2f260026920f1d43bed8d2b775564b1f64a6f6a)
@@ -50,5 +50,5 @@
 extern tcb_t *rtld_tls_make(rtld_t *);
 extern unsigned long rtld_get_next_id(rtld_t *);
-extern void *rtld_tls_get_addr(rtld_t *, void *, unsigned long, unsigned long);
+extern void *rtld_tls_get_addr(rtld_t *, unsigned long, unsigned long);
 
 #endif
Index: uspace/lib/c/include/tls.h
===================================================================
--- uspace/lib/c/include/tls.h	(revision bab0f42542f9964d547692bfd310e99993b1003f)
+++ uspace/lib/c/include/tls.h	(revision e2f260026920f1d43bed8d2b775564b1f64a6f6a)
@@ -53,4 +53,5 @@
 extern void tls_free_arch(tcb_t *, size_t);
 extern size_t tls_get_size(void);
+extern void *tls_get(void);
 
 #ifdef CONFIG_TLS_VARIANT_1
Index: uspace/lib/dltest/libdltest.h
===================================================================
--- uspace/lib/dltest/libdltest.h	(revision bab0f42542f9964d547692bfd310e99993b1003f)
+++ uspace/lib/dltest/libdltest.h	(revision e2f260026920f1d43bed8d2b775564b1f64a6f6a)
@@ -43,6 +43,6 @@
 	dl_private_var_val = 220022,
 	dl_public_var_val = 330033,
-	dl_private_fib_var_val = 220022,
-	dl_public_fib_var_val = 330033
+	dl_private_fib_var_val = 440044,
+	dl_public_fib_var_val = 550055
 };
 
