1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker * All rights reserved.
4*8d67ca89SAndroid Build Coastguard Worker *
5*8d67ca89SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
6*8d67ca89SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
7*8d67ca89SAndroid Build Coastguard Worker * are met:
8*8d67ca89SAndroid Build Coastguard Worker * * Redistributions of source code must retain the above copyright
9*8d67ca89SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
10*8d67ca89SAndroid Build Coastguard Worker * * Redistributions in binary form must reproduce the above copyright
11*8d67ca89SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in
12*8d67ca89SAndroid Build Coastguard Worker * the documentation and/or other materials provided with the
13*8d67ca89SAndroid Build Coastguard Worker * distribution.
14*8d67ca89SAndroid Build Coastguard Worker *
15*8d67ca89SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16*8d67ca89SAndroid Build Coastguard Worker * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17*8d67ca89SAndroid Build Coastguard Worker * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18*8d67ca89SAndroid Build Coastguard Worker * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19*8d67ca89SAndroid Build Coastguard Worker * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20*8d67ca89SAndroid Build Coastguard Worker * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21*8d67ca89SAndroid Build Coastguard Worker * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22*8d67ca89SAndroid Build Coastguard Worker * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23*8d67ca89SAndroid Build Coastguard Worker * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*8d67ca89SAndroid Build Coastguard Worker * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25*8d67ca89SAndroid Build Coastguard Worker * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*8d67ca89SAndroid Build Coastguard Worker * SUCH DAMAGE.
27*8d67ca89SAndroid Build Coastguard Worker */
28*8d67ca89SAndroid Build Coastguard Worker
29*8d67ca89SAndroid Build Coastguard Worker #pragma once
30*8d67ca89SAndroid Build Coastguard Worker
31*8d67ca89SAndroid Build Coastguard Worker #include <link.h>
32*8d67ca89SAndroid Build Coastguard Worker #include <pthread.h>
33*8d67ca89SAndroid Build Coastguard Worker #include <stdatomic.h>
34*8d67ca89SAndroid Build Coastguard Worker #include <stdint.h>
35*8d67ca89SAndroid Build Coastguard Worker #include <sys/cdefs.h>
36*8d67ca89SAndroid Build Coastguard Worker
37*8d67ca89SAndroid Build Coastguard Worker #include "bionic_elf_dtv_offset.h"
38*8d67ca89SAndroid Build Coastguard Worker
39*8d67ca89SAndroid Build Coastguard Worker __LIBC_HIDDEN__ extern _Atomic(size_t) __libc_tls_generation_copy;
40*8d67ca89SAndroid Build Coastguard Worker
41*8d67ca89SAndroid Build Coastguard Worker struct TlsAlign {
42*8d67ca89SAndroid Build Coastguard Worker size_t value = 1;
43*8d67ca89SAndroid Build Coastguard Worker size_t skew = 0; // p_vaddr % p_align
44*8d67ca89SAndroid Build Coastguard Worker
45*8d67ca89SAndroid Build Coastguard Worker template <typename T>
of_typeTlsAlign46*8d67ca89SAndroid Build Coastguard Worker static constexpr TlsAlign of_type() {
47*8d67ca89SAndroid Build Coastguard Worker return TlsAlign{.value = alignof(T)};
48*8d67ca89SAndroid Build Coastguard Worker }
49*8d67ca89SAndroid Build Coastguard Worker };
50*8d67ca89SAndroid Build Coastguard Worker
51*8d67ca89SAndroid Build Coastguard Worker struct TlsAlignedSize {
52*8d67ca89SAndroid Build Coastguard Worker size_t size = 0;
53*8d67ca89SAndroid Build Coastguard Worker TlsAlign align;
54*8d67ca89SAndroid Build Coastguard Worker
55*8d67ca89SAndroid Build Coastguard Worker template <typename T>
of_typeTlsAlignedSize56*8d67ca89SAndroid Build Coastguard Worker static constexpr TlsAlignedSize of_type() {
57*8d67ca89SAndroid Build Coastguard Worker return TlsAlignedSize{.size = sizeof(T), .align = TlsAlign::of_type<T>()};
58*8d67ca89SAndroid Build Coastguard Worker }
59*8d67ca89SAndroid Build Coastguard Worker };
60*8d67ca89SAndroid Build Coastguard Worker
61*8d67ca89SAndroid Build Coastguard Worker struct TlsSegment {
62*8d67ca89SAndroid Build Coastguard Worker TlsAlignedSize aligned_size;
63*8d67ca89SAndroid Build Coastguard Worker const void* init_ptr = ""; // Field is non-null even when init_size is 0.
64*8d67ca89SAndroid Build Coastguard Worker size_t init_size = 0;
65*8d67ca89SAndroid Build Coastguard Worker };
66*8d67ca89SAndroid Build Coastguard Worker
67*8d67ca89SAndroid Build Coastguard Worker __LIBC_HIDDEN__ bool __bionic_get_tls_segment(const ElfW(Phdr)* phdr_table, size_t phdr_count,
68*8d67ca89SAndroid Build Coastguard Worker ElfW(Addr) load_bias, TlsSegment* out);
69*8d67ca89SAndroid Build Coastguard Worker
70*8d67ca89SAndroid Build Coastguard Worker __LIBC_HIDDEN__ bool __bionic_check_tls_align(size_t align);
71*8d67ca89SAndroid Build Coastguard Worker
72*8d67ca89SAndroid Build Coastguard Worker struct StaticTlsLayout {
StaticTlsLayoutStaticTlsLayout73*8d67ca89SAndroid Build Coastguard Worker constexpr StaticTlsLayout() {}
74*8d67ca89SAndroid Build Coastguard Worker
75*8d67ca89SAndroid Build Coastguard Worker public:
offset_bionic_tcbStaticTlsLayout76*8d67ca89SAndroid Build Coastguard Worker size_t offset_bionic_tcb() const { return offset_bionic_tcb_; }
offset_bionic_tlsStaticTlsLayout77*8d67ca89SAndroid Build Coastguard Worker size_t offset_bionic_tls() const { return offset_bionic_tls_; }
78*8d67ca89SAndroid Build Coastguard Worker size_t offset_thread_pointer() const;
offset_exeStaticTlsLayout79*8d67ca89SAndroid Build Coastguard Worker size_t offset_exe() const { return offset_exe_; }
80*8d67ca89SAndroid Build Coastguard Worker
sizeStaticTlsLayout81*8d67ca89SAndroid Build Coastguard Worker size_t size() const { return cursor_; }
82*8d67ca89SAndroid Build Coastguard Worker
83*8d67ca89SAndroid Build Coastguard Worker size_t reserve_exe_segment_and_tcb(const TlsSegment* exe_segment, const char* progname);
84*8d67ca89SAndroid Build Coastguard Worker size_t reserve_bionic_tls();
reserve_solib_segmentStaticTlsLayout85*8d67ca89SAndroid Build Coastguard Worker size_t reserve_solib_segment(const TlsSegment& segment) { return reserve(segment.aligned_size); }
86*8d67ca89SAndroid Build Coastguard Worker void finish_layout();
87*8d67ca89SAndroid Build Coastguard Worker
88*8d67ca89SAndroid Build Coastguard Worker #if !defined(STATIC_TLS_LAYOUT_TEST)
89*8d67ca89SAndroid Build Coastguard Worker private:
90*8d67ca89SAndroid Build Coastguard Worker #endif
91*8d67ca89SAndroid Build Coastguard Worker size_t cursor_ = 0;
92*8d67ca89SAndroid Build Coastguard Worker size_t align_ = 1;
93*8d67ca89SAndroid Build Coastguard Worker
94*8d67ca89SAndroid Build Coastguard Worker // Offsets to various Bionic TLS structs from the beginning of static TLS.
95*8d67ca89SAndroid Build Coastguard Worker size_t offset_bionic_tcb_ = SIZE_MAX;
96*8d67ca89SAndroid Build Coastguard Worker size_t offset_bionic_tls_ = SIZE_MAX;
97*8d67ca89SAndroid Build Coastguard Worker
98*8d67ca89SAndroid Build Coastguard Worker size_t offset_exe_ = SIZE_MAX;
99*8d67ca89SAndroid Build Coastguard Worker
100*8d67ca89SAndroid Build Coastguard Worker struct TpAllocations {
101*8d67ca89SAndroid Build Coastguard Worker size_t before;
102*8d67ca89SAndroid Build Coastguard Worker size_t tp;
103*8d67ca89SAndroid Build Coastguard Worker size_t after;
104*8d67ca89SAndroid Build Coastguard Worker };
105*8d67ca89SAndroid Build Coastguard Worker
106*8d67ca89SAndroid Build Coastguard Worker size_t align_cursor(TlsAlign align);
107*8d67ca89SAndroid Build Coastguard Worker size_t align_cursor_unskewed(size_t align);
108*8d67ca89SAndroid Build Coastguard Worker size_t reserve(TlsAlignedSize aligned_size);
109*8d67ca89SAndroid Build Coastguard Worker TpAllocations reserve_tp_pair(TlsAlignedSize before, TlsAlignedSize after);
110*8d67ca89SAndroid Build Coastguard Worker
reserve_typeStaticTlsLayout111*8d67ca89SAndroid Build Coastguard Worker template <typename T> size_t reserve_type() {
112*8d67ca89SAndroid Build Coastguard Worker return reserve(TlsAlignedSize::of_type<T>());
113*8d67ca89SAndroid Build Coastguard Worker }
114*8d67ca89SAndroid Build Coastguard Worker };
115*8d67ca89SAndroid Build Coastguard Worker
116*8d67ca89SAndroid Build Coastguard Worker static constexpr size_t kTlsGenerationNone = 0;
117*8d67ca89SAndroid Build Coastguard Worker static constexpr size_t kTlsGenerationFirst = 1;
118*8d67ca89SAndroid Build Coastguard Worker
119*8d67ca89SAndroid Build Coastguard Worker // The first ELF TLS module has ID 1. Zero is reserved for the first word of
120*8d67ca89SAndroid Build Coastguard Worker // the DTV, a generation count. Unresolved weak symbols also use module ID 0.
121*8d67ca89SAndroid Build Coastguard Worker static constexpr size_t kTlsUninitializedModuleId = 0;
122*8d67ca89SAndroid Build Coastguard Worker
__tls_module_id_to_idx(size_t id)123*8d67ca89SAndroid Build Coastguard Worker static inline size_t __tls_module_id_to_idx(size_t id) { return id - 1; }
__tls_module_idx_to_id(size_t idx)124*8d67ca89SAndroid Build Coastguard Worker static inline size_t __tls_module_idx_to_id(size_t idx) { return idx + 1; }
125*8d67ca89SAndroid Build Coastguard Worker
126*8d67ca89SAndroid Build Coastguard Worker // A descriptor for a single ELF TLS module.
127*8d67ca89SAndroid Build Coastguard Worker struct TlsModule {
128*8d67ca89SAndroid Build Coastguard Worker TlsSegment segment;
129*8d67ca89SAndroid Build Coastguard Worker
130*8d67ca89SAndroid Build Coastguard Worker // Offset into the static TLS block or SIZE_MAX for a dynamic module.
131*8d67ca89SAndroid Build Coastguard Worker size_t static_offset = SIZE_MAX;
132*8d67ca89SAndroid Build Coastguard Worker
133*8d67ca89SAndroid Build Coastguard Worker // The generation in which this module was loaded. Dynamic TLS lookups use
134*8d67ca89SAndroid Build Coastguard Worker // this field to detect when a module has been unloaded.
135*8d67ca89SAndroid Build Coastguard Worker size_t first_generation = kTlsGenerationNone;
136*8d67ca89SAndroid Build Coastguard Worker
137*8d67ca89SAndroid Build Coastguard Worker // Used by the dynamic linker to track the associated soinfo* object.
138*8d67ca89SAndroid Build Coastguard Worker void* soinfo_ptr = nullptr;
139*8d67ca89SAndroid Build Coastguard Worker };
140*8d67ca89SAndroid Build Coastguard Worker
141*8d67ca89SAndroid Build Coastguard Worker // Signature of the callbacks that will be called after DTLS creation and
142*8d67ca89SAndroid Build Coastguard Worker // before DTLS destruction.
143*8d67ca89SAndroid Build Coastguard Worker typedef void (*dtls_listener_t)(void* dynamic_tls_begin, void* dynamic_tls_end);
144*8d67ca89SAndroid Build Coastguard Worker
145*8d67ca89SAndroid Build Coastguard Worker // Signature of the thread-exit callbacks.
146*8d67ca89SAndroid Build Coastguard Worker typedef void (*thread_exit_cb_t)(void);
147*8d67ca89SAndroid Build Coastguard Worker
148*8d67ca89SAndroid Build Coastguard Worker struct CallbackHolder {
149*8d67ca89SAndroid Build Coastguard Worker thread_exit_cb_t cb;
150*8d67ca89SAndroid Build Coastguard Worker CallbackHolder* prev;
151*8d67ca89SAndroid Build Coastguard Worker };
152*8d67ca89SAndroid Build Coastguard Worker
153*8d67ca89SAndroid Build Coastguard Worker // Table of the ELF TLS modules. Either the dynamic linker or the static
154*8d67ca89SAndroid Build Coastguard Worker // initialization code prepares this table, and it's then used during thread
155*8d67ca89SAndroid Build Coastguard Worker // creation and for dynamic TLS lookups.
156*8d67ca89SAndroid Build Coastguard Worker struct TlsModules {
TlsModulesTlsModules157*8d67ca89SAndroid Build Coastguard Worker constexpr TlsModules() {}
158*8d67ca89SAndroid Build Coastguard Worker
159*8d67ca89SAndroid Build Coastguard Worker // A pointer to the TLS generation counter in libc.so. The counter is
160*8d67ca89SAndroid Build Coastguard Worker // incremented each time an solib is loaded or unloaded.
161*8d67ca89SAndroid Build Coastguard Worker _Atomic(size_t) generation = kTlsGenerationFirst;
162*8d67ca89SAndroid Build Coastguard Worker _Atomic(size_t) *generation_libc_so = nullptr;
163*8d67ca89SAndroid Build Coastguard Worker
164*8d67ca89SAndroid Build Coastguard Worker // Access to the TlsModule[] table requires taking this lock.
165*8d67ca89SAndroid Build Coastguard Worker pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
166*8d67ca89SAndroid Build Coastguard Worker
167*8d67ca89SAndroid Build Coastguard Worker // Pointer to a block of TlsModule objects. The first module has ID 1 and
168*8d67ca89SAndroid Build Coastguard Worker // is stored at index 0 in this table.
169*8d67ca89SAndroid Build Coastguard Worker size_t module_count = 0;
170*8d67ca89SAndroid Build Coastguard Worker size_t static_module_count = 0;
171*8d67ca89SAndroid Build Coastguard Worker TlsModule* module_table = nullptr;
172*8d67ca89SAndroid Build Coastguard Worker
173*8d67ca89SAndroid Build Coastguard Worker // Callback to be invoked after a dynamic TLS allocation.
174*8d67ca89SAndroid Build Coastguard Worker dtls_listener_t on_creation_cb = nullptr;
175*8d67ca89SAndroid Build Coastguard Worker
176*8d67ca89SAndroid Build Coastguard Worker // Callback to be invoked before a dynamic TLS deallocation.
177*8d67ca89SAndroid Build Coastguard Worker dtls_listener_t on_destruction_cb = nullptr;
178*8d67ca89SAndroid Build Coastguard Worker
179*8d67ca89SAndroid Build Coastguard Worker // The first thread-exit callback; inlined to avoid allocation.
180*8d67ca89SAndroid Build Coastguard Worker thread_exit_cb_t first_thread_exit_callback = nullptr;
181*8d67ca89SAndroid Build Coastguard Worker
182*8d67ca89SAndroid Build Coastguard Worker // The additional callbacks, if any.
183*8d67ca89SAndroid Build Coastguard Worker CallbackHolder* thread_exit_callback_tail_node = nullptr;
184*8d67ca89SAndroid Build Coastguard Worker };
185*8d67ca89SAndroid Build Coastguard Worker
186*8d67ca89SAndroid Build Coastguard Worker void __init_static_tls(void* static_tls);
187*8d67ca89SAndroid Build Coastguard Worker
188*8d67ca89SAndroid Build Coastguard Worker // Dynamic Thread Vector. Each thread has a different DTV. For each module
189*8d67ca89SAndroid Build Coastguard Worker // (executable or solib), the DTV has a pointer to that module's TLS memory. The
190*8d67ca89SAndroid Build Coastguard Worker // DTV is initially empty and is allocated on-demand. It grows as more modules
191*8d67ca89SAndroid Build Coastguard Worker // are dlopen'ed. See https://www.akkadia.org/drepper/tls.pdf.
192*8d67ca89SAndroid Build Coastguard Worker //
193*8d67ca89SAndroid Build Coastguard Worker // The layout of the DTV is specified in various documents, but it is not part
194*8d67ca89SAndroid Build Coastguard Worker // of Bionic's public ABI. A compiler can't generate code to access it directly,
195*8d67ca89SAndroid Build Coastguard Worker // because it can't access libc's global generation counter.
196*8d67ca89SAndroid Build Coastguard Worker struct TlsDtv {
197*8d67ca89SAndroid Build Coastguard Worker // Number of elements in this object's modules field.
198*8d67ca89SAndroid Build Coastguard Worker size_t count;
199*8d67ca89SAndroid Build Coastguard Worker
200*8d67ca89SAndroid Build Coastguard Worker // A pointer to an older TlsDtv object that should be freed when the thread
201*8d67ca89SAndroid Build Coastguard Worker // exits. The objects aren't immediately freed because a DTV could be
202*8d67ca89SAndroid Build Coastguard Worker // reallocated by a signal handler that interrupted __tls_get_addr's fast
203*8d67ca89SAndroid Build Coastguard Worker // path.
204*8d67ca89SAndroid Build Coastguard Worker TlsDtv* next;
205*8d67ca89SAndroid Build Coastguard Worker
206*8d67ca89SAndroid Build Coastguard Worker // The DTV slot points at this field, which allows omitting an add instruction
207*8d67ca89SAndroid Build Coastguard Worker // on the fast path for a TLS lookup. The arm64 tlsdesc_resolver.S depends on
208*8d67ca89SAndroid Build Coastguard Worker // the layout of fields past this point.
209*8d67ca89SAndroid Build Coastguard Worker size_t generation;
210*8d67ca89SAndroid Build Coastguard Worker void* modules[];
211*8d67ca89SAndroid Build Coastguard Worker };
212*8d67ca89SAndroid Build Coastguard Worker
213*8d67ca89SAndroid Build Coastguard Worker struct TlsIndex {
214*8d67ca89SAndroid Build Coastguard Worker size_t module_id;
215*8d67ca89SAndroid Build Coastguard Worker size_t offset;
216*8d67ca89SAndroid Build Coastguard Worker };
217*8d67ca89SAndroid Build Coastguard Worker
218*8d67ca89SAndroid Build Coastguard Worker #if defined(__i386__)
219*8d67ca89SAndroid Build Coastguard Worker #define TLS_GET_ADDR_CALLING_CONVENTION __attribute__((regparm(1)))
220*8d67ca89SAndroid Build Coastguard Worker #define TLS_GET_ADDR ___tls_get_addr
221*8d67ca89SAndroid Build Coastguard Worker #else
222*8d67ca89SAndroid Build Coastguard Worker #define TLS_GET_ADDR_CALLING_CONVENTION
223*8d67ca89SAndroid Build Coastguard Worker #define TLS_GET_ADDR __tls_get_addr
224*8d67ca89SAndroid Build Coastguard Worker #endif
225*8d67ca89SAndroid Build Coastguard Worker
226*8d67ca89SAndroid Build Coastguard Worker extern "C" void* TLS_GET_ADDR(const TlsIndex* ti) TLS_GET_ADDR_CALLING_CONVENTION;
227*8d67ca89SAndroid Build Coastguard Worker
228*8d67ca89SAndroid Build Coastguard Worker struct bionic_tcb;
229*8d67ca89SAndroid Build Coastguard Worker void __free_dynamic_tls(bionic_tcb* tcb);
230*8d67ca89SAndroid Build Coastguard Worker void __notify_thread_exit_callbacks();
231*8d67ca89SAndroid Build Coastguard Worker
232