12d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//===-- sanitizer_tls_get_addr.h --------------------------------*- C++ -*-===//
22d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
32d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//                     The LLVM Compiler Infrastructure
42d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
52d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// This file is distributed under the University of Illinois Open Source
62d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// License. See LICENSE.TXT for details.
72d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
82d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//===----------------------------------------------------------------------===//
92d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Handle the __tls_get_addr call.
112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// All this magic is specific to glibc and is required to workaround
132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// the lack of interface that would tell us about the Dynamic TLS (DTLS).
142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// https://sourceware.org/bugzilla/show_bug.cgi?id=16291
152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// The matters get worse because the glibc implementation changed between
172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// 2.18 and 2.19:
182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// https://groups.google.com/forum/#!topic/address-sanitizer/BfwYD8HMxTM
192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Before 2.19, every DTLS chunk is allocated with __libc_memalign,
212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// which we intercept and thus know where is the DTLS.
222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Since 2.19, DTLS chunks are allocated with __signal_safe_memalign,
232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// which is an internal function that wraps a mmap call, neither of which
242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// we can intercept. Luckily, __signal_safe_memalign has a simple parseable
252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// header which we can use.
262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//===----------------------------------------------------------------------===//
282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#ifndef SANITIZER_TLS_GET_ADDR_H
302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define SANITIZER_TLS_GET_ADDR_H
312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_common.h"
332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesnamespace __sanitizer {
352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstruct DTLS {
372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // Array of DTLS chunks for the current Thread.
382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // If beg == 0, the chunk is unused.
392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  struct DTV {
402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    uptr beg, size;
412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  };
422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr dtv_size;
442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  DTV *dtv;  // dtv_size elements, allocated by MmapOrDie.
452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // Auxiliary fields, don't access them outside sanitizer_tls_get_addr.cc
472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr last_memalign_size;
482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr last_memalign_ptr;
492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines};
502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
515d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// Returns pointer and size of a linker-allocated TLS block.
525d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// Each block is returned exactly once.
535d71de26cedae3dafc17449fe0182045c0bd20e8Stephen HinesDTLS::DTV *DTLS_on_tls_get_addr(void *arg, void *res);
542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid DTLS_on_libc_memalign(void *ptr, uptr size);
552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesDTLS *DTLS_Get();
562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid DTLS_Destroy();  // Make sure to call this before the thread is destroyed.
572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}  // namespace __sanitizer
592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_TLS_GET_ADDR_H
61