summaryrefslogtreecommitdiff
path: root/lib/lsan/lsan_common_linux.cc
diff options
context:
space:
mode:
authorSergey Matveev <earthdok@google.com>2014-01-23 15:10:35 +0000
committerSergey Matveev <earthdok@google.com>2014-01-23 15:10:35 +0000
commitf17f4176b74547e6f629f3b3879f20aa465a2138 (patch)
tree5eeee65668bac832f6ea2cec6e5bd74c731e35ce /lib/lsan/lsan_common_linux.cc
parent4c37ee69d9ecf1d0e820e3ebe19b18792b2e9124 (diff)
[lsan] Expand a comment to document our dynamic TLS hack.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@199900 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/lsan/lsan_common_linux.cc')
-rw-r--r--lib/lsan/lsan_common_linux.cc15
1 files changed, 15 insertions, 0 deletions
diff --git a/lib/lsan/lsan_common_linux.cc b/lib/lsan/lsan_common_linux.cc
index 2daee3fdf..49329826c 100644
--- a/lib/lsan/lsan_common_linux.cc
+++ b/lib/lsan/lsan_common_linux.cc
@@ -130,6 +130,21 @@ static void ProcessPlatformSpecificAllocationsCb(uptr chunk, void *arg) {
// Handles dynamically allocated TLS blocks by treating all chunks allocated
// from ld-linux.so as reachable.
+// Dynamic TLS blocks contain the TLS variables of dynamically loaded modules.
+// They are allocated with a __libc_memalign() call in allocate_and_init()
+// (elf/dl-tls.c). Glibc won't tell us the address ranges occupied by those
+// blocks, but we can make sure they come from our own allocator by intercepting
+// __libc_memalign(). On top of that, there is no easy way to reach them. Their
+// addresses are stored in a dynamically allocated array (the DTV) which is
+// referenced from the static TLS. Unfortunately, we can't just rely on the DTV
+// being reachable from the static TLS, and the dynamic TLS being reachable from
+// the DTV. This is because the initial DTV is allocated before our interception
+// mechanism kicks in, and thus we don't recognize it as allocated memory. We
+// can't special-case it either, since we don't know its size.
+// Our solution is to include in the root set all allocations made from
+// ld-linux.so (which is where allocate_and_init() is implemented). This is
+// guaranteed to include all dynamic TLS blocks (and possibly other allocations
+// which we don't care about).
void ProcessPlatformSpecificAllocations(Frontier *frontier) {
if (!flags()->use_tls) return;
if (!linker) return;