@@ -130,6 +130,21 @@ static void ProcessPlatformSpecificAllocationsCb(uptr chunk, void *arg) {
130
130
131
131
// Handles dynamically allocated TLS blocks by treating all chunks allocated
132
132
// from ld-linux.so as reachable.
133
+ // Dynamic TLS blocks contain the TLS variables of dynamically loaded modules.
134
+ // They are allocated with a __libc_memalign() call in allocate_and_init()
135
+ // (elf/dl-tls.c). Glibc won't tell us the address ranges occupied by those
136
+ // blocks, but we can make sure they come from our own allocator by intercepting
137
+ // __libc_memalign(). On top of that, there is no easy way to reach them. Their
138
+ // addresses are stored in a dynamically allocated array (the DTV) which is
139
+ // referenced from the static TLS. Unfortunately, we can't just rely on the DTV
140
+ // being reachable from the static TLS, and the dynamic TLS being reachable from
141
+ // the DTV. This is because the initial DTV is allocated before our interception
142
+ // mechanism kicks in, and thus we don't recognize it as allocated memory. We
143
+ // can't special-case it either, since we don't know its size.
144
+ // Our solution is to include in the root set all allocations made from
145
+ // ld-linux.so (which is where allocate_and_init() is implemented). This is
146
+ // guaranteed to include all dynamic TLS blocks (and possibly other allocations
147
+ // which we don't care about).
133
148
void ProcessPlatformSpecificAllocations (Frontier *frontier) {
134
149
if (!flags ()->use_tls ) return ;
135
150
if (!linker) return ;
0 commit comments