]>
Commit | Line | Data |
---|---|---|
ef1b3fda KS |
1 | //===-- sanitizer_linux_libcdep.cc ----------------------------------------===// |
2 | // | |
3 | // This file is distributed under the University of Illinois Open Source | |
4 | // License. See LICENSE.TXT for details. | |
5 | // | |
6 | //===----------------------------------------------------------------------===// | |
7 | // | |
8 | // This file is shared between AddressSanitizer and ThreadSanitizer | |
9 | // run-time libraries and implements linux-specific functions from | |
10 | // sanitizer_libc.h. | |
11 | //===----------------------------------------------------------------------===// | |
12 | ||
13 | #include "sanitizer_platform.h" | |
696d846a | 14 | |
eac97531 ML |
15 | #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ |
16 | SANITIZER_OPENBSD || SANITIZER_SOLARIS | |
ef1b3fda | 17 | |
696d846a MO |
18 | #include "sanitizer_allocator_internal.h" |
19 | #include "sanitizer_atomic.h" | |
ef1b3fda | 20 | #include "sanitizer_common.h" |
5d3805fc | 21 | #include "sanitizer_file.h" |
df77f0e4 | 22 | #include "sanitizer_flags.h" |
866e32ad | 23 | #include "sanitizer_freebsd.h" |
ef1b3fda KS |
24 | #include "sanitizer_linux.h" |
25 | #include "sanitizer_placement_new.h" | |
26 | #include "sanitizer_procmaps.h" | |
866e32ad | 27 | |
866e32ad | 28 | #include <dlfcn.h> // for dlsym() |
696d846a | 29 | #include <link.h> |
ef1b3fda | 30 | #include <pthread.h> |
dee5ea7a | 31 | #include <signal.h> |
ef1b3fda | 32 | #include <sys/resource.h> |
10189819 | 33 | #include <syslog.h> |
ef1b3fda | 34 | |
dee5ea7a KS |
35 | #if SANITIZER_FREEBSD |
36 | #include <pthread_np.h> | |
866e32ad | 37 | #include <osreldate.h> |
eac97531 | 38 | #include <sys/sysctl.h> |
dee5ea7a KS |
39 | #define pthread_getattr_np pthread_attr_get_np |
40 | #endif | |
41 | ||
eac97531 ML |
42 | #if SANITIZER_OPENBSD |
43 | #include <pthread_np.h> | |
44 | #include <sys/sysctl.h> | |
45 | #endif | |
46 | ||
47 | #if SANITIZER_NETBSD | |
48 | #include <sys/sysctl.h> | |
49 | #include <sys/tls.h> | |
50 | #endif | |
51 | ||
52 | #if SANITIZER_SOLARIS | |
53 | #include <thread.h> | |
dee5ea7a KS |
54 | #endif |
55 | ||
696d846a MO |
56 | #if SANITIZER_ANDROID |
57 | #include <android/api-level.h> | |
eac97531 ML |
58 | #if !defined(CPU_COUNT) && !defined(__aarch64__) |
59 | #include <dirent.h> | |
60 | #include <fcntl.h> | |
61 | struct __sanitizer::linux_dirent { | |
62 | long d_ino; | |
63 | off_t d_off; | |
64 | unsigned short d_reclen; | |
65 | char d_name[]; | |
66 | }; | |
696d846a | 67 | #endif |
696d846a MO |
68 | #endif |
69 | ||
ef1b3fda KS |
70 | #if !SANITIZER_ANDROID |
71 | #include <elf.h> | |
5ab39ec3 | 72 | #include <unistd.h> |
ef1b3fda KS |
73 | #endif |
74 | ||
dee5ea7a KS |
75 | namespace __sanitizer { |
76 | ||
dee5ea7a KS |
77 | SANITIZER_WEAK_ATTRIBUTE int |
78 | real_sigaction(int signum, const void *act, void *oldact); | |
79 | ||
80 | int internal_sigaction(int signum, const void *act, void *oldact) { | |
696d846a MO |
81 | #if !SANITIZER_GO |
82 | if (&real_sigaction) | |
dee5ea7a | 83 | return real_sigaction(signum, act, oldact); |
696d846a MO |
84 | #endif |
85 | return sigaction(signum, (const struct sigaction *)act, | |
86 | (struct sigaction *)oldact); | |
dee5ea7a | 87 | } |
ef1b3fda KS |
88 | |
89 | void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, | |
90 | uptr *stack_bottom) { | |
ef1b3fda KS |
91 | CHECK(stack_top); |
92 | CHECK(stack_bottom); | |
93 | if (at_initialization) { | |
94 | // This is the main thread. Libpthread may not be initialized yet. | |
95 | struct rlimit rl; | |
96 | CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0); | |
97 | ||
98 | // Find the mapping that contains a stack variable. | |
99 | MemoryMappingLayout proc_maps(/*cache_enabled*/true); | |
5d3805fc | 100 | MemoryMappedSegment segment; |
ef1b3fda | 101 | uptr prev_end = 0; |
5d3805fc JJ |
102 | while (proc_maps.Next(&segment)) { |
103 | if ((uptr)&rl < segment.end) break; | |
104 | prev_end = segment.end; | |
ef1b3fda | 105 | } |
5d3805fc | 106 | CHECK((uptr)&rl >= segment.start && (uptr)&rl < segment.end); |
ef1b3fda KS |
107 | |
108 | // Get stacksize from rlimit, but clip it so that it does not overlap | |
109 | // with other mappings. | |
110 | uptr stacksize = rl.rlim_cur; | |
5d3805fc | 111 | if (stacksize > segment.end - prev_end) stacksize = segment.end - prev_end; |
ef1b3fda KS |
112 | // When running with unlimited stack size, we still want to set some limit. |
113 | // The unlimited stack size is caused by 'ulimit -s unlimited'. | |
114 | // Also, for some reason, GNU make spawns subprocesses with unlimited stack. | |
115 | if (stacksize > kMaxThreadStackSize) | |
116 | stacksize = kMaxThreadStackSize; | |
5d3805fc JJ |
117 | *stack_top = segment.end; |
118 | *stack_bottom = segment.end - stacksize; | |
ef1b3fda KS |
119 | return; |
120 | } | |
eac97531 ML |
121 | uptr stacksize = 0; |
122 | void *stackaddr = nullptr; | |
123 | #if SANITIZER_SOLARIS | |
124 | stack_t ss; | |
125 | CHECK_EQ(thr_stksegment(&ss), 0); | |
126 | stacksize = ss.ss_size; | |
127 | stackaddr = (char *)ss.ss_sp - stacksize; | |
128 | #elif SANITIZER_OPENBSD | |
129 | stack_t sattr; | |
130 | CHECK_EQ(pthread_stackseg_np(pthread_self(), &sattr), 0); | |
131 | stackaddr = sattr.ss_sp; | |
132 | stacksize = sattr.ss_size; | |
133 | #else // !SANITIZER_SOLARIS | |
ef1b3fda | 134 | pthread_attr_t attr; |
dee5ea7a | 135 | pthread_attr_init(&attr); |
ef1b3fda | 136 | CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0); |
55aea9f5 | 137 | my_pthread_attr_getstack(&attr, &stackaddr, &stacksize); |
ef1b3fda | 138 | pthread_attr_destroy(&attr); |
eac97531 | 139 | #endif // SANITIZER_SOLARIS |
ef1b3fda | 140 | |
ef1b3fda KS |
141 | *stack_top = (uptr)stackaddr + stacksize; |
142 | *stack_bottom = (uptr)stackaddr; | |
143 | } | |
144 | ||
696d846a | 145 | #if !SANITIZER_GO |
ef1b3fda KS |
146 | bool SetEnv(const char *name, const char *value) { |
147 | void *f = dlsym(RTLD_NEXT, "setenv"); | |
696d846a | 148 | if (!f) |
ef1b3fda KS |
149 | return false; |
150 | typedef int(*setenv_ft)(const char *name, const char *value, int overwrite); | |
151 | setenv_ft setenv_f; | |
152 | CHECK_EQ(sizeof(setenv_f), sizeof(f)); | |
153 | internal_memcpy(&setenv_f, &f, sizeof(f)); | |
696d846a | 154 | return setenv_f(name, value, 1) == 0; |
ef1b3fda | 155 | } |
696d846a | 156 | #endif |
ef1b3fda | 157 | |
eac97531 ML |
158 | __attribute__((unused)) static bool GetLibcVersion(int *major, int *minor, |
159 | int *patch) { | |
160 | #ifdef _CS_GNU_LIBC_VERSION | |
161 | char buf[64]; | |
162 | uptr len = confstr(_CS_GNU_LIBC_VERSION, buf, sizeof(buf)); | |
163 | if (len >= sizeof(buf)) | |
164 | return false; | |
165 | buf[len] = 0; | |
166 | static const char kGLibC[] = "glibc "; | |
167 | if (internal_strncmp(buf, kGLibC, sizeof(kGLibC) - 1) != 0) | |
168 | return false; | |
169 | const char *p = buf + sizeof(kGLibC) - 1; | |
170 | *major = internal_simple_strtoll(p, &p, 10); | |
171 | *minor = (*p == '.') ? internal_simple_strtoll(p + 1, &p, 10) : 0; | |
172 | *patch = (*p == '.') ? internal_simple_strtoll(p + 1, &p, 10) : 0; | |
173 | return true; | |
ef1b3fda KS |
174 | #else |
175 | return false; | |
176 | #endif | |
177 | } | |
178 | ||
eac97531 ML |
179 | #if !SANITIZER_FREEBSD && !SANITIZER_ANDROID && !SANITIZER_GO && \ |
180 | !SANITIZER_NETBSD && !SANITIZER_OPENBSD && !SANITIZER_SOLARIS | |
181 | static uptr g_tls_size; | |
182 | ||
183 | #ifdef __i386__ | |
184 | # ifndef __GLIBC_PREREQ | |
185 | # define CHECK_GET_TLS_STATIC_INFO_VERSION 1 | |
186 | # else | |
187 | # define CHECK_GET_TLS_STATIC_INFO_VERSION (!__GLIBC_PREREQ(2, 27)) | |
188 | # endif | |
ef1b3fda | 189 | #else |
eac97531 | 190 | # define CHECK_GET_TLS_STATIC_INFO_VERSION 0 |
ef1b3fda | 191 | #endif |
ef1b3fda | 192 | |
eac97531 ML |
193 | #if CHECK_GET_TLS_STATIC_INFO_VERSION |
194 | # define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall)) | |
195 | #else | |
196 | # define DL_INTERNAL_FUNCTION | |
359ea407 JJ |
197 | #endif |
198 | ||
eac97531 ML |
199 | namespace { |
200 | struct GetTlsStaticInfoCall { | |
201 | typedef void (*get_tls_func)(size_t*, size_t*); | |
202 | }; | |
203 | struct GetTlsStaticInfoRegparmCall { | |
204 | typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION; | |
205 | }; | |
206 | ||
207 | template <typename T> | |
208 | void CallGetTls(void* ptr, size_t* size, size_t* align) { | |
209 | typename T::get_tls_func get_tls; | |
210 | CHECK_EQ(sizeof(get_tls), sizeof(ptr)); | |
211 | internal_memcpy(&get_tls, &ptr, sizeof(ptr)); | |
212 | CHECK_NE(get_tls, 0); | |
213 | get_tls(size, align); | |
214 | } | |
215 | ||
216 | bool CmpLibcVersion(int major, int minor, int patch) { | |
217 | int ma; | |
218 | int mi; | |
219 | int pa; | |
220 | if (!GetLibcVersion(&ma, &mi, &pa)) | |
221 | return false; | |
222 | if (ma > major) | |
223 | return true; | |
224 | if (ma < major) | |
225 | return false; | |
226 | if (mi > minor) | |
227 | return true; | |
228 | if (mi < minor) | |
229 | return false; | |
230 | return pa >= patch; | |
231 | } | |
232 | ||
233 | } // namespace | |
ef1b3fda | 234 | |
ef1b3fda | 235 | void InitTlsSize() { |
eac97531 | 236 | // all current supported platforms have 16 bytes stack alignment |
696d846a | 237 | const size_t kStackAlign = 16; |
eac97531 | 238 | void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info"); |
ef1b3fda KS |
239 | size_t tls_size = 0; |
240 | size_t tls_align = 0; | |
eac97531 ML |
241 | // On i?86, _dl_get_tls_static_info used to be internal_function, i.e. |
242 | // __attribute__((regparm(3), stdcall)) before glibc 2.27 and is normal | |
243 | // function in 2.27 and later. | |
244 | if (CHECK_GET_TLS_STATIC_INFO_VERSION && !CmpLibcVersion(2, 27, 0)) | |
245 | CallGetTls<GetTlsStaticInfoRegparmCall>(get_tls_static_info_ptr, | |
246 | &tls_size, &tls_align); | |
247 | else | |
248 | CallGetTls<GetTlsStaticInfoCall>(get_tls_static_info_ptr, | |
249 | &tls_size, &tls_align); | |
696d846a MO |
250 | if (tls_align < kStackAlign) |
251 | tls_align = kStackAlign; | |
252 | g_tls_size = RoundUpTo(tls_size, tls_align); | |
ef1b3fda | 253 | } |
10189819 MO |
254 | #else |
255 | void InitTlsSize() { } | |
5d3805fc | 256 | #endif // !SANITIZER_FREEBSD && !SANITIZER_ANDROID && !SANITIZER_GO && |
eac97531 | 257 | // !SANITIZER_NETBSD && !SANITIZER_SOLARIS |
ef1b3fda | 258 | |
eac97531 ML |
259 | #if (defined(__x86_64__) || defined(__i386__) || defined(__mips__) || \ |
260 | defined(__aarch64__) || defined(__powerpc64__) || defined(__s390__) || \ | |
261 | defined(__arm__)) && \ | |
262 | SANITIZER_LINUX && !SANITIZER_ANDROID | |
55aea9f5 | 263 | // sizeof(struct pthread) from glibc. |
eac97531 | 264 | static atomic_uintptr_t thread_descriptor_size; |
ef1b3fda KS |
265 | |
266 | uptr ThreadDescriptorSize() { | |
eac97531 | 267 | uptr val = atomic_load_relaxed(&thread_descriptor_size); |
5ab39ec3 JJ |
268 | if (val) |
269 | return val; | |
5d3805fc | 270 | #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) |
eac97531 ML |
271 | int major; |
272 | int minor; | |
273 | int patch; | |
274 | if (GetLibcVersion(&major, &minor, &patch) && major == 2) { | |
275 | /* sizeof(struct pthread) values from various glibc versions. */ | |
276 | if (SANITIZER_X32) | |
277 | val = 1728; // Assume only one particular version for x32. | |
278 | // For ARM sizeof(struct pthread) changed in Glibc 2.23. | |
279 | else if (SANITIZER_ARM) | |
280 | val = minor <= 22 ? 1120 : 1216; | |
281 | else if (minor <= 3) | |
282 | val = FIRST_32_SECOND_64(1104, 1696); | |
283 | else if (minor == 4) | |
284 | val = FIRST_32_SECOND_64(1120, 1728); | |
285 | else if (minor == 5) | |
286 | val = FIRST_32_SECOND_64(1136, 1728); | |
287 | else if (minor <= 9) | |
288 | val = FIRST_32_SECOND_64(1136, 1712); | |
289 | else if (minor == 10) | |
290 | val = FIRST_32_SECOND_64(1168, 1776); | |
291 | else if (minor == 11 || (minor == 12 && patch == 1)) | |
292 | val = FIRST_32_SECOND_64(1168, 2288); | |
293 | else if (minor <= 14) | |
294 | val = FIRST_32_SECOND_64(1168, 2304); | |
295 | else | |
296 | val = FIRST_32_SECOND_64(1216, 2304); | |
5ab39ec3 | 297 | } |
696d846a MO |
298 | #elif defined(__mips__) |
299 | // TODO(sagarthakur): add more values as per different glibc versions. | |
300 | val = FIRST_32_SECOND_64(1152, 1776); | |
696d846a MO |
301 | #elif defined(__aarch64__) |
302 | // The sizeof (struct pthread) is the same from GLIBC 2.17 to 2.22. | |
303 | val = 1776; | |
55aea9f5 MO |
304 | #elif defined(__powerpc64__) |
305 | val = 1776; // from glibc.ppc64le 2.20-8.fc21 | |
10189819 MO |
306 | #elif defined(__s390__) |
307 | val = FIRST_32_SECOND_64(1152, 1776); // valid for glibc 2.22 | |
5ab39ec3 | 308 | #endif |
eac97531 ML |
309 | if (val) |
310 | atomic_store_relaxed(&thread_descriptor_size, val); | |
311 | return val; | |
ef1b3fda KS |
312 | } |
313 | ||
314 | // The offset at which pointer to self is located in the thread descriptor. | |
315 | const uptr kThreadSelfOffset = FIRST_32_SECOND_64(8, 16); | |
316 | ||
317 | uptr ThreadSelfOffset() { | |
318 | return kThreadSelfOffset; | |
319 | } | |
320 | ||
10189819 MO |
321 | #if defined(__mips__) || defined(__powerpc64__) |
322 | // TlsPreTcbSize includes size of struct pthread_descr and size of tcb | |
323 | // head structure. It lies before the static tls blocks. | |
324 | static uptr TlsPreTcbSize() { | |
325 | # if defined(__mips__) | |
326 | const uptr kTcbHead = 16; // sizeof (tcbhead_t) | |
327 | # elif defined(__powerpc64__) | |
328 | const uptr kTcbHead = 88; // sizeof (tcbhead_t) | |
329 | # endif | |
330 | const uptr kTlsAlign = 16; | |
331 | const uptr kTlsPreTcbSize = | |
5d3805fc | 332 | RoundUpTo(ThreadDescriptorSize() + kTcbHead, kTlsAlign); |
10189819 MO |
333 | return kTlsPreTcbSize; |
334 | } | |
335 | #endif | |
336 | ||
ef1b3fda KS |
337 | uptr ThreadSelf() { |
338 | uptr descr_addr; | |
dee5ea7a | 339 | # if defined(__i386__) |
ef1b3fda | 340 | asm("mov %%gs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset)); |
dee5ea7a | 341 | # elif defined(__x86_64__) |
ef1b3fda | 342 | asm("mov %%fs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset)); |
696d846a MO |
343 | # elif defined(__mips__) |
344 | // MIPS uses TLS variant I. The thread pointer (in hardware register $29) | |
345 | // points to the end of the TCB + 0x7000. The pthread_descr structure is | |
346 | // immediately in front of the TCB. TlsPreTcbSize() includes the size of the | |
347 | // TCB and the size of pthread_descr. | |
348 | const uptr kTlsTcbOffset = 0x7000; | |
349 | uptr thread_pointer; | |
350 | asm volatile(".set push;\ | |
351 | .set mips64r2;\ | |
352 | rdhwr %0,$29;\ | |
353 | .set pop" : "=r" (thread_pointer)); | |
354 | descr_addr = thread_pointer - kTlsTcbOffset - TlsPreTcbSize(); | |
5d3805fc | 355 | # elif defined(__aarch64__) || defined(__arm__) |
10189819 MO |
356 | descr_addr = reinterpret_cast<uptr>(__builtin_thread_pointer()) - |
357 | ThreadDescriptorSize(); | |
358 | # elif defined(__s390__) | |
696d846a | 359 | descr_addr = reinterpret_cast<uptr>(__builtin_thread_pointer()); |
55aea9f5 MO |
360 | # elif defined(__powerpc64__) |
361 | // PPC64LE uses TLS variant I. The thread pointer (in GPR 13) | |
362 | // points to the end of the TCB + 0x7000. The pthread_descr structure is | |
363 | // immediately in front of the TCB. TlsPreTcbSize() includes the size of the | |
364 | // TCB and the size of pthread_descr. | |
365 | const uptr kTlsTcbOffset = 0x7000; | |
366 | uptr thread_pointer; | |
367 | asm("addi %0,13,%1" : "=r"(thread_pointer) : "I"(-kTlsTcbOffset)); | |
368 | descr_addr = thread_pointer - TlsPreTcbSize(); | |
dee5ea7a KS |
369 | # else |
370 | # error "unsupported CPU arch" | |
371 | # endif | |
ef1b3fda KS |
372 | return descr_addr; |
373 | } | |
696d846a | 374 | #endif // (x86_64 || i386 || MIPS) && SANITIZER_LINUX |
dee5ea7a KS |
375 | |
376 | #if SANITIZER_FREEBSD | |
377 | static void **ThreadSelfSegbase() { | |
378 | void **segbase = 0; | |
379 | # if defined(__i386__) | |
380 | // sysarch(I386_GET_GSBASE, segbase); | |
381 | __asm __volatile("mov %%gs:0, %0" : "=r" (segbase)); | |
382 | # elif defined(__x86_64__) | |
383 | // sysarch(AMD64_GET_FSBASE, segbase); | |
384 | __asm __volatile("movq %%fs:0, %0" : "=r" (segbase)); | |
385 | # else | |
eac97531 | 386 | # error "unsupported CPU arch" |
dee5ea7a KS |
387 | # endif |
388 | return segbase; | |
389 | } | |
ef1b3fda | 390 | |
dee5ea7a KS |
391 | uptr ThreadSelf() { |
392 | return (uptr)ThreadSelfSegbase()[2]; | |
393 | } | |
eac97531 ML |
394 | #endif // SANITIZER_FREEBSD |
395 | ||
396 | #if SANITIZER_NETBSD | |
397 | static struct tls_tcb * ThreadSelfTlsTcb() { | |
398 | struct tls_tcb * tcb; | |
399 | # ifdef __HAVE___LWP_GETTCB_FAST | |
400 | tcb = (struct tls_tcb *)__lwp_gettcb_fast(); | |
401 | # elif defined(__HAVE___LWP_GETPRIVATE_FAST) | |
402 | tcb = (struct tls_tcb *)__lwp_getprivate_fast(); | |
403 | # endif | |
404 | return tcb; | |
405 | } | |
406 | ||
407 | uptr ThreadSelf() { | |
408 | return (uptr)ThreadSelfTlsTcb()->tcb_pthread; | |
409 | } | |
410 | ||
411 | int GetSizeFromHdr(struct dl_phdr_info *info, size_t size, void *data) { | |
412 | const Elf_Phdr *hdr = info->dlpi_phdr; | |
413 | const Elf_Phdr *last_hdr = hdr + info->dlpi_phnum; | |
414 | ||
415 | for (; hdr != last_hdr; ++hdr) { | |
416 | if (hdr->p_type == PT_TLS && info->dlpi_tls_modid == 1) { | |
417 | *(uptr*)data = hdr->p_memsz; | |
418 | break; | |
419 | } | |
420 | } | |
421 | return 0; | |
422 | } | |
5d3805fc | 423 | #endif // SANITIZER_NETBSD |
dee5ea7a | 424 | |
696d846a | 425 | #if !SANITIZER_GO |
dee5ea7a | 426 | static void GetTls(uptr *addr, uptr *size) { |
696d846a | 427 | #if SANITIZER_LINUX && !SANITIZER_ANDROID |
10189819 | 428 | # if defined(__x86_64__) || defined(__i386__) || defined(__s390__) |
dee5ea7a KS |
429 | *addr = ThreadSelf(); |
430 | *size = GetTlsSize(); | |
431 | *addr -= *size; | |
432 | *addr += ThreadDescriptorSize(); | |
5d3805fc JJ |
433 | # elif defined(__mips__) || defined(__aarch64__) || defined(__powerpc64__) \ |
434 | || defined(__arm__) | |
696d846a MO |
435 | *addr = ThreadSelf(); |
436 | *size = GetTlsSize(); | |
dee5ea7a KS |
437 | # else |
438 | *addr = 0; | |
439 | *size = 0; | |
440 | # endif | |
441 | #elif SANITIZER_FREEBSD | |
442 | void** segbase = ThreadSelfSegbase(); | |
443 | *addr = 0; | |
444 | *size = 0; | |
445 | if (segbase != 0) { | |
446 | // tcbalign = 16 | |
447 | // tls_size = round(tls_static_space, tcbalign); | |
448 | // dtv = segbase[1]; | |
449 | // dtv[2] = segbase - tls_static_space; | |
450 | void **dtv = (void**) segbase[1]; | |
451 | *addr = (uptr) dtv[2]; | |
452 | *size = (*addr == 0) ? 0 : ((uptr) segbase[0] - (uptr) dtv[2]); | |
453 | } | |
eac97531 ML |
454 | #elif SANITIZER_NETBSD |
455 | struct tls_tcb * const tcb = ThreadSelfTlsTcb(); | |
456 | *addr = 0; | |
457 | *size = 0; | |
458 | if (tcb != 0) { | |
459 | // Find size (p_memsz) of dlpi_tls_modid 1 (TLS block of the main program). | |
460 | // ld.elf_so hardcodes the index 1. | |
461 | dl_iterate_phdr(GetSizeFromHdr, size); | |
462 | ||
463 | if (*size != 0) { | |
464 | // The block has been found and tcb_dtv[1] contains the base address | |
465 | *addr = (uptr)tcb->tcb_dtv[1]; | |
466 | } | |
467 | } | |
468 | #elif SANITIZER_OPENBSD | |
469 | *addr = 0; | |
470 | *size = 0; | |
471 | #elif SANITIZER_ANDROID | |
472 | *addr = 0; | |
473 | *size = 0; | |
474 | #elif SANITIZER_SOLARIS | |
475 | // FIXME | |
696d846a MO |
476 | *addr = 0; |
477 | *size = 0; | |
dee5ea7a KS |
478 | #else |
479 | # error "Unknown OS" | |
480 | #endif | |
481 | } | |
696d846a | 482 | #endif |
dee5ea7a | 483 | |
696d846a | 484 | #if !SANITIZER_GO |
dee5ea7a | 485 | uptr GetTlsSize() { |
eac97531 ML |
486 | #if SANITIZER_FREEBSD || SANITIZER_ANDROID || SANITIZER_NETBSD || \ |
487 | SANITIZER_OPENBSD || SANITIZER_SOLARIS | |
dee5ea7a KS |
488 | uptr addr, size; |
489 | GetTls(&addr, &size); | |
490 | return size; | |
5d3805fc JJ |
491 | #elif defined(__mips__) || defined(__powerpc64__) |
492 | return RoundUpTo(g_tls_size + TlsPreTcbSize(), 16); | |
ef1b3fda | 493 | #else |
dee5ea7a | 494 | return g_tls_size; |
ef1b3fda | 495 | #endif |
dee5ea7a | 496 | } |
696d846a | 497 | #endif |
dee5ea7a KS |
498 | |
499 | void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, | |
500 | uptr *tls_addr, uptr *tls_size) { | |
696d846a MO |
501 | #if SANITIZER_GO |
502 | // Stub implementation for Go. | |
503 | *stk_addr = *stk_size = *tls_addr = *tls_size = 0; | |
504 | #else | |
dee5ea7a | 505 | GetTls(tls_addr, tls_size); |
ef1b3fda KS |
506 | |
507 | uptr stack_top, stack_bottom; | |
508 | GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom); | |
509 | *stk_addr = stack_bottom; | |
510 | *stk_size = stack_top - stack_bottom; | |
511 | ||
512 | if (!main) { | |
513 | // If stack and tls intersect, make them non-intersecting. | |
514 | if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) { | |
515 | CHECK_GT(*tls_addr + *tls_size, *stk_addr); | |
516 | CHECK_LE(*tls_addr + *tls_size, *stk_addr + *stk_size); | |
517 | *stk_size -= *tls_size; | |
518 | *tls_addr = *stk_addr + *stk_size; | |
519 | } | |
520 | } | |
696d846a | 521 | #endif |
ef1b3fda KS |
522 | } |
523 | ||
eac97531 | 524 | #if !SANITIZER_FREEBSD && !SANITIZER_OPENBSD |
ef1b3fda | 525 | typedef ElfW(Phdr) Elf_Phdr; |
eac97531 ML |
526 | #elif SANITIZER_WORDSIZE == 32 && __FreeBSD_version <= 902001 // v9.2 |
527 | #define Elf_Phdr XElf32_Phdr | |
528 | #define dl_phdr_info xdl_phdr_info | |
529 | #define dl_iterate_phdr(c, b) xdl_iterate_phdr((c), (b)) | |
530 | #endif // !SANITIZER_FREEBSD && !SANITIZER_OPENBSD | |
ef1b3fda KS |
531 | |
532 | struct DlIteratePhdrData { | |
5d3805fc | 533 | InternalMmapVectorNoCtor<LoadedModule> *modules; |
ef1b3fda | 534 | bool first; |
ef1b3fda KS |
535 | }; |
536 | ||
537 | static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { | |
538 | DlIteratePhdrData *data = (DlIteratePhdrData*)arg; | |
696d846a | 539 | InternalScopedString module_name(kMaxPathLength); |
ef1b3fda KS |
540 | if (data->first) { |
541 | data->first = false; | |
542 | // First module is the binary itself. | |
696d846a | 543 | ReadBinaryNameCached(module_name.data(), module_name.size()); |
ef1b3fda | 544 | } else if (info->dlpi_name) { |
696d846a | 545 | module_name.append("%s", info->dlpi_name); |
ef1b3fda | 546 | } |
696d846a | 547 | if (module_name[0] == '\0') |
ef1b3fda | 548 | return 0; |
10189819 MO |
549 | LoadedModule cur_module; |
550 | cur_module.set(module_name.data(), info->dlpi_addr); | |
eac97531 | 551 | for (int i = 0; i < (int)info->dlpi_phnum; i++) { |
ef1b3fda KS |
552 | const Elf_Phdr *phdr = &info->dlpi_phdr[i]; |
553 | if (phdr->p_type == PT_LOAD) { | |
554 | uptr cur_beg = info->dlpi_addr + phdr->p_vaddr; | |
555 | uptr cur_end = cur_beg + phdr->p_memsz; | |
866e32ad | 556 | bool executable = phdr->p_flags & PF_X; |
5d3805fc JJ |
557 | bool writable = phdr->p_flags & PF_W; |
558 | cur_module.addAddressRange(cur_beg, cur_end, executable, | |
559 | writable); | |
ef1b3fda KS |
560 | } |
561 | } | |
10189819 | 562 | data->modules->push_back(cur_module); |
ef1b3fda KS |
563 | return 0; |
564 | } | |
565 | ||
696d846a MO |
566 | #if SANITIZER_ANDROID && __ANDROID_API__ < 21 |
567 | extern "C" __attribute__((weak)) int dl_iterate_phdr( | |
568 | int (*)(struct dl_phdr_info *, size_t, void *), void *); | |
569 | #endif | |
570 | ||
5d3805fc | 571 | static bool requiresProcmaps() { |
696d846a | 572 | #if SANITIZER_ANDROID && __ANDROID_API__ <= 22 |
696d846a MO |
573 | // Fall back to /proc/maps if dl_iterate_phdr is unavailable or broken. |
574 | // The runtime check allows the same library to work with | |
575 | // both K and L (and future) Android releases. | |
5d3805fc JJ |
576 | return AndroidGetApiLevel() <= ANDROID_LOLLIPOP_MR1; |
577 | #else | |
578 | return false; | |
696d846a | 579 | #endif |
5d3805fc JJ |
580 | } |
581 | ||
582 | static void procmapsInit(InternalMmapVectorNoCtor<LoadedModule> *modules) { | |
583 | MemoryMappingLayout memory_mapping(/*cache_enabled*/true); | |
584 | memory_mapping.DumpListOfModules(modules); | |
585 | } | |
586 | ||
587 | void ListOfModules::init() { | |
588 | clearOrInit(); | |
589 | if (requiresProcmaps()) { | |
590 | procmapsInit(&modules_); | |
591 | } else { | |
592 | DlIteratePhdrData data = {&modules_, true}; | |
593 | dl_iterate_phdr(dl_iterate_phdr_cb, &data); | |
594 | } | |
595 | } | |
596 | ||
597 | // When a custom loader is used, dl_iterate_phdr may not contain the full | |
598 | // list of modules. Allow callers to fall back to using procmaps. | |
599 | void ListOfModules::fallbackInit() { | |
600 | if (!requiresProcmaps()) { | |
601 | clearOrInit(); | |
602 | procmapsInit(&modules_); | |
603 | } else { | |
604 | clear(); | |
605 | } | |
ef1b3fda | 606 | } |
ef1b3fda | 607 | |
696d846a MO |
608 | // getrusage does not give us the current RSS, only the max RSS. |
609 | // Still, this is better than nothing if /proc/self/statm is not available | |
610 | // for some reason, e.g. due to a sandbox. | |
611 | static uptr GetRSSFromGetrusage() { | |
612 | struct rusage usage; | |
613 | if (getrusage(RUSAGE_SELF, &usage)) // Failed, probably due to a sandbox. | |
614 | return 0; | |
615 | return usage.ru_maxrss << 10; // ru_maxrss is in Kb. | |
616 | } | |
617 | ||
618 | uptr GetRSS() { | |
619 | if (!common_flags()->can_use_proc_maps_statm) | |
620 | return GetRSSFromGetrusage(); | |
621 | fd_t fd = OpenFile("/proc/self/statm", RdOnly); | |
622 | if (fd == kInvalidFd) | |
623 | return GetRSSFromGetrusage(); | |
624 | char buf[64]; | |
625 | uptr len = internal_read(fd, buf, sizeof(buf) - 1); | |
626 | internal_close(fd); | |
627 | if ((sptr)len <= 0) | |
628 | return 0; | |
629 | buf[len] = 0; | |
630 | // The format of the file is: | |
631 | // 1084 89 69 11 0 79 0 | |
632 | // We need the second number which is RSS in pages. | |
633 | char *pos = buf; | |
634 | // Skip the first number. | |
635 | while (*pos >= '0' && *pos <= '9') | |
636 | pos++; | |
637 | // Skip whitespaces. | |
638 | while (!(*pos >= '0' && *pos <= '9') && *pos != 0) | |
639 | pos++; | |
640 | // Read the number. | |
641 | uptr rss = 0; | |
642 | while (*pos >= '0' && *pos <= '9') | |
643 | rss = rss * 10 + *pos++ - '0'; | |
644 | return rss * GetPageSizeCached(); | |
645 | } | |
646 | ||
eac97531 ML |
647 | // sysconf(_SC_NPROCESSORS_{CONF,ONLN}) cannot be used on most platforms as |
648 | // they allocate memory. | |
649 | u32 GetNumberOfCPUs() { | |
650 | #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD | |
651 | u32 ncpu; | |
652 | int req[2]; | |
653 | uptr len = sizeof(ncpu); | |
654 | req[0] = CTL_HW; | |
655 | req[1] = HW_NCPU; | |
656 | CHECK_EQ(internal_sysctl(req, 2, &ncpu, &len, NULL, 0), 0); | |
657 | return ncpu; | |
658 | #elif SANITIZER_ANDROID && !defined(CPU_COUNT) && !defined(__aarch64__) | |
659 | // Fall back to /sys/devices/system/cpu on Android when cpu_set_t doesn't | |
660 | // exist in sched.h. That is the case for toolchains generated with older | |
661 | // NDKs. | |
662 | // This code doesn't work on AArch64 because internal_getdents makes use of | |
663 | // the 64bit getdents syscall, but cpu_set_t seems to always exist on AArch64. | |
664 | uptr fd = internal_open("/sys/devices/system/cpu", O_RDONLY | O_DIRECTORY); | |
665 | if (internal_iserror(fd)) | |
666 | return 0; | |
667 | InternalMmapVector<u8> buffer(4096); | |
668 | uptr bytes_read = buffer.size(); | |
669 | uptr n_cpus = 0; | |
670 | u8 *d_type; | |
671 | struct linux_dirent *entry = (struct linux_dirent *)&buffer[bytes_read]; | |
672 | while (true) { | |
673 | if ((u8 *)entry >= &buffer[bytes_read]) { | |
674 | bytes_read = internal_getdents(fd, (struct linux_dirent *)buffer.data(), | |
675 | buffer.size()); | |
676 | if (internal_iserror(bytes_read) || !bytes_read) | |
677 | break; | |
678 | entry = (struct linux_dirent *)buffer.data(); | |
679 | } | |
680 | d_type = (u8 *)entry + entry->d_reclen - 1; | |
681 | if (d_type >= &buffer[bytes_read] || | |
682 | (u8 *)&entry->d_name[3] >= &buffer[bytes_read]) | |
683 | break; | |
684 | if (entry->d_ino != 0 && *d_type == DT_DIR) { | |
685 | if (entry->d_name[0] == 'c' && entry->d_name[1] == 'p' && | |
686 | entry->d_name[2] == 'u' && | |
687 | entry->d_name[3] >= '0' && entry->d_name[3] <= '9') | |
688 | n_cpus++; | |
689 | } | |
690 | entry = (struct linux_dirent *)(((u8 *)entry) + entry->d_reclen); | |
691 | } | |
692 | internal_close(fd); | |
693 | return n_cpus; | |
694 | #elif SANITIZER_SOLARIS | |
695 | return sysconf(_SC_NPROCESSORS_ONLN); | |
696 | #else | |
697 | cpu_set_t CPUs; | |
698 | CHECK_EQ(sched_getaffinity(0, sizeof(cpu_set_t), &CPUs), 0); | |
699 | return CPU_COUNT(&CPUs); | |
700 | #endif | |
701 | } | |
702 | ||
696d846a MO |
703 | #if SANITIZER_LINUX |
704 | ||
eac97531 | 705 | # if SANITIZER_ANDROID |
696d846a | 706 | static atomic_uint8_t android_log_initialized; |
dee5ea7a | 707 | |
696d846a | 708 | void AndroidLogInit() { |
10189819 | 709 | openlog(GetProcessName(), 0, LOG_USER); |
696d846a | 710 | atomic_store(&android_log_initialized, 1, memory_order_release); |
dee5ea7a KS |
711 | } |
712 | ||
10189819 | 713 | static bool ShouldLogAfterPrintf() { |
696d846a MO |
714 | return atomic_load(&android_log_initialized, memory_order_acquire); |
715 | } | |
696d846a | 716 | |
eac97531 ML |
717 | extern "C" SANITIZER_WEAK_ATTRIBUTE |
718 | int async_safe_write_log(int pri, const char* tag, const char* msg); | |
719 | extern "C" SANITIZER_WEAK_ATTRIBUTE | |
720 | int __android_log_write(int prio, const char* tag, const char* msg); | |
696d846a | 721 | |
eac97531 ML |
722 | // ANDROID_LOG_INFO is 4, but can't be resolved at runtime. |
723 | #define SANITIZER_ANDROID_LOG_INFO 4 | |
724 | ||
725 | // async_safe_write_log is a new public version of __libc_write_log that is | |
726 | // used behind syslog. It is preferable to syslog as it will not do any dynamic | |
727 | // memory allocation or formatting. | |
728 | // If the function is not available, syslog is preferred for L+ (it was broken | |
729 | // pre-L) as __android_log_write triggers a racey behavior with the strncpy | |
730 | // interceptor. Fallback to __android_log_write pre-L. | |
10189819 | 731 | void WriteOneLineToSyslog(const char *s) { |
eac97531 ML |
732 | if (&async_safe_write_log) { |
733 | async_safe_write_log(SANITIZER_ANDROID_LOG_INFO, GetProcessName(), s); | |
734 | } else if (AndroidGetApiLevel() > ANDROID_KITKAT) { | |
735 | syslog(LOG_INFO, "%s", s); | |
736 | } else { | |
737 | CHECK(&__android_log_write); | |
738 | __android_log_write(SANITIZER_ANDROID_LOG_INFO, nullptr, s); | |
739 | } | |
866e32ad KS |
740 | } |
741 | ||
eac97531 ML |
742 | extern "C" SANITIZER_WEAK_ATTRIBUTE |
743 | void android_set_abort_message(const char *); | |
744 | ||
745 | void SetAbortMessage(const char *str) { | |
746 | if (&android_set_abort_message) | |
747 | android_set_abort_message(str); | |
748 | } | |
749 | # else | |
750 | void AndroidLogInit() {} | |
751 | ||
752 | static bool ShouldLogAfterPrintf() { return true; } | |
753 | ||
754 | void WriteOneLineToSyslog(const char *s) { syslog(LOG_INFO, "%s", s); } | |
755 | ||
756 | void SetAbortMessage(const char *str) {} | |
757 | # endif // SANITIZER_ANDROID | |
758 | ||
10189819 MO |
759 | void LogMessageOnPrintf(const char *str) { |
760 | if (common_flags()->log_to_syslog && ShouldLogAfterPrintf()) | |
761 | WriteToSyslog(str); | |
696d846a | 762 | } |
10189819 | 763 | |
eac97531 ML |
764 | #endif // SANITIZER_LINUX |
765 | ||
766 | #if SANITIZER_LINUX && !SANITIZER_GO | |
767 | // glibc crashes when using clock_gettime from a preinit_array function as the | |
768 | // vDSO function pointers haven't been initialized yet. __progname is | |
769 | // initialized after the vDSO function pointers, so if it exists, is not null | |
770 | // and is not empty, we can use clock_gettime. | |
771 | extern "C" SANITIZER_WEAK_ATTRIBUTE char *__progname; | |
772 | INLINE bool CanUseVDSO() { | |
773 | // Bionic is safe, it checks for the vDSO function pointers to be initialized. | |
774 | if (SANITIZER_ANDROID) | |
775 | return true; | |
776 | if (&__progname && __progname && *__progname) | |
777 | return true; | |
778 | return false; | |
5d3805fc | 779 | } |
5d3805fc | 780 | |
eac97531 ML |
781 | // MonotonicNanoTime is a timing function that can leverage the vDSO by calling |
782 | // clock_gettime. real_clock_gettime only exists if clock_gettime is | |
783 | // intercepted, so define it weakly and use it if available. | |
784 | extern "C" SANITIZER_WEAK_ATTRIBUTE | |
785 | int real_clock_gettime(u32 clk_id, void *tp); | |
786 | u64 MonotonicNanoTime() { | |
787 | timespec ts; | |
788 | if (CanUseVDSO()) { | |
789 | if (&real_clock_gettime) | |
790 | real_clock_gettime(CLOCK_MONOTONIC, &ts); | |
791 | else | |
792 | clock_gettime(CLOCK_MONOTONIC, &ts); | |
793 | } else { | |
794 | internal_clock_gettime(CLOCK_MONOTONIC, &ts); | |
795 | } | |
796 | return (u64)ts.tv_sec * (1000ULL * 1000 * 1000) + ts.tv_nsec; | |
797 | } | |
798 | #else | |
799 | // Non-Linux & Go always use the syscall. | |
800 | u64 MonotonicNanoTime() { | |
801 | timespec ts; | |
802 | internal_clock_gettime(CLOCK_MONOTONIC, &ts); | |
803 | return (u64)ts.tv_sec * (1000ULL * 1000 * 1000) + ts.tv_nsec; | |
804 | } | |
805 | #endif // SANITIZER_LINUX && !SANITIZER_GO | |
696d846a MO |
806 | |
807 | } // namespace __sanitizer | |
ef1b3fda | 808 | |
eac97531 | 809 | #endif |