Fix dlsym and dladdr for TLS symbols

 * dlsym: call __tls_get_addr for TLS symbols

 * dladdr: skip TLS symbols

Bug: b/123772574
Test: bionic unit tests
Change-Id: I59a8bc4a7d455e1018b0d577b027b6417c8487cd
diff --git a/linker/linker_soinfo.cpp b/linker/linker_soinfo.cpp
index 89119aa..31ee74c 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -297,7 +297,11 @@
 }
 
 static bool symbol_matches_soaddr(const ElfW(Sym)* sym, ElfW(Addr) soaddr) {
+  // Skip TLS symbols. A TLS symbol's value is relative to the start of the TLS segment rather than
+  // to the start of the solib. The solib only reserves space for the initialized part of the TLS
+  // segment. (i.e. .tdata is followed by .tbss, and .tbss overlaps other sections.)
   return sym->st_shndx != SHN_UNDEF &&
+      ELF_ST_TYPE(sym->st_info) != STT_TLS &&
       soaddr >= sym->st_value &&
       soaddr < sym->st_value + sym->st_size;
 }