1 //===-- asan_interceptors.cc ----------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of AddressSanitizer, an address sanity checker.
10 // Intercept various libc functions.
11 //===----------------------------------------------------------------------===//
12 #include "asan_interceptors.h"
14 #include "asan_allocator.h"
15 #include "asan_intercepted_functions.h"
16 #include "asan_internal.h"
17 #include "asan_mapping.h"
18 #include "asan_report.h"
19 #include "asan_stack.h"
20 #include "asan_stats.h"
21 #include "asan_thread_registry.h"
22 #include "interception/interception.h"
23 #include "sanitizer/asan_interface.h"
24 #include "sanitizer_common/sanitizer_libc.h"
28 // Instruments read/write access to a single byte in memory.
29 // On error calls __asan_report_error, which aborts the program.
30 #define ACCESS_ADDRESS(address, isWrite) do { \
31 if (!AddrIsInMem(address) || AddressIsPoisoned(address)) { \
32 GET_CURRENT_PC_BP_SP; \
33 __asan_report_error(pc, bp, sp, address, isWrite, /* access_size */ 1); \
37 // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
38 // and ASAN_WRITE_RANGE as macro instead of function so
39 // that no extra frames are created, and stack trace contains
40 // relevant information only.
42 // Instruments read/write access to a memory range.
43 // More complex implementation is possible, for now just
44 // checking the first and the last byte of a range.
45 #define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
47 uptr ptr = (uptr)(offset); \
48 ACCESS_ADDRESS(ptr, isWrite); \
49 ACCESS_ADDRESS(ptr + (size) - 1, isWrite); \
53 #define ASAN_READ_RANGE(offset, size) do { \
54 ACCESS_MEMORY_RANGE(offset, size, false); \
57 #define ASAN_WRITE_RANGE(offset, size) do { \
58 ACCESS_MEMORY_RANGE(offset, size, true); \
61 // Behavior of functions like "memcpy" or "strcpy" is undefined
62 // if memory intervals overlap. We report error in this case.
63 // Macro is used to avoid creation of new frames.
64 static inline bool RangesOverlap(const char *offset1
, uptr length1
,
65 const char *offset2
, uptr length2
) {
66 return !((offset1
+ length1
<= offset2
) || (offset2
+ length2
<= offset1
));
68 #define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
69 const char *offset1 = (const char*)_offset1; \
70 const char *offset2 = (const char*)_offset2; \
71 if (RangesOverlap(offset1, length1, offset2, length2)) { \
72 GET_STACK_TRACE_HERE(kStackTraceMax); \
73 ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
74 offset2, length2, &stack); \
78 #define ENSURE_ASAN_INITED() do { \
79 CHECK(!asan_init_is_running); \
85 static inline uptr
MaybeRealStrnlen(const char *s
, uptr maxlen
) {
86 #if ASAN_INTERCEPT_STRNLEN
87 if (REAL(strnlen
) != 0) {
88 return REAL(strnlen
)(s
, maxlen
);
91 return internal_strnlen(s
, maxlen
);
96 // ---------------------- Wrappers ---------------- {{{1
97 using namespace __asan
; // NOLINT
99 static thread_return_t THREAD_CALLING_CONV
asan_thread_start(void *arg
) {
100 AsanThread
*t
= (AsanThread
*)arg
;
101 asanThreadRegistry().SetCurrent(t
);
102 return t
->ThreadStart();
105 #if ASAN_INTERCEPT_PTHREAD_CREATE
106 INTERCEPTOR(int, pthread_create
, void *thread
,
107 void *attr
, void *(*start_routine
)(void*), void *arg
) {
108 GET_STACK_TRACE_HERE(kStackTraceMax
);
109 u32 current_tid
= asanThreadRegistry().GetCurrentTidOrInvalid();
110 AsanThread
*t
= AsanThread::Create(current_tid
, start_routine
, arg
, &stack
);
111 asanThreadRegistry().RegisterThread(t
);
112 return REAL(pthread_create
)(thread
, attr
, asan_thread_start
, t
);
114 #endif // ASAN_INTERCEPT_PTHREAD_CREATE
116 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
117 INTERCEPTOR(void*, signal
, int signum
, void *handler
) {
118 if (!AsanInterceptsSignal(signum
)) {
119 return REAL(signal
)(signum
, handler
);
124 INTERCEPTOR(int, sigaction
, int signum
, const struct sigaction
*act
,
125 struct sigaction
*oldact
) {
126 if (!AsanInterceptsSignal(signum
)) {
127 return REAL(sigaction
)(signum
, act
, oldact
);
132 // We need to have defined REAL(sigaction) on posix systems.
133 DEFINE_REAL(int, sigaction
, int signum
, const struct sigaction
*act
,
134 struct sigaction
*oldact
);
135 #endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
137 #if ASAN_INTERCEPT_SWAPCONTEXT
138 INTERCEPTOR(int, swapcontext
, struct ucontext_t
*oucp
,
139 struct ucontext_t
*ucp
) {
140 static bool reported_warning
= false;
141 if (!reported_warning
) {
142 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
143 "functions and may produce false positives in some cases!\n");
144 reported_warning
= true;
146 // Clear shadow memory for new context (it may share stack
147 // with current context).
148 ClearShadowMemoryForContext(ucp
);
149 int res
= REAL(swapcontext
)(oucp
, ucp
);
150 // swapcontext technically does not return, but program may swap context to
151 // "oucp" later, that would look as if swapcontext() returned 0.
152 // We need to clear shadow for ucp once again, as it may be in arbitrary
154 ClearShadowMemoryForContext(ucp
);
159 INTERCEPTOR(void, longjmp
, void *env
, int val
) {
160 __asan_handle_no_return();
161 REAL(longjmp
)(env
, val
);
164 #if ASAN_INTERCEPT__LONGJMP
165 INTERCEPTOR(void, _longjmp
, void *env
, int val
) {
166 __asan_handle_no_return();
167 REAL(_longjmp
)(env
, val
);
171 #if ASAN_INTERCEPT_SIGLONGJMP
172 INTERCEPTOR(void, siglongjmp
, void *env
, int val
) {
173 __asan_handle_no_return();
174 REAL(siglongjmp
)(env
, val
);
178 #if ASAN_INTERCEPT___CXA_THROW
179 INTERCEPTOR(void, __cxa_throw
, void *a
, void *b
, void *c
) {
180 CHECK(REAL(__cxa_throw
));
181 __asan_handle_no_return();
182 REAL(__cxa_throw
)(a
, b
, c
);
186 // intercept mlock and friends.
187 // Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
188 // All functions return 0 (success).
189 static void MlockIsUnsupported() {
190 static bool printed
= 0;
193 Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n");
197 INTERCEPTOR(int, mlock
, const void *addr
, uptr len
) {
198 MlockIsUnsupported();
202 INTERCEPTOR(int, munlock
, const void *addr
, uptr len
) {
203 MlockIsUnsupported();
207 INTERCEPTOR(int, mlockall
, int flags
) {
208 MlockIsUnsupported();
212 INTERCEPTOR(int, munlockall
, void) {
213 MlockIsUnsupported();
218 static inline int CharCmp(unsigned char c1
, unsigned char c2
) {
219 return (c1
== c2
) ? 0 : (c1
< c2
) ? -1 : 1;
222 static inline int CharCaseCmp(unsigned char c1
, unsigned char c2
) {
223 int c1_low
= ToLower(c1
);
224 int c2_low
= ToLower(c2
);
225 return c1_low
- c2_low
;
228 INTERCEPTOR(int, memcmp
, const void *a1
, const void *a2
, uptr size
) {
229 if (!asan_inited
) return internal_memcmp(a1
, a2
, size
);
230 ENSURE_ASAN_INITED();
231 unsigned char c1
= 0, c2
= 0;
232 const unsigned char *s1
= (const unsigned char*)a1
;
233 const unsigned char *s2
= (const unsigned char*)a2
;
235 for (i
= 0; i
< size
; i
++) {
240 ASAN_READ_RANGE(s1
, Min(i
+ 1, size
));
241 ASAN_READ_RANGE(s2
, Min(i
+ 1, size
));
242 return CharCmp(c1
, c2
);
245 INTERCEPTOR(void*, memcpy
, void *to
, const void *from
, uptr size
) {
246 if (!asan_inited
) return internal_memcpy(to
, from
, size
);
247 // memcpy is called during __asan_init() from the internals
249 if (asan_init_is_running
) {
250 return REAL(memcpy
)(to
, from
, size
);
252 ENSURE_ASAN_INITED();
253 if (flags()->replace_intrin
) {
255 // We do not treat memcpy with to==from as a bug.
256 // See http://llvm.org/bugs/show_bug.cgi?id=11763.
257 CHECK_RANGES_OVERLAP("memcpy", to
, size
, from
, size
);
259 ASAN_WRITE_RANGE(from
, size
);
260 ASAN_READ_RANGE(to
, size
);
262 #if MAC_INTERPOSE_FUNCTIONS
263 // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
264 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
265 return internal_memcpy(to
, from
, size
);
267 return REAL(memcpy
)(to
, from
, size
);
271 INTERCEPTOR(void*, memmove
, void *to
, const void *from
, uptr size
) {
272 if (!asan_inited
) return internal_memmove(to
, from
, size
);
273 if (asan_init_is_running
) {
274 return REAL(memmove
)(to
, from
, size
);
276 ENSURE_ASAN_INITED();
277 if (flags()->replace_intrin
) {
278 ASAN_WRITE_RANGE(from
, size
);
279 ASAN_READ_RANGE(to
, size
);
281 #if MAC_INTERPOSE_FUNCTIONS
282 // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
283 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
284 return internal_memmove(to
, from
, size
);
286 return REAL(memmove
)(to
, from
, size
);
290 INTERCEPTOR(void*, memset
, void *block
, int c
, uptr size
) {
291 if (!asan_inited
) return internal_memset(block
, c
, size
);
292 // memset is called inside Printf.
293 if (asan_init_is_running
) {
294 return REAL(memset
)(block
, c
, size
);
296 ENSURE_ASAN_INITED();
297 if (flags()->replace_intrin
) {
298 ASAN_WRITE_RANGE(block
, size
);
300 return REAL(memset
)(block
, c
, size
);
303 INTERCEPTOR(char*, strchr
, const char *str
, int c
) {
304 if (!asan_inited
) return internal_strchr(str
, c
);
305 // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
307 if (asan_init_is_running
) {
308 return REAL(strchr
)(str
, c
);
310 ENSURE_ASAN_INITED();
311 char *result
= REAL(strchr
)(str
, c
);
312 if (flags()->replace_str
) {
313 uptr bytes_read
= (result
? result
- str
: REAL(strlen
)(str
)) + 1;
314 ASAN_READ_RANGE(str
, bytes_read
);
319 #if ASAN_INTERCEPT_INDEX
320 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
321 INTERCEPTOR(char*, index
, const char *string
, int c
)
322 ALIAS(WRAPPER_NAME(strchr
));
324 DEFINE_REAL(char*, index
, const char *string
, int c
)
326 #endif // ASAN_INTERCEPT_INDEX
328 // For both strcat() and strncat() we need to check the validity of |to|
329 // argument irrespective of the |from| length.
330 INTERCEPTOR(char*, strcat
, char *to
, const char *from
) { // NOLINT
331 ENSURE_ASAN_INITED();
332 if (flags()->replace_str
) {
333 uptr from_length
= REAL(strlen
)(from
);
334 ASAN_READ_RANGE(from
, from_length
+ 1);
335 uptr to_length
= REAL(strlen
)(to
);
336 ASAN_READ_RANGE(to
, to_length
);
337 ASAN_WRITE_RANGE(to
+ to_length
, from_length
+ 1);
338 // If the copying actually happens, the |from| string should not overlap
339 // with the resulting string starting at |to|, which has a length of
340 // to_length + from_length + 1.
341 if (from_length
> 0) {
342 CHECK_RANGES_OVERLAP("strcat", to
, from_length
+ to_length
+ 1,
343 from
, from_length
+ 1);
346 return REAL(strcat
)(to
, from
); // NOLINT
349 INTERCEPTOR(char*, strncat
, char *to
, const char *from
, uptr size
) {
350 ENSURE_ASAN_INITED();
351 if (flags()->replace_str
) {
352 uptr from_length
= MaybeRealStrnlen(from
, size
);
353 uptr copy_length
= Min(size
, from_length
+ 1);
354 ASAN_READ_RANGE(from
, copy_length
);
355 uptr to_length
= REAL(strlen
)(to
);
356 ASAN_READ_RANGE(to
, to_length
);
357 ASAN_WRITE_RANGE(to
+ to_length
, from_length
+ 1);
358 if (from_length
> 0) {
359 CHECK_RANGES_OVERLAP("strncat", to
, to_length
+ copy_length
+ 1,
363 return REAL(strncat
)(to
, from
, size
);
366 INTERCEPTOR(int, strcmp
, const char *s1
, const char *s2
) {
367 if (!asan_inited
) return internal_strcmp(s1
, s2
);
368 if (asan_init_is_running
) {
369 return REAL(strcmp
)(s1
, s2
);
371 ENSURE_ASAN_INITED();
372 unsigned char c1
, c2
;
375 c1
= (unsigned char)s1
[i
];
376 c2
= (unsigned char)s2
[i
];
377 if (c1
!= c2
|| c1
== '\0') break;
379 ASAN_READ_RANGE(s1
, i
+ 1);
380 ASAN_READ_RANGE(s2
, i
+ 1);
381 return CharCmp(c1
, c2
);
384 INTERCEPTOR(char*, strcpy
, char *to
, const char *from
) { // NOLINT
385 #if MAC_INTERPOSE_FUNCTIONS
386 if (!asan_inited
) return REAL(strcpy
)(to
, from
); // NOLINT
388 // strcpy is called from malloc_default_purgeable_zone()
389 // in __asan::ReplaceSystemAlloc() on Mac.
390 if (asan_init_is_running
) {
391 return REAL(strcpy
)(to
, from
); // NOLINT
393 ENSURE_ASAN_INITED();
394 if (flags()->replace_str
) {
395 uptr from_size
= REAL(strlen
)(from
) + 1;
396 CHECK_RANGES_OVERLAP("strcpy", to
, from_size
, from
, from_size
);
397 ASAN_READ_RANGE(from
, from_size
);
398 ASAN_WRITE_RANGE(to
, from_size
);
400 return REAL(strcpy
)(to
, from
); // NOLINT
403 #if ASAN_INTERCEPT_STRDUP
404 INTERCEPTOR(char*, strdup
, const char *s
) {
405 #if MAC_INTERPOSE_FUNCTIONS
406 // FIXME: because internal_strdup() uses InternalAlloc(), which currently
407 // just calls malloc() on Mac, we can't use internal_strdup() with the
408 // dynamic runtime. We can remove the call to REAL(strdup) once InternalAlloc
409 // starts using mmap() instead.
410 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=123.
411 if (!asan_inited
) return REAL(strdup
)(s
);
413 if (!asan_inited
) return internal_strdup(s
);
414 ENSURE_ASAN_INITED();
415 if (flags()->replace_str
) {
416 uptr length
= REAL(strlen
)(s
);
417 ASAN_READ_RANGE(s
, length
+ 1);
419 return REAL(strdup
)(s
);
423 INTERCEPTOR(uptr
, strlen
, const char *s
) {
424 if (!asan_inited
) return internal_strlen(s
);
425 // strlen is called from malloc_default_purgeable_zone()
426 // in __asan::ReplaceSystemAlloc() on Mac.
427 if (asan_init_is_running
) {
428 return REAL(strlen
)(s
);
430 ENSURE_ASAN_INITED();
431 uptr length
= REAL(strlen
)(s
);
432 if (flags()->replace_str
) {
433 ASAN_READ_RANGE(s
, length
+ 1);
438 #if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
439 INTERCEPTOR(int, strcasecmp
, const char *s1
, const char *s2
) {
440 ENSURE_ASAN_INITED();
441 unsigned char c1
, c2
;
444 c1
= (unsigned char)s1
[i
];
445 c2
= (unsigned char)s2
[i
];
446 if (CharCaseCmp(c1
, c2
) != 0 || c1
== '\0') break;
448 ASAN_READ_RANGE(s1
, i
+ 1);
449 ASAN_READ_RANGE(s2
, i
+ 1);
450 return CharCaseCmp(c1
, c2
);
453 INTERCEPTOR(int, strncasecmp
, const char *s1
, const char *s2
, uptr n
) {
454 ENSURE_ASAN_INITED();
455 unsigned char c1
= 0, c2
= 0;
457 for (i
= 0; i
< n
; i
++) {
458 c1
= (unsigned char)s1
[i
];
459 c2
= (unsigned char)s2
[i
];
460 if (CharCaseCmp(c1
, c2
) != 0 || c1
== '\0') break;
462 ASAN_READ_RANGE(s1
, Min(i
+ 1, n
));
463 ASAN_READ_RANGE(s2
, Min(i
+ 1, n
));
464 return CharCaseCmp(c1
, c2
);
466 #endif // ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
468 INTERCEPTOR(int, strncmp
, const char *s1
, const char *s2
, uptr size
) {
469 if (!asan_inited
) return internal_strncmp(s1
, s2
, size
);
470 // strncmp is called from malloc_default_purgeable_zone()
471 // in __asan::ReplaceSystemAlloc() on Mac.
472 if (asan_init_is_running
) {
473 return REAL(strncmp
)(s1
, s2
, size
);
475 ENSURE_ASAN_INITED();
476 unsigned char c1
= 0, c2
= 0;
478 for (i
= 0; i
< size
; i
++) {
479 c1
= (unsigned char)s1
[i
];
480 c2
= (unsigned char)s2
[i
];
481 if (c1
!= c2
|| c1
== '\0') break;
483 ASAN_READ_RANGE(s1
, Min(i
+ 1, size
));
484 ASAN_READ_RANGE(s2
, Min(i
+ 1, size
));
485 return CharCmp(c1
, c2
);
488 INTERCEPTOR(char*, strncpy
, char *to
, const char *from
, uptr size
) {
489 ENSURE_ASAN_INITED();
490 if (flags()->replace_str
) {
491 uptr from_size
= Min(size
, MaybeRealStrnlen(from
, size
) + 1);
492 CHECK_RANGES_OVERLAP("strncpy", to
, from_size
, from
, from_size
);
493 ASAN_READ_RANGE(from
, from_size
);
494 ASAN_WRITE_RANGE(to
, size
);
496 return REAL(strncpy
)(to
, from
, size
);
499 #if ASAN_INTERCEPT_STRNLEN
500 INTERCEPTOR(uptr
, strnlen
, const char *s
, uptr maxlen
) {
501 ENSURE_ASAN_INITED();
502 uptr length
= REAL(strnlen
)(s
, maxlen
);
503 if (flags()->replace_str
) {
504 ASAN_READ_RANGE(s
, Min(length
+ 1, maxlen
));
508 #endif // ASAN_INTERCEPT_STRNLEN
510 static inline bool IsValidStrtolBase(int base
) {
511 return (base
== 0) || (2 <= base
&& base
<= 36);
514 static inline void FixRealStrtolEndptr(const char *nptr
, char **endptr
) {
516 if (nptr
== *endptr
) {
517 // No digits were found at strtol call, we need to find out the last
518 // symbol accessed by strtoll on our own.
519 // We get this symbol by skipping leading blanks and optional +/- sign.
520 while (IsSpace(*nptr
)) nptr
++;
521 if (*nptr
== '+' || *nptr
== '-') nptr
++;
522 *endptr
= (char*)nptr
;
524 CHECK(*endptr
>= nptr
);
527 INTERCEPTOR(long, strtol
, const char *nptr
, // NOLINT
528 char **endptr
, int base
) {
529 ENSURE_ASAN_INITED();
530 if (!flags()->replace_str
) {
531 return REAL(strtol
)(nptr
, endptr
, base
);
534 long result
= REAL(strtol
)(nptr
, &real_endptr
, base
); // NOLINT
536 *endptr
= real_endptr
;
538 if (IsValidStrtolBase(base
)) {
539 FixRealStrtolEndptr(nptr
, &real_endptr
);
540 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
545 INTERCEPTOR(int, atoi
, const char *nptr
) {
546 #if MAC_INTERPOSE_FUNCTIONS
547 if (!asan_inited
) return REAL(atoi
)(nptr
);
549 ENSURE_ASAN_INITED();
550 if (!flags()->replace_str
) {
551 return REAL(atoi
)(nptr
);
554 // "man atoi" tells that behavior of atoi(nptr) is the same as
555 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
556 // parsed integer can't be stored in *long* type (even if it's
557 // different from int). So, we just imitate this behavior.
558 int result
= REAL(strtol
)(nptr
, &real_endptr
, 10);
559 FixRealStrtolEndptr(nptr
, &real_endptr
);
560 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
564 INTERCEPTOR(long, atol
, const char *nptr
) { // NOLINT
565 #if MAC_INTERPOSE_FUNCTIONS
566 if (!asan_inited
) return REAL(atol
)(nptr
);
568 ENSURE_ASAN_INITED();
569 if (!flags()->replace_str
) {
570 return REAL(atol
)(nptr
);
573 long result
= REAL(strtol
)(nptr
, &real_endptr
, 10); // NOLINT
574 FixRealStrtolEndptr(nptr
, &real_endptr
);
575 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
579 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
580 INTERCEPTOR(long long, strtoll
, const char *nptr
, // NOLINT
581 char **endptr
, int base
) {
582 ENSURE_ASAN_INITED();
583 if (!flags()->replace_str
) {
584 return REAL(strtoll
)(nptr
, endptr
, base
);
587 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, base
); // NOLINT
589 *endptr
= real_endptr
;
591 // If base has unsupported value, strtoll can exit with EINVAL
592 // without reading any characters. So do additional checks only
594 if (IsValidStrtolBase(base
)) {
595 FixRealStrtolEndptr(nptr
, &real_endptr
);
596 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
601 INTERCEPTOR(long long, atoll
, const char *nptr
) { // NOLINT
602 ENSURE_ASAN_INITED();
603 if (!flags()->replace_str
) {
604 return REAL(atoll
)(nptr
);
607 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, 10); // NOLINT
608 FixRealStrtolEndptr(nptr
, &real_endptr
);
609 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
612 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
614 #define ASAN_INTERCEPT_FUNC(name) do { \
615 if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \
616 Report("AddressSanitizer: failed to intercept '" #name "'\n"); \
620 INTERCEPTOR_WINAPI(DWORD
, CreateThread
,
621 void* security
, uptr stack_size
,
622 DWORD (__stdcall
*start_routine
)(void*), void* arg
,
623 DWORD flags
, void* tid
) {
624 GET_STACK_TRACE_HERE(kStackTraceMax
);
625 u32 current_tid
= asanThreadRegistry().GetCurrentTidOrInvalid();
626 AsanThread
*t
= AsanThread::Create(current_tid
, start_routine
, arg
, &stack
);
627 asanThreadRegistry().RegisterThread(t
);
628 return REAL(CreateThread
)(security
, stack_size
,
629 asan_thread_start
, t
, flags
, tid
);
633 void InitializeWindowsInterceptors() {
634 ASAN_INTERCEPT_FUNC(CreateThread
);
637 } // namespace __asan
640 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
642 void InitializeAsanInterceptors() {
643 static bool was_called_once
;
644 CHECK(was_called_once
== false);
645 was_called_once
= true;
646 #if MAC_INTERPOSE_FUNCTIONS
649 // Intercept mem* functions.
650 ASAN_INTERCEPT_FUNC(memcmp
);
651 ASAN_INTERCEPT_FUNC(memmove
);
652 ASAN_INTERCEPT_FUNC(memset
);
653 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE
) {
654 ASAN_INTERCEPT_FUNC(memcpy
);
656 #if !MAC_INTERPOSE_FUNCTIONS
657 // If we're using dynamic interceptors on Mac, these two are just plain
659 internal_memcpy(&REAL(memcpy
), &REAL(memmove
), sizeof(REAL(memmove
)));
663 // Intercept str* functions.
664 ASAN_INTERCEPT_FUNC(strcat
); // NOLINT
665 ASAN_INTERCEPT_FUNC(strchr
);
666 ASAN_INTERCEPT_FUNC(strcmp
);
667 ASAN_INTERCEPT_FUNC(strcpy
); // NOLINT
668 ASAN_INTERCEPT_FUNC(strlen
);
669 ASAN_INTERCEPT_FUNC(strncat
);
670 ASAN_INTERCEPT_FUNC(strncmp
);
671 ASAN_INTERCEPT_FUNC(strncpy
);
672 #if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
673 ASAN_INTERCEPT_FUNC(strcasecmp
);
674 ASAN_INTERCEPT_FUNC(strncasecmp
);
676 #if ASAN_INTERCEPT_STRDUP
677 ASAN_INTERCEPT_FUNC(strdup
);
679 #if ASAN_INTERCEPT_STRNLEN
680 ASAN_INTERCEPT_FUNC(strnlen
);
682 #if ASAN_INTERCEPT_INDEX
683 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
684 ASAN_INTERCEPT_FUNC(index
);
686 CHECK(OVERRIDE_FUNCTION(index
, WRAP(strchr
)));
690 ASAN_INTERCEPT_FUNC(atoi
);
691 ASAN_INTERCEPT_FUNC(atol
);
692 ASAN_INTERCEPT_FUNC(strtol
);
693 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
694 ASAN_INTERCEPT_FUNC(atoll
);
695 ASAN_INTERCEPT_FUNC(strtoll
);
698 #if ASAN_INTERCEPT_MLOCKX
699 // Intercept mlock/munlock.
700 ASAN_INTERCEPT_FUNC(mlock
);
701 ASAN_INTERCEPT_FUNC(munlock
);
702 ASAN_INTERCEPT_FUNC(mlockall
);
703 ASAN_INTERCEPT_FUNC(munlockall
);
706 // Intecept signal- and jump-related functions.
707 ASAN_INTERCEPT_FUNC(longjmp
);
708 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
709 ASAN_INTERCEPT_FUNC(sigaction
);
710 ASAN_INTERCEPT_FUNC(signal
);
712 #if ASAN_INTERCEPT_SWAPCONTEXT
713 ASAN_INTERCEPT_FUNC(swapcontext
);
715 #if ASAN_INTERCEPT__LONGJMP
716 ASAN_INTERCEPT_FUNC(_longjmp
);
718 #if ASAN_INTERCEPT_SIGLONGJMP
719 ASAN_INTERCEPT_FUNC(siglongjmp
);
722 // Intercept exception handling functions.
723 #if ASAN_INTERCEPT___CXA_THROW
724 INTERCEPT_FUNCTION(__cxa_throw
);
727 // Intercept threading-related functions
728 #if ASAN_INTERCEPT_PTHREAD_CREATE
729 ASAN_INTERCEPT_FUNC(pthread_create
);
732 // Some Windows-specific interceptors.
734 InitializeWindowsInterceptors();
737 // Some Mac-specific interceptors.
738 #if defined(__APPLE__)
739 InitializeMacInterceptors();
742 if (flags()->verbosity
> 0) {
743 Report("AddressSanitizer: libc interceptors initialized\n");
747 } // namespace __asan