Index: projects/clang390-import/contrib/compiler-rt/LICENSE.TXT =================================================================== --- projects/clang390-import/contrib/compiler-rt/LICENSE.TXT (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/LICENSE.TXT (revision 305364) @@ -1,91 +1,91 @@ ============================================================================== compiler_rt License ============================================================================== The compiler_rt library is dual licensed under both the University of Illinois "BSD-Like" license and the MIT license. As a user of this code you may choose to use it under either license. As a contributor, you agree to allow your code to be used under both. Full text of the relevant licenses is included below. ============================================================================== University of Illinois/NCSA Open Source License -Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT +Copyright (c) 2009-2016 by the contributors listed in CREDITS.TXT All rights reserved. Developed by: LLVM Team University of Illinois at Urbana-Champaign http://llvm.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. * Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. ============================================================================== Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ============================================================================== Copyrights and Licenses for Third Party Software Distributed with LLVM: ============================================================================== The LLVM software contains code written by third parties. Such software will have its own individual LICENSE.TXT file in the directory in which it appears. This file will describe the copyrights, license, and restrictions which apply to that code. The disclaimer of warranty in the University of Illinois Open Source License applies to all code in the LLVM Distribution, and nothing in any of the other licenses gives permission to use the names of the LLVM Team or the University of Illinois to endorse or promote products derived from this Software. Index: projects/clang390-import/contrib/compiler-rt/include/sanitizer/allocator_interface.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/include/sanitizer/allocator_interface.h (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/include/sanitizer/allocator_interface.h (revision 305364) @@ -1,66 +1,83 @@ //===-- allocator_interface.h ---------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Public interface header for allocator used in sanitizers (ASan/TSan/MSan). //===----------------------------------------------------------------------===// #ifndef SANITIZER_ALLOCATOR_INTERFACE_H #define SANITIZER_ALLOCATOR_INTERFACE_H #include #ifdef __cplusplus extern "C" { #endif /* Returns the estimated number of bytes that will be reserved by allocator for request of "size" bytes. If allocator can't allocate that much memory, returns the maximal possible allocation size, otherwise returns "size". */ size_t __sanitizer_get_estimated_allocated_size(size_t size); /* Returns true if p was returned by the allocator and is not yet freed. */ int __sanitizer_get_ownership(const volatile void *p); /* Returns the number of bytes reserved for the pointer p. Requires (get_ownership(p) == true) or (p == 0). */ size_t __sanitizer_get_allocated_size(const volatile void *p); /* Number of bytes, allocated and not yet freed by the application. */ size_t __sanitizer_get_current_allocated_bytes(); /* Number of bytes, mmaped by the allocator to fulfill allocation requests. Generally, for request of X bytes, allocator can reserve and add to free lists a large number of chunks of size X to use them for future requests. All these chunks count toward the heap size. Currently, allocator never releases memory to OS (instead, it just puts freed chunks to free lists). */ size_t __sanitizer_get_heap_size(); /* Number of bytes, mmaped by the allocator, which can be used to fulfill allocation requests. When a user program frees memory chunk, it can first fall into quarantine and will count toward __sanitizer_get_free_bytes() later. */ size_t __sanitizer_get_free_bytes(); /* Number of bytes in unmapped pages, that are released to OS. Currently, always returns 0. */ size_t __sanitizer_get_unmapped_bytes(); /* Malloc hooks that may be optionally provided by user. __sanitizer_malloc_hook(ptr, size) is called immediately after allocation of "size" bytes, which returned "ptr". __sanitizer_free_hook(ptr) is called immediately before deallocation of "ptr". */ void __sanitizer_malloc_hook(const volatile void *ptr, size_t size); void __sanitizer_free_hook(const volatile void *ptr); + + /* Installs a pair of hooks for malloc/free. + Several (currently, 5) hook pairs may be installed, they are executed + in the order they were installed and after calling + __sanitizer_malloc_hook/__sanitizer_free_hook. + Unlike __sanitizer_malloc_hook/__sanitizer_free_hook these hooks can be + chained and do not rely on weak symbols working on the platform, but + require __sanitizer_install_malloc_and_free_hooks to be called at startup + and thus will not be called on malloc/free very early in the process. + Returns the number of hooks currently installed or 0 on failure. + Not thread-safe, should be called in the main thread before starting + other threads. + */ + int __sanitizer_install_malloc_and_free_hooks( + void (*malloc_hook)(const volatile void *, size_t), + void (*free_hook)(const volatile void *)); + #ifdef __cplusplus } // extern "C" #endif #endif Index: projects/clang390-import/contrib/compiler-rt/include/sanitizer/common_interface_defs.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/include/sanitizer/common_interface_defs.h (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/include/sanitizer/common_interface_defs.h (revision 305364) @@ -1,137 +1,177 @@ //===-- sanitizer/common_interface_defs.h -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Common part of the public sanitizer interface. //===----------------------------------------------------------------------===// #ifndef SANITIZER_COMMON_INTERFACE_DEFS_H #define SANITIZER_COMMON_INTERFACE_DEFS_H #include #include // GCC does not understand __has_feature. #if !defined(__has_feature) # define __has_feature(x) 0 #endif #ifdef __cplusplus extern "C" { #endif // Arguments for __sanitizer_sandbox_on_notify() below. typedef struct { // Enable sandbox support in sanitizer coverage. int coverage_sandboxed; // File descriptor to write coverage data to. If -1 is passed, a file will // be pre-opened by __sanitizer_sandobx_on_notify(). This field has no // effect if coverage_sandboxed == 0. intptr_t coverage_fd; // If non-zero, split the coverage data into well-formed blocks. This is // useful when coverage_fd is a socket descriptor. Each block will contain // a header, allowing data from multiple processes to be sent over the same // socket. unsigned int coverage_max_block_size; } __sanitizer_sandbox_arguments; // Tell the tools to write their reports to "path." instead of stderr. void __sanitizer_set_report_path(const char *path); + // Tell the tools to write their reports to the provided file descriptor + // (casted to void *). + void __sanitizer_set_report_fd(void *fd); // Notify the tools that the sandbox is going to be turned on. The reserved // parameter will be used in the future to hold a structure with functions // that the tools may call to bypass the sandbox. void __sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args); // This function is called by the tool when it has just finished reporting // an error. 'error_summary' is a one-line string that summarizes // the error message. This function can be overridden by the client. void __sanitizer_report_error_summary(const char *error_summary); // Some of the sanitizers (e.g. asan/tsan) may miss bugs that happen // in unaligned loads/stores. In order to find such bugs reliably one needs // to replace plain unaligned loads/stores with these calls. uint16_t __sanitizer_unaligned_load16(const void *p); uint32_t __sanitizer_unaligned_load32(const void *p); uint64_t __sanitizer_unaligned_load64(const void *p); void __sanitizer_unaligned_store16(void *p, uint16_t x); void __sanitizer_unaligned_store32(void *p, uint32_t x); void __sanitizer_unaligned_store64(void *p, uint64_t x); // Annotate the current state of a contiguous container, such as // std::vector, std::string or similar. // A contiguous container is a container that keeps all of its elements // in a contiguous region of memory. The container owns the region of memory // [beg, end); the memory [beg, mid) is used to store the current elements // and the memory [mid, end) is reserved for future elements; // beg <= mid <= end. For example, in "std::vector<> v" // beg = &v[0]; // end = beg + v.capacity() * sizeof(v[0]); // mid = beg + v.size() * sizeof(v[0]); // // This annotation tells the Sanitizer tool about the current state of the // container so that the tool can report errors when memory from [mid, end) // is accessed. Insert this annotation into methods like push_back/pop_back. // Supply the old and the new values of mid (old_mid/new_mid). // In the initial state mid == end and so should be the final // state when the container is destroyed or when it reallocates the storage. // // Use with caution and don't use for anything other than vector-like classes. // // For AddressSanitizer, 'beg' should be 8-aligned and 'end' should // be either 8-aligned or it should point to the end of a separate heap-, // stack-, or global- allocated buffer. I.e. the following will not work: // int64_t x[2]; // 16 bytes, 8-aligned. // char *beg = (char *)&x[0]; // char *end = beg + 12; // Not 8 aligned, not the end of the buffer. // This however will work fine: // int32_t x[3]; // 12 bytes, but 8-aligned under AddressSanitizer. // char *beg = (char*)&x[0]; // char *end = beg + 12; // Not 8-aligned, but is the end of the buffer. void __sanitizer_annotate_contiguous_container(const void *beg, const void *end, const void *old_mid, const void *new_mid); // Returns true if the contiguous container [beg, end) is properly poisoned // (e.g. with __sanitizer_annotate_contiguous_container), i.e. if // - [beg, mid) is addressable, // - [mid, end) is unaddressable. // Full verification requires O(end-beg) time; this function tries to avoid // such complexity by touching only parts of the container around beg/mid/end. int __sanitizer_verify_contiguous_container(const void *beg, const void *mid, const void *end); // Similar to __sanitizer_verify_contiguous_container but returns the address // of the first improperly poisoned byte otherwise. Returns null if the area // is poisoned properly. const void *__sanitizer_contiguous_container_find_bad_address( const void *beg, const void *mid, const void *end); // Print the stack trace leading to this call. Useful for debugging user code. void __sanitizer_print_stack_trace(); // Sets the callback to be called right before death on error. // Passing 0 will unset the callback. void __sanitizer_set_death_callback(void (*callback)(void)); // Interceptor hooks. // Whenever a libc function interceptor is called it checks if the // corresponding weak hook is defined, and it so -- calls it. // The primary use case is data-flow-guided fuzzing, where the fuzzer needs // to know what is being passed to libc functions, e.g. memcmp. // FIXME: implement more hooks. void __sanitizer_weak_hook_memcmp(void *called_pc, const void *s1, const void *s2, size_t n, int result); void __sanitizer_weak_hook_strncmp(void *called_pc, const char *s1, const char *s2, size_t n, int result); + void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1, + const char *s2, size_t n, int result); void __sanitizer_weak_hook_strcmp(void *called_pc, const char *s1, const char *s2, int result); + void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1, + const char *s2, int result); + void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1, + const char *s2, char *result); + void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1, + const char *s2, char *result); + void __sanitizer_weak_hook_memmem(void *called_pc, + const void *s1, size_t len1, + const void *s2, size_t len2, void *result); + + // Prints stack traces for all live heap allocations ordered by total + // allocation size until `top_percent` of total live heap is shown. + // `top_percent` should be between 1 and 100. + // Experimental feature currently available only with asan on Linux/x86_64. + void __sanitizer_print_memory_profile(size_t top_percent); + + // Fiber annotation interface. + // Before switching to a different stack, one must call + // __sanitizer_start_switch_fiber with a pointer to the bottom of the + // destination stack and its size. When code starts running on the new stack, + // it must call __sanitizer_finish_switch_fiber to finalize the switch. + // The start_switch function takes a void** to store the current fake stack if + // there is one (it is needed when detect_stack_use_after_return is enabled). + // When restoring a stack, this pointer must be given to the finish_switch + // function. In most cases, this void* can be stored on the stack just before + // switching. When leaving a fiber definitely, null must be passed as first + // argument to the start_switch function so that the fake stack is destroyed. + // If you do not want support for stack use-after-return detection, you can + // always pass null to these two functions. + // Note that the fake stack mechanism is disabled during fiber switch, so if a + // signal callback runs during the switch, it will not benefit from the stack + // use-after-return detection. + void __sanitizer_start_switch_fiber(void **fake_stack_save, + const void *bottom, size_t size); + void __sanitizer_finish_switch_fiber(void *fake_stack_save); #ifdef __cplusplus } // extern "C" #endif #endif // SANITIZER_COMMON_INTERFACE_DEFS_H Index: projects/clang390-import/contrib/compiler-rt/include/sanitizer/esan_interface.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/include/sanitizer/esan_interface.h (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/include/sanitizer/esan_interface.h (revision 305364) @@ -0,0 +1,50 @@ +//===-- sanitizer/esan_interface.h ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +// Public interface header. +//===----------------------------------------------------------------------===// +#ifndef SANITIZER_ESAN_INTERFACE_H +#define SANITIZER_ESAN_INTERFACE_H + +#include + +// We declare our interface routines as weak to allow the user to avoid +// ifdefs and instead use this pattern to allow building the same sources +// with and without our runtime library: +// if (__esan_report) +// __esan_report(); +#ifdef _MSC_VER +/* selectany is as close to weak as we'll get. */ +#define COMPILER_RT_WEAK __declspec(selectany) +#elif __GNUC__ +#define COMPILER_RT_WEAK __attribute__((weak)) +#else +#define COMPILER_RT_WEAK +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// This function can be called mid-run (or at the end of a run for +// a server process that doesn't shut down normally) to request that +// data for that point in the run be reported from the tool. +void COMPILER_RT_WEAK __esan_report(); + +// This function returns the number of samples that the esan tool has collected +// to this point. This is useful for testing. +unsigned int COMPILER_RT_WEAK __esan_get_sample_count(); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // SANITIZER_ESAN_INTERFACE_H Property changes on: projects/clang390-import/contrib/compiler-rt/include/sanitizer/esan_interface.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/include/sanitizer/linux_syscall_hooks.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/include/sanitizer/linux_syscall_hooks.h (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/include/sanitizer/linux_syscall_hooks.h (revision 305364) @@ -1,3070 +1,3083 @@ //===-- linux_syscall_hooks.h ---------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of public sanitizer interface. // // System call handlers. // // Interface methods declared in this header implement pre- and post- syscall // actions for the active sanitizer. // Usage: // __sanitizer_syscall_pre_getfoo(...args...); // long res = syscall(__NR_getfoo, ...args...); // __sanitizer_syscall_post_getfoo(res, ...args...); //===----------------------------------------------------------------------===// #ifndef SANITIZER_LINUX_SYSCALL_HOOKS_H #define SANITIZER_LINUX_SYSCALL_HOOKS_H #define __sanitizer_syscall_pre_time(tloc) \ __sanitizer_syscall_pre_impl_time((long)(tloc)) #define __sanitizer_syscall_post_time(res, tloc) \ __sanitizer_syscall_post_impl_time(res, (long)(tloc)) #define __sanitizer_syscall_pre_stime(tptr) \ __sanitizer_syscall_pre_impl_stime((long)(tptr)) #define __sanitizer_syscall_post_stime(res, tptr) \ __sanitizer_syscall_post_impl_stime(res, (long)(tptr)) #define __sanitizer_syscall_pre_gettimeofday(tv, tz) \ __sanitizer_syscall_pre_impl_gettimeofday((long)(tv), (long)(tz)) #define __sanitizer_syscall_post_gettimeofday(res, tv, tz) \ __sanitizer_syscall_post_impl_gettimeofday(res, (long)(tv), (long)(tz)) #define __sanitizer_syscall_pre_settimeofday(tv, tz) \ __sanitizer_syscall_pre_impl_settimeofday((long)(tv), (long)(tz)) #define __sanitizer_syscall_post_settimeofday(res, tv, tz) \ __sanitizer_syscall_post_impl_settimeofday(res, (long)(tv), (long)(tz)) #define __sanitizer_syscall_pre_adjtimex(txc_p) \ __sanitizer_syscall_pre_impl_adjtimex((long)(txc_p)) #define __sanitizer_syscall_post_adjtimex(res, txc_p) \ __sanitizer_syscall_post_impl_adjtimex(res, (long)(txc_p)) #define __sanitizer_syscall_pre_times(tbuf) \ __sanitizer_syscall_pre_impl_times((long)(tbuf)) #define __sanitizer_syscall_post_times(res, tbuf) \ __sanitizer_syscall_post_impl_times(res, (long)(tbuf)) #define __sanitizer_syscall_pre_gettid() __sanitizer_syscall_pre_impl_gettid() #define __sanitizer_syscall_post_gettid(res) \ __sanitizer_syscall_post_impl_gettid(res) #define __sanitizer_syscall_pre_nanosleep(rqtp, rmtp) \ __sanitizer_syscall_pre_impl_nanosleep((long)(rqtp), (long)(rmtp)) #define __sanitizer_syscall_post_nanosleep(res, rqtp, rmtp) \ __sanitizer_syscall_post_impl_nanosleep(res, (long)(rqtp), (long)(rmtp)) #define __sanitizer_syscall_pre_alarm(seconds) \ __sanitizer_syscall_pre_impl_alarm((long)(seconds)) #define __sanitizer_syscall_post_alarm(res, seconds) \ __sanitizer_syscall_post_impl_alarm(res, (long)(seconds)) #define __sanitizer_syscall_pre_getpid() __sanitizer_syscall_pre_impl_getpid() #define __sanitizer_syscall_post_getpid(res) \ __sanitizer_syscall_post_impl_getpid(res) #define __sanitizer_syscall_pre_getppid() __sanitizer_syscall_pre_impl_getppid() #define __sanitizer_syscall_post_getppid(res) \ __sanitizer_syscall_post_impl_getppid(res) #define __sanitizer_syscall_pre_getuid() __sanitizer_syscall_pre_impl_getuid() #define __sanitizer_syscall_post_getuid(res) \ __sanitizer_syscall_post_impl_getuid(res) #define __sanitizer_syscall_pre_geteuid() __sanitizer_syscall_pre_impl_geteuid() #define __sanitizer_syscall_post_geteuid(res) \ __sanitizer_syscall_post_impl_geteuid(res) #define __sanitizer_syscall_pre_getgid() __sanitizer_syscall_pre_impl_getgid() #define __sanitizer_syscall_post_getgid(res) \ __sanitizer_syscall_post_impl_getgid(res) #define __sanitizer_syscall_pre_getegid() __sanitizer_syscall_pre_impl_getegid() #define __sanitizer_syscall_post_getegid(res) \ __sanitizer_syscall_post_impl_getegid(res) #define __sanitizer_syscall_pre_getresuid(ruid, euid, suid) \ __sanitizer_syscall_pre_impl_getresuid((long)(ruid), (long)(euid), \ (long)(suid)) #define __sanitizer_syscall_post_getresuid(res, ruid, euid, suid) \ __sanitizer_syscall_post_impl_getresuid(res, (long)(ruid), (long)(euid), \ (long)(suid)) #define __sanitizer_syscall_pre_getresgid(rgid, egid, sgid) \ __sanitizer_syscall_pre_impl_getresgid((long)(rgid), (long)(egid), \ (long)(sgid)) #define __sanitizer_syscall_post_getresgid(res, rgid, egid, sgid) \ __sanitizer_syscall_post_impl_getresgid(res, (long)(rgid), (long)(egid), \ (long)(sgid)) #define __sanitizer_syscall_pre_getpgid(pid) \ __sanitizer_syscall_pre_impl_getpgid((long)(pid)) #define __sanitizer_syscall_post_getpgid(res, pid) \ __sanitizer_syscall_post_impl_getpgid(res, (long)(pid)) #define __sanitizer_syscall_pre_getpgrp() __sanitizer_syscall_pre_impl_getpgrp() #define __sanitizer_syscall_post_getpgrp(res) \ __sanitizer_syscall_post_impl_getpgrp(res) #define __sanitizer_syscall_pre_getsid(pid) \ __sanitizer_syscall_pre_impl_getsid((long)(pid)) #define __sanitizer_syscall_post_getsid(res, pid) \ __sanitizer_syscall_post_impl_getsid(res, (long)(pid)) #define __sanitizer_syscall_pre_getgroups(gidsetsize, grouplist) \ __sanitizer_syscall_pre_impl_getgroups((long)(gidsetsize), (long)(grouplist)) #define __sanitizer_syscall_post_getgroups(res, gidsetsize, grouplist) \ __sanitizer_syscall_post_impl_getgroups(res, (long)(gidsetsize), \ (long)(grouplist)) #define __sanitizer_syscall_pre_setregid(rgid, egid) \ __sanitizer_syscall_pre_impl_setregid((long)(rgid), (long)(egid)) #define __sanitizer_syscall_post_setregid(res, rgid, egid) \ __sanitizer_syscall_post_impl_setregid(res, (long)(rgid), (long)(egid)) #define __sanitizer_syscall_pre_setgid(gid) \ __sanitizer_syscall_pre_impl_setgid((long)(gid)) #define __sanitizer_syscall_post_setgid(res, gid) \ __sanitizer_syscall_post_impl_setgid(res, (long)(gid)) #define __sanitizer_syscall_pre_setreuid(ruid, euid) \ __sanitizer_syscall_pre_impl_setreuid((long)(ruid), (long)(euid)) #define __sanitizer_syscall_post_setreuid(res, ruid, euid) \ __sanitizer_syscall_post_impl_setreuid(res, (long)(ruid), (long)(euid)) #define __sanitizer_syscall_pre_setuid(uid) \ __sanitizer_syscall_pre_impl_setuid((long)(uid)) #define __sanitizer_syscall_post_setuid(res, uid) \ __sanitizer_syscall_post_impl_setuid(res, (long)(uid)) #define __sanitizer_syscall_pre_setresuid(ruid, euid, suid) \ __sanitizer_syscall_pre_impl_setresuid((long)(ruid), (long)(euid), \ (long)(suid)) #define __sanitizer_syscall_post_setresuid(res, ruid, euid, suid) \ __sanitizer_syscall_post_impl_setresuid(res, (long)(ruid), (long)(euid), \ (long)(suid)) #define __sanitizer_syscall_pre_setresgid(rgid, egid, sgid) \ __sanitizer_syscall_pre_impl_setresgid((long)(rgid), (long)(egid), \ (long)(sgid)) #define __sanitizer_syscall_post_setresgid(res, rgid, egid, sgid) \ __sanitizer_syscall_post_impl_setresgid(res, (long)(rgid), (long)(egid), \ (long)(sgid)) #define __sanitizer_syscall_pre_setfsuid(uid) \ __sanitizer_syscall_pre_impl_setfsuid((long)(uid)) #define __sanitizer_syscall_post_setfsuid(res, uid) \ __sanitizer_syscall_post_impl_setfsuid(res, (long)(uid)) #define __sanitizer_syscall_pre_setfsgid(gid) \ __sanitizer_syscall_pre_impl_setfsgid((long)(gid)) #define __sanitizer_syscall_post_setfsgid(res, gid) \ __sanitizer_syscall_post_impl_setfsgid(res, (long)(gid)) #define __sanitizer_syscall_pre_setpgid(pid, pgid) \ __sanitizer_syscall_pre_impl_setpgid((long)(pid), (long)(pgid)) #define __sanitizer_syscall_post_setpgid(res, pid, pgid) \ __sanitizer_syscall_post_impl_setpgid(res, (long)(pid), (long)(pgid)) #define __sanitizer_syscall_pre_setsid() __sanitizer_syscall_pre_impl_setsid() #define __sanitizer_syscall_post_setsid(res) \ __sanitizer_syscall_post_impl_setsid(res) #define __sanitizer_syscall_pre_setgroups(gidsetsize, grouplist) \ __sanitizer_syscall_pre_impl_setgroups((long)(gidsetsize), (long)(grouplist)) #define __sanitizer_syscall_post_setgroups(res, gidsetsize, grouplist) \ __sanitizer_syscall_post_impl_setgroups(res, (long)(gidsetsize), \ (long)(grouplist)) #define __sanitizer_syscall_pre_acct(name) \ __sanitizer_syscall_pre_impl_acct((long)(name)) #define __sanitizer_syscall_post_acct(res, name) \ __sanitizer_syscall_post_impl_acct(res, (long)(name)) #define __sanitizer_syscall_pre_capget(header, dataptr) \ __sanitizer_syscall_pre_impl_capget((long)(header), (long)(dataptr)) #define __sanitizer_syscall_post_capget(res, header, dataptr) \ __sanitizer_syscall_post_impl_capget(res, (long)(header), (long)(dataptr)) #define __sanitizer_syscall_pre_capset(header, data) \ __sanitizer_syscall_pre_impl_capset((long)(header), (long)(data)) #define __sanitizer_syscall_post_capset(res, header, data) \ __sanitizer_syscall_post_impl_capset(res, (long)(header), (long)(data)) #define __sanitizer_syscall_pre_personality(personality) \ __sanitizer_syscall_pre_impl_personality((long)(personality)) #define __sanitizer_syscall_post_personality(res, personality) \ __sanitizer_syscall_post_impl_personality(res, (long)(personality)) #define __sanitizer_syscall_pre_sigpending(set) \ __sanitizer_syscall_pre_impl_sigpending((long)(set)) #define __sanitizer_syscall_post_sigpending(res, set) \ __sanitizer_syscall_post_impl_sigpending(res, (long)(set)) #define __sanitizer_syscall_pre_sigprocmask(how, set, oset) \ __sanitizer_syscall_pre_impl_sigprocmask((long)(how), (long)(set), \ (long)(oset)) #define __sanitizer_syscall_post_sigprocmask(res, how, set, oset) \ __sanitizer_syscall_post_impl_sigprocmask(res, (long)(how), (long)(set), \ (long)(oset)) #define __sanitizer_syscall_pre_getitimer(which, value) \ __sanitizer_syscall_pre_impl_getitimer((long)(which), (long)(value)) #define __sanitizer_syscall_post_getitimer(res, which, value) \ __sanitizer_syscall_post_impl_getitimer(res, (long)(which), (long)(value)) #define __sanitizer_syscall_pre_setitimer(which, value, ovalue) \ __sanitizer_syscall_pre_impl_setitimer((long)(which), (long)(value), \ (long)(ovalue)) #define __sanitizer_syscall_post_setitimer(res, which, value, ovalue) \ __sanitizer_syscall_post_impl_setitimer(res, (long)(which), (long)(value), \ (long)(ovalue)) #define __sanitizer_syscall_pre_timer_create(which_clock, timer_event_spec, \ created_timer_id) \ __sanitizer_syscall_pre_impl_timer_create( \ (long)(which_clock), (long)(timer_event_spec), (long)(created_timer_id)) #define __sanitizer_syscall_post_timer_create( \ res, which_clock, timer_event_spec, created_timer_id) \ __sanitizer_syscall_post_impl_timer_create(res, (long)(which_clock), \ (long)(timer_event_spec), \ (long)(created_timer_id)) #define __sanitizer_syscall_pre_timer_gettime(timer_id, setting) \ __sanitizer_syscall_pre_impl_timer_gettime((long)(timer_id), (long)(setting)) #define __sanitizer_syscall_post_timer_gettime(res, timer_id, setting) \ __sanitizer_syscall_post_impl_timer_gettime(res, (long)(timer_id), \ (long)(setting)) #define __sanitizer_syscall_pre_timer_getoverrun(timer_id) \ __sanitizer_syscall_pre_impl_timer_getoverrun((long)(timer_id)) #define __sanitizer_syscall_post_timer_getoverrun(res, timer_id) \ __sanitizer_syscall_post_impl_timer_getoverrun(res, (long)(timer_id)) #define __sanitizer_syscall_pre_timer_settime(timer_id, flags, new_setting, \ old_setting) \ __sanitizer_syscall_pre_impl_timer_settime((long)(timer_id), (long)(flags), \ (long)(new_setting), \ (long)(old_setting)) #define __sanitizer_syscall_post_timer_settime(res, timer_id, flags, \ new_setting, old_setting) \ __sanitizer_syscall_post_impl_timer_settime( \ res, (long)(timer_id), (long)(flags), (long)(new_setting), \ (long)(old_setting)) #define __sanitizer_syscall_pre_timer_delete(timer_id) \ __sanitizer_syscall_pre_impl_timer_delete((long)(timer_id)) #define __sanitizer_syscall_post_timer_delete(res, timer_id) \ __sanitizer_syscall_post_impl_timer_delete(res, (long)(timer_id)) #define __sanitizer_syscall_pre_clock_settime(which_clock, tp) \ __sanitizer_syscall_pre_impl_clock_settime((long)(which_clock), (long)(tp)) #define __sanitizer_syscall_post_clock_settime(res, which_clock, tp) \ __sanitizer_syscall_post_impl_clock_settime(res, (long)(which_clock), \ (long)(tp)) #define __sanitizer_syscall_pre_clock_gettime(which_clock, tp) \ __sanitizer_syscall_pre_impl_clock_gettime((long)(which_clock), (long)(tp)) #define __sanitizer_syscall_post_clock_gettime(res, which_clock, tp) \ __sanitizer_syscall_post_impl_clock_gettime(res, (long)(which_clock), \ (long)(tp)) #define __sanitizer_syscall_pre_clock_adjtime(which_clock, tx) \ __sanitizer_syscall_pre_impl_clock_adjtime((long)(which_clock), (long)(tx)) #define __sanitizer_syscall_post_clock_adjtime(res, which_clock, tx) \ __sanitizer_syscall_post_impl_clock_adjtime(res, (long)(which_clock), \ (long)(tx)) #define __sanitizer_syscall_pre_clock_getres(which_clock, tp) \ __sanitizer_syscall_pre_impl_clock_getres((long)(which_clock), (long)(tp)) #define __sanitizer_syscall_post_clock_getres(res, which_clock, tp) \ __sanitizer_syscall_post_impl_clock_getres(res, (long)(which_clock), \ (long)(tp)) #define __sanitizer_syscall_pre_clock_nanosleep(which_clock, flags, rqtp, \ rmtp) \ __sanitizer_syscall_pre_impl_clock_nanosleep( \ (long)(which_clock), (long)(flags), (long)(rqtp), (long)(rmtp)) #define __sanitizer_syscall_post_clock_nanosleep(res, which_clock, flags, \ rqtp, rmtp) \ __sanitizer_syscall_post_impl_clock_nanosleep( \ res, (long)(which_clock), (long)(flags), (long)(rqtp), (long)(rmtp)) #define __sanitizer_syscall_pre_nice(increment) \ __sanitizer_syscall_pre_impl_nice((long)(increment)) #define __sanitizer_syscall_post_nice(res, increment) \ __sanitizer_syscall_post_impl_nice(res, (long)(increment)) #define __sanitizer_syscall_pre_sched_setscheduler(pid, policy, param) \ __sanitizer_syscall_pre_impl_sched_setscheduler((long)(pid), (long)(policy), \ (long)(param)) #define __sanitizer_syscall_post_sched_setscheduler(res, pid, policy, param) \ __sanitizer_syscall_post_impl_sched_setscheduler( \ res, (long)(pid), (long)(policy), (long)(param)) #define __sanitizer_syscall_pre_sched_setparam(pid, param) \ __sanitizer_syscall_pre_impl_sched_setparam((long)(pid), (long)(param)) #define __sanitizer_syscall_post_sched_setparam(res, pid, param) \ __sanitizer_syscall_post_impl_sched_setparam(res, (long)(pid), (long)(param)) #define __sanitizer_syscall_pre_sched_getscheduler(pid) \ __sanitizer_syscall_pre_impl_sched_getscheduler((long)(pid)) #define __sanitizer_syscall_post_sched_getscheduler(res, pid) \ __sanitizer_syscall_post_impl_sched_getscheduler(res, (long)(pid)) #define __sanitizer_syscall_pre_sched_getparam(pid, param) \ __sanitizer_syscall_pre_impl_sched_getparam((long)(pid), (long)(param)) #define __sanitizer_syscall_post_sched_getparam(res, pid, param) \ __sanitizer_syscall_post_impl_sched_getparam(res, (long)(pid), (long)(param)) #define __sanitizer_syscall_pre_sched_setaffinity(pid, len, user_mask_ptr) \ __sanitizer_syscall_pre_impl_sched_setaffinity((long)(pid), (long)(len), \ (long)(user_mask_ptr)) #define __sanitizer_syscall_post_sched_setaffinity(res, pid, len, \ user_mask_ptr) \ __sanitizer_syscall_post_impl_sched_setaffinity( \ res, (long)(pid), (long)(len), (long)(user_mask_ptr)) #define __sanitizer_syscall_pre_sched_getaffinity(pid, len, user_mask_ptr) \ __sanitizer_syscall_pre_impl_sched_getaffinity((long)(pid), (long)(len), \ (long)(user_mask_ptr)) #define __sanitizer_syscall_post_sched_getaffinity(res, pid, len, \ user_mask_ptr) \ __sanitizer_syscall_post_impl_sched_getaffinity( \ res, (long)(pid), (long)(len), (long)(user_mask_ptr)) #define __sanitizer_syscall_pre_sched_yield() \ __sanitizer_syscall_pre_impl_sched_yield() #define __sanitizer_syscall_post_sched_yield(res) \ __sanitizer_syscall_post_impl_sched_yield(res) #define __sanitizer_syscall_pre_sched_get_priority_max(policy) \ __sanitizer_syscall_pre_impl_sched_get_priority_max((long)(policy)) #define __sanitizer_syscall_post_sched_get_priority_max(res, policy) \ __sanitizer_syscall_post_impl_sched_get_priority_max(res, (long)(policy)) #define __sanitizer_syscall_pre_sched_get_priority_min(policy) \ __sanitizer_syscall_pre_impl_sched_get_priority_min((long)(policy)) #define __sanitizer_syscall_post_sched_get_priority_min(res, policy) \ __sanitizer_syscall_post_impl_sched_get_priority_min(res, (long)(policy)) #define __sanitizer_syscall_pre_sched_rr_get_interval(pid, interval) \ __sanitizer_syscall_pre_impl_sched_rr_get_interval((long)(pid), \ (long)(interval)) #define __sanitizer_syscall_post_sched_rr_get_interval(res, pid, interval) \ __sanitizer_syscall_post_impl_sched_rr_get_interval(res, (long)(pid), \ (long)(interval)) #define __sanitizer_syscall_pre_setpriority(which, who, niceval) \ __sanitizer_syscall_pre_impl_setpriority((long)(which), (long)(who), \ (long)(niceval)) #define __sanitizer_syscall_post_setpriority(res, which, who, niceval) \ __sanitizer_syscall_post_impl_setpriority(res, (long)(which), (long)(who), \ (long)(niceval)) #define __sanitizer_syscall_pre_getpriority(which, who) \ __sanitizer_syscall_pre_impl_getpriority((long)(which), (long)(who)) #define __sanitizer_syscall_post_getpriority(res, which, who) \ __sanitizer_syscall_post_impl_getpriority(res, (long)(which), (long)(who)) #define __sanitizer_syscall_pre_shutdown(arg0, arg1) \ __sanitizer_syscall_pre_impl_shutdown((long)(arg0), (long)(arg1)) #define __sanitizer_syscall_post_shutdown(res, arg0, arg1) \ __sanitizer_syscall_post_impl_shutdown(res, (long)(arg0), (long)(arg1)) #define __sanitizer_syscall_pre_reboot(magic1, magic2, cmd, arg) \ __sanitizer_syscall_pre_impl_reboot((long)(magic1), (long)(magic2), \ (long)(cmd), (long)(arg)) #define __sanitizer_syscall_post_reboot(res, magic1, magic2, cmd, arg) \ __sanitizer_syscall_post_impl_reboot(res, (long)(magic1), (long)(magic2), \ (long)(cmd), (long)(arg)) #define __sanitizer_syscall_pre_restart_syscall() \ __sanitizer_syscall_pre_impl_restart_syscall() #define __sanitizer_syscall_post_restart_syscall(res) \ __sanitizer_syscall_post_impl_restart_syscall(res) #define __sanitizer_syscall_pre_kexec_load(entry, nr_segments, segments, \ flags) \ __sanitizer_syscall_pre_impl_kexec_load((long)(entry), (long)(nr_segments), \ (long)(segments), (long)(flags)) #define __sanitizer_syscall_post_kexec_load(res, entry, nr_segments, segments, \ flags) \ __sanitizer_syscall_post_impl_kexec_load(res, (long)(entry), \ (long)(nr_segments), \ (long)(segments), (long)(flags)) #define __sanitizer_syscall_pre_exit(error_code) \ __sanitizer_syscall_pre_impl_exit((long)(error_code)) #define __sanitizer_syscall_post_exit(res, error_code) \ __sanitizer_syscall_post_impl_exit(res, (long)(error_code)) #define __sanitizer_syscall_pre_exit_group(error_code) \ __sanitizer_syscall_pre_impl_exit_group((long)(error_code)) #define __sanitizer_syscall_post_exit_group(res, error_code) \ __sanitizer_syscall_post_impl_exit_group(res, (long)(error_code)) #define __sanitizer_syscall_pre_wait4(pid, stat_addr, options, ru) \ __sanitizer_syscall_pre_impl_wait4((long)(pid), (long)(stat_addr), \ (long)(options), (long)(ru)) #define __sanitizer_syscall_post_wait4(res, pid, stat_addr, options, ru) \ __sanitizer_syscall_post_impl_wait4(res, (long)(pid), (long)(stat_addr), \ (long)(options), (long)(ru)) #define __sanitizer_syscall_pre_waitid(which, pid, infop, options, ru) \ __sanitizer_syscall_pre_impl_waitid( \ (long)(which), (long)(pid), (long)(infop), (long)(options), (long)(ru)) #define __sanitizer_syscall_post_waitid(res, which, pid, infop, options, ru) \ __sanitizer_syscall_post_impl_waitid(res, (long)(which), (long)(pid), \ (long)(infop), (long)(options), \ (long)(ru)) #define __sanitizer_syscall_pre_waitpid(pid, stat_addr, options) \ __sanitizer_syscall_pre_impl_waitpid((long)(pid), (long)(stat_addr), \ (long)(options)) #define __sanitizer_syscall_post_waitpid(res, pid, stat_addr, options) \ __sanitizer_syscall_post_impl_waitpid(res, (long)(pid), (long)(stat_addr), \ (long)(options)) #define __sanitizer_syscall_pre_set_tid_address(tidptr) \ __sanitizer_syscall_pre_impl_set_tid_address((long)(tidptr)) #define __sanitizer_syscall_post_set_tid_address(res, tidptr) \ __sanitizer_syscall_post_impl_set_tid_address(res, (long)(tidptr)) #define __sanitizer_syscall_pre_init_module(umod, len, uargs) \ __sanitizer_syscall_pre_impl_init_module((long)(umod), (long)(len), \ (long)(uargs)) #define __sanitizer_syscall_post_init_module(res, umod, len, uargs) \ __sanitizer_syscall_post_impl_init_module(res, (long)(umod), (long)(len), \ (long)(uargs)) #define __sanitizer_syscall_pre_delete_module(name_user, flags) \ __sanitizer_syscall_pre_impl_delete_module((long)(name_user), (long)(flags)) #define __sanitizer_syscall_post_delete_module(res, name_user, flags) \ __sanitizer_syscall_post_impl_delete_module(res, (long)(name_user), \ (long)(flags)) #define __sanitizer_syscall_pre_rt_sigprocmask(how, set, oset, sigsetsize) \ __sanitizer_syscall_pre_impl_rt_sigprocmask( \ (long)(how), (long)(set), (long)(oset), (long)(sigsetsize)) #define __sanitizer_syscall_post_rt_sigprocmask(res, how, set, oset, \ sigsetsize) \ __sanitizer_syscall_post_impl_rt_sigprocmask( \ res, (long)(how), (long)(set), (long)(oset), (long)(sigsetsize)) #define __sanitizer_syscall_pre_rt_sigpending(set, sigsetsize) \ __sanitizer_syscall_pre_impl_rt_sigpending((long)(set), (long)(sigsetsize)) #define __sanitizer_syscall_post_rt_sigpending(res, set, sigsetsize) \ __sanitizer_syscall_post_impl_rt_sigpending(res, (long)(set), \ (long)(sigsetsize)) #define __sanitizer_syscall_pre_rt_sigtimedwait(uthese, uinfo, uts, \ sigsetsize) \ __sanitizer_syscall_pre_impl_rt_sigtimedwait( \ (long)(uthese), (long)(uinfo), (long)(uts), (long)(sigsetsize)) #define __sanitizer_syscall_post_rt_sigtimedwait(res, uthese, uinfo, uts, \ sigsetsize) \ __sanitizer_syscall_post_impl_rt_sigtimedwait( \ res, (long)(uthese), (long)(uinfo), (long)(uts), (long)(sigsetsize)) #define __sanitizer_syscall_pre_rt_tgsigqueueinfo(tgid, pid, sig, uinfo) \ __sanitizer_syscall_pre_impl_rt_tgsigqueueinfo((long)(tgid), (long)(pid), \ (long)(sig), (long)(uinfo)) #define __sanitizer_syscall_post_rt_tgsigqueueinfo(res, tgid, pid, sig, uinfo) \ __sanitizer_syscall_post_impl_rt_tgsigqueueinfo( \ res, (long)(tgid), (long)(pid), (long)(sig), (long)(uinfo)) #define __sanitizer_syscall_pre_kill(pid, sig) \ __sanitizer_syscall_pre_impl_kill((long)(pid), (long)(sig)) #define __sanitizer_syscall_post_kill(res, pid, sig) \ __sanitizer_syscall_post_impl_kill(res, (long)(pid), (long)(sig)) #define __sanitizer_syscall_pre_tgkill(tgid, pid, sig) \ __sanitizer_syscall_pre_impl_tgkill((long)(tgid), (long)(pid), (long)(sig)) #define __sanitizer_syscall_post_tgkill(res, tgid, pid, sig) \ __sanitizer_syscall_post_impl_tgkill(res, (long)(tgid), (long)(pid), \ (long)(sig)) #define __sanitizer_syscall_pre_tkill(pid, sig) \ __sanitizer_syscall_pre_impl_tkill((long)(pid), (long)(sig)) #define __sanitizer_syscall_post_tkill(res, pid, sig) \ __sanitizer_syscall_post_impl_tkill(res, (long)(pid), (long)(sig)) #define __sanitizer_syscall_pre_rt_sigqueueinfo(pid, sig, uinfo) \ __sanitizer_syscall_pre_impl_rt_sigqueueinfo((long)(pid), (long)(sig), \ (long)(uinfo)) #define __sanitizer_syscall_post_rt_sigqueueinfo(res, pid, sig, uinfo) \ __sanitizer_syscall_post_impl_rt_sigqueueinfo(res, (long)(pid), (long)(sig), \ (long)(uinfo)) #define __sanitizer_syscall_pre_sgetmask() \ __sanitizer_syscall_pre_impl_sgetmask() #define __sanitizer_syscall_post_sgetmask(res) \ __sanitizer_syscall_post_impl_sgetmask(res) #define __sanitizer_syscall_pre_ssetmask(newmask) \ __sanitizer_syscall_pre_impl_ssetmask((long)(newmask)) #define __sanitizer_syscall_post_ssetmask(res, newmask) \ __sanitizer_syscall_post_impl_ssetmask(res, (long)(newmask)) #define __sanitizer_syscall_pre_signal(sig, handler) \ __sanitizer_syscall_pre_impl_signal((long)(sig), (long)(handler)) #define __sanitizer_syscall_post_signal(res, sig, handler) \ __sanitizer_syscall_post_impl_signal(res, (long)(sig), (long)(handler)) #define __sanitizer_syscall_pre_pause() __sanitizer_syscall_pre_impl_pause() #define __sanitizer_syscall_post_pause(res) \ __sanitizer_syscall_post_impl_pause(res) #define __sanitizer_syscall_pre_sync() __sanitizer_syscall_pre_impl_sync() #define __sanitizer_syscall_post_sync(res) \ __sanitizer_syscall_post_impl_sync(res) #define __sanitizer_syscall_pre_fsync(fd) \ __sanitizer_syscall_pre_impl_fsync((long)(fd)) #define __sanitizer_syscall_post_fsync(res, fd) \ __sanitizer_syscall_post_impl_fsync(res, (long)(fd)) #define __sanitizer_syscall_pre_fdatasync(fd) \ __sanitizer_syscall_pre_impl_fdatasync((long)(fd)) #define __sanitizer_syscall_post_fdatasync(res, fd) \ __sanitizer_syscall_post_impl_fdatasync(res, (long)(fd)) #define __sanitizer_syscall_pre_bdflush(func, data) \ __sanitizer_syscall_pre_impl_bdflush((long)(func), (long)(data)) #define __sanitizer_syscall_post_bdflush(res, func, data) \ __sanitizer_syscall_post_impl_bdflush(res, (long)(func), (long)(data)) #define __sanitizer_syscall_pre_mount(dev_name, dir_name, type, flags, data) \ __sanitizer_syscall_pre_impl_mount((long)(dev_name), (long)(dir_name), \ (long)(type), (long)(flags), \ (long)(data)) #define __sanitizer_syscall_post_mount(res, dev_name, dir_name, type, flags, \ data) \ __sanitizer_syscall_post_impl_mount(res, (long)(dev_name), (long)(dir_name), \ (long)(type), (long)(flags), \ (long)(data)) #define __sanitizer_syscall_pre_umount(name, flags) \ __sanitizer_syscall_pre_impl_umount((long)(name), (long)(flags)) #define __sanitizer_syscall_post_umount(res, name, flags) \ __sanitizer_syscall_post_impl_umount(res, (long)(name), (long)(flags)) #define __sanitizer_syscall_pre_oldumount(name) \ __sanitizer_syscall_pre_impl_oldumount((long)(name)) #define __sanitizer_syscall_post_oldumount(res, name) \ __sanitizer_syscall_post_impl_oldumount(res, (long)(name)) #define __sanitizer_syscall_pre_truncate(path, length) \ __sanitizer_syscall_pre_impl_truncate((long)(path), (long)(length)) #define __sanitizer_syscall_post_truncate(res, path, length) \ __sanitizer_syscall_post_impl_truncate(res, (long)(path), (long)(length)) #define __sanitizer_syscall_pre_ftruncate(fd, length) \ __sanitizer_syscall_pre_impl_ftruncate((long)(fd), (long)(length)) #define __sanitizer_syscall_post_ftruncate(res, fd, length) \ __sanitizer_syscall_post_impl_ftruncate(res, (long)(fd), (long)(length)) #define __sanitizer_syscall_pre_stat(filename, statbuf) \ __sanitizer_syscall_pre_impl_stat((long)(filename), (long)(statbuf)) #define __sanitizer_syscall_post_stat(res, filename, statbuf) \ __sanitizer_syscall_post_impl_stat(res, (long)(filename), (long)(statbuf)) #define __sanitizer_syscall_pre_statfs(path, buf) \ __sanitizer_syscall_pre_impl_statfs((long)(path), (long)(buf)) #define __sanitizer_syscall_post_statfs(res, path, buf) \ __sanitizer_syscall_post_impl_statfs(res, (long)(path), (long)(buf)) #define __sanitizer_syscall_pre_statfs64(path, sz, buf) \ __sanitizer_syscall_pre_impl_statfs64((long)(path), (long)(sz), (long)(buf)) #define __sanitizer_syscall_post_statfs64(res, path, sz, buf) \ __sanitizer_syscall_post_impl_statfs64(res, (long)(path), (long)(sz), \ (long)(buf)) #define __sanitizer_syscall_pre_fstatfs(fd, buf) \ __sanitizer_syscall_pre_impl_fstatfs((long)(fd), (long)(buf)) #define __sanitizer_syscall_post_fstatfs(res, fd, buf) \ __sanitizer_syscall_post_impl_fstatfs(res, (long)(fd), (long)(buf)) #define __sanitizer_syscall_pre_fstatfs64(fd, sz, buf) \ __sanitizer_syscall_pre_impl_fstatfs64((long)(fd), (long)(sz), (long)(buf)) #define __sanitizer_syscall_post_fstatfs64(res, fd, sz, buf) \ __sanitizer_syscall_post_impl_fstatfs64(res, (long)(fd), (long)(sz), \ (long)(buf)) #define __sanitizer_syscall_pre_lstat(filename, statbuf) \ __sanitizer_syscall_pre_impl_lstat((long)(filename), (long)(statbuf)) #define __sanitizer_syscall_post_lstat(res, filename, statbuf) \ __sanitizer_syscall_post_impl_lstat(res, (long)(filename), (long)(statbuf)) #define __sanitizer_syscall_pre_fstat(fd, statbuf) \ __sanitizer_syscall_pre_impl_fstat((long)(fd), (long)(statbuf)) #define __sanitizer_syscall_post_fstat(res, fd, statbuf) \ __sanitizer_syscall_post_impl_fstat(res, (long)(fd), (long)(statbuf)) #define __sanitizer_syscall_pre_newstat(filename, statbuf) \ __sanitizer_syscall_pre_impl_newstat((long)(filename), (long)(statbuf)) #define __sanitizer_syscall_post_newstat(res, filename, statbuf) \ __sanitizer_syscall_post_impl_newstat(res, (long)(filename), (long)(statbuf)) #define __sanitizer_syscall_pre_newlstat(filename, statbuf) \ __sanitizer_syscall_pre_impl_newlstat((long)(filename), (long)(statbuf)) #define __sanitizer_syscall_post_newlstat(res, filename, statbuf) \ __sanitizer_syscall_post_impl_newlstat(res, (long)(filename), (long)(statbuf)) #define __sanitizer_syscall_pre_newfstat(fd, statbuf) \ __sanitizer_syscall_pre_impl_newfstat((long)(fd), (long)(statbuf)) #define __sanitizer_syscall_post_newfstat(res, fd, statbuf) \ __sanitizer_syscall_post_impl_newfstat(res, (long)(fd), (long)(statbuf)) #define __sanitizer_syscall_pre_ustat(dev, ubuf) \ __sanitizer_syscall_pre_impl_ustat((long)(dev), (long)(ubuf)) #define __sanitizer_syscall_post_ustat(res, dev, ubuf) \ __sanitizer_syscall_post_impl_ustat(res, (long)(dev), (long)(ubuf)) #define __sanitizer_syscall_pre_stat64(filename, statbuf) \ __sanitizer_syscall_pre_impl_stat64((long)(filename), (long)(statbuf)) #define __sanitizer_syscall_post_stat64(res, filename, statbuf) \ __sanitizer_syscall_post_impl_stat64(res, (long)(filename), (long)(statbuf)) #define __sanitizer_syscall_pre_fstat64(fd, statbuf) \ __sanitizer_syscall_pre_impl_fstat64((long)(fd), (long)(statbuf)) #define __sanitizer_syscall_post_fstat64(res, fd, statbuf) \ __sanitizer_syscall_post_impl_fstat64(res, (long)(fd), (long)(statbuf)) #define __sanitizer_syscall_pre_lstat64(filename, statbuf) \ __sanitizer_syscall_pre_impl_lstat64((long)(filename), (long)(statbuf)) #define __sanitizer_syscall_post_lstat64(res, filename, statbuf) \ __sanitizer_syscall_post_impl_lstat64(res, (long)(filename), (long)(statbuf)) #define __sanitizer_syscall_pre_setxattr(path, name, value, size, flags) \ __sanitizer_syscall_pre_impl_setxattr( \ (long)(path), (long)(name), (long)(value), (long)(size), (long)(flags)) #define __sanitizer_syscall_post_setxattr(res, path, name, value, size, flags) \ __sanitizer_syscall_post_impl_setxattr(res, (long)(path), (long)(name), \ (long)(value), (long)(size), \ (long)(flags)) #define __sanitizer_syscall_pre_lsetxattr(path, name, value, size, flags) \ __sanitizer_syscall_pre_impl_lsetxattr( \ (long)(path), (long)(name), (long)(value), (long)(size), (long)(flags)) #define __sanitizer_syscall_post_lsetxattr(res, path, name, value, size, \ flags) \ __sanitizer_syscall_post_impl_lsetxattr(res, (long)(path), (long)(name), \ (long)(value), (long)(size), \ (long)(flags)) #define __sanitizer_syscall_pre_fsetxattr(fd, name, value, size, flags) \ __sanitizer_syscall_pre_impl_fsetxattr( \ (long)(fd), (long)(name), (long)(value), (long)(size), (long)(flags)) #define __sanitizer_syscall_post_fsetxattr(res, fd, name, value, size, flags) \ __sanitizer_syscall_post_impl_fsetxattr(res, (long)(fd), (long)(name), \ (long)(value), (long)(size), \ (long)(flags)) #define __sanitizer_syscall_pre_getxattr(path, name, value, size) \ __sanitizer_syscall_pre_impl_getxattr((long)(path), (long)(name), \ (long)(value), (long)(size)) #define __sanitizer_syscall_post_getxattr(res, path, name, value, size) \ __sanitizer_syscall_post_impl_getxattr(res, (long)(path), (long)(name), \ (long)(value), (long)(size)) #define __sanitizer_syscall_pre_lgetxattr(path, name, value, size) \ __sanitizer_syscall_pre_impl_lgetxattr((long)(path), (long)(name), \ (long)(value), (long)(size)) #define __sanitizer_syscall_post_lgetxattr(res, path, name, value, size) \ __sanitizer_syscall_post_impl_lgetxattr(res, (long)(path), (long)(name), \ (long)(value), (long)(size)) #define __sanitizer_syscall_pre_fgetxattr(fd, name, value, size) \ __sanitizer_syscall_pre_impl_fgetxattr((long)(fd), (long)(name), \ (long)(value), (long)(size)) #define __sanitizer_syscall_post_fgetxattr(res, fd, name, value, size) \ __sanitizer_syscall_post_impl_fgetxattr(res, (long)(fd), (long)(name), \ (long)(value), (long)(size)) #define __sanitizer_syscall_pre_listxattr(path, list, size) \ __sanitizer_syscall_pre_impl_listxattr((long)(path), (long)(list), \ (long)(size)) #define __sanitizer_syscall_post_listxattr(res, path, list, size) \ __sanitizer_syscall_post_impl_listxattr(res, (long)(path), (long)(list), \ (long)(size)) #define __sanitizer_syscall_pre_llistxattr(path, list, size) \ __sanitizer_syscall_pre_impl_llistxattr((long)(path), (long)(list), \ (long)(size)) #define __sanitizer_syscall_post_llistxattr(res, path, list, size) \ __sanitizer_syscall_post_impl_llistxattr(res, (long)(path), (long)(list), \ (long)(size)) #define __sanitizer_syscall_pre_flistxattr(fd, list, size) \ __sanitizer_syscall_pre_impl_flistxattr((long)(fd), (long)(list), \ (long)(size)) #define __sanitizer_syscall_post_flistxattr(res, fd, list, size) \ __sanitizer_syscall_post_impl_flistxattr(res, (long)(fd), (long)(list), \ (long)(size)) #define __sanitizer_syscall_pre_removexattr(path, name) \ __sanitizer_syscall_pre_impl_removexattr((long)(path), (long)(name)) #define __sanitizer_syscall_post_removexattr(res, path, name) \ __sanitizer_syscall_post_impl_removexattr(res, (long)(path), (long)(name)) #define __sanitizer_syscall_pre_lremovexattr(path, name) \ __sanitizer_syscall_pre_impl_lremovexattr((long)(path), (long)(name)) #define __sanitizer_syscall_post_lremovexattr(res, path, name) \ __sanitizer_syscall_post_impl_lremovexattr(res, (long)(path), (long)(name)) #define __sanitizer_syscall_pre_fremovexattr(fd, name) \ __sanitizer_syscall_pre_impl_fremovexattr((long)(fd), (long)(name)) #define __sanitizer_syscall_post_fremovexattr(res, fd, name) \ __sanitizer_syscall_post_impl_fremovexattr(res, (long)(fd), (long)(name)) #define __sanitizer_syscall_pre_brk(brk) \ __sanitizer_syscall_pre_impl_brk((long)(brk)) #define __sanitizer_syscall_post_brk(res, brk) \ __sanitizer_syscall_post_impl_brk(res, (long)(brk)) #define __sanitizer_syscall_pre_mprotect(start, len, prot) \ __sanitizer_syscall_pre_impl_mprotect((long)(start), (long)(len), \ (long)(prot)) #define __sanitizer_syscall_post_mprotect(res, start, len, prot) \ __sanitizer_syscall_post_impl_mprotect(res, (long)(start), (long)(len), \ (long)(prot)) #define __sanitizer_syscall_pre_mremap(addr, old_len, new_len, flags, \ new_addr) \ __sanitizer_syscall_pre_impl_mremap((long)(addr), (long)(old_len), \ (long)(new_len), (long)(flags), \ (long)(new_addr)) #define __sanitizer_syscall_post_mremap(res, addr, old_len, new_len, flags, \ new_addr) \ __sanitizer_syscall_post_impl_mremap(res, (long)(addr), (long)(old_len), \ (long)(new_len), (long)(flags), \ (long)(new_addr)) #define __sanitizer_syscall_pre_remap_file_pages(start, size, prot, pgoff, \ flags) \ __sanitizer_syscall_pre_impl_remap_file_pages( \ (long)(start), (long)(size), (long)(prot), (long)(pgoff), (long)(flags)) #define __sanitizer_syscall_post_remap_file_pages(res, start, size, prot, \ pgoff, flags) \ __sanitizer_syscall_post_impl_remap_file_pages(res, (long)(start), \ (long)(size), (long)(prot), \ (long)(pgoff), (long)(flags)) #define __sanitizer_syscall_pre_msync(start, len, flags) \ __sanitizer_syscall_pre_impl_msync((long)(start), (long)(len), (long)(flags)) #define __sanitizer_syscall_post_msync(res, start, len, flags) \ __sanitizer_syscall_post_impl_msync(res, (long)(start), (long)(len), \ (long)(flags)) #define __sanitizer_syscall_pre_munmap(addr, len) \ __sanitizer_syscall_pre_impl_munmap((long)(addr), (long)(len)) #define __sanitizer_syscall_post_munmap(res, addr, len) \ __sanitizer_syscall_post_impl_munmap(res, (long)(addr), (long)(len)) #define __sanitizer_syscall_pre_mlock(start, len) \ __sanitizer_syscall_pre_impl_mlock((long)(start), (long)(len)) #define __sanitizer_syscall_post_mlock(res, start, len) \ __sanitizer_syscall_post_impl_mlock(res, (long)(start), (long)(len)) #define __sanitizer_syscall_pre_munlock(start, len) \ __sanitizer_syscall_pre_impl_munlock((long)(start), (long)(len)) #define __sanitizer_syscall_post_munlock(res, start, len) \ __sanitizer_syscall_post_impl_munlock(res, (long)(start), (long)(len)) #define __sanitizer_syscall_pre_mlockall(flags) \ __sanitizer_syscall_pre_impl_mlockall((long)(flags)) #define __sanitizer_syscall_post_mlockall(res, flags) \ __sanitizer_syscall_post_impl_mlockall(res, (long)(flags)) #define __sanitizer_syscall_pre_munlockall() \ __sanitizer_syscall_pre_impl_munlockall() #define __sanitizer_syscall_post_munlockall(res) \ __sanitizer_syscall_post_impl_munlockall(res) #define __sanitizer_syscall_pre_madvise(start, len, behavior) \ __sanitizer_syscall_pre_impl_madvise((long)(start), (long)(len), \ (long)(behavior)) #define __sanitizer_syscall_post_madvise(res, start, len, behavior) \ __sanitizer_syscall_post_impl_madvise(res, (long)(start), (long)(len), \ (long)(behavior)) #define __sanitizer_syscall_pre_mincore(start, len, vec) \ __sanitizer_syscall_pre_impl_mincore((long)(start), (long)(len), (long)(vec)) #define __sanitizer_syscall_post_mincore(res, start, len, vec) \ __sanitizer_syscall_post_impl_mincore(res, (long)(start), (long)(len), \ (long)(vec)) #define __sanitizer_syscall_pre_pivot_root(new_root, put_old) \ __sanitizer_syscall_pre_impl_pivot_root((long)(new_root), (long)(put_old)) #define __sanitizer_syscall_post_pivot_root(res, new_root, put_old) \ __sanitizer_syscall_post_impl_pivot_root(res, (long)(new_root), \ (long)(put_old)) #define __sanitizer_syscall_pre_chroot(filename) \ __sanitizer_syscall_pre_impl_chroot((long)(filename)) #define __sanitizer_syscall_post_chroot(res, filename) \ __sanitizer_syscall_post_impl_chroot(res, (long)(filename)) #define __sanitizer_syscall_pre_mknod(filename, mode, dev) \ __sanitizer_syscall_pre_impl_mknod((long)(filename), (long)(mode), \ (long)(dev)) #define __sanitizer_syscall_post_mknod(res, filename, mode, dev) \ __sanitizer_syscall_post_impl_mknod(res, (long)(filename), (long)(mode), \ (long)(dev)) #define __sanitizer_syscall_pre_link(oldname, newname) \ __sanitizer_syscall_pre_impl_link((long)(oldname), (long)(newname)) #define __sanitizer_syscall_post_link(res, oldname, newname) \ __sanitizer_syscall_post_impl_link(res, (long)(oldname), (long)(newname)) #define __sanitizer_syscall_pre_symlink(old, new_) \ __sanitizer_syscall_pre_impl_symlink((long)(old), (long)(new_)) #define __sanitizer_syscall_post_symlink(res, old, new_) \ __sanitizer_syscall_post_impl_symlink(res, (long)(old), (long)(new_)) #define __sanitizer_syscall_pre_unlink(pathname) \ __sanitizer_syscall_pre_impl_unlink((long)(pathname)) #define __sanitizer_syscall_post_unlink(res, pathname) \ __sanitizer_syscall_post_impl_unlink(res, (long)(pathname)) #define __sanitizer_syscall_pre_rename(oldname, newname) \ __sanitizer_syscall_pre_impl_rename((long)(oldname), (long)(newname)) #define __sanitizer_syscall_post_rename(res, oldname, newname) \ __sanitizer_syscall_post_impl_rename(res, (long)(oldname), (long)(newname)) #define __sanitizer_syscall_pre_chmod(filename, mode) \ __sanitizer_syscall_pre_impl_chmod((long)(filename), (long)(mode)) #define __sanitizer_syscall_post_chmod(res, filename, mode) \ __sanitizer_syscall_post_impl_chmod(res, (long)(filename), (long)(mode)) #define __sanitizer_syscall_pre_fchmod(fd, mode) \ __sanitizer_syscall_pre_impl_fchmod((long)(fd), (long)(mode)) #define __sanitizer_syscall_post_fchmod(res, fd, mode) \ __sanitizer_syscall_post_impl_fchmod(res, (long)(fd), (long)(mode)) #define __sanitizer_syscall_pre_fcntl(fd, cmd, arg) \ __sanitizer_syscall_pre_impl_fcntl((long)(fd), (long)(cmd), (long)(arg)) #define __sanitizer_syscall_post_fcntl(res, fd, cmd, arg) \ __sanitizer_syscall_post_impl_fcntl(res, (long)(fd), (long)(cmd), (long)(arg)) #define __sanitizer_syscall_pre_fcntl64(fd, cmd, arg) \ __sanitizer_syscall_pre_impl_fcntl64((long)(fd), (long)(cmd), (long)(arg)) #define __sanitizer_syscall_post_fcntl64(res, fd, cmd, arg) \ __sanitizer_syscall_post_impl_fcntl64(res, (long)(fd), (long)(cmd), \ (long)(arg)) #define __sanitizer_syscall_pre_pipe(fildes) \ __sanitizer_syscall_pre_impl_pipe((long)(fildes)) #define __sanitizer_syscall_post_pipe(res, fildes) \ __sanitizer_syscall_post_impl_pipe(res, (long)(fildes)) #define __sanitizer_syscall_pre_pipe2(fildes, flags) \ __sanitizer_syscall_pre_impl_pipe2((long)(fildes), (long)(flags)) #define __sanitizer_syscall_post_pipe2(res, fildes, flags) \ __sanitizer_syscall_post_impl_pipe2(res, (long)(fildes), (long)(flags)) #define __sanitizer_syscall_pre_dup(fildes) \ __sanitizer_syscall_pre_impl_dup((long)(fildes)) #define __sanitizer_syscall_post_dup(res, fildes) \ __sanitizer_syscall_post_impl_dup(res, (long)(fildes)) #define __sanitizer_syscall_pre_dup2(oldfd, newfd) \ __sanitizer_syscall_pre_impl_dup2((long)(oldfd), (long)(newfd)) #define __sanitizer_syscall_post_dup2(res, oldfd, newfd) \ __sanitizer_syscall_post_impl_dup2(res, (long)(oldfd), (long)(newfd)) #define __sanitizer_syscall_pre_dup3(oldfd, newfd, flags) \ __sanitizer_syscall_pre_impl_dup3((long)(oldfd), (long)(newfd), (long)(flags)) #define __sanitizer_syscall_post_dup3(res, oldfd, newfd, flags) \ __sanitizer_syscall_post_impl_dup3(res, (long)(oldfd), (long)(newfd), \ (long)(flags)) #define __sanitizer_syscall_pre_ioperm(from, num, on) \ __sanitizer_syscall_pre_impl_ioperm((long)(from), (long)(num), (long)(on)) #define __sanitizer_syscall_post_ioperm(res, from, num, on) \ __sanitizer_syscall_post_impl_ioperm(res, (long)(from), (long)(num), \ (long)(on)) #define __sanitizer_syscall_pre_ioctl(fd, cmd, arg) \ __sanitizer_syscall_pre_impl_ioctl((long)(fd), (long)(cmd), (long)(arg)) #define __sanitizer_syscall_post_ioctl(res, fd, cmd, arg) \ __sanitizer_syscall_post_impl_ioctl(res, (long)(fd), (long)(cmd), (long)(arg)) #define __sanitizer_syscall_pre_flock(fd, cmd) \ __sanitizer_syscall_pre_impl_flock((long)(fd), (long)(cmd)) #define __sanitizer_syscall_post_flock(res, fd, cmd) \ __sanitizer_syscall_post_impl_flock(res, (long)(fd), (long)(cmd)) #define __sanitizer_syscall_pre_io_setup(nr_reqs, ctx) \ __sanitizer_syscall_pre_impl_io_setup((long)(nr_reqs), (long)(ctx)) #define __sanitizer_syscall_post_io_setup(res, nr_reqs, ctx) \ __sanitizer_syscall_post_impl_io_setup(res, (long)(nr_reqs), (long)(ctx)) #define __sanitizer_syscall_pre_io_destroy(ctx) \ __sanitizer_syscall_pre_impl_io_destroy((long)(ctx)) #define __sanitizer_syscall_post_io_destroy(res, ctx) \ __sanitizer_syscall_post_impl_io_destroy(res, (long)(ctx)) #define __sanitizer_syscall_pre_io_getevents(ctx_id, min_nr, nr, events, \ timeout) \ __sanitizer_syscall_pre_impl_io_getevents((long)(ctx_id), (long)(min_nr), \ (long)(nr), (long)(events), \ (long)(timeout)) #define __sanitizer_syscall_post_io_getevents(res, ctx_id, min_nr, nr, events, \ timeout) \ __sanitizer_syscall_post_impl_io_getevents(res, (long)(ctx_id), \ (long)(min_nr), (long)(nr), \ (long)(events), (long)(timeout)) #define __sanitizer_syscall_pre_io_submit(ctx_id, arg1, arg2) \ __sanitizer_syscall_pre_impl_io_submit((long)(ctx_id), (long)(arg1), \ (long)(arg2)) #define __sanitizer_syscall_post_io_submit(res, ctx_id, arg1, arg2) \ __sanitizer_syscall_post_impl_io_submit(res, (long)(ctx_id), (long)(arg1), \ (long)(arg2)) #define __sanitizer_syscall_pre_io_cancel(ctx_id, iocb, result) \ __sanitizer_syscall_pre_impl_io_cancel((long)(ctx_id), (long)(iocb), \ (long)(result)) #define __sanitizer_syscall_post_io_cancel(res, ctx_id, iocb, result) \ __sanitizer_syscall_post_impl_io_cancel(res, (long)(ctx_id), (long)(iocb), \ (long)(result)) #define __sanitizer_syscall_pre_sendfile(out_fd, in_fd, offset, count) \ __sanitizer_syscall_pre_impl_sendfile((long)(out_fd), (long)(in_fd), \ (long)(offset), (long)(count)) #define __sanitizer_syscall_post_sendfile(res, out_fd, in_fd, offset, count) \ __sanitizer_syscall_post_impl_sendfile(res, (long)(out_fd), (long)(in_fd), \ (long)(offset), (long)(count)) #define __sanitizer_syscall_pre_sendfile64(out_fd, in_fd, offset, count) \ __sanitizer_syscall_pre_impl_sendfile64((long)(out_fd), (long)(in_fd), \ (long)(offset), (long)(count)) #define __sanitizer_syscall_post_sendfile64(res, out_fd, in_fd, offset, count) \ __sanitizer_syscall_post_impl_sendfile64(res, (long)(out_fd), (long)(in_fd), \ (long)(offset), (long)(count)) #define __sanitizer_syscall_pre_readlink(path, buf, bufsiz) \ __sanitizer_syscall_pre_impl_readlink((long)(path), (long)(buf), \ (long)(bufsiz)) #define __sanitizer_syscall_post_readlink(res, path, buf, bufsiz) \ __sanitizer_syscall_post_impl_readlink(res, (long)(path), (long)(buf), \ (long)(bufsiz)) #define __sanitizer_syscall_pre_creat(pathname, mode) \ __sanitizer_syscall_pre_impl_creat((long)(pathname), (long)(mode)) #define __sanitizer_syscall_post_creat(res, pathname, mode) \ __sanitizer_syscall_post_impl_creat(res, (long)(pathname), (long)(mode)) #define __sanitizer_syscall_pre_open(filename, flags, mode) \ __sanitizer_syscall_pre_impl_open((long)(filename), (long)(flags), \ (long)(mode)) #define __sanitizer_syscall_post_open(res, filename, flags, mode) \ __sanitizer_syscall_post_impl_open(res, (long)(filename), (long)(flags), \ (long)(mode)) #define __sanitizer_syscall_pre_close(fd) \ __sanitizer_syscall_pre_impl_close((long)(fd)) #define __sanitizer_syscall_post_close(res, fd) \ __sanitizer_syscall_post_impl_close(res, (long)(fd)) #define __sanitizer_syscall_pre_access(filename, mode) \ __sanitizer_syscall_pre_impl_access((long)(filename), (long)(mode)) #define __sanitizer_syscall_post_access(res, filename, mode) \ __sanitizer_syscall_post_impl_access(res, (long)(filename), (long)(mode)) #define __sanitizer_syscall_pre_vhangup() __sanitizer_syscall_pre_impl_vhangup() #define __sanitizer_syscall_post_vhangup(res) \ __sanitizer_syscall_post_impl_vhangup(res) #define __sanitizer_syscall_pre_chown(filename, user, group) \ __sanitizer_syscall_pre_impl_chown((long)(filename), (long)(user), \ (long)(group)) #define __sanitizer_syscall_post_chown(res, filename, user, group) \ __sanitizer_syscall_post_impl_chown(res, (long)(filename), (long)(user), \ (long)(group)) #define __sanitizer_syscall_pre_lchown(filename, user, group) \ __sanitizer_syscall_pre_impl_lchown((long)(filename), (long)(user), \ (long)(group)) #define __sanitizer_syscall_post_lchown(res, filename, user, group) \ __sanitizer_syscall_post_impl_lchown(res, (long)(filename), (long)(user), \ (long)(group)) #define __sanitizer_syscall_pre_fchown(fd, user, group) \ __sanitizer_syscall_pre_impl_fchown((long)(fd), (long)(user), (long)(group)) #define __sanitizer_syscall_post_fchown(res, fd, user, group) \ __sanitizer_syscall_post_impl_fchown(res, (long)(fd), (long)(user), \ (long)(group)) #define __sanitizer_syscall_pre_chown16(filename, user, group) \ __sanitizer_syscall_pre_impl_chown16((long)(filename), (long)user, \ (long)group) #define __sanitizer_syscall_post_chown16(res, filename, user, group) \ __sanitizer_syscall_post_impl_chown16(res, (long)(filename), (long)user, \ (long)group) #define __sanitizer_syscall_pre_lchown16(filename, user, group) \ __sanitizer_syscall_pre_impl_lchown16((long)(filename), (long)user, \ (long)group) #define __sanitizer_syscall_post_lchown16(res, filename, user, group) \ __sanitizer_syscall_post_impl_lchown16(res, (long)(filename), (long)user, \ (long)group) #define __sanitizer_syscall_pre_fchown16(fd, user, group) \ __sanitizer_syscall_pre_impl_fchown16((long)(fd), (long)user, (long)group) #define __sanitizer_syscall_post_fchown16(res, fd, user, group) \ __sanitizer_syscall_post_impl_fchown16(res, (long)(fd), (long)user, \ (long)group) #define __sanitizer_syscall_pre_setregid16(rgid, egid) \ __sanitizer_syscall_pre_impl_setregid16((long)rgid, (long)egid) #define __sanitizer_syscall_post_setregid16(res, rgid, egid) \ __sanitizer_syscall_post_impl_setregid16(res, (long)rgid, (long)egid) #define __sanitizer_syscall_pre_setgid16(gid) \ __sanitizer_syscall_pre_impl_setgid16((long)gid) #define __sanitizer_syscall_post_setgid16(res, gid) \ __sanitizer_syscall_post_impl_setgid16(res, (long)gid) #define __sanitizer_syscall_pre_setreuid16(ruid, euid) \ __sanitizer_syscall_pre_impl_setreuid16((long)ruid, (long)euid) #define __sanitizer_syscall_post_setreuid16(res, ruid, euid) \ __sanitizer_syscall_post_impl_setreuid16(res, (long)ruid, (long)euid) #define __sanitizer_syscall_pre_setuid16(uid) \ __sanitizer_syscall_pre_impl_setuid16((long)uid) #define __sanitizer_syscall_post_setuid16(res, uid) \ __sanitizer_syscall_post_impl_setuid16(res, (long)uid) #define __sanitizer_syscall_pre_setresuid16(ruid, euid, suid) \ __sanitizer_syscall_pre_impl_setresuid16((long)ruid, (long)euid, (long)suid) #define __sanitizer_syscall_post_setresuid16(res, ruid, euid, suid) \ __sanitizer_syscall_post_impl_setresuid16(res, (long)ruid, (long)euid, \ (long)suid) #define __sanitizer_syscall_pre_getresuid16(ruid, euid, suid) \ __sanitizer_syscall_pre_impl_getresuid16((long)(ruid), (long)(euid), \ (long)(suid)) #define __sanitizer_syscall_post_getresuid16(res, ruid, euid, suid) \ __sanitizer_syscall_post_impl_getresuid16(res, (long)(ruid), (long)(euid), \ (long)(suid)) #define __sanitizer_syscall_pre_setresgid16(rgid, egid, sgid) \ __sanitizer_syscall_pre_impl_setresgid16((long)rgid, (long)egid, (long)sgid) #define __sanitizer_syscall_post_setresgid16(res, rgid, egid, sgid) \ __sanitizer_syscall_post_impl_setresgid16(res, (long)rgid, (long)egid, \ (long)sgid) #define __sanitizer_syscall_pre_getresgid16(rgid, egid, sgid) \ __sanitizer_syscall_pre_impl_getresgid16((long)(rgid), (long)(egid), \ (long)(sgid)) #define __sanitizer_syscall_post_getresgid16(res, rgid, egid, sgid) \ __sanitizer_syscall_post_impl_getresgid16(res, (long)(rgid), (long)(egid), \ (long)(sgid)) #define __sanitizer_syscall_pre_setfsuid16(uid) \ __sanitizer_syscall_pre_impl_setfsuid16((long)uid) #define __sanitizer_syscall_post_setfsuid16(res, uid) \ __sanitizer_syscall_post_impl_setfsuid16(res, (long)uid) #define __sanitizer_syscall_pre_setfsgid16(gid) \ __sanitizer_syscall_pre_impl_setfsgid16((long)gid) #define __sanitizer_syscall_post_setfsgid16(res, gid) \ __sanitizer_syscall_post_impl_setfsgid16(res, (long)gid) #define __sanitizer_syscall_pre_getgroups16(gidsetsize, grouplist) \ __sanitizer_syscall_pre_impl_getgroups16((long)(gidsetsize), \ (long)(grouplist)) #define __sanitizer_syscall_post_getgroups16(res, gidsetsize, grouplist) \ __sanitizer_syscall_post_impl_getgroups16(res, (long)(gidsetsize), \ (long)(grouplist)) #define __sanitizer_syscall_pre_setgroups16(gidsetsize, grouplist) \ __sanitizer_syscall_pre_impl_setgroups16((long)(gidsetsize), \ (long)(grouplist)) #define __sanitizer_syscall_post_setgroups16(res, gidsetsize, grouplist) \ __sanitizer_syscall_post_impl_setgroups16(res, (long)(gidsetsize), \ (long)(grouplist)) #define __sanitizer_syscall_pre_getuid16() \ __sanitizer_syscall_pre_impl_getuid16() #define __sanitizer_syscall_post_getuid16(res) \ __sanitizer_syscall_post_impl_getuid16(res) #define __sanitizer_syscall_pre_geteuid16() \ __sanitizer_syscall_pre_impl_geteuid16() #define __sanitizer_syscall_post_geteuid16(res) \ __sanitizer_syscall_post_impl_geteuid16(res) #define __sanitizer_syscall_pre_getgid16() \ __sanitizer_syscall_pre_impl_getgid16() #define __sanitizer_syscall_post_getgid16(res) \ __sanitizer_syscall_post_impl_getgid16(res) #define __sanitizer_syscall_pre_getegid16() \ __sanitizer_syscall_pre_impl_getegid16() #define __sanitizer_syscall_post_getegid16(res) \ __sanitizer_syscall_post_impl_getegid16(res) #define __sanitizer_syscall_pre_utime(filename, times) \ __sanitizer_syscall_pre_impl_utime((long)(filename), (long)(times)) #define __sanitizer_syscall_post_utime(res, filename, times) \ __sanitizer_syscall_post_impl_utime(res, (long)(filename), (long)(times)) #define __sanitizer_syscall_pre_utimes(filename, utimes) \ __sanitizer_syscall_pre_impl_utimes((long)(filename), (long)(utimes)) #define __sanitizer_syscall_post_utimes(res, filename, utimes) \ __sanitizer_syscall_post_impl_utimes(res, (long)(filename), (long)(utimes)) #define __sanitizer_syscall_pre_lseek(fd, offset, origin) \ __sanitizer_syscall_pre_impl_lseek((long)(fd), (long)(offset), (long)(origin)) #define __sanitizer_syscall_post_lseek(res, fd, offset, origin) \ __sanitizer_syscall_post_impl_lseek(res, (long)(fd), (long)(offset), \ (long)(origin)) #define __sanitizer_syscall_pre_llseek(fd, offset_high, offset_low, result, \ origin) \ __sanitizer_syscall_pre_impl_llseek((long)(fd), (long)(offset_high), \ (long)(offset_low), (long)(result), \ (long)(origin)) #define __sanitizer_syscall_post_llseek(res, fd, offset_high, offset_low, \ result, origin) \ __sanitizer_syscall_post_impl_llseek(res, (long)(fd), (long)(offset_high), \ (long)(offset_low), (long)(result), \ (long)(origin)) #define __sanitizer_syscall_pre_read(fd, buf, count) \ __sanitizer_syscall_pre_impl_read((long)(fd), (long)(buf), (long)(count)) #define __sanitizer_syscall_post_read(res, fd, buf, count) \ __sanitizer_syscall_post_impl_read(res, (long)(fd), (long)(buf), \ (long)(count)) #define __sanitizer_syscall_pre_readv(fd, vec, vlen) \ __sanitizer_syscall_pre_impl_readv((long)(fd), (long)(vec), (long)(vlen)) #define __sanitizer_syscall_post_readv(res, fd, vec, vlen) \ __sanitizer_syscall_post_impl_readv(res, (long)(fd), (long)(vec), \ (long)(vlen)) #define __sanitizer_syscall_pre_write(fd, buf, count) \ __sanitizer_syscall_pre_impl_write((long)(fd), (long)(buf), (long)(count)) #define __sanitizer_syscall_post_write(res, fd, buf, count) \ __sanitizer_syscall_post_impl_write(res, (long)(fd), (long)(buf), \ (long)(count)) #define __sanitizer_syscall_pre_writev(fd, vec, vlen) \ __sanitizer_syscall_pre_impl_writev((long)(fd), (long)(vec), (long)(vlen)) #define __sanitizer_syscall_post_writev(res, fd, vec, vlen) \ __sanitizer_syscall_post_impl_writev(res, (long)(fd), (long)(vec), \ (long)(vlen)) #ifdef _LP64 #define __sanitizer_syscall_pre_pread64(fd, buf, count, pos) \ __sanitizer_syscall_pre_impl_pread64((long)(fd), (long)(buf), (long)(count), \ (long)(pos)) #define __sanitizer_syscall_post_pread64(res, fd, buf, count, pos) \ __sanitizer_syscall_post_impl_pread64(res, (long)(fd), (long)(buf), \ (long)(count), (long)(pos)) #define __sanitizer_syscall_pre_pwrite64(fd, buf, count, pos) \ __sanitizer_syscall_pre_impl_pwrite64((long)(fd), (long)(buf), \ (long)(count), (long)(pos)) #define __sanitizer_syscall_post_pwrite64(res, fd, buf, count, pos) \ __sanitizer_syscall_post_impl_pwrite64(res, (long)(fd), (long)(buf), \ (long)(count), (long)(pos)) #else #define __sanitizer_syscall_pre_pread64(fd, buf, count, pos0, pos1) \ __sanitizer_syscall_pre_impl_pread64((long)(fd), (long)(buf), (long)(count), \ (long)(pos0), (long)(pos1)) #define __sanitizer_syscall_post_pread64(res, fd, buf, count, pos0, pos1) \ __sanitizer_syscall_post_impl_pread64(res, (long)(fd), (long)(buf), \ (long)(count), (long)(pos0), \ (long)(pos1)) #define __sanitizer_syscall_pre_pwrite64(fd, buf, count, pos0, pos1) \ __sanitizer_syscall_pre_impl_pwrite64( \ (long)(fd), (long)(buf), (long)(count), (long)(pos0), (long)(pos1)) #define __sanitizer_syscall_post_pwrite64(res, fd, buf, count, pos0, pos1) \ __sanitizer_syscall_post_impl_pwrite64( \ res, (long)(fd), (long)(buf), (long)(count), (long)(pos0), (long)(pos1)) #endif #define __sanitizer_syscall_pre_preadv(fd, vec, vlen, pos_l, pos_h) \ __sanitizer_syscall_pre_impl_preadv((long)(fd), (long)(vec), (long)(vlen), \ (long)(pos_l), (long)(pos_h)) #define __sanitizer_syscall_post_preadv(res, fd, vec, vlen, pos_l, pos_h) \ __sanitizer_syscall_post_impl_preadv(res, (long)(fd), (long)(vec), \ (long)(vlen), (long)(pos_l), \ (long)(pos_h)) #define __sanitizer_syscall_pre_pwritev(fd, vec, vlen, pos_l, pos_h) \ __sanitizer_syscall_pre_impl_pwritev((long)(fd), (long)(vec), (long)(vlen), \ (long)(pos_l), (long)(pos_h)) #define __sanitizer_syscall_post_pwritev(res, fd, vec, vlen, pos_l, pos_h) \ __sanitizer_syscall_post_impl_pwritev(res, (long)(fd), (long)(vec), \ (long)(vlen), (long)(pos_l), \ (long)(pos_h)) #define __sanitizer_syscall_pre_getcwd(buf, size) \ __sanitizer_syscall_pre_impl_getcwd((long)(buf), (long)(size)) #define __sanitizer_syscall_post_getcwd(res, buf, size) \ __sanitizer_syscall_post_impl_getcwd(res, (long)(buf), (long)(size)) #define __sanitizer_syscall_pre_mkdir(pathname, mode) \ __sanitizer_syscall_pre_impl_mkdir((long)(pathname), (long)(mode)) #define __sanitizer_syscall_post_mkdir(res, pathname, mode) \ __sanitizer_syscall_post_impl_mkdir(res, (long)(pathname), (long)(mode)) #define __sanitizer_syscall_pre_chdir(filename) \ __sanitizer_syscall_pre_impl_chdir((long)(filename)) #define __sanitizer_syscall_post_chdir(res, filename) \ __sanitizer_syscall_post_impl_chdir(res, (long)(filename)) #define __sanitizer_syscall_pre_fchdir(fd) \ __sanitizer_syscall_pre_impl_fchdir((long)(fd)) #define __sanitizer_syscall_post_fchdir(res, fd) \ __sanitizer_syscall_post_impl_fchdir(res, (long)(fd)) #define __sanitizer_syscall_pre_rmdir(pathname) \ __sanitizer_syscall_pre_impl_rmdir((long)(pathname)) #define __sanitizer_syscall_post_rmdir(res, pathname) \ __sanitizer_syscall_post_impl_rmdir(res, (long)(pathname)) #define __sanitizer_syscall_pre_lookup_dcookie(cookie64, buf, len) \ __sanitizer_syscall_pre_impl_lookup_dcookie((long)(cookie64), (long)(buf), \ (long)(len)) #define __sanitizer_syscall_post_lookup_dcookie(res, cookie64, buf, len) \ __sanitizer_syscall_post_impl_lookup_dcookie(res, (long)(cookie64), \ (long)(buf), (long)(len)) #define __sanitizer_syscall_pre_quotactl(cmd, special, id, addr) \ __sanitizer_syscall_pre_impl_quotactl((long)(cmd), (long)(special), \ (long)(id), (long)(addr)) #define __sanitizer_syscall_post_quotactl(res, cmd, special, id, addr) \ __sanitizer_syscall_post_impl_quotactl(res, (long)(cmd), (long)(special), \ (long)(id), (long)(addr)) #define __sanitizer_syscall_pre_getdents(fd, dirent, count) \ __sanitizer_syscall_pre_impl_getdents((long)(fd), (long)(dirent), \ (long)(count)) #define __sanitizer_syscall_post_getdents(res, fd, dirent, count) \ __sanitizer_syscall_post_impl_getdents(res, (long)(fd), (long)(dirent), \ (long)(count)) #define __sanitizer_syscall_pre_getdents64(fd, dirent, count) \ __sanitizer_syscall_pre_impl_getdents64((long)(fd), (long)(dirent), \ (long)(count)) #define __sanitizer_syscall_post_getdents64(res, fd, dirent, count) \ __sanitizer_syscall_post_impl_getdents64(res, (long)(fd), (long)(dirent), \ (long)(count)) #define __sanitizer_syscall_pre_setsockopt(fd, level, optname, optval, optlen) \ __sanitizer_syscall_pre_impl_setsockopt((long)(fd), (long)(level), \ (long)(optname), (long)(optval), \ (long)(optlen)) #define __sanitizer_syscall_post_setsockopt(res, fd, level, optname, optval, \ optlen) \ __sanitizer_syscall_post_impl_setsockopt(res, (long)(fd), (long)(level), \ (long)(optname), (long)(optval), \ (long)(optlen)) #define __sanitizer_syscall_pre_getsockopt(fd, level, optname, optval, optlen) \ __sanitizer_syscall_pre_impl_getsockopt((long)(fd), (long)(level), \ (long)(optname), (long)(optval), \ (long)(optlen)) #define __sanitizer_syscall_post_getsockopt(res, fd, level, optname, optval, \ optlen) \ __sanitizer_syscall_post_impl_getsockopt(res, (long)(fd), (long)(level), \ (long)(optname), (long)(optval), \ (long)(optlen)) #define __sanitizer_syscall_pre_bind(arg0, arg1, arg2) \ __sanitizer_syscall_pre_impl_bind((long)(arg0), (long)(arg1), (long)(arg2)) #define __sanitizer_syscall_post_bind(res, arg0, arg1, arg2) \ __sanitizer_syscall_post_impl_bind(res, (long)(arg0), (long)(arg1), \ (long)(arg2)) #define __sanitizer_syscall_pre_connect(arg0, arg1, arg2) \ __sanitizer_syscall_pre_impl_connect((long)(arg0), (long)(arg1), (long)(arg2)) #define __sanitizer_syscall_post_connect(res, arg0, arg1, arg2) \ __sanitizer_syscall_post_impl_connect(res, (long)(arg0), (long)(arg1), \ (long)(arg2)) #define __sanitizer_syscall_pre_accept(arg0, arg1, arg2) \ __sanitizer_syscall_pre_impl_accept((long)(arg0), (long)(arg1), (long)(arg2)) #define __sanitizer_syscall_post_accept(res, arg0, arg1, arg2) \ __sanitizer_syscall_post_impl_accept(res, (long)(arg0), (long)(arg1), \ (long)(arg2)) #define __sanitizer_syscall_pre_accept4(arg0, arg1, arg2, arg3) \ __sanitizer_syscall_pre_impl_accept4((long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3)) #define __sanitizer_syscall_post_accept4(res, arg0, arg1, arg2, arg3) \ __sanitizer_syscall_post_impl_accept4(res, (long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3)) #define __sanitizer_syscall_pre_getsockname(arg0, arg1, arg2) \ __sanitizer_syscall_pre_impl_getsockname((long)(arg0), (long)(arg1), \ (long)(arg2)) #define __sanitizer_syscall_post_getsockname(res, arg0, arg1, arg2) \ __sanitizer_syscall_post_impl_getsockname(res, (long)(arg0), (long)(arg1), \ (long)(arg2)) #define __sanitizer_syscall_pre_getpeername(arg0, arg1, arg2) \ __sanitizer_syscall_pre_impl_getpeername((long)(arg0), (long)(arg1), \ (long)(arg2)) #define __sanitizer_syscall_post_getpeername(res, arg0, arg1, arg2) \ __sanitizer_syscall_post_impl_getpeername(res, (long)(arg0), (long)(arg1), \ (long)(arg2)) #define __sanitizer_syscall_pre_send(arg0, arg1, arg2, arg3) \ __sanitizer_syscall_pre_impl_send((long)(arg0), (long)(arg1), (long)(arg2), \ (long)(arg3)) #define __sanitizer_syscall_post_send(res, arg0, arg1, arg2, arg3) \ __sanitizer_syscall_post_impl_send(res, (long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3)) #define __sanitizer_syscall_pre_sendto(arg0, arg1, arg2, arg3, arg4, arg5) \ __sanitizer_syscall_pre_impl_sendto((long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3), \ (long)(arg4), (long)(arg5)) #define __sanitizer_syscall_post_sendto(res, arg0, arg1, arg2, arg3, arg4, \ arg5) \ __sanitizer_syscall_post_impl_sendto(res, (long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3), \ (long)(arg4), (long)(arg5)) #define __sanitizer_syscall_pre_sendmsg(fd, msg, flags) \ __sanitizer_syscall_pre_impl_sendmsg((long)(fd), (long)(msg), (long)(flags)) #define __sanitizer_syscall_post_sendmsg(res, fd, msg, flags) \ __sanitizer_syscall_post_impl_sendmsg(res, (long)(fd), (long)(msg), \ (long)(flags)) #define __sanitizer_syscall_pre_sendmmsg(fd, msg, vlen, flags) \ __sanitizer_syscall_pre_impl_sendmmsg((long)(fd), (long)(msg), (long)(vlen), \ (long)(flags)) #define __sanitizer_syscall_post_sendmmsg(res, fd, msg, vlen, flags) \ __sanitizer_syscall_post_impl_sendmmsg(res, (long)(fd), (long)(msg), \ (long)(vlen), (long)(flags)) #define __sanitizer_syscall_pre_recv(arg0, arg1, arg2, arg3) \ __sanitizer_syscall_pre_impl_recv((long)(arg0), (long)(arg1), (long)(arg2), \ (long)(arg3)) #define __sanitizer_syscall_post_recv(res, arg0, arg1, arg2, arg3) \ __sanitizer_syscall_post_impl_recv(res, (long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3)) #define __sanitizer_syscall_pre_recvfrom(arg0, arg1, arg2, arg3, arg4, arg5) \ __sanitizer_syscall_pre_impl_recvfrom((long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3), \ (long)(arg4), (long)(arg5)) #define __sanitizer_syscall_post_recvfrom(res, arg0, arg1, arg2, arg3, arg4, \ arg5) \ __sanitizer_syscall_post_impl_recvfrom(res, (long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3), \ (long)(arg4), (long)(arg5)) #define __sanitizer_syscall_pre_recvmsg(fd, msg, flags) \ __sanitizer_syscall_pre_impl_recvmsg((long)(fd), (long)(msg), (long)(flags)) #define __sanitizer_syscall_post_recvmsg(res, fd, msg, flags) \ __sanitizer_syscall_post_impl_recvmsg(res, (long)(fd), (long)(msg), \ (long)(flags)) #define __sanitizer_syscall_pre_recvmmsg(fd, msg, vlen, flags, timeout) \ __sanitizer_syscall_pre_impl_recvmmsg((long)(fd), (long)(msg), (long)(vlen), \ (long)(flags), (long)(timeout)) #define __sanitizer_syscall_post_recvmmsg(res, fd, msg, vlen, flags, timeout) \ __sanitizer_syscall_post_impl_recvmmsg(res, (long)(fd), (long)(msg), \ (long)(vlen), (long)(flags), \ (long)(timeout)) #define __sanitizer_syscall_pre_socket(arg0, arg1, arg2) \ __sanitizer_syscall_pre_impl_socket((long)(arg0), (long)(arg1), (long)(arg2)) #define __sanitizer_syscall_post_socket(res, arg0, arg1, arg2) \ __sanitizer_syscall_post_impl_socket(res, (long)(arg0), (long)(arg1), \ (long)(arg2)) #define __sanitizer_syscall_pre_socketpair(arg0, arg1, arg2, arg3) \ __sanitizer_syscall_pre_impl_socketpair((long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3)) #define __sanitizer_syscall_post_socketpair(res, arg0, arg1, arg2, arg3) \ __sanitizer_syscall_post_impl_socketpair(res, (long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3)) #define __sanitizer_syscall_pre_socketcall(call, args) \ __sanitizer_syscall_pre_impl_socketcall((long)(call), (long)(args)) #define __sanitizer_syscall_post_socketcall(res, call, args) \ __sanitizer_syscall_post_impl_socketcall(res, (long)(call), (long)(args)) #define __sanitizer_syscall_pre_listen(arg0, arg1) \ __sanitizer_syscall_pre_impl_listen((long)(arg0), (long)(arg1)) #define __sanitizer_syscall_post_listen(res, arg0, arg1) \ __sanitizer_syscall_post_impl_listen(res, (long)(arg0), (long)(arg1)) #define __sanitizer_syscall_pre_poll(ufds, nfds, timeout) \ __sanitizer_syscall_pre_impl_poll((long)(ufds), (long)(nfds), (long)(timeout)) #define __sanitizer_syscall_post_poll(res, ufds, nfds, timeout) \ __sanitizer_syscall_post_impl_poll(res, (long)(ufds), (long)(nfds), \ (long)(timeout)) #define __sanitizer_syscall_pre_select(n, inp, outp, exp, tvp) \ __sanitizer_syscall_pre_impl_select((long)(n), (long)(inp), (long)(outp), \ (long)(exp), (long)(tvp)) #define __sanitizer_syscall_post_select(res, n, inp, outp, exp, tvp) \ __sanitizer_syscall_post_impl_select(res, (long)(n), (long)(inp), \ (long)(outp), (long)(exp), (long)(tvp)) #define __sanitizer_syscall_pre_old_select(arg) \ __sanitizer_syscall_pre_impl_old_select((long)(arg)) #define __sanitizer_syscall_post_old_select(res, arg) \ __sanitizer_syscall_post_impl_old_select(res, (long)(arg)) #define __sanitizer_syscall_pre_epoll_create(size) \ __sanitizer_syscall_pre_impl_epoll_create((long)(size)) #define __sanitizer_syscall_post_epoll_create(res, size) \ __sanitizer_syscall_post_impl_epoll_create(res, (long)(size)) #define __sanitizer_syscall_pre_epoll_create1(flags) \ __sanitizer_syscall_pre_impl_epoll_create1((long)(flags)) #define __sanitizer_syscall_post_epoll_create1(res, flags) \ __sanitizer_syscall_post_impl_epoll_create1(res, (long)(flags)) #define __sanitizer_syscall_pre_epoll_ctl(epfd, op, fd, event) \ __sanitizer_syscall_pre_impl_epoll_ctl((long)(epfd), (long)(op), (long)(fd), \ (long)(event)) #define __sanitizer_syscall_post_epoll_ctl(res, epfd, op, fd, event) \ __sanitizer_syscall_post_impl_epoll_ctl(res, (long)(epfd), (long)(op), \ (long)(fd), (long)(event)) #define __sanitizer_syscall_pre_epoll_wait(epfd, events, maxevents, timeout) \ __sanitizer_syscall_pre_impl_epoll_wait((long)(epfd), (long)(events), \ (long)(maxevents), (long)(timeout)) #define __sanitizer_syscall_post_epoll_wait(res, epfd, events, maxevents, \ timeout) \ __sanitizer_syscall_post_impl_epoll_wait(res, (long)(epfd), (long)(events), \ (long)(maxevents), (long)(timeout)) #define __sanitizer_syscall_pre_epoll_pwait(epfd, events, maxevents, timeout, \ sigmask, sigsetsize) \ __sanitizer_syscall_pre_impl_epoll_pwait( \ (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \ (long)(sigmask), (long)(sigsetsize)) #define __sanitizer_syscall_post_epoll_pwait(res, epfd, events, maxevents, \ timeout, sigmask, sigsetsize) \ __sanitizer_syscall_post_impl_epoll_pwait( \ res, (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \ (long)(sigmask), (long)(sigsetsize)) #define __sanitizer_syscall_pre_gethostname(name, len) \ __sanitizer_syscall_pre_impl_gethostname((long)(name), (long)(len)) #define __sanitizer_syscall_post_gethostname(res, name, len) \ __sanitizer_syscall_post_impl_gethostname(res, (long)(name), (long)(len)) #define __sanitizer_syscall_pre_sethostname(name, len) \ __sanitizer_syscall_pre_impl_sethostname((long)(name), (long)(len)) #define __sanitizer_syscall_post_sethostname(res, name, len) \ __sanitizer_syscall_post_impl_sethostname(res, (long)(name), (long)(len)) #define __sanitizer_syscall_pre_setdomainname(name, len) \ __sanitizer_syscall_pre_impl_setdomainname((long)(name), (long)(len)) #define __sanitizer_syscall_post_setdomainname(res, name, len) \ __sanitizer_syscall_post_impl_setdomainname(res, (long)(name), (long)(len)) #define __sanitizer_syscall_pre_newuname(name) \ __sanitizer_syscall_pre_impl_newuname((long)(name)) #define __sanitizer_syscall_post_newuname(res, name) \ __sanitizer_syscall_post_impl_newuname(res, (long)(name)) #define __sanitizer_syscall_pre_uname(arg0) \ __sanitizer_syscall_pre_impl_uname((long)(arg0)) #define __sanitizer_syscall_post_uname(res, arg0) \ __sanitizer_syscall_post_impl_uname(res, (long)(arg0)) #define __sanitizer_syscall_pre_olduname(arg0) \ __sanitizer_syscall_pre_impl_olduname((long)(arg0)) #define __sanitizer_syscall_post_olduname(res, arg0) \ __sanitizer_syscall_post_impl_olduname(res, (long)(arg0)) #define __sanitizer_syscall_pre_getrlimit(resource, rlim) \ __sanitizer_syscall_pre_impl_getrlimit((long)(resource), (long)(rlim)) #define __sanitizer_syscall_post_getrlimit(res, resource, rlim) \ __sanitizer_syscall_post_impl_getrlimit(res, (long)(resource), (long)(rlim)) #define __sanitizer_syscall_pre_old_getrlimit(resource, rlim) \ __sanitizer_syscall_pre_impl_old_getrlimit((long)(resource), (long)(rlim)) #define __sanitizer_syscall_post_old_getrlimit(res, resource, rlim) \ __sanitizer_syscall_post_impl_old_getrlimit(res, (long)(resource), \ (long)(rlim)) #define __sanitizer_syscall_pre_setrlimit(resource, rlim) \ __sanitizer_syscall_pre_impl_setrlimit((long)(resource), (long)(rlim)) #define __sanitizer_syscall_post_setrlimit(res, resource, rlim) \ __sanitizer_syscall_post_impl_setrlimit(res, (long)(resource), (long)(rlim)) #define __sanitizer_syscall_pre_prlimit64(pid, resource, new_rlim, old_rlim) \ __sanitizer_syscall_pre_impl_prlimit64((long)(pid), (long)(resource), \ (long)(new_rlim), (long)(old_rlim)) #define __sanitizer_syscall_post_prlimit64(res, pid, resource, new_rlim, \ old_rlim) \ __sanitizer_syscall_post_impl_prlimit64(res, (long)(pid), (long)(resource), \ (long)(new_rlim), (long)(old_rlim)) #define __sanitizer_syscall_pre_getrusage(who, ru) \ __sanitizer_syscall_pre_impl_getrusage((long)(who), (long)(ru)) #define __sanitizer_syscall_post_getrusage(res, who, ru) \ __sanitizer_syscall_post_impl_getrusage(res, (long)(who), (long)(ru)) #define __sanitizer_syscall_pre_umask(mask) \ __sanitizer_syscall_pre_impl_umask((long)(mask)) #define __sanitizer_syscall_post_umask(res, mask) \ __sanitizer_syscall_post_impl_umask(res, (long)(mask)) #define __sanitizer_syscall_pre_msgget(key, msgflg) \ __sanitizer_syscall_pre_impl_msgget((long)(key), (long)(msgflg)) #define __sanitizer_syscall_post_msgget(res, key, msgflg) \ __sanitizer_syscall_post_impl_msgget(res, (long)(key), (long)(msgflg)) #define __sanitizer_syscall_pre_msgsnd(msqid, msgp, msgsz, msgflg) \ __sanitizer_syscall_pre_impl_msgsnd((long)(msqid), (long)(msgp), \ (long)(msgsz), (long)(msgflg)) #define __sanitizer_syscall_post_msgsnd(res, msqid, msgp, msgsz, msgflg) \ __sanitizer_syscall_post_impl_msgsnd(res, (long)(msqid), (long)(msgp), \ (long)(msgsz), (long)(msgflg)) #define __sanitizer_syscall_pre_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg) \ __sanitizer_syscall_pre_impl_msgrcv((long)(msqid), (long)(msgp), \ (long)(msgsz), (long)(msgtyp), \ (long)(msgflg)) #define __sanitizer_syscall_post_msgrcv(res, msqid, msgp, msgsz, msgtyp, \ msgflg) \ __sanitizer_syscall_post_impl_msgrcv(res, (long)(msqid), (long)(msgp), \ (long)(msgsz), (long)(msgtyp), \ (long)(msgflg)) #define __sanitizer_syscall_pre_msgctl(msqid, cmd, buf) \ __sanitizer_syscall_pre_impl_msgctl((long)(msqid), (long)(cmd), (long)(buf)) #define __sanitizer_syscall_post_msgctl(res, msqid, cmd, buf) \ __sanitizer_syscall_post_impl_msgctl(res, (long)(msqid), (long)(cmd), \ (long)(buf)) #define __sanitizer_syscall_pre_semget(key, nsems, semflg) \ __sanitizer_syscall_pre_impl_semget((long)(key), (long)(nsems), \ (long)(semflg)) #define __sanitizer_syscall_post_semget(res, key, nsems, semflg) \ __sanitizer_syscall_post_impl_semget(res, (long)(key), (long)(nsems), \ (long)(semflg)) #define __sanitizer_syscall_pre_semop(semid, sops, nsops) \ __sanitizer_syscall_pre_impl_semop((long)(semid), (long)(sops), (long)(nsops)) #define __sanitizer_syscall_post_semop(res, semid, sops, nsops) \ __sanitizer_syscall_post_impl_semop(res, (long)(semid), (long)(sops), \ (long)(nsops)) #define __sanitizer_syscall_pre_semctl(semid, semnum, cmd, arg) \ __sanitizer_syscall_pre_impl_semctl((long)(semid), (long)(semnum), \ (long)(cmd), (long)(arg)) #define __sanitizer_syscall_post_semctl(res, semid, semnum, cmd, arg) \ __sanitizer_syscall_post_impl_semctl(res, (long)(semid), (long)(semnum), \ (long)(cmd), (long)(arg)) #define __sanitizer_syscall_pre_semtimedop(semid, sops, nsops, timeout) \ __sanitizer_syscall_pre_impl_semtimedop((long)(semid), (long)(sops), \ (long)(nsops), (long)(timeout)) #define __sanitizer_syscall_post_semtimedop(res, semid, sops, nsops, timeout) \ __sanitizer_syscall_post_impl_semtimedop(res, (long)(semid), (long)(sops), \ (long)(nsops), (long)(timeout)) #define __sanitizer_syscall_pre_shmat(shmid, shmaddr, shmflg) \ __sanitizer_syscall_pre_impl_shmat((long)(shmid), (long)(shmaddr), \ (long)(shmflg)) #define __sanitizer_syscall_post_shmat(res, shmid, shmaddr, shmflg) \ __sanitizer_syscall_post_impl_shmat(res, (long)(shmid), (long)(shmaddr), \ (long)(shmflg)) #define __sanitizer_syscall_pre_shmget(key, size, flag) \ __sanitizer_syscall_pre_impl_shmget((long)(key), (long)(size), (long)(flag)) #define __sanitizer_syscall_post_shmget(res, key, size, flag) \ __sanitizer_syscall_post_impl_shmget(res, (long)(key), (long)(size), \ (long)(flag)) #define __sanitizer_syscall_pre_shmdt(shmaddr) \ __sanitizer_syscall_pre_impl_shmdt((long)(shmaddr)) #define __sanitizer_syscall_post_shmdt(res, shmaddr) \ __sanitizer_syscall_post_impl_shmdt(res, (long)(shmaddr)) #define __sanitizer_syscall_pre_shmctl(shmid, cmd, buf) \ __sanitizer_syscall_pre_impl_shmctl((long)(shmid), (long)(cmd), (long)(buf)) #define __sanitizer_syscall_post_shmctl(res, shmid, cmd, buf) \ __sanitizer_syscall_post_impl_shmctl(res, (long)(shmid), (long)(cmd), \ (long)(buf)) #define __sanitizer_syscall_pre_ipc(call, first, second, third, ptr, fifth) \ __sanitizer_syscall_pre_impl_ipc((long)(call), (long)(first), \ (long)(second), (long)(third), (long)(ptr), \ (long)(fifth)) #define __sanitizer_syscall_post_ipc(res, call, first, second, third, ptr, \ fifth) \ __sanitizer_syscall_post_impl_ipc(res, (long)(call), (long)(first), \ (long)(second), (long)(third), \ (long)(ptr), (long)(fifth)) #define __sanitizer_syscall_pre_mq_open(name, oflag, mode, attr) \ __sanitizer_syscall_pre_impl_mq_open((long)(name), (long)(oflag), \ (long)(mode), (long)(attr)) #define __sanitizer_syscall_post_mq_open(res, name, oflag, mode, attr) \ __sanitizer_syscall_post_impl_mq_open(res, (long)(name), (long)(oflag), \ (long)(mode), (long)(attr)) #define __sanitizer_syscall_pre_mq_unlink(name) \ __sanitizer_syscall_pre_impl_mq_unlink((long)(name)) #define __sanitizer_syscall_post_mq_unlink(res, name) \ __sanitizer_syscall_post_impl_mq_unlink(res, (long)(name)) #define __sanitizer_syscall_pre_mq_timedsend(mqdes, msg_ptr, msg_len, \ msg_prio, abs_timeout) \ __sanitizer_syscall_pre_impl_mq_timedsend((long)(mqdes), (long)(msg_ptr), \ (long)(msg_len), (long)(msg_prio), \ (long)(abs_timeout)) #define __sanitizer_syscall_post_mq_timedsend(res, mqdes, msg_ptr, msg_len, \ msg_prio, abs_timeout) \ __sanitizer_syscall_post_impl_mq_timedsend( \ res, (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \ (long)(abs_timeout)) #define __sanitizer_syscall_pre_mq_timedreceive(mqdes, msg_ptr, msg_len, \ msg_prio, abs_timeout) \ __sanitizer_syscall_pre_impl_mq_timedreceive( \ (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \ (long)(abs_timeout)) #define __sanitizer_syscall_post_mq_timedreceive(res, mqdes, msg_ptr, msg_len, \ msg_prio, abs_timeout) \ __sanitizer_syscall_post_impl_mq_timedreceive( \ res, (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \ (long)(abs_timeout)) #define __sanitizer_syscall_pre_mq_notify(mqdes, notification) \ __sanitizer_syscall_pre_impl_mq_notify((long)(mqdes), (long)(notification)) #define __sanitizer_syscall_post_mq_notify(res, mqdes, notification) \ __sanitizer_syscall_post_impl_mq_notify(res, (long)(mqdes), \ (long)(notification)) #define __sanitizer_syscall_pre_mq_getsetattr(mqdes, mqstat, omqstat) \ __sanitizer_syscall_pre_impl_mq_getsetattr((long)(mqdes), (long)(mqstat), \ (long)(omqstat)) #define __sanitizer_syscall_post_mq_getsetattr(res, mqdes, mqstat, omqstat) \ __sanitizer_syscall_post_impl_mq_getsetattr(res, (long)(mqdes), \ (long)(mqstat), (long)(omqstat)) #define __sanitizer_syscall_pre_pciconfig_iobase(which, bus, devfn) \ __sanitizer_syscall_pre_impl_pciconfig_iobase((long)(which), (long)(bus), \ (long)(devfn)) #define __sanitizer_syscall_post_pciconfig_iobase(res, which, bus, devfn) \ __sanitizer_syscall_post_impl_pciconfig_iobase(res, (long)(which), \ (long)(bus), (long)(devfn)) #define __sanitizer_syscall_pre_pciconfig_read(bus, dfn, off, len, buf) \ __sanitizer_syscall_pre_impl_pciconfig_read( \ (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf)) #define __sanitizer_syscall_post_pciconfig_read(res, bus, dfn, off, len, buf) \ __sanitizer_syscall_post_impl_pciconfig_read( \ res, (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf)) #define __sanitizer_syscall_pre_pciconfig_write(bus, dfn, off, len, buf) \ __sanitizer_syscall_pre_impl_pciconfig_write( \ (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf)) #define __sanitizer_syscall_post_pciconfig_write(res, bus, dfn, off, len, buf) \ __sanitizer_syscall_post_impl_pciconfig_write( \ res, (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf)) #define __sanitizer_syscall_pre_swapon(specialfile, swap_flags) \ __sanitizer_syscall_pre_impl_swapon((long)(specialfile), (long)(swap_flags)) #define __sanitizer_syscall_post_swapon(res, specialfile, swap_flags) \ __sanitizer_syscall_post_impl_swapon(res, (long)(specialfile), \ (long)(swap_flags)) #define __sanitizer_syscall_pre_swapoff(specialfile) \ __sanitizer_syscall_pre_impl_swapoff((long)(specialfile)) #define __sanitizer_syscall_post_swapoff(res, specialfile) \ __sanitizer_syscall_post_impl_swapoff(res, (long)(specialfile)) #define __sanitizer_syscall_pre_sysctl(args) \ __sanitizer_syscall_pre_impl_sysctl((long)(args)) #define __sanitizer_syscall_post_sysctl(res, args) \ __sanitizer_syscall_post_impl_sysctl(res, (long)(args)) #define __sanitizer_syscall_pre_sysinfo(info) \ __sanitizer_syscall_pre_impl_sysinfo((long)(info)) #define __sanitizer_syscall_post_sysinfo(res, info) \ __sanitizer_syscall_post_impl_sysinfo(res, (long)(info)) #define __sanitizer_syscall_pre_sysfs(option, arg1, arg2) \ __sanitizer_syscall_pre_impl_sysfs((long)(option), (long)(arg1), (long)(arg2)) #define __sanitizer_syscall_post_sysfs(res, option, arg1, arg2) \ __sanitizer_syscall_post_impl_sysfs(res, (long)(option), (long)(arg1), \ (long)(arg2)) #define __sanitizer_syscall_pre_syslog(type, buf, len) \ __sanitizer_syscall_pre_impl_syslog((long)(type), (long)(buf), (long)(len)) #define __sanitizer_syscall_post_syslog(res, type, buf, len) \ __sanitizer_syscall_post_impl_syslog(res, (long)(type), (long)(buf), \ (long)(len)) #define __sanitizer_syscall_pre_uselib(library) \ __sanitizer_syscall_pre_impl_uselib((long)(library)) #define __sanitizer_syscall_post_uselib(res, library) \ __sanitizer_syscall_post_impl_uselib(res, (long)(library)) #define __sanitizer_syscall_pre_ni_syscall() \ __sanitizer_syscall_pre_impl_ni_syscall() #define __sanitizer_syscall_post_ni_syscall(res) \ __sanitizer_syscall_post_impl_ni_syscall(res) #define __sanitizer_syscall_pre_ptrace(request, pid, addr, data) \ __sanitizer_syscall_pre_impl_ptrace((long)(request), (long)(pid), \ (long)(addr), (long)(data)) #define __sanitizer_syscall_post_ptrace(res, request, pid, addr, data) \ __sanitizer_syscall_post_impl_ptrace(res, (long)(request), (long)(pid), \ (long)(addr), (long)(data)) #define __sanitizer_syscall_pre_add_key(_type, _description, _payload, plen, \ destringid) \ __sanitizer_syscall_pre_impl_add_key((long)(_type), (long)(_description), \ (long)(_payload), (long)(plen), \ (long)(destringid)) #define __sanitizer_syscall_post_add_key(res, _type, _description, _payload, \ plen, destringid) \ __sanitizer_syscall_post_impl_add_key( \ res, (long)(_type), (long)(_description), (long)(_payload), \ (long)(plen), (long)(destringid)) #define __sanitizer_syscall_pre_request_key(_type, _description, \ _callout_info, destringid) \ __sanitizer_syscall_pre_impl_request_key( \ (long)(_type), (long)(_description), (long)(_callout_info), \ (long)(destringid)) #define __sanitizer_syscall_post_request_key(res, _type, _description, \ _callout_info, destringid) \ __sanitizer_syscall_post_impl_request_key( \ res, (long)(_type), (long)(_description), (long)(_callout_info), \ (long)(destringid)) #define __sanitizer_syscall_pre_keyctl(cmd, arg2, arg3, arg4, arg5) \ __sanitizer_syscall_pre_impl_keyctl((long)(cmd), (long)(arg2), (long)(arg3), \ (long)(arg4), (long)(arg5)) #define __sanitizer_syscall_post_keyctl(res, cmd, arg2, arg3, arg4, arg5) \ __sanitizer_syscall_post_impl_keyctl(res, (long)(cmd), (long)(arg2), \ (long)(arg3), (long)(arg4), \ (long)(arg5)) #define __sanitizer_syscall_pre_ioprio_set(which, who, ioprio) \ __sanitizer_syscall_pre_impl_ioprio_set((long)(which), (long)(who), \ (long)(ioprio)) #define __sanitizer_syscall_post_ioprio_set(res, which, who, ioprio) \ __sanitizer_syscall_post_impl_ioprio_set(res, (long)(which), (long)(who), \ (long)(ioprio)) #define __sanitizer_syscall_pre_ioprio_get(which, who) \ __sanitizer_syscall_pre_impl_ioprio_get((long)(which), (long)(who)) #define __sanitizer_syscall_post_ioprio_get(res, which, who) \ __sanitizer_syscall_post_impl_ioprio_get(res, (long)(which), (long)(who)) #define __sanitizer_syscall_pre_set_mempolicy(mode, nmask, maxnode) \ __sanitizer_syscall_pre_impl_set_mempolicy((long)(mode), (long)(nmask), \ (long)(maxnode)) #define __sanitizer_syscall_post_set_mempolicy(res, mode, nmask, maxnode) \ __sanitizer_syscall_post_impl_set_mempolicy(res, (long)(mode), \ (long)(nmask), (long)(maxnode)) #define __sanitizer_syscall_pre_migrate_pages(pid, maxnode, from, to) \ __sanitizer_syscall_pre_impl_migrate_pages((long)(pid), (long)(maxnode), \ (long)(from), (long)(to)) #define __sanitizer_syscall_post_migrate_pages(res, pid, maxnode, from, to) \ __sanitizer_syscall_post_impl_migrate_pages( \ res, (long)(pid), (long)(maxnode), (long)(from), (long)(to)) #define __sanitizer_syscall_pre_move_pages(pid, nr_pages, pages, nodes, \ status, flags) \ __sanitizer_syscall_pre_impl_move_pages((long)(pid), (long)(nr_pages), \ (long)(pages), (long)(nodes), \ (long)(status), (long)(flags)) #define __sanitizer_syscall_post_move_pages(res, pid, nr_pages, pages, nodes, \ status, flags) \ __sanitizer_syscall_post_impl_move_pages(res, (long)(pid), (long)(nr_pages), \ (long)(pages), (long)(nodes), \ (long)(status), (long)(flags)) #define __sanitizer_syscall_pre_mbind(start, len, mode, nmask, maxnode, flags) \ __sanitizer_syscall_pre_impl_mbind((long)(start), (long)(len), (long)(mode), \ (long)(nmask), (long)(maxnode), \ (long)(flags)) #define __sanitizer_syscall_post_mbind(res, start, len, mode, nmask, maxnode, \ flags) \ __sanitizer_syscall_post_impl_mbind(res, (long)(start), (long)(len), \ (long)(mode), (long)(nmask), \ (long)(maxnode), (long)(flags)) #define __sanitizer_syscall_pre_get_mempolicy(policy, nmask, maxnode, addr, \ flags) \ __sanitizer_syscall_pre_impl_get_mempolicy((long)(policy), (long)(nmask), \ (long)(maxnode), (long)(addr), \ (long)(flags)) #define __sanitizer_syscall_post_get_mempolicy(res, policy, nmask, maxnode, \ addr, flags) \ __sanitizer_syscall_post_impl_get_mempolicy(res, (long)(policy), \ (long)(nmask), (long)(maxnode), \ (long)(addr), (long)(flags)) #define __sanitizer_syscall_pre_inotify_init() \ __sanitizer_syscall_pre_impl_inotify_init() #define __sanitizer_syscall_post_inotify_init(res) \ __sanitizer_syscall_post_impl_inotify_init(res) #define __sanitizer_syscall_pre_inotify_init1(flags) \ __sanitizer_syscall_pre_impl_inotify_init1((long)(flags)) #define __sanitizer_syscall_post_inotify_init1(res, flags) \ __sanitizer_syscall_post_impl_inotify_init1(res, (long)(flags)) #define __sanitizer_syscall_pre_inotify_add_watch(fd, path, mask) \ __sanitizer_syscall_pre_impl_inotify_add_watch((long)(fd), (long)(path), \ (long)(mask)) #define __sanitizer_syscall_post_inotify_add_watch(res, fd, path, mask) \ __sanitizer_syscall_post_impl_inotify_add_watch(res, (long)(fd), \ (long)(path), (long)(mask)) #define __sanitizer_syscall_pre_inotify_rm_watch(fd, wd) \ __sanitizer_syscall_pre_impl_inotify_rm_watch((long)(fd), (long)(wd)) #define __sanitizer_syscall_post_inotify_rm_watch(res, fd, wd) \ __sanitizer_syscall_post_impl_inotify_rm_watch(res, (long)(fd), (long)(wd)) #define __sanitizer_syscall_pre_spu_run(fd, unpc, ustatus) \ __sanitizer_syscall_pre_impl_spu_run((long)(fd), (long)(unpc), \ (long)(ustatus)) #define __sanitizer_syscall_post_spu_run(res, fd, unpc, ustatus) \ __sanitizer_syscall_post_impl_spu_run(res, (long)(fd), (long)(unpc), \ (long)(ustatus)) #define __sanitizer_syscall_pre_spu_create(name, flags, mode, fd) \ __sanitizer_syscall_pre_impl_spu_create((long)(name), (long)(flags), \ (long)(mode), (long)(fd)) #define __sanitizer_syscall_post_spu_create(res, name, flags, mode, fd) \ __sanitizer_syscall_post_impl_spu_create(res, (long)(name), (long)(flags), \ (long)(mode), (long)(fd)) #define __sanitizer_syscall_pre_mknodat(dfd, filename, mode, dev) \ __sanitizer_syscall_pre_impl_mknodat((long)(dfd), (long)(filename), \ (long)(mode), (long)(dev)) #define __sanitizer_syscall_post_mknodat(res, dfd, filename, mode, dev) \ __sanitizer_syscall_post_impl_mknodat(res, (long)(dfd), (long)(filename), \ (long)(mode), (long)(dev)) #define __sanitizer_syscall_pre_mkdirat(dfd, pathname, mode) \ __sanitizer_syscall_pre_impl_mkdirat((long)(dfd), (long)(pathname), \ (long)(mode)) #define __sanitizer_syscall_post_mkdirat(res, dfd, pathname, mode) \ __sanitizer_syscall_post_impl_mkdirat(res, (long)(dfd), (long)(pathname), \ (long)(mode)) #define __sanitizer_syscall_pre_unlinkat(dfd, pathname, flag) \ __sanitizer_syscall_pre_impl_unlinkat((long)(dfd), (long)(pathname), \ (long)(flag)) #define __sanitizer_syscall_post_unlinkat(res, dfd, pathname, flag) \ __sanitizer_syscall_post_impl_unlinkat(res, (long)(dfd), (long)(pathname), \ (long)(flag)) #define __sanitizer_syscall_pre_symlinkat(oldname, newdfd, newname) \ __sanitizer_syscall_pre_impl_symlinkat((long)(oldname), (long)(newdfd), \ (long)(newname)) #define __sanitizer_syscall_post_symlinkat(res, oldname, newdfd, newname) \ __sanitizer_syscall_post_impl_symlinkat(res, (long)(oldname), \ (long)(newdfd), (long)(newname)) #define __sanitizer_syscall_pre_linkat(olddfd, oldname, newdfd, newname, \ flags) \ __sanitizer_syscall_pre_impl_linkat((long)(olddfd), (long)(oldname), \ (long)(newdfd), (long)(newname), \ (long)(flags)) #define __sanitizer_syscall_post_linkat(res, olddfd, oldname, newdfd, newname, \ flags) \ __sanitizer_syscall_post_impl_linkat(res, (long)(olddfd), (long)(oldname), \ (long)(newdfd), (long)(newname), \ (long)(flags)) #define __sanitizer_syscall_pre_renameat(olddfd, oldname, newdfd, newname) \ __sanitizer_syscall_pre_impl_renameat((long)(olddfd), (long)(oldname), \ (long)(newdfd), (long)(newname)) #define __sanitizer_syscall_post_renameat(res, olddfd, oldname, newdfd, \ newname) \ __sanitizer_syscall_post_impl_renameat(res, (long)(olddfd), (long)(oldname), \ (long)(newdfd), (long)(newname)) #define __sanitizer_syscall_pre_futimesat(dfd, filename, utimes) \ __sanitizer_syscall_pre_impl_futimesat((long)(dfd), (long)(filename), \ (long)(utimes)) #define __sanitizer_syscall_post_futimesat(res, dfd, filename, utimes) \ __sanitizer_syscall_post_impl_futimesat(res, (long)(dfd), (long)(filename), \ (long)(utimes)) #define __sanitizer_syscall_pre_faccessat(dfd, filename, mode) \ __sanitizer_syscall_pre_impl_faccessat((long)(dfd), (long)(filename), \ (long)(mode)) #define __sanitizer_syscall_post_faccessat(res, dfd, filename, mode) \ __sanitizer_syscall_post_impl_faccessat(res, (long)(dfd), (long)(filename), \ (long)(mode)) #define __sanitizer_syscall_pre_fchmodat(dfd, filename, mode) \ __sanitizer_syscall_pre_impl_fchmodat((long)(dfd), (long)(filename), \ (long)(mode)) #define __sanitizer_syscall_post_fchmodat(res, dfd, filename, mode) \ __sanitizer_syscall_post_impl_fchmodat(res, (long)(dfd), (long)(filename), \ (long)(mode)) #define __sanitizer_syscall_pre_fchownat(dfd, filename, user, group, flag) \ __sanitizer_syscall_pre_impl_fchownat((long)(dfd), (long)(filename), \ (long)(user), (long)(group), \ (long)(flag)) #define __sanitizer_syscall_post_fchownat(res, dfd, filename, user, group, \ flag) \ __sanitizer_syscall_post_impl_fchownat(res, (long)(dfd), (long)(filename), \ (long)(user), (long)(group), \ (long)(flag)) #define __sanitizer_syscall_pre_openat(dfd, filename, flags, mode) \ __sanitizer_syscall_pre_impl_openat((long)(dfd), (long)(filename), \ (long)(flags), (long)(mode)) #define __sanitizer_syscall_post_openat(res, dfd, filename, flags, mode) \ __sanitizer_syscall_post_impl_openat(res, (long)(dfd), (long)(filename), \ (long)(flags), (long)(mode)) #define __sanitizer_syscall_pre_newfstatat(dfd, filename, statbuf, flag) \ __sanitizer_syscall_pre_impl_newfstatat((long)(dfd), (long)(filename), \ (long)(statbuf), (long)(flag)) #define __sanitizer_syscall_post_newfstatat(res, dfd, filename, statbuf, flag) \ __sanitizer_syscall_post_impl_newfstatat(res, (long)(dfd), (long)(filename), \ (long)(statbuf), (long)(flag)) #define __sanitizer_syscall_pre_fstatat64(dfd, filename, statbuf, flag) \ __sanitizer_syscall_pre_impl_fstatat64((long)(dfd), (long)(filename), \ (long)(statbuf), (long)(flag)) #define __sanitizer_syscall_post_fstatat64(res, dfd, filename, statbuf, flag) \ __sanitizer_syscall_post_impl_fstatat64(res, (long)(dfd), (long)(filename), \ (long)(statbuf), (long)(flag)) #define __sanitizer_syscall_pre_readlinkat(dfd, path, buf, bufsiz) \ __sanitizer_syscall_pre_impl_readlinkat((long)(dfd), (long)(path), \ (long)(buf), (long)(bufsiz)) #define __sanitizer_syscall_post_readlinkat(res, dfd, path, buf, bufsiz) \ __sanitizer_syscall_post_impl_readlinkat(res, (long)(dfd), (long)(path), \ (long)(buf), (long)(bufsiz)) #define __sanitizer_syscall_pre_utimensat(dfd, filename, utimes, flags) \ __sanitizer_syscall_pre_impl_utimensat((long)(dfd), (long)(filename), \ (long)(utimes), (long)(flags)) #define __sanitizer_syscall_post_utimensat(res, dfd, filename, utimes, flags) \ __sanitizer_syscall_post_impl_utimensat(res, (long)(dfd), (long)(filename), \ (long)(utimes), (long)(flags)) #define __sanitizer_syscall_pre_unshare(unshare_flags) \ __sanitizer_syscall_pre_impl_unshare((long)(unshare_flags)) #define __sanitizer_syscall_post_unshare(res, unshare_flags) \ __sanitizer_syscall_post_impl_unshare(res, (long)(unshare_flags)) #define __sanitizer_syscall_pre_splice(fd_in, off_in, fd_out, off_out, len, \ flags) \ __sanitizer_syscall_pre_impl_splice((long)(fd_in), (long)(off_in), \ (long)(fd_out), (long)(off_out), \ (long)(len), (long)(flags)) #define __sanitizer_syscall_post_splice(res, fd_in, off_in, fd_out, off_out, \ len, flags) \ __sanitizer_syscall_post_impl_splice(res, (long)(fd_in), (long)(off_in), \ (long)(fd_out), (long)(off_out), \ (long)(len), (long)(flags)) #define __sanitizer_syscall_pre_vmsplice(fd, iov, nr_segs, flags) \ __sanitizer_syscall_pre_impl_vmsplice((long)(fd), (long)(iov), \ (long)(nr_segs), (long)(flags)) #define __sanitizer_syscall_post_vmsplice(res, fd, iov, nr_segs, flags) \ __sanitizer_syscall_post_impl_vmsplice(res, (long)(fd), (long)(iov), \ (long)(nr_segs), (long)(flags)) #define __sanitizer_syscall_pre_tee(fdin, fdout, len, flags) \ __sanitizer_syscall_pre_impl_tee((long)(fdin), (long)(fdout), (long)(len), \ (long)(flags)) #define __sanitizer_syscall_post_tee(res, fdin, fdout, len, flags) \ __sanitizer_syscall_post_impl_tee(res, (long)(fdin), (long)(fdout), \ (long)(len), (long)(flags)) #define __sanitizer_syscall_pre_get_robust_list(pid, head_ptr, len_ptr) \ __sanitizer_syscall_pre_impl_get_robust_list((long)(pid), (long)(head_ptr), \ (long)(len_ptr)) #define __sanitizer_syscall_post_get_robust_list(res, pid, head_ptr, len_ptr) \ __sanitizer_syscall_post_impl_get_robust_list( \ res, (long)(pid), (long)(head_ptr), (long)(len_ptr)) #define __sanitizer_syscall_pre_set_robust_list(head, len) \ __sanitizer_syscall_pre_impl_set_robust_list((long)(head), (long)(len)) #define __sanitizer_syscall_post_set_robust_list(res, head, len) \ __sanitizer_syscall_post_impl_set_robust_list(res, (long)(head), (long)(len)) #define __sanitizer_syscall_pre_getcpu(cpu, node, cache) \ __sanitizer_syscall_pre_impl_getcpu((long)(cpu), (long)(node), (long)(cache)) #define __sanitizer_syscall_post_getcpu(res, cpu, node, cache) \ __sanitizer_syscall_post_impl_getcpu(res, (long)(cpu), (long)(node), \ (long)(cache)) #define __sanitizer_syscall_pre_signalfd(ufd, user_mask, sizemask) \ __sanitizer_syscall_pre_impl_signalfd((long)(ufd), (long)(user_mask), \ (long)(sizemask)) #define __sanitizer_syscall_post_signalfd(res, ufd, user_mask, sizemask) \ __sanitizer_syscall_post_impl_signalfd(res, (long)(ufd), (long)(user_mask), \ (long)(sizemask)) #define __sanitizer_syscall_pre_signalfd4(ufd, user_mask, sizemask, flags) \ __sanitizer_syscall_pre_impl_signalfd4((long)(ufd), (long)(user_mask), \ (long)(sizemask), (long)(flags)) #define __sanitizer_syscall_post_signalfd4(res, ufd, user_mask, sizemask, \ flags) \ __sanitizer_syscall_post_impl_signalfd4(res, (long)(ufd), (long)(user_mask), \ (long)(sizemask), (long)(flags)) #define __sanitizer_syscall_pre_timerfd_create(clockid, flags) \ __sanitizer_syscall_pre_impl_timerfd_create((long)(clockid), (long)(flags)) #define __sanitizer_syscall_post_timerfd_create(res, clockid, flags) \ __sanitizer_syscall_post_impl_timerfd_create(res, (long)(clockid), \ (long)(flags)) #define __sanitizer_syscall_pre_timerfd_settime(ufd, flags, utmr, otmr) \ __sanitizer_syscall_pre_impl_timerfd_settime((long)(ufd), (long)(flags), \ (long)(utmr), (long)(otmr)) #define __sanitizer_syscall_post_timerfd_settime(res, ufd, flags, utmr, otmr) \ __sanitizer_syscall_post_impl_timerfd_settime( \ res, (long)(ufd), (long)(flags), (long)(utmr), (long)(otmr)) #define __sanitizer_syscall_pre_timerfd_gettime(ufd, otmr) \ __sanitizer_syscall_pre_impl_timerfd_gettime((long)(ufd), (long)(otmr)) #define __sanitizer_syscall_post_timerfd_gettime(res, ufd, otmr) \ __sanitizer_syscall_post_impl_timerfd_gettime(res, (long)(ufd), (long)(otmr)) #define __sanitizer_syscall_pre_eventfd(count) \ __sanitizer_syscall_pre_impl_eventfd((long)(count)) #define __sanitizer_syscall_post_eventfd(res, count) \ __sanitizer_syscall_post_impl_eventfd(res, (long)(count)) #define __sanitizer_syscall_pre_eventfd2(count, flags) \ __sanitizer_syscall_pre_impl_eventfd2((long)(count), (long)(flags)) #define __sanitizer_syscall_post_eventfd2(res, count, flags) \ __sanitizer_syscall_post_impl_eventfd2(res, (long)(count), (long)(flags)) #define __sanitizer_syscall_pre_old_readdir(arg0, arg1, arg2) \ __sanitizer_syscall_pre_impl_old_readdir((long)(arg0), (long)(arg1), \ (long)(arg2)) #define __sanitizer_syscall_post_old_readdir(res, arg0, arg1, arg2) \ __sanitizer_syscall_post_impl_old_readdir(res, (long)(arg0), (long)(arg1), \ (long)(arg2)) #define __sanitizer_syscall_pre_pselect6(arg0, arg1, arg2, arg3, arg4, arg5) \ __sanitizer_syscall_pre_impl_pselect6((long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3), \ (long)(arg4), (long)(arg5)) #define __sanitizer_syscall_post_pselect6(res, arg0, arg1, arg2, arg3, arg4, \ arg5) \ __sanitizer_syscall_post_impl_pselect6(res, (long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3), \ (long)(arg4), (long)(arg5)) #define __sanitizer_syscall_pre_ppoll(arg0, arg1, arg2, arg3, arg4) \ __sanitizer_syscall_pre_impl_ppoll((long)(arg0), (long)(arg1), (long)(arg2), \ (long)(arg3), (long)(arg4)) #define __sanitizer_syscall_post_ppoll(res, arg0, arg1, arg2, arg3, arg4) \ __sanitizer_syscall_post_impl_ppoll(res, (long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3), \ (long)(arg4)) #define __sanitizer_syscall_pre_syncfs(fd) \ __sanitizer_syscall_pre_impl_syncfs((long)(fd)) #define __sanitizer_syscall_post_syncfs(res, fd) \ __sanitizer_syscall_post_impl_syncfs(res, (long)(fd)) #define __sanitizer_syscall_pre_perf_event_open(attr_uptr, pid, cpu, group_fd, \ flags) \ __sanitizer_syscall_pre_impl_perf_event_open((long)(attr_uptr), (long)(pid), \ (long)(cpu), (long)(group_fd), \ (long)(flags)) #define __sanitizer_syscall_post_perf_event_open(res, attr_uptr, pid, cpu, \ group_fd, flags) \ __sanitizer_syscall_post_impl_perf_event_open( \ res, (long)(attr_uptr), (long)(pid), (long)(cpu), (long)(group_fd), \ (long)(flags)) #define __sanitizer_syscall_pre_mmap_pgoff(addr, len, prot, flags, fd, pgoff) \ __sanitizer_syscall_pre_impl_mmap_pgoff((long)(addr), (long)(len), \ (long)(prot), (long)(flags), \ (long)(fd), (long)(pgoff)) #define __sanitizer_syscall_post_mmap_pgoff(res, addr, len, prot, flags, fd, \ pgoff) \ __sanitizer_syscall_post_impl_mmap_pgoff(res, (long)(addr), (long)(len), \ (long)(prot), (long)(flags), \ (long)(fd), (long)(pgoff)) #define __sanitizer_syscall_pre_old_mmap(arg) \ __sanitizer_syscall_pre_impl_old_mmap((long)(arg)) #define __sanitizer_syscall_post_old_mmap(res, arg) \ __sanitizer_syscall_post_impl_old_mmap(res, (long)(arg)) #define __sanitizer_syscall_pre_name_to_handle_at(dfd, name, handle, mnt_id, \ flag) \ __sanitizer_syscall_pre_impl_name_to_handle_at( \ (long)(dfd), (long)(name), (long)(handle), (long)(mnt_id), (long)(flag)) #define __sanitizer_syscall_post_name_to_handle_at(res, dfd, name, handle, \ mnt_id, flag) \ __sanitizer_syscall_post_impl_name_to_handle_at( \ res, (long)(dfd), (long)(name), (long)(handle), (long)(mnt_id), \ (long)(flag)) #define __sanitizer_syscall_pre_open_by_handle_at(mountdirfd, handle, flags) \ __sanitizer_syscall_pre_impl_open_by_handle_at( \ (long)(mountdirfd), (long)(handle), (long)(flags)) #define __sanitizer_syscall_post_open_by_handle_at(res, mountdirfd, handle, \ flags) \ __sanitizer_syscall_post_impl_open_by_handle_at( \ res, (long)(mountdirfd), (long)(handle), (long)(flags)) #define __sanitizer_syscall_pre_setns(fd, nstype) \ __sanitizer_syscall_pre_impl_setns((long)(fd), (long)(nstype)) #define __sanitizer_syscall_post_setns(res, fd, nstype) \ __sanitizer_syscall_post_impl_setns(res, (long)(fd), (long)(nstype)) #define __sanitizer_syscall_pre_process_vm_readv(pid, lvec, liovcnt, rvec, \ riovcnt, flags) \ __sanitizer_syscall_pre_impl_process_vm_readv( \ (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \ (long)(riovcnt), (long)(flags)) #define __sanitizer_syscall_post_process_vm_readv(res, pid, lvec, liovcnt, \ rvec, riovcnt, flags) \ __sanitizer_syscall_post_impl_process_vm_readv( \ res, (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \ (long)(riovcnt), (long)(flags)) #define __sanitizer_syscall_pre_process_vm_writev(pid, lvec, liovcnt, rvec, \ riovcnt, flags) \ __sanitizer_syscall_pre_impl_process_vm_writev( \ (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \ (long)(riovcnt), (long)(flags)) #define __sanitizer_syscall_post_process_vm_writev(res, pid, lvec, liovcnt, \ rvec, riovcnt, flags) \ __sanitizer_syscall_post_impl_process_vm_writev( \ res, (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \ (long)(riovcnt), (long)(flags)) #define __sanitizer_syscall_pre_fork() \ __sanitizer_syscall_pre_impl_fork() #define __sanitizer_syscall_post_fork(res) \ __sanitizer_syscall_post_impl_fork(res) #define __sanitizer_syscall_pre_vfork() \ __sanitizer_syscall_pre_impl_vfork() #define __sanitizer_syscall_post_vfork(res) \ __sanitizer_syscall_post_impl_vfork(res) +#define __sanitizer_syscall_pre_sigaction(signum, act, oldact) \ + __sanitizer_syscall_pre_impl_sigaction((long)signum, (long)act, (long)oldact) +#define __sanitizer_syscall_post_sigaction(res, signum, act, oldact) \ + __sanitizer_syscall_post_impl_sigaction(res, (long)signum, (long)act, \ + (long)oldact) +#define __sanitizer_syscall_pre_rt_sigaction(signum, act, oldact, sz) \ + __sanitizer_syscall_pre_impl_rt_sigaction((long)signum, (long)act, \ + (long)oldact, (long)sz) +#define __sanitizer_syscall_post_rt_sigaction(res, signum, act, oldact, sz) \ + __sanitizer_syscall_post_impl_rt_sigaction(res, (long)signum, (long)act, \ + (long)oldact, (long)sz) // And now a few syscalls we don't handle yet. #define __sanitizer_syscall_pre_afs_syscall(...) #define __sanitizer_syscall_pre_arch_prctl(...) #define __sanitizer_syscall_pre_break(...) #define __sanitizer_syscall_pre_chown32(...) #define __sanitizer_syscall_pre_clone(...) #define __sanitizer_syscall_pre_create_module(...) #define __sanitizer_syscall_pre_epoll_ctl_old(...) #define __sanitizer_syscall_pre_epoll_wait_old(...) #define __sanitizer_syscall_pre_execve(...) #define __sanitizer_syscall_pre_fadvise64(...) #define __sanitizer_syscall_pre_fadvise64_64(...) #define __sanitizer_syscall_pre_fallocate(...) #define __sanitizer_syscall_pre_fanotify_init(...) #define __sanitizer_syscall_pre_fanotify_mark(...) #define __sanitizer_syscall_pre_fchown32(...) #define __sanitizer_syscall_pre_ftime(...) #define __sanitizer_syscall_pre_ftruncate64(...) #define __sanitizer_syscall_pre_futex(...) #define __sanitizer_syscall_pre_getegid32(...) #define __sanitizer_syscall_pre_geteuid32(...) #define __sanitizer_syscall_pre_getgid32(...) #define __sanitizer_syscall_pre_getgroups32(...) #define __sanitizer_syscall_pre_get_kernel_syms(...) #define __sanitizer_syscall_pre_getpmsg(...) #define __sanitizer_syscall_pre_getresgid32(...) #define __sanitizer_syscall_pre_getresuid32(...) #define __sanitizer_syscall_pre_get_thread_area(...) #define __sanitizer_syscall_pre_getuid32(...) #define __sanitizer_syscall_pre_gtty(...) #define __sanitizer_syscall_pre_idle(...) #define __sanitizer_syscall_pre_iopl(...) #define __sanitizer_syscall_pre_lchown32(...) #define __sanitizer_syscall_pre__llseek(...) #define __sanitizer_syscall_pre_lock(...) #define __sanitizer_syscall_pre_madvise1(...) #define __sanitizer_syscall_pre_mmap(...) #define __sanitizer_syscall_pre_mmap2(...) #define __sanitizer_syscall_pre_modify_ldt(...) #define __sanitizer_syscall_pre_mpx(...) #define __sanitizer_syscall_pre__newselect(...) #define __sanitizer_syscall_pre_nfsservctl(...) #define __sanitizer_syscall_pre_oldfstat(...) #define __sanitizer_syscall_pre_oldlstat(...) #define __sanitizer_syscall_pre_oldolduname(...) #define __sanitizer_syscall_pre_oldstat(...) #define __sanitizer_syscall_pre_prctl(...) #define __sanitizer_syscall_pre_prof(...) #define __sanitizer_syscall_pre_profil(...) #define __sanitizer_syscall_pre_putpmsg(...) #define __sanitizer_syscall_pre_query_module(...) #define __sanitizer_syscall_pre_readahead(...) #define __sanitizer_syscall_pre_readdir(...) -#define __sanitizer_syscall_pre_rt_sigaction(...) #define __sanitizer_syscall_pre_rt_sigreturn(...) #define __sanitizer_syscall_pre_rt_sigsuspend(...) #define __sanitizer_syscall_pre_security(...) #define __sanitizer_syscall_pre_setfsgid32(...) #define __sanitizer_syscall_pre_setfsuid32(...) #define __sanitizer_syscall_pre_setgid32(...) #define __sanitizer_syscall_pre_setgroups32(...) #define __sanitizer_syscall_pre_setregid32(...) #define __sanitizer_syscall_pre_setresgid32(...) #define __sanitizer_syscall_pre_setresuid32(...) #define __sanitizer_syscall_pre_setreuid32(...) #define __sanitizer_syscall_pre_set_thread_area(...) #define __sanitizer_syscall_pre_setuid32(...) -#define __sanitizer_syscall_pre_sigaction(...) #define __sanitizer_syscall_pre_sigaltstack(...) #define __sanitizer_syscall_pre_sigreturn(...) #define __sanitizer_syscall_pre_sigsuspend(...) #define __sanitizer_syscall_pre_stty(...) #define __sanitizer_syscall_pre_sync_file_range(...) #define __sanitizer_syscall_pre__sysctl(...) #define __sanitizer_syscall_pre_truncate64(...) #define __sanitizer_syscall_pre_tuxcall(...) #define __sanitizer_syscall_pre_ugetrlimit(...) #define __sanitizer_syscall_pre_ulimit(...) #define __sanitizer_syscall_pre_umount2(...) #define __sanitizer_syscall_pre_vm86(...) #define __sanitizer_syscall_pre_vm86old(...) #define __sanitizer_syscall_pre_vserver(...) #define __sanitizer_syscall_post_afs_syscall(res, ...) #define __sanitizer_syscall_post_arch_prctl(res, ...) #define __sanitizer_syscall_post_break(res, ...) #define __sanitizer_syscall_post_chown32(res, ...) #define __sanitizer_syscall_post_clone(res, ...) #define __sanitizer_syscall_post_create_module(res, ...) #define __sanitizer_syscall_post_epoll_ctl_old(res, ...) #define __sanitizer_syscall_post_epoll_wait_old(res, ...) #define __sanitizer_syscall_post_execve(res, ...) #define __sanitizer_syscall_post_fadvise64(res, ...) #define __sanitizer_syscall_post_fadvise64_64(res, ...) #define __sanitizer_syscall_post_fallocate(res, ...) #define __sanitizer_syscall_post_fanotify_init(res, ...) #define __sanitizer_syscall_post_fanotify_mark(res, ...) #define __sanitizer_syscall_post_fchown32(res, ...) #define __sanitizer_syscall_post_ftime(res, ...) #define __sanitizer_syscall_post_ftruncate64(res, ...) #define __sanitizer_syscall_post_futex(res, ...) #define __sanitizer_syscall_post_getegid32(res, ...) #define __sanitizer_syscall_post_geteuid32(res, ...) #define __sanitizer_syscall_post_getgid32(res, ...) #define __sanitizer_syscall_post_getgroups32(res, ...) #define __sanitizer_syscall_post_get_kernel_syms(res, ...) #define __sanitizer_syscall_post_getpmsg(res, ...) #define __sanitizer_syscall_post_getresgid32(res, ...) #define __sanitizer_syscall_post_getresuid32(res, ...) #define __sanitizer_syscall_post_get_thread_area(res, ...) #define __sanitizer_syscall_post_getuid32(res, ...) #define __sanitizer_syscall_post_gtty(res, ...) #define __sanitizer_syscall_post_idle(res, ...) #define __sanitizer_syscall_post_iopl(res, ...) #define __sanitizer_syscall_post_lchown32(res, ...) #define __sanitizer_syscall_post__llseek(res, ...) #define __sanitizer_syscall_post_lock(res, ...) #define __sanitizer_syscall_post_madvise1(res, ...) #define __sanitizer_syscall_post_mmap2(res, ...) #define __sanitizer_syscall_post_mmap(res, ...) #define __sanitizer_syscall_post_modify_ldt(res, ...) #define __sanitizer_syscall_post_mpx(res, ...) #define __sanitizer_syscall_post__newselect(res, ...) #define __sanitizer_syscall_post_nfsservctl(res, ...) #define __sanitizer_syscall_post_oldfstat(res, ...) #define __sanitizer_syscall_post_oldlstat(res, ...) #define __sanitizer_syscall_post_oldolduname(res, ...) #define __sanitizer_syscall_post_oldstat(res, ...) #define __sanitizer_syscall_post_prctl(res, ...) #define __sanitizer_syscall_post_profil(res, ...) #define __sanitizer_syscall_post_prof(res, ...) #define __sanitizer_syscall_post_putpmsg(res, ...) #define __sanitizer_syscall_post_query_module(res, ...) #define __sanitizer_syscall_post_readahead(res, ...) #define __sanitizer_syscall_post_readdir(res, ...) -#define __sanitizer_syscall_post_rt_sigaction(res, ...) #define __sanitizer_syscall_post_rt_sigreturn(res, ...) #define __sanitizer_syscall_post_rt_sigsuspend(res, ...) #define __sanitizer_syscall_post_security(res, ...) #define __sanitizer_syscall_post_setfsgid32(res, ...) #define __sanitizer_syscall_post_setfsuid32(res, ...) #define __sanitizer_syscall_post_setgid32(res, ...) #define __sanitizer_syscall_post_setgroups32(res, ...) #define __sanitizer_syscall_post_setregid32(res, ...) #define __sanitizer_syscall_post_setresgid32(res, ...) #define __sanitizer_syscall_post_setresuid32(res, ...) #define __sanitizer_syscall_post_setreuid32(res, ...) #define __sanitizer_syscall_post_set_thread_area(res, ...) #define __sanitizer_syscall_post_setuid32(res, ...) -#define __sanitizer_syscall_post_sigaction(res, ...) #define __sanitizer_syscall_post_sigaltstack(res, ...) #define __sanitizer_syscall_post_sigreturn(res, ...) #define __sanitizer_syscall_post_sigsuspend(res, ...) #define __sanitizer_syscall_post_stty(res, ...) #define __sanitizer_syscall_post_sync_file_range(res, ...) #define __sanitizer_syscall_post__sysctl(res, ...) #define __sanitizer_syscall_post_truncate64(res, ...) #define __sanitizer_syscall_post_tuxcall(res, ...) #define __sanitizer_syscall_post_ugetrlimit(res, ...) #define __sanitizer_syscall_post_ulimit(res, ...) #define __sanitizer_syscall_post_umount2(res, ...) #define __sanitizer_syscall_post_vm86old(res, ...) #define __sanitizer_syscall_post_vm86(res, ...) #define __sanitizer_syscall_post_vserver(res, ...) #ifdef __cplusplus extern "C" { #endif // Private declarations. Do not call directly from user code. Use macros above. void __sanitizer_syscall_pre_impl_time(long tloc); void __sanitizer_syscall_post_impl_time(long res, long tloc); void __sanitizer_syscall_pre_impl_stime(long tptr); void __sanitizer_syscall_post_impl_stime(long res, long tptr); void __sanitizer_syscall_pre_impl_gettimeofday(long tv, long tz); void __sanitizer_syscall_post_impl_gettimeofday(long res, long tv, long tz); void __sanitizer_syscall_pre_impl_settimeofday(long tv, long tz); void __sanitizer_syscall_post_impl_settimeofday(long res, long tv, long tz); void __sanitizer_syscall_pre_impl_adjtimex(long txc_p); void __sanitizer_syscall_post_impl_adjtimex(long res, long txc_p); void __sanitizer_syscall_pre_impl_times(long tbuf); void __sanitizer_syscall_post_impl_times(long res, long tbuf); void __sanitizer_syscall_pre_impl_gettid(); void __sanitizer_syscall_post_impl_gettid(long res); void __sanitizer_syscall_pre_impl_nanosleep(long rqtp, long rmtp); void __sanitizer_syscall_post_impl_nanosleep(long res, long rqtp, long rmtp); void __sanitizer_syscall_pre_impl_alarm(long seconds); void __sanitizer_syscall_post_impl_alarm(long res, long seconds); void __sanitizer_syscall_pre_impl_getpid(); void __sanitizer_syscall_post_impl_getpid(long res); void __sanitizer_syscall_pre_impl_getppid(); void __sanitizer_syscall_post_impl_getppid(long res); void __sanitizer_syscall_pre_impl_getuid(); void __sanitizer_syscall_post_impl_getuid(long res); void __sanitizer_syscall_pre_impl_geteuid(); void __sanitizer_syscall_post_impl_geteuid(long res); void __sanitizer_syscall_pre_impl_getgid(); void __sanitizer_syscall_post_impl_getgid(long res); void __sanitizer_syscall_pre_impl_getegid(); void __sanitizer_syscall_post_impl_getegid(long res); void __sanitizer_syscall_pre_impl_getresuid(long ruid, long euid, long suid); void __sanitizer_syscall_post_impl_getresuid(long res, long ruid, long euid, long suid); void __sanitizer_syscall_pre_impl_getresgid(long rgid, long egid, long sgid); void __sanitizer_syscall_post_impl_getresgid(long res, long rgid, long egid, long sgid); void __sanitizer_syscall_pre_impl_getpgid(long pid); void __sanitizer_syscall_post_impl_getpgid(long res, long pid); void __sanitizer_syscall_pre_impl_getpgrp(); void __sanitizer_syscall_post_impl_getpgrp(long res); void __sanitizer_syscall_pre_impl_getsid(long pid); void __sanitizer_syscall_post_impl_getsid(long res, long pid); void __sanitizer_syscall_pre_impl_getgroups(long gidsetsize, long grouplist); void __sanitizer_syscall_post_impl_getgroups(long res, long gidsetsize, long grouplist); void __sanitizer_syscall_pre_impl_setregid(long rgid, long egid); void __sanitizer_syscall_post_impl_setregid(long res, long rgid, long egid); void __sanitizer_syscall_pre_impl_setgid(long gid); void __sanitizer_syscall_post_impl_setgid(long res, long gid); void __sanitizer_syscall_pre_impl_setreuid(long ruid, long euid); void __sanitizer_syscall_post_impl_setreuid(long res, long ruid, long euid); void __sanitizer_syscall_pre_impl_setuid(long uid); void __sanitizer_syscall_post_impl_setuid(long res, long uid); void __sanitizer_syscall_pre_impl_setresuid(long ruid, long euid, long suid); void __sanitizer_syscall_post_impl_setresuid(long res, long ruid, long euid, long suid); void __sanitizer_syscall_pre_impl_setresgid(long rgid, long egid, long sgid); void __sanitizer_syscall_post_impl_setresgid(long res, long rgid, long egid, long sgid); void __sanitizer_syscall_pre_impl_setfsuid(long uid); void __sanitizer_syscall_post_impl_setfsuid(long res, long uid); void __sanitizer_syscall_pre_impl_setfsgid(long gid); void __sanitizer_syscall_post_impl_setfsgid(long res, long gid); void __sanitizer_syscall_pre_impl_setpgid(long pid, long pgid); void __sanitizer_syscall_post_impl_setpgid(long res, long pid, long pgid); void __sanitizer_syscall_pre_impl_setsid(); void __sanitizer_syscall_post_impl_setsid(long res); void __sanitizer_syscall_pre_impl_setgroups(long gidsetsize, long grouplist); void __sanitizer_syscall_post_impl_setgroups(long res, long gidsetsize, long grouplist); void __sanitizer_syscall_pre_impl_acct(long name); void __sanitizer_syscall_post_impl_acct(long res, long name); void __sanitizer_syscall_pre_impl_capget(long header, long dataptr); void __sanitizer_syscall_post_impl_capget(long res, long header, long dataptr); void __sanitizer_syscall_pre_impl_capset(long header, long data); void __sanitizer_syscall_post_impl_capset(long res, long header, long data); void __sanitizer_syscall_pre_impl_personality(long personality); void __sanitizer_syscall_post_impl_personality(long res, long personality); void __sanitizer_syscall_pre_impl_sigpending(long set); void __sanitizer_syscall_post_impl_sigpending(long res, long set); void __sanitizer_syscall_pre_impl_sigprocmask(long how, long set, long oset); void __sanitizer_syscall_post_impl_sigprocmask(long res, long how, long set, long oset); void __sanitizer_syscall_pre_impl_getitimer(long which, long value); void __sanitizer_syscall_post_impl_getitimer(long res, long which, long value); void __sanitizer_syscall_pre_impl_setitimer(long which, long value, long ovalue); void __sanitizer_syscall_post_impl_setitimer(long res, long which, long value, long ovalue); void __sanitizer_syscall_pre_impl_timer_create(long which_clock, long timer_event_spec, long created_timer_id); void __sanitizer_syscall_post_impl_timer_create(long res, long which_clock, long timer_event_spec, long created_timer_id); void __sanitizer_syscall_pre_impl_timer_gettime(long timer_id, long setting); void __sanitizer_syscall_post_impl_timer_gettime(long res, long timer_id, long setting); void __sanitizer_syscall_pre_impl_timer_getoverrun(long timer_id); void __sanitizer_syscall_post_impl_timer_getoverrun(long res, long timer_id); void __sanitizer_syscall_pre_impl_timer_settime(long timer_id, long flags, long new_setting, long old_setting); void __sanitizer_syscall_post_impl_timer_settime(long res, long timer_id, long flags, long new_setting, long old_setting); void __sanitizer_syscall_pre_impl_timer_delete(long timer_id); void __sanitizer_syscall_post_impl_timer_delete(long res, long timer_id); void __sanitizer_syscall_pre_impl_clock_settime(long which_clock, long tp); void __sanitizer_syscall_post_impl_clock_settime(long res, long which_clock, long tp); void __sanitizer_syscall_pre_impl_clock_gettime(long which_clock, long tp); void __sanitizer_syscall_post_impl_clock_gettime(long res, long which_clock, long tp); void __sanitizer_syscall_pre_impl_clock_adjtime(long which_clock, long tx); void __sanitizer_syscall_post_impl_clock_adjtime(long res, long which_clock, long tx); void __sanitizer_syscall_pre_impl_clock_getres(long which_clock, long tp); void __sanitizer_syscall_post_impl_clock_getres(long res, long which_clock, long tp); void __sanitizer_syscall_pre_impl_clock_nanosleep(long which_clock, long flags, long rqtp, long rmtp); void __sanitizer_syscall_post_impl_clock_nanosleep(long res, long which_clock, long flags, long rqtp, long rmtp); void __sanitizer_syscall_pre_impl_nice(long increment); void __sanitizer_syscall_post_impl_nice(long res, long increment); void __sanitizer_syscall_pre_impl_sched_setscheduler(long pid, long policy, long param); void __sanitizer_syscall_post_impl_sched_setscheduler(long res, long pid, long policy, long param); void __sanitizer_syscall_pre_impl_sched_setparam(long pid, long param); void __sanitizer_syscall_post_impl_sched_setparam(long res, long pid, long param); void __sanitizer_syscall_pre_impl_sched_getscheduler(long pid); void __sanitizer_syscall_post_impl_sched_getscheduler(long res, long pid); void __sanitizer_syscall_pre_impl_sched_getparam(long pid, long param); void __sanitizer_syscall_post_impl_sched_getparam(long res, long pid, long param); void __sanitizer_syscall_pre_impl_sched_setaffinity(long pid, long len, long user_mask_ptr); void __sanitizer_syscall_post_impl_sched_setaffinity(long res, long pid, long len, long user_mask_ptr); void __sanitizer_syscall_pre_impl_sched_getaffinity(long pid, long len, long user_mask_ptr); void __sanitizer_syscall_post_impl_sched_getaffinity(long res, long pid, long len, long user_mask_ptr); void __sanitizer_syscall_pre_impl_sched_yield(); void __sanitizer_syscall_post_impl_sched_yield(long res); void __sanitizer_syscall_pre_impl_sched_get_priority_max(long policy); void __sanitizer_syscall_post_impl_sched_get_priority_max(long res, long policy); void __sanitizer_syscall_pre_impl_sched_get_priority_min(long policy); void __sanitizer_syscall_post_impl_sched_get_priority_min(long res, long policy); void __sanitizer_syscall_pre_impl_sched_rr_get_interval(long pid, long interval); void __sanitizer_syscall_post_impl_sched_rr_get_interval(long res, long pid, long interval); void __sanitizer_syscall_pre_impl_setpriority(long which, long who, long niceval); void __sanitizer_syscall_post_impl_setpriority(long res, long which, long who, long niceval); void __sanitizer_syscall_pre_impl_getpriority(long which, long who); void __sanitizer_syscall_post_impl_getpriority(long res, long which, long who); void __sanitizer_syscall_pre_impl_shutdown(long arg0, long arg1); void __sanitizer_syscall_post_impl_shutdown(long res, long arg0, long arg1); void __sanitizer_syscall_pre_impl_reboot(long magic1, long magic2, long cmd, long arg); void __sanitizer_syscall_post_impl_reboot(long res, long magic1, long magic2, long cmd, long arg); void __sanitizer_syscall_pre_impl_restart_syscall(); void __sanitizer_syscall_post_impl_restart_syscall(long res); void __sanitizer_syscall_pre_impl_kexec_load(long entry, long nr_segments, long segments, long flags); void __sanitizer_syscall_post_impl_kexec_load(long res, long entry, long nr_segments, long segments, long flags); void __sanitizer_syscall_pre_impl_exit(long error_code); void __sanitizer_syscall_post_impl_exit(long res, long error_code); void __sanitizer_syscall_pre_impl_exit_group(long error_code); void __sanitizer_syscall_post_impl_exit_group(long res, long error_code); void __sanitizer_syscall_pre_impl_wait4(long pid, long stat_addr, long options, long ru); void __sanitizer_syscall_post_impl_wait4(long res, long pid, long stat_addr, long options, long ru); void __sanitizer_syscall_pre_impl_waitid(long which, long pid, long infop, long options, long ru); void __sanitizer_syscall_post_impl_waitid(long res, long which, long pid, long infop, long options, long ru); void __sanitizer_syscall_pre_impl_waitpid(long pid, long stat_addr, long options); void __sanitizer_syscall_post_impl_waitpid(long res, long pid, long stat_addr, long options); void __sanitizer_syscall_pre_impl_set_tid_address(long tidptr); void __sanitizer_syscall_post_impl_set_tid_address(long res, long tidptr); void __sanitizer_syscall_pre_impl_init_module(long umod, long len, long uargs); void __sanitizer_syscall_post_impl_init_module(long res, long umod, long len, long uargs); void __sanitizer_syscall_pre_impl_delete_module(long name_user, long flags); void __sanitizer_syscall_post_impl_delete_module(long res, long name_user, long flags); void __sanitizer_syscall_pre_impl_rt_sigprocmask(long how, long set, long oset, long sigsetsize); void __sanitizer_syscall_post_impl_rt_sigprocmask(long res, long how, long set, long oset, long sigsetsize); void __sanitizer_syscall_pre_impl_rt_sigpending(long set, long sigsetsize); void __sanitizer_syscall_post_impl_rt_sigpending(long res, long set, long sigsetsize); void __sanitizer_syscall_pre_impl_rt_sigtimedwait(long uthese, long uinfo, long uts, long sigsetsize); void __sanitizer_syscall_post_impl_rt_sigtimedwait(long res, long uthese, long uinfo, long uts, long sigsetsize); void __sanitizer_syscall_pre_impl_rt_tgsigqueueinfo(long tgid, long pid, long sig, long uinfo); void __sanitizer_syscall_post_impl_rt_tgsigqueueinfo(long res, long tgid, long pid, long sig, long uinfo); void __sanitizer_syscall_pre_impl_kill(long pid, long sig); void __sanitizer_syscall_post_impl_kill(long res, long pid, long sig); void __sanitizer_syscall_pre_impl_tgkill(long tgid, long pid, long sig); void __sanitizer_syscall_post_impl_tgkill(long res, long tgid, long pid, long sig); void __sanitizer_syscall_pre_impl_tkill(long pid, long sig); void __sanitizer_syscall_post_impl_tkill(long res, long pid, long sig); void __sanitizer_syscall_pre_impl_rt_sigqueueinfo(long pid, long sig, long uinfo); void __sanitizer_syscall_post_impl_rt_sigqueueinfo(long res, long pid, long sig, long uinfo); void __sanitizer_syscall_pre_impl_sgetmask(); void __sanitizer_syscall_post_impl_sgetmask(long res); void __sanitizer_syscall_pre_impl_ssetmask(long newmask); void __sanitizer_syscall_post_impl_ssetmask(long res, long newmask); void __sanitizer_syscall_pre_impl_signal(long sig, long handler); void __sanitizer_syscall_post_impl_signal(long res, long sig, long handler); void __sanitizer_syscall_pre_impl_pause(); void __sanitizer_syscall_post_impl_pause(long res); void __sanitizer_syscall_pre_impl_sync(); void __sanitizer_syscall_post_impl_sync(long res); void __sanitizer_syscall_pre_impl_fsync(long fd); void __sanitizer_syscall_post_impl_fsync(long res, long fd); void __sanitizer_syscall_pre_impl_fdatasync(long fd); void __sanitizer_syscall_post_impl_fdatasync(long res, long fd); void __sanitizer_syscall_pre_impl_bdflush(long func, long data); void __sanitizer_syscall_post_impl_bdflush(long res, long func, long data); void __sanitizer_syscall_pre_impl_mount(long dev_name, long dir_name, long type, long flags, long data); void __sanitizer_syscall_post_impl_mount(long res, long dev_name, long dir_name, long type, long flags, long data); void __sanitizer_syscall_pre_impl_umount(long name, long flags); void __sanitizer_syscall_post_impl_umount(long res, long name, long flags); void __sanitizer_syscall_pre_impl_oldumount(long name); void __sanitizer_syscall_post_impl_oldumount(long res, long name); void __sanitizer_syscall_pre_impl_truncate(long path, long length); void __sanitizer_syscall_post_impl_truncate(long res, long path, long length); void __sanitizer_syscall_pre_impl_ftruncate(long fd, long length); void __sanitizer_syscall_post_impl_ftruncate(long res, long fd, long length); void __sanitizer_syscall_pre_impl_stat(long filename, long statbuf); void __sanitizer_syscall_post_impl_stat(long res, long filename, long statbuf); void __sanitizer_syscall_pre_impl_statfs(long path, long buf); void __sanitizer_syscall_post_impl_statfs(long res, long path, long buf); void __sanitizer_syscall_pre_impl_statfs64(long path, long sz, long buf); void __sanitizer_syscall_post_impl_statfs64(long res, long path, long sz, long buf); void __sanitizer_syscall_pre_impl_fstatfs(long fd, long buf); void __sanitizer_syscall_post_impl_fstatfs(long res, long fd, long buf); void __sanitizer_syscall_pre_impl_fstatfs64(long fd, long sz, long buf); void __sanitizer_syscall_post_impl_fstatfs64(long res, long fd, long sz, long buf); void __sanitizer_syscall_pre_impl_lstat(long filename, long statbuf); void __sanitizer_syscall_post_impl_lstat(long res, long filename, long statbuf); void __sanitizer_syscall_pre_impl_fstat(long fd, long statbuf); void __sanitizer_syscall_post_impl_fstat(long res, long fd, long statbuf); void __sanitizer_syscall_pre_impl_newstat(long filename, long statbuf); void __sanitizer_syscall_post_impl_newstat(long res, long filename, long statbuf); void __sanitizer_syscall_pre_impl_newlstat(long filename, long statbuf); void __sanitizer_syscall_post_impl_newlstat(long res, long filename, long statbuf); void __sanitizer_syscall_pre_impl_newfstat(long fd, long statbuf); void __sanitizer_syscall_post_impl_newfstat(long res, long fd, long statbuf); void __sanitizer_syscall_pre_impl_ustat(long dev, long ubuf); void __sanitizer_syscall_post_impl_ustat(long res, long dev, long ubuf); void __sanitizer_syscall_pre_impl_stat64(long filename, long statbuf); void __sanitizer_syscall_post_impl_stat64(long res, long filename, long statbuf); void __sanitizer_syscall_pre_impl_fstat64(long fd, long statbuf); void __sanitizer_syscall_post_impl_fstat64(long res, long fd, long statbuf); void __sanitizer_syscall_pre_impl_lstat64(long filename, long statbuf); void __sanitizer_syscall_post_impl_lstat64(long res, long filename, long statbuf); void __sanitizer_syscall_pre_impl_setxattr(long path, long name, long value, long size, long flags); void __sanitizer_syscall_post_impl_setxattr(long res, long path, long name, long value, long size, long flags); void __sanitizer_syscall_pre_impl_lsetxattr(long path, long name, long value, long size, long flags); void __sanitizer_syscall_post_impl_lsetxattr(long res, long path, long name, long value, long size, long flags); void __sanitizer_syscall_pre_impl_fsetxattr(long fd, long name, long value, long size, long flags); void __sanitizer_syscall_post_impl_fsetxattr(long res, long fd, long name, long value, long size, long flags); void __sanitizer_syscall_pre_impl_getxattr(long path, long name, long value, long size); void __sanitizer_syscall_post_impl_getxattr(long res, long path, long name, long value, long size); void __sanitizer_syscall_pre_impl_lgetxattr(long path, long name, long value, long size); void __sanitizer_syscall_post_impl_lgetxattr(long res, long path, long name, long value, long size); void __sanitizer_syscall_pre_impl_fgetxattr(long fd, long name, long value, long size); void __sanitizer_syscall_post_impl_fgetxattr(long res, long fd, long name, long value, long size); void __sanitizer_syscall_pre_impl_listxattr(long path, long list, long size); void __sanitizer_syscall_post_impl_listxattr(long res, long path, long list, long size); void __sanitizer_syscall_pre_impl_llistxattr(long path, long list, long size); void __sanitizer_syscall_post_impl_llistxattr(long res, long path, long list, long size); void __sanitizer_syscall_pre_impl_flistxattr(long fd, long list, long size); void __sanitizer_syscall_post_impl_flistxattr(long res, long fd, long list, long size); void __sanitizer_syscall_pre_impl_removexattr(long path, long name); void __sanitizer_syscall_post_impl_removexattr(long res, long path, long name); void __sanitizer_syscall_pre_impl_lremovexattr(long path, long name); void __sanitizer_syscall_post_impl_lremovexattr(long res, long path, long name); void __sanitizer_syscall_pre_impl_fremovexattr(long fd, long name); void __sanitizer_syscall_post_impl_fremovexattr(long res, long fd, long name); void __sanitizer_syscall_pre_impl_brk(long brk); void __sanitizer_syscall_post_impl_brk(long res, long brk); void __sanitizer_syscall_pre_impl_mprotect(long start, long len, long prot); void __sanitizer_syscall_post_impl_mprotect(long res, long start, long len, long prot); void __sanitizer_syscall_pre_impl_mremap(long addr, long old_len, long new_len, long flags, long new_addr); void __sanitizer_syscall_post_impl_mremap(long res, long addr, long old_len, long new_len, long flags, long new_addr); void __sanitizer_syscall_pre_impl_remap_file_pages(long start, long size, long prot, long pgoff, long flags); void __sanitizer_syscall_post_impl_remap_file_pages(long res, long start, long size, long prot, long pgoff, long flags); void __sanitizer_syscall_pre_impl_msync(long start, long len, long flags); void __sanitizer_syscall_post_impl_msync(long res, long start, long len, long flags); void __sanitizer_syscall_pre_impl_munmap(long addr, long len); void __sanitizer_syscall_post_impl_munmap(long res, long addr, long len); void __sanitizer_syscall_pre_impl_mlock(long start, long len); void __sanitizer_syscall_post_impl_mlock(long res, long start, long len); void __sanitizer_syscall_pre_impl_munlock(long start, long len); void __sanitizer_syscall_post_impl_munlock(long res, long start, long len); void __sanitizer_syscall_pre_impl_mlockall(long flags); void __sanitizer_syscall_post_impl_mlockall(long res, long flags); void __sanitizer_syscall_pre_impl_munlockall(); void __sanitizer_syscall_post_impl_munlockall(long res); void __sanitizer_syscall_pre_impl_madvise(long start, long len, long behavior); void __sanitizer_syscall_post_impl_madvise(long res, long start, long len, long behavior); void __sanitizer_syscall_pre_impl_mincore(long start, long len, long vec); void __sanitizer_syscall_post_impl_mincore(long res, long start, long len, long vec); void __sanitizer_syscall_pre_impl_pivot_root(long new_root, long put_old); void __sanitizer_syscall_post_impl_pivot_root(long res, long new_root, long put_old); void __sanitizer_syscall_pre_impl_chroot(long filename); void __sanitizer_syscall_post_impl_chroot(long res, long filename); void __sanitizer_syscall_pre_impl_mknod(long filename, long mode, long dev); void __sanitizer_syscall_post_impl_mknod(long res, long filename, long mode, long dev); void __sanitizer_syscall_pre_impl_link(long oldname, long newname); void __sanitizer_syscall_post_impl_link(long res, long oldname, long newname); void __sanitizer_syscall_pre_impl_symlink(long old, long new_); void __sanitizer_syscall_post_impl_symlink(long res, long old, long new_); void __sanitizer_syscall_pre_impl_unlink(long pathname); void __sanitizer_syscall_post_impl_unlink(long res, long pathname); void __sanitizer_syscall_pre_impl_rename(long oldname, long newname); void __sanitizer_syscall_post_impl_rename(long res, long oldname, long newname); void __sanitizer_syscall_pre_impl_chmod(long filename, long mode); void __sanitizer_syscall_post_impl_chmod(long res, long filename, long mode); void __sanitizer_syscall_pre_impl_fchmod(long fd, long mode); void __sanitizer_syscall_post_impl_fchmod(long res, long fd, long mode); void __sanitizer_syscall_pre_impl_fcntl(long fd, long cmd, long arg); void __sanitizer_syscall_post_impl_fcntl(long res, long fd, long cmd, long arg); void __sanitizer_syscall_pre_impl_fcntl64(long fd, long cmd, long arg); void __sanitizer_syscall_post_impl_fcntl64(long res, long fd, long cmd, long arg); void __sanitizer_syscall_pre_impl_pipe(long fildes); void __sanitizer_syscall_post_impl_pipe(long res, long fildes); void __sanitizer_syscall_pre_impl_pipe2(long fildes, long flags); void __sanitizer_syscall_post_impl_pipe2(long res, long fildes, long flags); void __sanitizer_syscall_pre_impl_dup(long fildes); void __sanitizer_syscall_post_impl_dup(long res, long fildes); void __sanitizer_syscall_pre_impl_dup2(long oldfd, long newfd); void __sanitizer_syscall_post_impl_dup2(long res, long oldfd, long newfd); void __sanitizer_syscall_pre_impl_dup3(long oldfd, long newfd, long flags); void __sanitizer_syscall_post_impl_dup3(long res, long oldfd, long newfd, long flags); void __sanitizer_syscall_pre_impl_ioperm(long from, long num, long on); void __sanitizer_syscall_post_impl_ioperm(long res, long from, long num, long on); void __sanitizer_syscall_pre_impl_ioctl(long fd, long cmd, long arg); void __sanitizer_syscall_post_impl_ioctl(long res, long fd, long cmd, long arg); void __sanitizer_syscall_pre_impl_flock(long fd, long cmd); void __sanitizer_syscall_post_impl_flock(long res, long fd, long cmd); void __sanitizer_syscall_pre_impl_io_setup(long nr_reqs, long ctx); void __sanitizer_syscall_post_impl_io_setup(long res, long nr_reqs, long ctx); void __sanitizer_syscall_pre_impl_io_destroy(long ctx); void __sanitizer_syscall_post_impl_io_destroy(long res, long ctx); void __sanitizer_syscall_pre_impl_io_getevents(long ctx_id, long min_nr, long nr, long events, long timeout); void __sanitizer_syscall_post_impl_io_getevents(long res, long ctx_id, long min_nr, long nr, long events, long timeout); void __sanitizer_syscall_pre_impl_io_submit(long ctx_id, long arg1, long arg2); void __sanitizer_syscall_post_impl_io_submit(long res, long ctx_id, long arg1, long arg2); void __sanitizer_syscall_pre_impl_io_cancel(long ctx_id, long iocb, long result); void __sanitizer_syscall_post_impl_io_cancel(long res, long ctx_id, long iocb, long result); void __sanitizer_syscall_pre_impl_sendfile(long out_fd, long in_fd, long offset, long count); void __sanitizer_syscall_post_impl_sendfile(long res, long out_fd, long in_fd, long offset, long count); void __sanitizer_syscall_pre_impl_sendfile64(long out_fd, long in_fd, long offset, long count); void __sanitizer_syscall_post_impl_sendfile64(long res, long out_fd, long in_fd, long offset, long count); void __sanitizer_syscall_pre_impl_readlink(long path, long buf, long bufsiz); void __sanitizer_syscall_post_impl_readlink(long res, long path, long buf, long bufsiz); void __sanitizer_syscall_pre_impl_creat(long pathname, long mode); void __sanitizer_syscall_post_impl_creat(long res, long pathname, long mode); void __sanitizer_syscall_pre_impl_open(long filename, long flags, long mode); void __sanitizer_syscall_post_impl_open(long res, long filename, long flags, long mode); void __sanitizer_syscall_pre_impl_close(long fd); void __sanitizer_syscall_post_impl_close(long res, long fd); void __sanitizer_syscall_pre_impl_access(long filename, long mode); void __sanitizer_syscall_post_impl_access(long res, long filename, long mode); void __sanitizer_syscall_pre_impl_vhangup(); void __sanitizer_syscall_post_impl_vhangup(long res); void __sanitizer_syscall_pre_impl_chown(long filename, long user, long group); void __sanitizer_syscall_post_impl_chown(long res, long filename, long user, long group); void __sanitizer_syscall_pre_impl_lchown(long filename, long user, long group); void __sanitizer_syscall_post_impl_lchown(long res, long filename, long user, long group); void __sanitizer_syscall_pre_impl_fchown(long fd, long user, long group); void __sanitizer_syscall_post_impl_fchown(long res, long fd, long user, long group); void __sanitizer_syscall_pre_impl_chown16(long filename, long user, long group); void __sanitizer_syscall_post_impl_chown16(long res, long filename, long user, long group); void __sanitizer_syscall_pre_impl_lchown16(long filename, long user, long group); void __sanitizer_syscall_post_impl_lchown16(long res, long filename, long user, long group); void __sanitizer_syscall_pre_impl_fchown16(long fd, long user, long group); void __sanitizer_syscall_post_impl_fchown16(long res, long fd, long user, long group); void __sanitizer_syscall_pre_impl_setregid16(long rgid, long egid); void __sanitizer_syscall_post_impl_setregid16(long res, long rgid, long egid); void __sanitizer_syscall_pre_impl_setgid16(long gid); void __sanitizer_syscall_post_impl_setgid16(long res, long gid); void __sanitizer_syscall_pre_impl_setreuid16(long ruid, long euid); void __sanitizer_syscall_post_impl_setreuid16(long res, long ruid, long euid); void __sanitizer_syscall_pre_impl_setuid16(long uid); void __sanitizer_syscall_post_impl_setuid16(long res, long uid); void __sanitizer_syscall_pre_impl_setresuid16(long ruid, long euid, long suid); void __sanitizer_syscall_post_impl_setresuid16(long res, long ruid, long euid, long suid); void __sanitizer_syscall_pre_impl_getresuid16(long ruid, long euid, long suid); void __sanitizer_syscall_post_impl_getresuid16(long res, long ruid, long euid, long suid); void __sanitizer_syscall_pre_impl_setresgid16(long rgid, long egid, long sgid); void __sanitizer_syscall_post_impl_setresgid16(long res, long rgid, long egid, long sgid); void __sanitizer_syscall_pre_impl_getresgid16(long rgid, long egid, long sgid); void __sanitizer_syscall_post_impl_getresgid16(long res, long rgid, long egid, long sgid); void __sanitizer_syscall_pre_impl_setfsuid16(long uid); void __sanitizer_syscall_post_impl_setfsuid16(long res, long uid); void __sanitizer_syscall_pre_impl_setfsgid16(long gid); void __sanitizer_syscall_post_impl_setfsgid16(long res, long gid); void __sanitizer_syscall_pre_impl_getgroups16(long gidsetsize, long grouplist); void __sanitizer_syscall_post_impl_getgroups16(long res, long gidsetsize, long grouplist); void __sanitizer_syscall_pre_impl_setgroups16(long gidsetsize, long grouplist); void __sanitizer_syscall_post_impl_setgroups16(long res, long gidsetsize, long grouplist); void __sanitizer_syscall_pre_impl_getuid16(); void __sanitizer_syscall_post_impl_getuid16(long res); void __sanitizer_syscall_pre_impl_geteuid16(); void __sanitizer_syscall_post_impl_geteuid16(long res); void __sanitizer_syscall_pre_impl_getgid16(); void __sanitizer_syscall_post_impl_getgid16(long res); void __sanitizer_syscall_pre_impl_getegid16(); void __sanitizer_syscall_post_impl_getegid16(long res); void __sanitizer_syscall_pre_impl_utime(long filename, long times); void __sanitizer_syscall_post_impl_utime(long res, long filename, long times); void __sanitizer_syscall_pre_impl_utimes(long filename, long utimes); void __sanitizer_syscall_post_impl_utimes(long res, long filename, long utimes); void __sanitizer_syscall_pre_impl_lseek(long fd, long offset, long origin); void __sanitizer_syscall_post_impl_lseek(long res, long fd, long offset, long origin); void __sanitizer_syscall_pre_impl_llseek(long fd, long offset_high, long offset_low, long result, long origin); void __sanitizer_syscall_post_impl_llseek(long res, long fd, long offset_high, long offset_low, long result, long origin); void __sanitizer_syscall_pre_impl_read(long fd, long buf, long count); void __sanitizer_syscall_post_impl_read(long res, long fd, long buf, long count); void __sanitizer_syscall_pre_impl_readv(long fd, long vec, long vlen); void __sanitizer_syscall_post_impl_readv(long res, long fd, long vec, long vlen); void __sanitizer_syscall_pre_impl_write(long fd, long buf, long count); void __sanitizer_syscall_post_impl_write(long res, long fd, long buf, long count); void __sanitizer_syscall_pre_impl_writev(long fd, long vec, long vlen); void __sanitizer_syscall_post_impl_writev(long res, long fd, long vec, long vlen); #ifdef _LP64 void __sanitizer_syscall_pre_impl_pread64(long fd, long buf, long count, long pos); void __sanitizer_syscall_post_impl_pread64(long res, long fd, long buf, long count, long pos); void __sanitizer_syscall_pre_impl_pwrite64(long fd, long buf, long count, long pos); void __sanitizer_syscall_post_impl_pwrite64(long res, long fd, long buf, long count, long pos); #else void __sanitizer_syscall_pre_impl_pread64(long fd, long buf, long count, long pos0, long pos1); void __sanitizer_syscall_post_impl_pread64(long res, long fd, long buf, long count, long pos0, long pos1); void __sanitizer_syscall_pre_impl_pwrite64(long fd, long buf, long count, long pos0, long pos1); void __sanitizer_syscall_post_impl_pwrite64(long res, long fd, long buf, long count, long pos0, long pos1); #endif void __sanitizer_syscall_pre_impl_preadv(long fd, long vec, long vlen, long pos_l, long pos_h); void __sanitizer_syscall_post_impl_preadv(long res, long fd, long vec, long vlen, long pos_l, long pos_h); void __sanitizer_syscall_pre_impl_pwritev(long fd, long vec, long vlen, long pos_l, long pos_h); void __sanitizer_syscall_post_impl_pwritev(long res, long fd, long vec, long vlen, long pos_l, long pos_h); void __sanitizer_syscall_pre_impl_getcwd(long buf, long size); void __sanitizer_syscall_post_impl_getcwd(long res, long buf, long size); void __sanitizer_syscall_pre_impl_mkdir(long pathname, long mode); void __sanitizer_syscall_post_impl_mkdir(long res, long pathname, long mode); void __sanitizer_syscall_pre_impl_chdir(long filename); void __sanitizer_syscall_post_impl_chdir(long res, long filename); void __sanitizer_syscall_pre_impl_fchdir(long fd); void __sanitizer_syscall_post_impl_fchdir(long res, long fd); void __sanitizer_syscall_pre_impl_rmdir(long pathname); void __sanitizer_syscall_post_impl_rmdir(long res, long pathname); void __sanitizer_syscall_pre_impl_lookup_dcookie(long cookie64, long buf, long len); void __sanitizer_syscall_post_impl_lookup_dcookie(long res, long cookie64, long buf, long len); void __sanitizer_syscall_pre_impl_quotactl(long cmd, long special, long id, long addr); void __sanitizer_syscall_post_impl_quotactl(long res, long cmd, long special, long id, long addr); void __sanitizer_syscall_pre_impl_getdents(long fd, long dirent, long count); void __sanitizer_syscall_post_impl_getdents(long res, long fd, long dirent, long count); void __sanitizer_syscall_pre_impl_getdents64(long fd, long dirent, long count); void __sanitizer_syscall_post_impl_getdents64(long res, long fd, long dirent, long count); void __sanitizer_syscall_pre_impl_setsockopt(long fd, long level, long optname, long optval, long optlen); void __sanitizer_syscall_post_impl_setsockopt(long res, long fd, long level, long optname, long optval, long optlen); void __sanitizer_syscall_pre_impl_getsockopt(long fd, long level, long optname, long optval, long optlen); void __sanitizer_syscall_post_impl_getsockopt(long res, long fd, long level, long optname, long optval, long optlen); void __sanitizer_syscall_pre_impl_bind(long arg0, long arg1, long arg2); void __sanitizer_syscall_post_impl_bind(long res, long arg0, long arg1, long arg2); void __sanitizer_syscall_pre_impl_connect(long arg0, long arg1, long arg2); void __sanitizer_syscall_post_impl_connect(long res, long arg0, long arg1, long arg2); void __sanitizer_syscall_pre_impl_accept(long arg0, long arg1, long arg2); void __sanitizer_syscall_post_impl_accept(long res, long arg0, long arg1, long arg2); void __sanitizer_syscall_pre_impl_accept4(long arg0, long arg1, long arg2, long arg3); void __sanitizer_syscall_post_impl_accept4(long res, long arg0, long arg1, long arg2, long arg3); void __sanitizer_syscall_pre_impl_getsockname(long arg0, long arg1, long arg2); void __sanitizer_syscall_post_impl_getsockname(long res, long arg0, long arg1, long arg2); void __sanitizer_syscall_pre_impl_getpeername(long arg0, long arg1, long arg2); void __sanitizer_syscall_post_impl_getpeername(long res, long arg0, long arg1, long arg2); void __sanitizer_syscall_pre_impl_send(long arg0, long arg1, long arg2, long arg3); void __sanitizer_syscall_post_impl_send(long res, long arg0, long arg1, long arg2, long arg3); void __sanitizer_syscall_pre_impl_sendto(long arg0, long arg1, long arg2, long arg3, long arg4, long arg5); void __sanitizer_syscall_post_impl_sendto(long res, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5); void __sanitizer_syscall_pre_impl_sendmsg(long fd, long msg, long flags); void __sanitizer_syscall_post_impl_sendmsg(long res, long fd, long msg, long flags); void __sanitizer_syscall_pre_impl_sendmmsg(long fd, long msg, long vlen, long flags); void __sanitizer_syscall_post_impl_sendmmsg(long res, long fd, long msg, long vlen, long flags); void __sanitizer_syscall_pre_impl_recv(long arg0, long arg1, long arg2, long arg3); void __sanitizer_syscall_post_impl_recv(long res, long arg0, long arg1, long arg2, long arg3); void __sanitizer_syscall_pre_impl_recvfrom(long arg0, long arg1, long arg2, long arg3, long arg4, long arg5); void __sanitizer_syscall_post_impl_recvfrom(long res, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5); void __sanitizer_syscall_pre_impl_recvmsg(long fd, long msg, long flags); void __sanitizer_syscall_post_impl_recvmsg(long res, long fd, long msg, long flags); void __sanitizer_syscall_pre_impl_recvmmsg(long fd, long msg, long vlen, long flags, long timeout); void __sanitizer_syscall_post_impl_recvmmsg(long res, long fd, long msg, long vlen, long flags, long timeout); void __sanitizer_syscall_pre_impl_socket(long arg0, long arg1, long arg2); void __sanitizer_syscall_post_impl_socket(long res, long arg0, long arg1, long arg2); void __sanitizer_syscall_pre_impl_socketpair(long arg0, long arg1, long arg2, long arg3); void __sanitizer_syscall_post_impl_socketpair(long res, long arg0, long arg1, long arg2, long arg3); void __sanitizer_syscall_pre_impl_socketcall(long call, long args); void __sanitizer_syscall_post_impl_socketcall(long res, long call, long args); void __sanitizer_syscall_pre_impl_listen(long arg0, long arg1); void __sanitizer_syscall_post_impl_listen(long res, long arg0, long arg1); void __sanitizer_syscall_pre_impl_poll(long ufds, long nfds, long timeout); void __sanitizer_syscall_post_impl_poll(long res, long ufds, long nfds, long timeout); void __sanitizer_syscall_pre_impl_select(long n, long inp, long outp, long exp, long tvp); void __sanitizer_syscall_post_impl_select(long res, long n, long inp, long outp, long exp, long tvp); void __sanitizer_syscall_pre_impl_old_select(long arg); void __sanitizer_syscall_post_impl_old_select(long res, long arg); void __sanitizer_syscall_pre_impl_epoll_create(long size); void __sanitizer_syscall_post_impl_epoll_create(long res, long size); void __sanitizer_syscall_pre_impl_epoll_create1(long flags); void __sanitizer_syscall_post_impl_epoll_create1(long res, long flags); void __sanitizer_syscall_pre_impl_epoll_ctl(long epfd, long op, long fd, long event); void __sanitizer_syscall_post_impl_epoll_ctl(long res, long epfd, long op, long fd, long event); void __sanitizer_syscall_pre_impl_epoll_wait(long epfd, long events, long maxevents, long timeout); void __sanitizer_syscall_post_impl_epoll_wait(long res, long epfd, long events, long maxevents, long timeout); void __sanitizer_syscall_pre_impl_epoll_pwait(long epfd, long events, long maxevents, long timeout, long sigmask, long sigsetsize); void __sanitizer_syscall_post_impl_epoll_pwait(long res, long epfd, long events, long maxevents, long timeout, long sigmask, long sigsetsize); void __sanitizer_syscall_pre_impl_gethostname(long name, long len); void __sanitizer_syscall_post_impl_gethostname(long res, long name, long len); void __sanitizer_syscall_pre_impl_sethostname(long name, long len); void __sanitizer_syscall_post_impl_sethostname(long res, long name, long len); void __sanitizer_syscall_pre_impl_setdomainname(long name, long len); void __sanitizer_syscall_post_impl_setdomainname(long res, long name, long len); void __sanitizer_syscall_pre_impl_newuname(long name); void __sanitizer_syscall_post_impl_newuname(long res, long name); void __sanitizer_syscall_pre_impl_uname(long arg0); void __sanitizer_syscall_post_impl_uname(long res, long arg0); void __sanitizer_syscall_pre_impl_olduname(long arg0); void __sanitizer_syscall_post_impl_olduname(long res, long arg0); void __sanitizer_syscall_pre_impl_getrlimit(long resource, long rlim); void __sanitizer_syscall_post_impl_getrlimit(long res, long resource, long rlim); void __sanitizer_syscall_pre_impl_old_getrlimit(long resource, long rlim); void __sanitizer_syscall_post_impl_old_getrlimit(long res, long resource, long rlim); void __sanitizer_syscall_pre_impl_setrlimit(long resource, long rlim); void __sanitizer_syscall_post_impl_setrlimit(long res, long resource, long rlim); void __sanitizer_syscall_pre_impl_prlimit64(long pid, long resource, long new_rlim, long old_rlim); void __sanitizer_syscall_post_impl_prlimit64(long res, long pid, long resource, long new_rlim, long old_rlim); void __sanitizer_syscall_pre_impl_getrusage(long who, long ru); void __sanitizer_syscall_post_impl_getrusage(long res, long who, long ru); void __sanitizer_syscall_pre_impl_umask(long mask); void __sanitizer_syscall_post_impl_umask(long res, long mask); void __sanitizer_syscall_pre_impl_msgget(long key, long msgflg); void __sanitizer_syscall_post_impl_msgget(long res, long key, long msgflg); void __sanitizer_syscall_pre_impl_msgsnd(long msqid, long msgp, long msgsz, long msgflg); void __sanitizer_syscall_post_impl_msgsnd(long res, long msqid, long msgp, long msgsz, long msgflg); void __sanitizer_syscall_pre_impl_msgrcv(long msqid, long msgp, long msgsz, long msgtyp, long msgflg); void __sanitizer_syscall_post_impl_msgrcv(long res, long msqid, long msgp, long msgsz, long msgtyp, long msgflg); void __sanitizer_syscall_pre_impl_msgctl(long msqid, long cmd, long buf); void __sanitizer_syscall_post_impl_msgctl(long res, long msqid, long cmd, long buf); void __sanitizer_syscall_pre_impl_semget(long key, long nsems, long semflg); void __sanitizer_syscall_post_impl_semget(long res, long key, long nsems, long semflg); void __sanitizer_syscall_pre_impl_semop(long semid, long sops, long nsops); void __sanitizer_syscall_post_impl_semop(long res, long semid, long sops, long nsops); void __sanitizer_syscall_pre_impl_semctl(long semid, long semnum, long cmd, long arg); void __sanitizer_syscall_post_impl_semctl(long res, long semid, long semnum, long cmd, long arg); void __sanitizer_syscall_pre_impl_semtimedop(long semid, long sops, long nsops, long timeout); void __sanitizer_syscall_post_impl_semtimedop(long res, long semid, long sops, long nsops, long timeout); void __sanitizer_syscall_pre_impl_shmat(long shmid, long shmaddr, long shmflg); void __sanitizer_syscall_post_impl_shmat(long res, long shmid, long shmaddr, long shmflg); void __sanitizer_syscall_pre_impl_shmget(long key, long size, long flag); void __sanitizer_syscall_post_impl_shmget(long res, long key, long size, long flag); void __sanitizer_syscall_pre_impl_shmdt(long shmaddr); void __sanitizer_syscall_post_impl_shmdt(long res, long shmaddr); void __sanitizer_syscall_pre_impl_shmctl(long shmid, long cmd, long buf); void __sanitizer_syscall_post_impl_shmctl(long res, long shmid, long cmd, long buf); void __sanitizer_syscall_pre_impl_ipc(long call, long first, long second, long third, long ptr, long fifth); void __sanitizer_syscall_post_impl_ipc(long res, long call, long first, long second, long third, long ptr, long fifth); void __sanitizer_syscall_pre_impl_mq_open(long name, long oflag, long mode, long attr); void __sanitizer_syscall_post_impl_mq_open(long res, long name, long oflag, long mode, long attr); void __sanitizer_syscall_pre_impl_mq_unlink(long name); void __sanitizer_syscall_post_impl_mq_unlink(long res, long name); void __sanitizer_syscall_pre_impl_mq_timedsend(long mqdes, long msg_ptr, long msg_len, long msg_prio, long abs_timeout); void __sanitizer_syscall_post_impl_mq_timedsend(long res, long mqdes, long msg_ptr, long msg_len, long msg_prio, long abs_timeout); void __sanitizer_syscall_pre_impl_mq_timedreceive(long mqdes, long msg_ptr, long msg_len, long msg_prio, long abs_timeout); void __sanitizer_syscall_post_impl_mq_timedreceive(long res, long mqdes, long msg_ptr, long msg_len, long msg_prio, long abs_timeout); void __sanitizer_syscall_pre_impl_mq_notify(long mqdes, long notification); void __sanitizer_syscall_post_impl_mq_notify(long res, long mqdes, long notification); void __sanitizer_syscall_pre_impl_mq_getsetattr(long mqdes, long mqstat, long omqstat); void __sanitizer_syscall_post_impl_mq_getsetattr(long res, long mqdes, long mqstat, long omqstat); void __sanitizer_syscall_pre_impl_pciconfig_iobase(long which, long bus, long devfn); void __sanitizer_syscall_post_impl_pciconfig_iobase(long res, long which, long bus, long devfn); void __sanitizer_syscall_pre_impl_pciconfig_read(long bus, long dfn, long off, long len, long buf); void __sanitizer_syscall_post_impl_pciconfig_read(long res, long bus, long dfn, long off, long len, long buf); void __sanitizer_syscall_pre_impl_pciconfig_write(long bus, long dfn, long off, long len, long buf); void __sanitizer_syscall_post_impl_pciconfig_write(long res, long bus, long dfn, long off, long len, long buf); void __sanitizer_syscall_pre_impl_swapon(long specialfile, long swap_flags); void __sanitizer_syscall_post_impl_swapon(long res, long specialfile, long swap_flags); void __sanitizer_syscall_pre_impl_swapoff(long specialfile); void __sanitizer_syscall_post_impl_swapoff(long res, long specialfile); void __sanitizer_syscall_pre_impl_sysctl(long args); void __sanitizer_syscall_post_impl_sysctl(long res, long args); void __sanitizer_syscall_pre_impl_sysinfo(long info); void __sanitizer_syscall_post_impl_sysinfo(long res, long info); void __sanitizer_syscall_pre_impl_sysfs(long option, long arg1, long arg2); void __sanitizer_syscall_post_impl_sysfs(long res, long option, long arg1, long arg2); void __sanitizer_syscall_pre_impl_syslog(long type, long buf, long len); void __sanitizer_syscall_post_impl_syslog(long res, long type, long buf, long len); void __sanitizer_syscall_pre_impl_uselib(long library); void __sanitizer_syscall_post_impl_uselib(long res, long library); void __sanitizer_syscall_pre_impl_ni_syscall(); void __sanitizer_syscall_post_impl_ni_syscall(long res); void __sanitizer_syscall_pre_impl_ptrace(long request, long pid, long addr, long data); void __sanitizer_syscall_post_impl_ptrace(long res, long request, long pid, long addr, long data); void __sanitizer_syscall_pre_impl_add_key(long _type, long _description, long _payload, long plen, long destringid); void __sanitizer_syscall_post_impl_add_key(long res, long _type, long _description, long _payload, long plen, long destringid); void __sanitizer_syscall_pre_impl_request_key(long _type, long _description, long _callout_info, long destringid); void __sanitizer_syscall_post_impl_request_key(long res, long _type, long _description, long _callout_info, long destringid); void __sanitizer_syscall_pre_impl_keyctl(long cmd, long arg2, long arg3, long arg4, long arg5); void __sanitizer_syscall_post_impl_keyctl(long res, long cmd, long arg2, long arg3, long arg4, long arg5); void __sanitizer_syscall_pre_impl_ioprio_set(long which, long who, long ioprio); void __sanitizer_syscall_post_impl_ioprio_set(long res, long which, long who, long ioprio); void __sanitizer_syscall_pre_impl_ioprio_get(long which, long who); void __sanitizer_syscall_post_impl_ioprio_get(long res, long which, long who); void __sanitizer_syscall_pre_impl_set_mempolicy(long mode, long nmask, long maxnode); void __sanitizer_syscall_post_impl_set_mempolicy(long res, long mode, long nmask, long maxnode); void __sanitizer_syscall_pre_impl_migrate_pages(long pid, long maxnode, long from, long to); void __sanitizer_syscall_post_impl_migrate_pages(long res, long pid, long maxnode, long from, long to); void __sanitizer_syscall_pre_impl_move_pages(long pid, long nr_pages, long pages, long nodes, long status, long flags); void __sanitizer_syscall_post_impl_move_pages(long res, long pid, long nr_pages, long pages, long nodes, long status, long flags); void __sanitizer_syscall_pre_impl_mbind(long start, long len, long mode, long nmask, long maxnode, long flags); void __sanitizer_syscall_post_impl_mbind(long res, long start, long len, long mode, long nmask, long maxnode, long flags); void __sanitizer_syscall_pre_impl_get_mempolicy(long policy, long nmask, long maxnode, long addr, long flags); void __sanitizer_syscall_post_impl_get_mempolicy(long res, long policy, long nmask, long maxnode, long addr, long flags); void __sanitizer_syscall_pre_impl_inotify_init(); void __sanitizer_syscall_post_impl_inotify_init(long res); void __sanitizer_syscall_pre_impl_inotify_init1(long flags); void __sanitizer_syscall_post_impl_inotify_init1(long res, long flags); void __sanitizer_syscall_pre_impl_inotify_add_watch(long fd, long path, long mask); void __sanitizer_syscall_post_impl_inotify_add_watch(long res, long fd, long path, long mask); void __sanitizer_syscall_pre_impl_inotify_rm_watch(long fd, long wd); void __sanitizer_syscall_post_impl_inotify_rm_watch(long res, long fd, long wd); void __sanitizer_syscall_pre_impl_spu_run(long fd, long unpc, long ustatus); void __sanitizer_syscall_post_impl_spu_run(long res, long fd, long unpc, long ustatus); void __sanitizer_syscall_pre_impl_spu_create(long name, long flags, long mode, long fd); void __sanitizer_syscall_post_impl_spu_create(long res, long name, long flags, long mode, long fd); void __sanitizer_syscall_pre_impl_mknodat(long dfd, long filename, long mode, long dev); void __sanitizer_syscall_post_impl_mknodat(long res, long dfd, long filename, long mode, long dev); void __sanitizer_syscall_pre_impl_mkdirat(long dfd, long pathname, long mode); void __sanitizer_syscall_post_impl_mkdirat(long res, long dfd, long pathname, long mode); void __sanitizer_syscall_pre_impl_unlinkat(long dfd, long pathname, long flag); void __sanitizer_syscall_post_impl_unlinkat(long res, long dfd, long pathname, long flag); void __sanitizer_syscall_pre_impl_symlinkat(long oldname, long newdfd, long newname); void __sanitizer_syscall_post_impl_symlinkat(long res, long oldname, long newdfd, long newname); void __sanitizer_syscall_pre_impl_linkat(long olddfd, long oldname, long newdfd, long newname, long flags); void __sanitizer_syscall_post_impl_linkat(long res, long olddfd, long oldname, long newdfd, long newname, long flags); void __sanitizer_syscall_pre_impl_renameat(long olddfd, long oldname, long newdfd, long newname); void __sanitizer_syscall_post_impl_renameat(long res, long olddfd, long oldname, long newdfd, long newname); void __sanitizer_syscall_pre_impl_futimesat(long dfd, long filename, long utimes); void __sanitizer_syscall_post_impl_futimesat(long res, long dfd, long filename, long utimes); void __sanitizer_syscall_pre_impl_faccessat(long dfd, long filename, long mode); void __sanitizer_syscall_post_impl_faccessat(long res, long dfd, long filename, long mode); void __sanitizer_syscall_pre_impl_fchmodat(long dfd, long filename, long mode); void __sanitizer_syscall_post_impl_fchmodat(long res, long dfd, long filename, long mode); void __sanitizer_syscall_pre_impl_fchownat(long dfd, long filename, long user, long group, long flag); void __sanitizer_syscall_post_impl_fchownat(long res, long dfd, long filename, long user, long group, long flag); void __sanitizer_syscall_pre_impl_openat(long dfd, long filename, long flags, long mode); void __sanitizer_syscall_post_impl_openat(long res, long dfd, long filename, long flags, long mode); void __sanitizer_syscall_pre_impl_newfstatat(long dfd, long filename, long statbuf, long flag); void __sanitizer_syscall_post_impl_newfstatat(long res, long dfd, long filename, long statbuf, long flag); void __sanitizer_syscall_pre_impl_fstatat64(long dfd, long filename, long statbuf, long flag); void __sanitizer_syscall_post_impl_fstatat64(long res, long dfd, long filename, long statbuf, long flag); void __sanitizer_syscall_pre_impl_readlinkat(long dfd, long path, long buf, long bufsiz); void __sanitizer_syscall_post_impl_readlinkat(long res, long dfd, long path, long buf, long bufsiz); void __sanitizer_syscall_pre_impl_utimensat(long dfd, long filename, long utimes, long flags); void __sanitizer_syscall_post_impl_utimensat(long res, long dfd, long filename, long utimes, long flags); void __sanitizer_syscall_pre_impl_unshare(long unshare_flags); void __sanitizer_syscall_post_impl_unshare(long res, long unshare_flags); void __sanitizer_syscall_pre_impl_splice(long fd_in, long off_in, long fd_out, long off_out, long len, long flags); void __sanitizer_syscall_post_impl_splice(long res, long fd_in, long off_in, long fd_out, long off_out, long len, long flags); void __sanitizer_syscall_pre_impl_vmsplice(long fd, long iov, long nr_segs, long flags); void __sanitizer_syscall_post_impl_vmsplice(long res, long fd, long iov, long nr_segs, long flags); void __sanitizer_syscall_pre_impl_tee(long fdin, long fdout, long len, long flags); void __sanitizer_syscall_post_impl_tee(long res, long fdin, long fdout, long len, long flags); void __sanitizer_syscall_pre_impl_get_robust_list(long pid, long head_ptr, long len_ptr); void __sanitizer_syscall_post_impl_get_robust_list(long res, long pid, long head_ptr, long len_ptr); void __sanitizer_syscall_pre_impl_set_robust_list(long head, long len); void __sanitizer_syscall_post_impl_set_robust_list(long res, long head, long len); void __sanitizer_syscall_pre_impl_getcpu(long cpu, long node, long cache); void __sanitizer_syscall_post_impl_getcpu(long res, long cpu, long node, long cache); void __sanitizer_syscall_pre_impl_signalfd(long ufd, long user_mask, long sizemask); void __sanitizer_syscall_post_impl_signalfd(long res, long ufd, long user_mask, long sizemask); void __sanitizer_syscall_pre_impl_signalfd4(long ufd, long user_mask, long sizemask, long flags); void __sanitizer_syscall_post_impl_signalfd4(long res, long ufd, long user_mask, long sizemask, long flags); void __sanitizer_syscall_pre_impl_timerfd_create(long clockid, long flags); void __sanitizer_syscall_post_impl_timerfd_create(long res, long clockid, long flags); void __sanitizer_syscall_pre_impl_timerfd_settime(long ufd, long flags, long utmr, long otmr); void __sanitizer_syscall_post_impl_timerfd_settime(long res, long ufd, long flags, long utmr, long otmr); void __sanitizer_syscall_pre_impl_timerfd_gettime(long ufd, long otmr); void __sanitizer_syscall_post_impl_timerfd_gettime(long res, long ufd, long otmr); void __sanitizer_syscall_pre_impl_eventfd(long count); void __sanitizer_syscall_post_impl_eventfd(long res, long count); void __sanitizer_syscall_pre_impl_eventfd2(long count, long flags); void __sanitizer_syscall_post_impl_eventfd2(long res, long count, long flags); void __sanitizer_syscall_pre_impl_old_readdir(long arg0, long arg1, long arg2); void __sanitizer_syscall_post_impl_old_readdir(long res, long arg0, long arg1, long arg2); void __sanitizer_syscall_pre_impl_pselect6(long arg0, long arg1, long arg2, long arg3, long arg4, long arg5); void __sanitizer_syscall_post_impl_pselect6(long res, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5); void __sanitizer_syscall_pre_impl_ppoll(long arg0, long arg1, long arg2, long arg3, long arg4); void __sanitizer_syscall_post_impl_ppoll(long res, long arg0, long arg1, long arg2, long arg3, long arg4); void __sanitizer_syscall_pre_impl_fanotify_init(long flags, long event_f_flags); void __sanitizer_syscall_post_impl_fanotify_init(long res, long flags, long event_f_flags); void __sanitizer_syscall_pre_impl_fanotify_mark(long fanotify_fd, long flags, long mask, long fd, long pathname); void __sanitizer_syscall_post_impl_fanotify_mark(long res, long fanotify_fd, long flags, long mask, long fd, long pathname); void __sanitizer_syscall_pre_impl_syncfs(long fd); void __sanitizer_syscall_post_impl_syncfs(long res, long fd); void __sanitizer_syscall_pre_impl_perf_event_open(long attr_uptr, long pid, long cpu, long group_fd, long flags); void __sanitizer_syscall_post_impl_perf_event_open(long res, long attr_uptr, long pid, long cpu, long group_fd, long flags); void __sanitizer_syscall_pre_impl_mmap_pgoff(long addr, long len, long prot, long flags, long fd, long pgoff); void __sanitizer_syscall_post_impl_mmap_pgoff(long res, long addr, long len, long prot, long flags, long fd, long pgoff); void __sanitizer_syscall_pre_impl_old_mmap(long arg); void __sanitizer_syscall_post_impl_old_mmap(long res, long arg); void __sanitizer_syscall_pre_impl_name_to_handle_at(long dfd, long name, long handle, long mnt_id, long flag); void __sanitizer_syscall_post_impl_name_to_handle_at(long res, long dfd, long name, long handle, long mnt_id, long flag); void __sanitizer_syscall_pre_impl_open_by_handle_at(long mountdirfd, long handle, long flags); void __sanitizer_syscall_post_impl_open_by_handle_at(long res, long mountdirfd, long handle, long flags); void __sanitizer_syscall_pre_impl_setns(long fd, long nstype); void __sanitizer_syscall_post_impl_setns(long res, long fd, long nstype); void __sanitizer_syscall_pre_impl_process_vm_readv(long pid, long lvec, long liovcnt, long rvec, long riovcnt, long flags); void __sanitizer_syscall_post_impl_process_vm_readv(long res, long pid, long lvec, long liovcnt, long rvec, long riovcnt, long flags); void __sanitizer_syscall_pre_impl_process_vm_writev(long pid, long lvec, long liovcnt, long rvec, long riovcnt, long flags); void __sanitizer_syscall_post_impl_process_vm_writev(long res, long pid, long lvec, long liovcnt, long rvec, long riovcnt, long flags); void __sanitizer_syscall_pre_impl_fork(); void __sanitizer_syscall_post_impl_fork(long res); void __sanitizer_syscall_pre_impl_vfork(); void __sanitizer_syscall_post_impl_vfork(long res); - +void __sanitizer_syscall_pre_impl_sigaction(long signum, long act, long oldact); +void __sanitizer_syscall_post_impl_sigaction(long res, long signum, long act, + long oldact); +void __sanitizer_syscall_pre_impl_rt_sigaction(long signum, long act, + long oldact, long sz); +void __sanitizer_syscall_post_impl_rt_sigaction(long res, long signum, long act, + long oldact, long sz); #ifdef __cplusplus } // extern "C" #endif #endif // SANITIZER_LINUX_SYSCALL_HOOKS_H Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_activation.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_activation.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_activation.cc (revision 305364) @@ -1,139 +1,140 @@ //===-- asan_activation.cc --------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // ASan activation/deactivation logic. //===----------------------------------------------------------------------===// #include "asan_activation.h" #include "asan_allocator.h" #include "asan_flags.h" #include "asan_internal.h" #include "asan_poisoning.h" #include "asan_stack.h" #include "sanitizer_common/sanitizer_flags.h" namespace __asan { static struct AsanDeactivatedFlags { AllocatorOptions allocator_options; int malloc_context_size; bool poison_heap; bool coverage; const char *coverage_dir; void RegisterActivationFlags(FlagParser *parser, Flags *f, CommonFlags *cf) { #define ASAN_ACTIVATION_FLAG(Type, Name) \ RegisterFlag(parser, #Name, "", &f->Name); #define COMMON_ACTIVATION_FLAG(Type, Name) \ RegisterFlag(parser, #Name, "", &cf->Name); #include "asan_activation_flags.inc" #undef ASAN_ACTIVATION_FLAG #undef COMMON_ACTIVATION_FLAG RegisterIncludeFlags(parser, cf); } void OverrideFromActivationFlags() { Flags f; CommonFlags cf; FlagParser parser; RegisterActivationFlags(&parser, &f, &cf); + cf.SetDefaults(); // Copy the current activation flags. allocator_options.CopyTo(&f, &cf); cf.malloc_context_size = malloc_context_size; f.poison_heap = poison_heap; cf.coverage = coverage; cf.coverage_dir = coverage_dir; cf.verbosity = Verbosity(); cf.help = false; // this is activation-specific help // Check if activation flags need to be overriden. if (const char *env = GetEnv("ASAN_ACTIVATION_OPTIONS")) { parser.ParseString(env); } - SetVerbosity(cf.verbosity); + InitializeCommonFlags(&cf); if (Verbosity()) ReportUnrecognizedFlags(); if (cf.help) parser.PrintFlagDescriptions(); allocator_options.SetFrom(&f, &cf); malloc_context_size = cf.malloc_context_size; poison_heap = f.poison_heap; coverage = cf.coverage; coverage_dir = cf.coverage_dir; } void Print() { Report( "quarantine_size_mb %d, max_redzone %d, poison_heap %d, " "malloc_context_size %d, alloc_dealloc_mismatch %d, " "allocator_may_return_null %d, coverage %d, coverage_dir %s\n", allocator_options.quarantine_size_mb, allocator_options.max_redzone, poison_heap, malloc_context_size, allocator_options.alloc_dealloc_mismatch, allocator_options.may_return_null, coverage, coverage_dir); } } asan_deactivated_flags; static bool asan_is_deactivated; void AsanDeactivate() { CHECK(!asan_is_deactivated); VReport(1, "Deactivating ASan\n"); // Stash runtime state. GetAllocatorOptions(&asan_deactivated_flags.allocator_options); asan_deactivated_flags.malloc_context_size = GetMallocContextSize(); asan_deactivated_flags.poison_heap = CanPoisonMemory(); asan_deactivated_flags.coverage = common_flags()->coverage; asan_deactivated_flags.coverage_dir = common_flags()->coverage_dir; // Deactivate the runtime. SetCanPoisonMemory(false); SetMallocContextSize(1); ReInitializeCoverage(false, nullptr); AllocatorOptions disabled = asan_deactivated_flags.allocator_options; disabled.quarantine_size_mb = 0; disabled.min_redzone = 16; // Redzone must be at least 16 bytes long. disabled.max_redzone = 16; disabled.alloc_dealloc_mismatch = false; disabled.may_return_null = true; ReInitializeAllocator(disabled); asan_is_deactivated = true; } void AsanActivate() { if (!asan_is_deactivated) return; VReport(1, "Activating ASan\n"); UpdateProcessName(); asan_deactivated_flags.OverrideFromActivationFlags(); SetCanPoisonMemory(asan_deactivated_flags.poison_heap); SetMallocContextSize(asan_deactivated_flags.malloc_context_size); ReInitializeCoverage(asan_deactivated_flags.coverage, asan_deactivated_flags.coverage_dir); ReInitializeAllocator(asan_deactivated_flags.allocator_options); asan_is_deactivated = false; if (Verbosity()) { Report("Activated with flags:\n"); asan_deactivated_flags.Print(); } } } // namespace __asan Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_allocator.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_allocator.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_allocator.cc (revision 305364) @@ -1,908 +1,924 @@ //===-- asan_allocator.cc -------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // Implementation of ASan's memory allocator, 2-nd version. // This variant uses the allocator from sanitizer_common, i.e. the one shared // with ThreadSanitizer and MemorySanitizer. // //===----------------------------------------------------------------------===// #include "asan_allocator.h" #include "asan_mapping.h" #include "asan_poisoning.h" #include "asan_report.h" #include "asan_stack.h" #include "asan_thread.h" #include "sanitizer_common/sanitizer_allocator_interface.h" #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_internal_defs.h" #include "sanitizer_common/sanitizer_list.h" #include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_quarantine.h" #include "lsan/lsan_common.h" namespace __asan { // Valid redzone sizes are 16, 32, 64, ... 2048, so we encode them in 3 bits. // We use adaptive redzones: for larger allocation larger redzones are used. static u32 RZLog2Size(u32 rz_log) { CHECK_LT(rz_log, 8); return 16 << rz_log; } static u32 RZSize2Log(u32 rz_size) { CHECK_GE(rz_size, 16); CHECK_LE(rz_size, 2048); CHECK(IsPowerOfTwo(rz_size)); u32 res = Log2(rz_size) - 4; CHECK_EQ(rz_size, RZLog2Size(res)); return res; } static AsanAllocator &get_allocator(); // The memory chunk allocated from the underlying allocator looks like this: // L L L L L L H H U U U U U U R R // L -- left redzone words (0 or more bytes) // H -- ChunkHeader (16 bytes), which is also a part of the left redzone. // U -- user memory. // R -- right redzone (0 or more bytes) // ChunkBase consists of ChunkHeader and other bytes that overlap with user // memory. // If the left redzone is greater than the ChunkHeader size we store a magic // value in the first uptr word of the memory block and store the address of // ChunkBase in the next uptr. // M B L L L L L L L L L H H U U U U U U // | ^ // ---------------------| // M -- magic value kAllocBegMagic // B -- address of ChunkHeader pointing to the first 'H' static const uptr kAllocBegMagic = 0xCC6E96B9; struct ChunkHeader { // 1-st 8 bytes. u32 chunk_state : 8; // Must be first. u32 alloc_tid : 24; u32 free_tid : 24; u32 from_memalign : 1; u32 alloc_type : 2; u32 rz_log : 3; u32 lsan_tag : 2; // 2-nd 8 bytes // This field is used for small sizes. For large sizes it is equal to // SizeClassMap::kMaxSize and the actual size is stored in the // SecondaryAllocator's metadata. u32 user_requested_size; u32 alloc_context_id; }; struct ChunkBase : ChunkHeader { // Header2, intersects with user memory. u32 free_context_id; }; static const uptr kChunkHeaderSize = sizeof(ChunkHeader); static const uptr kChunkHeader2Size = sizeof(ChunkBase) - kChunkHeaderSize; COMPILER_CHECK(kChunkHeaderSize == 16); COMPILER_CHECK(kChunkHeader2Size <= 16); // Every chunk of memory allocated by this allocator can be in one of 3 states: // CHUNK_AVAILABLE: the chunk is in the free list and ready to be allocated. // CHUNK_ALLOCATED: the chunk is allocated and not yet freed. // CHUNK_QUARANTINE: the chunk was freed and put into quarantine zone. enum { CHUNK_AVAILABLE = 0, // 0 is the default value even if we didn't set it. CHUNK_ALLOCATED = 2, CHUNK_QUARANTINE = 3 }; struct AsanChunk: ChunkBase { uptr Beg() { return reinterpret_cast(this) + kChunkHeaderSize; } uptr UsedSize(bool locked_version = false) { if (user_requested_size != SizeClassMap::kMaxSize) return user_requested_size; return *reinterpret_cast( get_allocator().GetMetaData(AllocBeg(locked_version))); } void *AllocBeg(bool locked_version = false) { if (from_memalign) { if (locked_version) return get_allocator().GetBlockBeginFastLocked( reinterpret_cast(this)); return get_allocator().GetBlockBegin(reinterpret_cast(this)); } return reinterpret_cast(Beg() - RZLog2Size(rz_log)); } bool AddrIsInside(uptr addr, bool locked_version = false) { return (addr >= Beg()) && (addr < Beg() + UsedSize(locked_version)); } }; struct QuarantineCallback { explicit QuarantineCallback(AllocatorCache *cache) : cache_(cache) { } void Recycle(AsanChunk *m) { CHECK_EQ(m->chunk_state, CHUNK_QUARANTINE); atomic_store((atomic_uint8_t*)m, CHUNK_AVAILABLE, memory_order_relaxed); CHECK_NE(m->alloc_tid, kInvalidTid); CHECK_NE(m->free_tid, kInvalidTid); PoisonShadow(m->Beg(), RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY), kAsanHeapLeftRedzoneMagic); void *p = reinterpret_cast(m->AllocBeg()); if (p != m) { uptr *alloc_magic = reinterpret_cast(p); CHECK_EQ(alloc_magic[0], kAllocBegMagic); // Clear the magic value, as allocator internals may overwrite the // contents of deallocated chunk, confusing GetAsanChunk lookup. alloc_magic[0] = 0; CHECK_EQ(alloc_magic[1], reinterpret_cast(m)); } // Statistics. AsanStats &thread_stats = GetCurrentThreadStats(); thread_stats.real_frees++; thread_stats.really_freed += m->UsedSize(); get_allocator().Deallocate(cache_, p); } void *Allocate(uptr size) { return get_allocator().Allocate(cache_, size, 1, false); } void Deallocate(void *p) { get_allocator().Deallocate(cache_, p); } AllocatorCache *cache_; }; typedef Quarantine AsanQuarantine; typedef AsanQuarantine::Cache QuarantineCache; void AsanMapUnmapCallback::OnMap(uptr p, uptr size) const { PoisonShadow(p, size, kAsanHeapLeftRedzoneMagic); // Statistics. AsanStats &thread_stats = GetCurrentThreadStats(); thread_stats.mmaps++; thread_stats.mmaped += size; } void AsanMapUnmapCallback::OnUnmap(uptr p, uptr size) const { PoisonShadow(p, size, 0); // We are about to unmap a chunk of user memory. // Mark the corresponding shadow memory as not needed. FlushUnneededASanShadowMemory(p, size); // Statistics. AsanStats &thread_stats = GetCurrentThreadStats(); thread_stats.munmaps++; thread_stats.munmaped += size; } // We can not use THREADLOCAL because it is not supported on some of the // platforms we care about (OSX 10.6, Android). // static THREADLOCAL AllocatorCache cache; AllocatorCache *GetAllocatorCache(AsanThreadLocalMallocStorage *ms) { CHECK(ms); return &ms->allocator_cache; } QuarantineCache *GetQuarantineCache(AsanThreadLocalMallocStorage *ms) { CHECK(ms); CHECK_LE(sizeof(QuarantineCache), sizeof(ms->quarantine_cache)); return reinterpret_cast(ms->quarantine_cache); } void AllocatorOptions::SetFrom(const Flags *f, const CommonFlags *cf) { quarantine_size_mb = f->quarantine_size_mb; min_redzone = f->redzone; max_redzone = f->max_redzone; may_return_null = cf->allocator_may_return_null; alloc_dealloc_mismatch = f->alloc_dealloc_mismatch; } void AllocatorOptions::CopyTo(Flags *f, CommonFlags *cf) { f->quarantine_size_mb = quarantine_size_mb; f->redzone = min_redzone; f->max_redzone = max_redzone; cf->allocator_may_return_null = may_return_null; f->alloc_dealloc_mismatch = alloc_dealloc_mismatch; } struct Allocator { static const uptr kMaxAllowedMallocSize = - FIRST_32_SECOND_64(3UL << 30, 1UL << 40); + FIRST_32_SECOND_64(3UL << 30, 1ULL << 40); static const uptr kMaxThreadLocalQuarantine = FIRST_32_SECOND_64(1 << 18, 1 << 20); AsanAllocator allocator; AsanQuarantine quarantine; StaticSpinMutex fallback_mutex; AllocatorCache fallback_allocator_cache; QuarantineCache fallback_quarantine_cache; // ------------------- Options -------------------------- atomic_uint16_t min_redzone; atomic_uint16_t max_redzone; atomic_uint8_t alloc_dealloc_mismatch; // ------------------- Initialization ------------------------ explicit Allocator(LinkerInitialized) : quarantine(LINKER_INITIALIZED), fallback_quarantine_cache(LINKER_INITIALIZED) {} void CheckOptions(const AllocatorOptions &options) const { CHECK_GE(options.min_redzone, 16); CHECK_GE(options.max_redzone, options.min_redzone); CHECK_LE(options.max_redzone, 2048); CHECK(IsPowerOfTwo(options.min_redzone)); CHECK(IsPowerOfTwo(options.max_redzone)); } void SharedInitCode(const AllocatorOptions &options) { CheckOptions(options); quarantine.Init((uptr)options.quarantine_size_mb << 20, kMaxThreadLocalQuarantine); atomic_store(&alloc_dealloc_mismatch, options.alloc_dealloc_mismatch, memory_order_release); atomic_store(&min_redzone, options.min_redzone, memory_order_release); atomic_store(&max_redzone, options.max_redzone, memory_order_release); } void Initialize(const AllocatorOptions &options) { allocator.Init(options.may_return_null); SharedInitCode(options); } void ReInitialize(const AllocatorOptions &options) { allocator.SetMayReturnNull(options.may_return_null); SharedInitCode(options); } void GetOptions(AllocatorOptions *options) const { options->quarantine_size_mb = quarantine.GetSize() >> 20; options->min_redzone = atomic_load(&min_redzone, memory_order_acquire); options->max_redzone = atomic_load(&max_redzone, memory_order_acquire); options->may_return_null = allocator.MayReturnNull(); options->alloc_dealloc_mismatch = atomic_load(&alloc_dealloc_mismatch, memory_order_acquire); } // -------------------- Helper methods. ------------------------- uptr ComputeRZLog(uptr user_requested_size) { u32 rz_log = user_requested_size <= 64 - 16 ? 0 : user_requested_size <= 128 - 32 ? 1 : user_requested_size <= 512 - 64 ? 2 : user_requested_size <= 4096 - 128 ? 3 : user_requested_size <= (1 << 14) - 256 ? 4 : user_requested_size <= (1 << 15) - 512 ? 5 : user_requested_size <= (1 << 16) - 1024 ? 6 : 7; u32 min_rz = atomic_load(&min_redzone, memory_order_acquire); u32 max_rz = atomic_load(&max_redzone, memory_order_acquire); return Min(Max(rz_log, RZSize2Log(min_rz)), RZSize2Log(max_rz)); } // We have an address between two chunks, and we want to report just one. AsanChunk *ChooseChunk(uptr addr, AsanChunk *left_chunk, AsanChunk *right_chunk) { // Prefer an allocated chunk over freed chunk and freed chunk // over available chunk. if (left_chunk->chunk_state != right_chunk->chunk_state) { if (left_chunk->chunk_state == CHUNK_ALLOCATED) return left_chunk; if (right_chunk->chunk_state == CHUNK_ALLOCATED) return right_chunk; if (left_chunk->chunk_state == CHUNK_QUARANTINE) return left_chunk; if (right_chunk->chunk_state == CHUNK_QUARANTINE) return right_chunk; } // Same chunk_state: choose based on offset. sptr l_offset = 0, r_offset = 0; CHECK(AsanChunkView(left_chunk).AddrIsAtRight(addr, 1, &l_offset)); CHECK(AsanChunkView(right_chunk).AddrIsAtLeft(addr, 1, &r_offset)); if (l_offset < r_offset) return left_chunk; return right_chunk; } // -------------------- Allocation/Deallocation routines --------------- void *Allocate(uptr size, uptr alignment, BufferedStackTrace *stack, AllocType alloc_type, bool can_fill) { if (UNLIKELY(!asan_inited)) AsanInitFromRtl(); Flags &fl = *flags(); CHECK(stack); const uptr min_alignment = SHADOW_GRANULARITY; if (alignment < min_alignment) alignment = min_alignment; if (size == 0) { // We'd be happy to avoid allocating memory for zero-size requests, but // some programs/tests depend on this behavior and assume that malloc // would not return NULL even for zero-size allocations. Moreover, it // looks like operator new should never return NULL, and results of // consecutive "new" calls must be different even if the allocated size // is zero. size = 1; } CHECK(IsPowerOfTwo(alignment)); uptr rz_log = ComputeRZLog(size); uptr rz_size = RZLog2Size(rz_log); uptr rounded_size = RoundUpTo(Max(size, kChunkHeader2Size), alignment); uptr needed_size = rounded_size + rz_size; if (alignment > min_alignment) needed_size += alignment; bool using_primary_allocator = true; // If we are allocating from the secondary allocator, there will be no // automatic right redzone, so add the right redzone manually. if (!PrimaryAllocator::CanAllocate(needed_size, alignment)) { needed_size += rz_size; using_primary_allocator = false; } CHECK(IsAligned(needed_size, min_alignment)); if (size > kMaxAllowedMallocSize || needed_size > kMaxAllowedMallocSize) { Report("WARNING: AddressSanitizer failed to allocate 0x%zx bytes\n", (void*)size); return allocator.ReturnNullOrDie(); } AsanThread *t = GetCurrentThread(); void *allocated; bool check_rss_limit = true; if (t) { AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage()); allocated = allocator.Allocate(cache, needed_size, 8, false, check_rss_limit); } else { SpinMutexLock l(&fallback_mutex); AllocatorCache *cache = &fallback_allocator_cache; allocated = allocator.Allocate(cache, needed_size, 8, false, check_rss_limit); } if (!allocated) return allocator.ReturnNullOrDie(); if (*(u8 *)MEM_TO_SHADOW((uptr)allocated) == 0 && CanPoisonMemory()) { // Heap poisoning is enabled, but the allocator provides an unpoisoned // chunk. This is possible if CanPoisonMemory() was false for some // time, for example, due to flags()->start_disabled. // Anyway, poison the block before using it for anything else. uptr allocated_size = allocator.GetActuallyAllocatedSize(allocated); PoisonShadow((uptr)allocated, allocated_size, kAsanHeapLeftRedzoneMagic); } uptr alloc_beg = reinterpret_cast(allocated); uptr alloc_end = alloc_beg + needed_size; uptr beg_plus_redzone = alloc_beg + rz_size; uptr user_beg = beg_plus_redzone; if (!IsAligned(user_beg, alignment)) user_beg = RoundUpTo(user_beg, alignment); uptr user_end = user_beg + size; CHECK_LE(user_end, alloc_end); uptr chunk_beg = user_beg - kChunkHeaderSize; AsanChunk *m = reinterpret_cast(chunk_beg); m->alloc_type = alloc_type; m->rz_log = rz_log; u32 alloc_tid = t ? t->tid() : 0; m->alloc_tid = alloc_tid; CHECK_EQ(alloc_tid, m->alloc_tid); // Does alloc_tid fit into the bitfield? m->free_tid = kInvalidTid; m->from_memalign = user_beg != beg_plus_redzone; if (alloc_beg != chunk_beg) { CHECK_LE(alloc_beg+ 2 * sizeof(uptr), chunk_beg); reinterpret_cast(alloc_beg)[0] = kAllocBegMagic; reinterpret_cast(alloc_beg)[1] = chunk_beg; } if (using_primary_allocator) { CHECK(size); m->user_requested_size = size; CHECK(allocator.FromPrimary(allocated)); } else { CHECK(!allocator.FromPrimary(allocated)); m->user_requested_size = SizeClassMap::kMaxSize; uptr *meta = reinterpret_cast(allocator.GetMetaData(allocated)); meta[0] = size; meta[1] = chunk_beg; } m->alloc_context_id = StackDepotPut(*stack); uptr size_rounded_down_to_granularity = RoundDownTo(size, SHADOW_GRANULARITY); // Unpoison the bulk of the memory region. if (size_rounded_down_to_granularity) PoisonShadow(user_beg, size_rounded_down_to_granularity, 0); // Deal with the end of the region if size is not aligned to granularity. if (size != size_rounded_down_to_granularity && CanPoisonMemory()) { u8 *shadow = (u8 *)MemToShadow(user_beg + size_rounded_down_to_granularity); *shadow = fl.poison_partial ? (size & (SHADOW_GRANULARITY - 1)) : 0; } AsanStats &thread_stats = GetCurrentThreadStats(); thread_stats.mallocs++; thread_stats.malloced += size; thread_stats.malloced_redzones += needed_size - size; if (needed_size > SizeClassMap::kMaxSize) thread_stats.malloc_large++; else thread_stats.malloced_by_size[SizeClassMap::ClassID(needed_size)]++; void *res = reinterpret_cast(user_beg); if (can_fill && fl.max_malloc_fill_size) { uptr fill_size = Min(size, (uptr)fl.max_malloc_fill_size); REAL(memset)(res, fl.malloc_fill_byte, fill_size); } #if CAN_SANITIZE_LEAKS m->lsan_tag = __lsan::DisabledInThisThread() ? __lsan::kIgnored : __lsan::kDirectlyLeaked; #endif // Must be the last mutation of metadata in this function. atomic_store((atomic_uint8_t *)m, CHUNK_ALLOCATED, memory_order_release); ASAN_MALLOC_HOOK(res, size); return res; } - void AtomicallySetQuarantineFlag(AsanChunk *m, void *ptr, + // Set quarantine flag if chunk is allocated, issue ASan error report on + // available and quarantined chunks. Return true on success, false otherwise. + bool AtomicallySetQuarantineFlagIfAllocated(AsanChunk *m, void *ptr, BufferedStackTrace *stack) { u8 old_chunk_state = CHUNK_ALLOCATED; // Flip the chunk_state atomically to avoid race on double-free. - if (!atomic_compare_exchange_strong((atomic_uint8_t*)m, &old_chunk_state, - CHUNK_QUARANTINE, memory_order_acquire)) + if (!atomic_compare_exchange_strong((atomic_uint8_t *)m, &old_chunk_state, + CHUNK_QUARANTINE, + memory_order_acquire)) { ReportInvalidFree(ptr, old_chunk_state, stack); + // It's not safe to push a chunk in quarantine on invalid free. + return false; + } CHECK_EQ(CHUNK_ALLOCATED, old_chunk_state); + return true; } // Expects the chunk to already be marked as quarantined by using - // AtomicallySetQuarantineFlag. + // AtomicallySetQuarantineFlagIfAllocated. void QuarantineChunk(AsanChunk *m, void *ptr, BufferedStackTrace *stack, AllocType alloc_type) { CHECK_EQ(m->chunk_state, CHUNK_QUARANTINE); - - if (m->alloc_type != alloc_type) { - if (atomic_load(&alloc_dealloc_mismatch, memory_order_acquire)) { - ReportAllocTypeMismatch((uptr)ptr, stack, (AllocType)m->alloc_type, - (AllocType)alloc_type); - } - } - CHECK_GE(m->alloc_tid, 0); if (SANITIZER_WORDSIZE == 64) // On 32-bits this resides in user area. CHECK_EQ(m->free_tid, kInvalidTid); AsanThread *t = GetCurrentThread(); m->free_tid = t ? t->tid() : 0; m->free_context_id = StackDepotPut(*stack); // Poison the region. PoisonShadow(m->Beg(), RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY), kAsanHeapFreeMagic); AsanStats &thread_stats = GetCurrentThreadStats(); thread_stats.frees++; thread_stats.freed += m->UsedSize(); // Push into quarantine. if (t) { AsanThreadLocalMallocStorage *ms = &t->malloc_storage(); AllocatorCache *ac = GetAllocatorCache(ms); quarantine.Put(GetQuarantineCache(ms), QuarantineCallback(ac), m, m->UsedSize()); } else { SpinMutexLock l(&fallback_mutex); AllocatorCache *ac = &fallback_allocator_cache; quarantine.Put(&fallback_quarantine_cache, QuarantineCallback(ac), m, m->UsedSize()); } } void Deallocate(void *ptr, uptr delete_size, BufferedStackTrace *stack, AllocType alloc_type) { uptr p = reinterpret_cast(ptr); if (p == 0) return; uptr chunk_beg = p - kChunkHeaderSize; AsanChunk *m = reinterpret_cast(chunk_beg); + + ASAN_FREE_HOOK(ptr); + // Must mark the chunk as quarantined before any changes to its metadata. + // Do not quarantine given chunk if we failed to set CHUNK_QUARANTINE flag. + if (!AtomicallySetQuarantineFlagIfAllocated(m, ptr, stack)) return; + + if (m->alloc_type != alloc_type) { + if (atomic_load(&alloc_dealloc_mismatch, memory_order_acquire)) { + ReportAllocTypeMismatch((uptr)ptr, stack, (AllocType)m->alloc_type, + (AllocType)alloc_type); + } + } + if (delete_size && flags()->new_delete_type_mismatch && delete_size != m->UsedSize()) { - ReportNewDeleteSizeMismatch(p, delete_size, stack); + ReportNewDeleteSizeMismatch(p, m->UsedSize(), delete_size, stack); } - ASAN_FREE_HOOK(ptr); - // Must mark the chunk as quarantined before any changes to its metadata. - AtomicallySetQuarantineFlag(m, ptr, stack); + QuarantineChunk(m, ptr, stack, alloc_type); } void *Reallocate(void *old_ptr, uptr new_size, BufferedStackTrace *stack) { CHECK(old_ptr && new_size); uptr p = reinterpret_cast(old_ptr); uptr chunk_beg = p - kChunkHeaderSize; AsanChunk *m = reinterpret_cast(chunk_beg); AsanStats &thread_stats = GetCurrentThreadStats(); thread_stats.reallocs++; thread_stats.realloced += new_size; void *new_ptr = Allocate(new_size, 8, stack, FROM_MALLOC, true); if (new_ptr) { u8 chunk_state = m->chunk_state; if (chunk_state != CHUNK_ALLOCATED) ReportInvalidFree(old_ptr, chunk_state, stack); CHECK_NE(REAL(memcpy), nullptr); uptr memcpy_size = Min(new_size, m->UsedSize()); // If realloc() races with free(), we may start copying freed memory. // However, we will report racy double-free later anyway. REAL(memcpy)(new_ptr, old_ptr, memcpy_size); Deallocate(old_ptr, 0, stack, FROM_MALLOC); } return new_ptr; } void *Calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) { if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return allocator.ReturnNullOrDie(); void *ptr = Allocate(nmemb * size, 8, stack, FROM_MALLOC, false); // If the memory comes from the secondary allocator no need to clear it // as it comes directly from mmap. if (ptr && allocator.FromPrimary(ptr)) REAL(memset)(ptr, 0, nmemb * size); return ptr; } void ReportInvalidFree(void *ptr, u8 chunk_state, BufferedStackTrace *stack) { if (chunk_state == CHUNK_QUARANTINE) ReportDoubleFree((uptr)ptr, stack); else ReportFreeNotMalloced((uptr)ptr, stack); } void CommitBack(AsanThreadLocalMallocStorage *ms) { AllocatorCache *ac = GetAllocatorCache(ms); quarantine.Drain(GetQuarantineCache(ms), QuarantineCallback(ac)); allocator.SwallowCache(ac); } // -------------------------- Chunk lookup ---------------------- // Assumes alloc_beg == allocator.GetBlockBegin(alloc_beg). AsanChunk *GetAsanChunk(void *alloc_beg) { if (!alloc_beg) return nullptr; if (!allocator.FromPrimary(alloc_beg)) { uptr *meta = reinterpret_cast(allocator.GetMetaData(alloc_beg)); AsanChunk *m = reinterpret_cast(meta[1]); return m; } uptr *alloc_magic = reinterpret_cast(alloc_beg); if (alloc_magic[0] == kAllocBegMagic) return reinterpret_cast(alloc_magic[1]); return reinterpret_cast(alloc_beg); } AsanChunk *GetAsanChunkByAddr(uptr p) { void *alloc_beg = allocator.GetBlockBegin(reinterpret_cast(p)); return GetAsanChunk(alloc_beg); } // Allocator must be locked when this function is called. AsanChunk *GetAsanChunkByAddrFastLocked(uptr p) { void *alloc_beg = allocator.GetBlockBeginFastLocked(reinterpret_cast(p)); return GetAsanChunk(alloc_beg); } uptr AllocationSize(uptr p) { AsanChunk *m = GetAsanChunkByAddr(p); if (!m) return 0; if (m->chunk_state != CHUNK_ALLOCATED) return 0; if (m->Beg() != p) return 0; return m->UsedSize(); } AsanChunkView FindHeapChunkByAddress(uptr addr) { AsanChunk *m1 = GetAsanChunkByAddr(addr); if (!m1) return AsanChunkView(m1); sptr offset = 0; if (AsanChunkView(m1).AddrIsAtLeft(addr, 1, &offset)) { // The address is in the chunk's left redzone, so maybe it is actually // a right buffer overflow from the other chunk to the left. // Search a bit to the left to see if there is another chunk. AsanChunk *m2 = nullptr; for (uptr l = 1; l < GetPageSizeCached(); l++) { m2 = GetAsanChunkByAddr(addr - l); if (m2 == m1) continue; // Still the same chunk. break; } if (m2 && AsanChunkView(m2).AddrIsAtRight(addr, 1, &offset)) m1 = ChooseChunk(addr, m2, m1); } return AsanChunkView(m1); } void PrintStats() { allocator.PrintStats(); } void ForceLock() { allocator.ForceLock(); fallback_mutex.Lock(); } void ForceUnlock() { fallback_mutex.Unlock(); allocator.ForceUnlock(); } }; static Allocator instance(LINKER_INITIALIZED); static AsanAllocator &get_allocator() { return instance.allocator; } bool AsanChunkView::IsValid() { return chunk_ && chunk_->chunk_state != CHUNK_AVAILABLE; } +bool AsanChunkView::IsAllocated() { + return chunk_ && chunk_->chunk_state == CHUNK_ALLOCATED; +} uptr AsanChunkView::Beg() { return chunk_->Beg(); } uptr AsanChunkView::End() { return Beg() + UsedSize(); } uptr AsanChunkView::UsedSize() { return chunk_->UsedSize(); } uptr AsanChunkView::AllocTid() { return chunk_->alloc_tid; } uptr AsanChunkView::FreeTid() { return chunk_->free_tid; } static StackTrace GetStackTraceFromId(u32 id) { CHECK(id); StackTrace res = StackDepotGet(id); CHECK(res.trace); return res; } +u32 AsanChunkView::GetAllocStackId() { return chunk_->alloc_context_id; } +u32 AsanChunkView::GetFreeStackId() { return chunk_->free_context_id; } + StackTrace AsanChunkView::GetAllocStack() { - return GetStackTraceFromId(chunk_->alloc_context_id); + return GetStackTraceFromId(GetAllocStackId()); } StackTrace AsanChunkView::GetFreeStack() { - return GetStackTraceFromId(chunk_->free_context_id); + return GetStackTraceFromId(GetFreeStackId()); } void InitializeAllocator(const AllocatorOptions &options) { instance.Initialize(options); } void ReInitializeAllocator(const AllocatorOptions &options) { instance.ReInitialize(options); } void GetAllocatorOptions(AllocatorOptions *options) { instance.GetOptions(options); } AsanChunkView FindHeapChunkByAddress(uptr addr) { return instance.FindHeapChunkByAddress(addr); } void AsanThreadLocalMallocStorage::CommitBack() { instance.CommitBack(this); } void PrintInternalAllocatorStats() { instance.PrintStats(); } void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack, AllocType alloc_type) { return instance.Allocate(size, alignment, stack, alloc_type, true); } void asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type) { instance.Deallocate(ptr, 0, stack, alloc_type); } void asan_sized_free(void *ptr, uptr size, BufferedStackTrace *stack, AllocType alloc_type) { instance.Deallocate(ptr, size, stack, alloc_type); } void *asan_malloc(uptr size, BufferedStackTrace *stack) { return instance.Allocate(size, 8, stack, FROM_MALLOC, true); } void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) { return instance.Calloc(nmemb, size, stack); } void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack) { if (!p) return instance.Allocate(size, 8, stack, FROM_MALLOC, true); if (size == 0) { instance.Deallocate(p, 0, stack, FROM_MALLOC); return nullptr; } return instance.Reallocate(p, size, stack); } void *asan_valloc(uptr size, BufferedStackTrace *stack) { return instance.Allocate(size, GetPageSizeCached(), stack, FROM_MALLOC, true); } void *asan_pvalloc(uptr size, BufferedStackTrace *stack) { uptr PageSize = GetPageSizeCached(); size = RoundUpTo(size, PageSize); if (size == 0) { // pvalloc(0) should allocate one page. size = PageSize; } return instance.Allocate(size, PageSize, stack, FROM_MALLOC, true); } int asan_posix_memalign(void **memptr, uptr alignment, uptr size, BufferedStackTrace *stack) { void *ptr = instance.Allocate(size, alignment, stack, FROM_MALLOC, true); CHECK(IsAligned((uptr)ptr, alignment)); *memptr = ptr; return 0; } -uptr asan_malloc_usable_size(void *ptr, uptr pc, uptr bp) { +uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp) { if (!ptr) return 0; uptr usable_size = instance.AllocationSize(reinterpret_cast(ptr)); if (flags()->check_malloc_usable_size && (usable_size == 0)) { GET_STACK_TRACE_FATAL(pc, bp); ReportMallocUsableSizeNotOwned((uptr)ptr, &stack); } return usable_size; } uptr asan_mz_size(const void *ptr) { return instance.AllocationSize(reinterpret_cast(ptr)); } void asan_mz_force_lock() { instance.ForceLock(); } void asan_mz_force_unlock() { instance.ForceUnlock(); } void AsanSoftRssLimitExceededCallback(bool exceeded) { instance.allocator.SetRssLimitIsExceeded(exceeded); } } // namespace __asan // --- Implementation of LSan-specific functions --- {{{1 namespace __lsan { void LockAllocator() { __asan::get_allocator().ForceLock(); } void UnlockAllocator() { __asan::get_allocator().ForceUnlock(); } void GetAllocatorGlobalRange(uptr *begin, uptr *end) { *begin = (uptr)&__asan::get_allocator(); *end = *begin + sizeof(__asan::get_allocator()); } uptr PointsIntoChunk(void* p) { uptr addr = reinterpret_cast(p); __asan::AsanChunk *m = __asan::instance.GetAsanChunkByAddrFastLocked(addr); if (!m) return 0; uptr chunk = m->Beg(); if (m->chunk_state != __asan::CHUNK_ALLOCATED) return 0; if (m->AddrIsInside(addr, /*locked_version=*/true)) return chunk; if (IsSpecialCaseOfOperatorNew0(chunk, m->UsedSize(/*locked_version*/ true), addr)) return chunk; return 0; } uptr GetUserBegin(uptr chunk) { __asan::AsanChunk *m = __asan::instance.GetAsanChunkByAddrFastLocked(chunk); CHECK(m); return m->Beg(); } LsanMetadata::LsanMetadata(uptr chunk) { metadata_ = reinterpret_cast(chunk - __asan::kChunkHeaderSize); } bool LsanMetadata::allocated() const { __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_); return m->chunk_state == __asan::CHUNK_ALLOCATED; } ChunkTag LsanMetadata::tag() const { __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_); return static_cast(m->lsan_tag); } void LsanMetadata::set_tag(ChunkTag value) { __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_); m->lsan_tag = value; } uptr LsanMetadata::requested_size() const { __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_); return m->UsedSize(/*locked_version=*/true); } u32 LsanMetadata::stack_trace_id() const { __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_); return m->alloc_context_id; } void ForEachChunk(ForEachChunkCallback callback, void *arg) { __asan::get_allocator().ForEachChunk(callback, arg); } IgnoreObjectResult IgnoreObjectLocked(const void *p) { uptr addr = reinterpret_cast(p); __asan::AsanChunk *m = __asan::instance.GetAsanChunkByAddr(addr); if (!m) return kIgnoreObjectInvalid; if ((m->chunk_state == __asan::CHUNK_ALLOCATED) && m->AddrIsInside(addr)) { if (m->lsan_tag == kIgnored) return kIgnoreObjectAlreadyIgnored; m->lsan_tag = __lsan::kIgnored; return kIgnoreObjectSuccess; } else { return kIgnoreObjectInvalid; } } } // namespace __lsan // ---------------------- Interface ---------------- {{{1 using namespace __asan; // NOLINT // ASan allocator doesn't reserve extra bytes, so normally we would // just return "size". We don't want to expose our redzone sizes, etc here. uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; } int __sanitizer_get_ownership(const void *p) { uptr ptr = reinterpret_cast(p); return instance.AllocationSize(ptr) > 0; } uptr __sanitizer_get_allocated_size(const void *p) { if (!p) return 0; uptr ptr = reinterpret_cast(p); uptr allocated_size = instance.AllocationSize(ptr); // Die if p is not malloced or if it is already freed. if (allocated_size == 0) { GET_STACK_TRACE_FATAL_HERE; ReportSanitizerGetAllocatedSizeNotOwned(ptr, &stack); } return allocated_size; } #if !SANITIZER_SUPPORTS_WEAK_HOOKS // Provide default (no-op) implementation of malloc hooks. extern "C" { SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void __sanitizer_malloc_hook(void *ptr, uptr size) { (void)ptr; (void)size; } SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void __sanitizer_free_hook(void *ptr) { (void)ptr; } } // extern "C" #endif Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_allocator.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_allocator.h (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_allocator.h (revision 305364) @@ -1,184 +1,187 @@ //===-- asan_allocator.h ----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // ASan-private header for asan_allocator.cc. //===----------------------------------------------------------------------===// #ifndef ASAN_ALLOCATOR_H #define ASAN_ALLOCATOR_H #include "asan_flags.h" #include "asan_internal.h" #include "asan_interceptors.h" #include "sanitizer_common/sanitizer_allocator.h" #include "sanitizer_common/sanitizer_list.h" namespace __asan { enum AllocType { FROM_MALLOC = 1, // Memory block came from malloc, calloc, realloc, etc. FROM_NEW = 2, // Memory block came from operator new. FROM_NEW_BR = 3 // Memory block came from operator new [ ] }; struct AsanChunk; struct AllocatorOptions { u32 quarantine_size_mb; u16 min_redzone; u16 max_redzone; u8 may_return_null; u8 alloc_dealloc_mismatch; void SetFrom(const Flags *f, const CommonFlags *cf); void CopyTo(Flags *f, CommonFlags *cf); }; void InitializeAllocator(const AllocatorOptions &options); void ReInitializeAllocator(const AllocatorOptions &options); void GetAllocatorOptions(AllocatorOptions *options); class AsanChunkView { public: explicit AsanChunkView(AsanChunk *chunk) : chunk_(chunk) {} - bool IsValid(); // Checks if AsanChunkView points to a valid allocated - // or quarantined chunk. - uptr Beg(); // First byte of user memory. - uptr End(); // Last byte of user memory. - uptr UsedSize(); // Size requested by the user. + bool IsValid(); // Checks if AsanChunkView points to a valid allocated + // or quarantined chunk. + bool IsAllocated(); // Checks if the memory is currently allocated. + uptr Beg(); // First byte of user memory. + uptr End(); // Last byte of user memory. + uptr UsedSize(); // Size requested by the user. uptr AllocTid(); uptr FreeTid(); bool Eq(const AsanChunkView &c) const { return chunk_ == c.chunk_; } + u32 GetAllocStackId(); + u32 GetFreeStackId(); StackTrace GetAllocStack(); StackTrace GetFreeStack(); bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) { if (addr >= Beg() && (addr + access_size) <= End()) { *offset = addr - Beg(); return true; } return false; } bool AddrIsAtLeft(uptr addr, uptr access_size, sptr *offset) { (void)access_size; if (addr < Beg()) { *offset = Beg() - addr; return true; } return false; } bool AddrIsAtRight(uptr addr, uptr access_size, sptr *offset) { if (addr + access_size > End()) { *offset = addr - End(); return true; } return false; } private: AsanChunk *const chunk_; }; AsanChunkView FindHeapChunkByAddress(uptr address); // List of AsanChunks with total size. class AsanChunkFifoList: public IntrusiveList { public: explicit AsanChunkFifoList(LinkerInitialized) { } AsanChunkFifoList() { clear(); } void Push(AsanChunk *n); void PushList(AsanChunkFifoList *q); AsanChunk *Pop(); uptr size() { return size_; } void clear() { IntrusiveList::clear(); size_ = 0; } private: uptr size_; }; struct AsanMapUnmapCallback { void OnMap(uptr p, uptr size) const; void OnUnmap(uptr p, uptr size) const; }; #if SANITIZER_CAN_USE_ALLOCATOR64 # if defined(__powerpc64__) const uptr kAllocatorSpace = 0xa0000000000ULL; const uptr kAllocatorSize = 0x20000000000ULL; // 2T. # elif defined(__aarch64__) // AArch64/SANITIZIER_CAN_USER_ALLOCATOR64 is only for 42-bit VMA // so no need to different values for different VMA. const uptr kAllocatorSpace = 0x10000000000ULL; const uptr kAllocatorSize = 0x10000000000ULL; // 3T. # else const uptr kAllocatorSpace = 0x600000000000ULL; const uptr kAllocatorSize = 0x40000000000ULL; // 4T. # endif typedef DefaultSizeClassMap SizeClassMap; typedef SizeClassAllocator64 PrimaryAllocator; #else // Fallback to SizeClassAllocator32. static const uptr kRegionSizeLog = 20; static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; # if SANITIZER_WORDSIZE == 32 typedef FlatByteMap ByteMap; # elif SANITIZER_WORDSIZE == 64 typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; # endif typedef CompactSizeClassMap SizeClassMap; typedef SizeClassAllocator32<0, SANITIZER_MMAP_RANGE_SIZE, 16, SizeClassMap, kRegionSizeLog, ByteMap, AsanMapUnmapCallback> PrimaryAllocator; #endif // SANITIZER_CAN_USE_ALLOCATOR64 static const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses; typedef SizeClassAllocatorLocalCache AllocatorCache; typedef LargeMmapAllocator SecondaryAllocator; typedef CombinedAllocator AsanAllocator; struct AsanThreadLocalMallocStorage { uptr quarantine_cache[16]; AllocatorCache allocator_cache; void CommitBack(); private: // These objects are allocated via mmap() and are zero-initialized. AsanThreadLocalMallocStorage() {} }; void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack, AllocType alloc_type); void asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type); void asan_sized_free(void *ptr, uptr size, BufferedStackTrace *stack, AllocType alloc_type); void *asan_malloc(uptr size, BufferedStackTrace *stack); void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack); void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack); void *asan_valloc(uptr size, BufferedStackTrace *stack); void *asan_pvalloc(uptr size, BufferedStackTrace *stack); int asan_posix_memalign(void **memptr, uptr alignment, uptr size, BufferedStackTrace *stack); -uptr asan_malloc_usable_size(void *ptr, uptr pc, uptr bp); +uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp); uptr asan_mz_size(const void *ptr); void asan_mz_force_lock(); void asan_mz_force_unlock(); void PrintInternalAllocatorStats(); void AsanSoftRssLimitExceededCallback(bool exceeded); } // namespace __asan #endif // ASAN_ALLOCATOR_H Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_fake_stack.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_fake_stack.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_fake_stack.cc (revision 305364) @@ -1,283 +1,283 @@ //===-- asan_fake_stack.cc ------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // FakeStack is used to detect use-after-return bugs. //===----------------------------------------------------------------------===// #include "asan_allocator.h" #include "asan_poisoning.h" #include "asan_thread.h" namespace __asan { static const u64 kMagic1 = kAsanStackAfterReturnMagic; static const u64 kMagic2 = (kMagic1 << 8) | kMagic1; static const u64 kMagic4 = (kMagic2 << 16) | kMagic2; static const u64 kMagic8 = (kMagic4 << 32) | kMagic4; static const u64 kAllocaRedzoneSize = 32UL; static const u64 kAllocaRedzoneMask = 31UL; // For small size classes inline PoisonShadow for better performance. ALWAYS_INLINE void SetShadow(uptr ptr, uptr size, uptr class_id, u64 magic) { CHECK_EQ(SHADOW_SCALE, 3); // This code expects SHADOW_SCALE=3. u64 *shadow = reinterpret_cast(MemToShadow(ptr)); if (class_id <= 6) { - for (uptr i = 0; i < (1U << class_id); i++) { + for (uptr i = 0; i < (((uptr)1) << class_id); i++) { shadow[i] = magic; // Make sure this does not become memset. SanitizerBreakOptimization(nullptr); } } else { // The size class is too big, it's cheaper to poison only size bytes. PoisonShadow(ptr, size, static_cast(magic)); } } FakeStack *FakeStack::Create(uptr stack_size_log) { static uptr kMinStackSizeLog = 16; static uptr kMaxStackSizeLog = FIRST_32_SECOND_64(24, 28); if (stack_size_log < kMinStackSizeLog) stack_size_log = kMinStackSizeLog; if (stack_size_log > kMaxStackSizeLog) stack_size_log = kMaxStackSizeLog; uptr size = RequiredSize(stack_size_log); FakeStack *res = reinterpret_cast( flags()->uar_noreserve ? MmapNoReserveOrDie(size, "FakeStack") : MmapOrDie(size, "FakeStack")); res->stack_size_log_ = stack_size_log; u8 *p = reinterpret_cast(res); VReport(1, "T%d: FakeStack created: %p -- %p stack_size_log: %zd; " "mmapped %zdK, noreserve=%d \n", GetCurrentTidOrInvalid(), p, p + FakeStack::RequiredSize(stack_size_log), stack_size_log, size >> 10, flags()->uar_noreserve); return res; } void FakeStack::Destroy(int tid) { PoisonAll(0); if (Verbosity() >= 2) { InternalScopedString str(kNumberOfSizeClasses * 50); for (uptr class_id = 0; class_id < kNumberOfSizeClasses; class_id++) str.append("%zd: %zd/%zd; ", class_id, hint_position_[class_id], NumberOfFrames(stack_size_log(), class_id)); Report("T%d: FakeStack destroyed: %s\n", tid, str.data()); } uptr size = RequiredSize(stack_size_log_); FlushUnneededASanShadowMemory(reinterpret_cast(this), size); UnmapOrDie(this, size); } void FakeStack::PoisonAll(u8 magic) { PoisonShadow(reinterpret_cast(this), RequiredSize(stack_size_log()), magic); } #if !defined(_MSC_VER) || defined(__clang__) ALWAYS_INLINE USED #endif FakeFrame *FakeStack::Allocate(uptr stack_size_log, uptr class_id, uptr real_stack) { CHECK_LT(class_id, kNumberOfSizeClasses); if (needs_gc_) GC(real_stack); uptr &hint_position = hint_position_[class_id]; const int num_iter = NumberOfFrames(stack_size_log, class_id); u8 *flags = GetFlags(stack_size_log, class_id); for (int i = 0; i < num_iter; i++) { uptr pos = ModuloNumberOfFrames(stack_size_log, class_id, hint_position++); // This part is tricky. On one hand, checking and setting flags[pos] // should be atomic to ensure async-signal safety. But on the other hand, // if the signal arrives between checking and setting flags[pos], the // signal handler's fake stack will start from a different hint_position // and so will not touch this particular byte. So, it is safe to do this // with regular non-atimic load and store (at least I was not able to make // this code crash). if (flags[pos]) continue; flags[pos] = 1; FakeFrame *res = reinterpret_cast( GetFrame(stack_size_log, class_id, pos)); res->real_stack = real_stack; *SavedFlagPtr(reinterpret_cast(res), class_id) = &flags[pos]; return res; } return nullptr; // We are out of fake stack. } uptr FakeStack::AddrIsInFakeStack(uptr ptr, uptr *frame_beg, uptr *frame_end) { uptr stack_size_log = this->stack_size_log(); uptr beg = reinterpret_cast(GetFrame(stack_size_log, 0, 0)); uptr end = reinterpret_cast(this) + RequiredSize(stack_size_log); if (ptr < beg || ptr >= end) return 0; uptr class_id = (ptr - beg) >> stack_size_log; uptr base = beg + (class_id << stack_size_log); CHECK_LE(base, ptr); - CHECK_LT(ptr, base + (1UL << stack_size_log)); + CHECK_LT(ptr, base + (((uptr)1) << stack_size_log)); uptr pos = (ptr - base) >> (kMinStackFrameSizeLog + class_id); uptr res = base + pos * BytesInSizeClass(class_id); *frame_end = res + BytesInSizeClass(class_id); *frame_beg = res + sizeof(FakeFrame); return res; } void FakeStack::HandleNoReturn() { needs_gc_ = true; } // When throw, longjmp or some such happens we don't call OnFree() and // as the result may leak one or more fake frames, but the good news is that // we are notified about all such events by HandleNoReturn(). // If we recently had such no-return event we need to collect garbage frames. // We do it based on their 'real_stack' values -- everything that is lower // than the current real_stack is garbage. NOINLINE void FakeStack::GC(uptr real_stack) { uptr collected = 0; for (uptr class_id = 0; class_id < kNumberOfSizeClasses; class_id++) { u8 *flags = GetFlags(stack_size_log(), class_id); for (uptr i = 0, n = NumberOfFrames(stack_size_log(), class_id); i < n; i++) { if (flags[i] == 0) continue; // not allocated. FakeFrame *ff = reinterpret_cast( GetFrame(stack_size_log(), class_id, i)); if (ff->real_stack < real_stack) { flags[i] = 0; collected++; } } } needs_gc_ = false; } void FakeStack::ForEachFakeFrame(RangeIteratorCallback callback, void *arg) { for (uptr class_id = 0; class_id < kNumberOfSizeClasses; class_id++) { u8 *flags = GetFlags(stack_size_log(), class_id); for (uptr i = 0, n = NumberOfFrames(stack_size_log(), class_id); i < n; i++) { if (flags[i] == 0) continue; // not allocated. FakeFrame *ff = reinterpret_cast( GetFrame(stack_size_log(), class_id, i)); uptr begin = reinterpret_cast(ff); callback(begin, begin + FakeStack::BytesInSizeClass(class_id), arg); } } } #if SANITIZER_LINUX && !SANITIZER_ANDROID static THREADLOCAL FakeStack *fake_stack_tls; FakeStack *GetTLSFakeStack() { return fake_stack_tls; } void SetTLSFakeStack(FakeStack *fs) { fake_stack_tls = fs; } #else FakeStack *GetTLSFakeStack() { return 0; } void SetTLSFakeStack(FakeStack *fs) { } #endif // SANITIZER_LINUX && !SANITIZER_ANDROID static FakeStack *GetFakeStack() { AsanThread *t = GetCurrentThread(); if (!t) return nullptr; return t->fake_stack(); } static FakeStack *GetFakeStackFast() { if (FakeStack *fs = GetTLSFakeStack()) return fs; if (!__asan_option_detect_stack_use_after_return) return nullptr; return GetFakeStack(); } ALWAYS_INLINE uptr OnMalloc(uptr class_id, uptr size) { FakeStack *fs = GetFakeStackFast(); if (!fs) return 0; uptr local_stack; uptr real_stack = reinterpret_cast(&local_stack); FakeFrame *ff = fs->Allocate(fs->stack_size_log(), class_id, real_stack); if (!ff) return 0; // Out of fake stack. uptr ptr = reinterpret_cast(ff); SetShadow(ptr, size, class_id, 0); return ptr; } ALWAYS_INLINE void OnFree(uptr ptr, uptr class_id, uptr size) { FakeStack::Deallocate(ptr, class_id); SetShadow(ptr, size, class_id, kMagic8); } } // namespace __asan // ---------------------- Interface ---------------- {{{1 using namespace __asan; #define DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(class_id) \ extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr \ __asan_stack_malloc_##class_id(uptr size) { \ return OnMalloc(class_id, size); \ } \ extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __asan_stack_free_##class_id( \ uptr ptr, uptr size) { \ OnFree(ptr, class_id, size); \ } DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(0) DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(1) DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(2) DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(3) DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(4) DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(5) DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(6) DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(7) DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(8) DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(9) DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(10) extern "C" { SANITIZER_INTERFACE_ATTRIBUTE void *__asan_get_current_fake_stack() { return GetFakeStackFast(); } SANITIZER_INTERFACE_ATTRIBUTE void *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg, void **end) { FakeStack *fs = reinterpret_cast(fake_stack); if (!fs) return nullptr; uptr frame_beg, frame_end; FakeFrame *frame = reinterpret_cast(fs->AddrIsInFakeStack( reinterpret_cast(addr), &frame_beg, &frame_end)); if (!frame) return nullptr; if (frame->magic != kCurrentStackFrameMagic) return nullptr; if (beg) *beg = reinterpret_cast(frame_beg); if (end) *end = reinterpret_cast(frame_end); return reinterpret_cast(frame->real_stack); } SANITIZER_INTERFACE_ATTRIBUTE void __asan_alloca_poison(uptr addr, uptr size) { uptr LeftRedzoneAddr = addr - kAllocaRedzoneSize; uptr PartialRzAddr = addr + size; uptr RightRzAddr = (PartialRzAddr + kAllocaRedzoneMask) & ~kAllocaRedzoneMask; uptr PartialRzAligned = PartialRzAddr & ~(SHADOW_GRANULARITY - 1); FastPoisonShadow(LeftRedzoneAddr, kAllocaRedzoneSize, kAsanAllocaLeftMagic); FastPoisonShadowPartialRightRedzone( PartialRzAligned, PartialRzAddr % SHADOW_GRANULARITY, RightRzAddr - PartialRzAligned, kAsanAllocaRightMagic); FastPoisonShadow(RightRzAddr, kAllocaRedzoneSize, kAsanAllocaRightMagic); } SANITIZER_INTERFACE_ATTRIBUTE void __asan_allocas_unpoison(uptr top, uptr bottom) { if ((!top) || (top > bottom)) return; REAL(memset)(reinterpret_cast(MemToShadow(top)), 0, (bottom - top) / SHADOW_GRANULARITY); } } // extern "C" Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_fake_stack.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_fake_stack.h (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_fake_stack.h (revision 305364) @@ -1,175 +1,176 @@ //===-- asan_fake_stack.h ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // ASan-private header for asan_fake_stack.cc, implements FakeStack. //===----------------------------------------------------------------------===// #ifndef ASAN_FAKE_STACK_H #define ASAN_FAKE_STACK_H #include "sanitizer_common/sanitizer_common.h" namespace __asan { // Fake stack frame contains local variables of one function. struct FakeFrame { uptr magic; // Modified by the instrumented code. uptr descr; // Modified by the instrumented code. uptr pc; // Modified by the instrumented code. uptr real_stack; }; // For each thread we create a fake stack and place stack objects on this fake // stack instead of the real stack. The fake stack is not really a stack but // a fast malloc-like allocator so that when a function exits the fake stack // is not popped but remains there for quite some time until gets used again. // So, we poison the objects on the fake stack when function returns. // It helps us find use-after-return bugs. // // The FakeStack objects is allocated by a single mmap call and has no other // pointers. The size of the fake stack depends on the actual thread stack size // and thus can not be a constant. // stack_size is a power of two greater or equal to the thread's stack size; // we store it as its logarithm (stack_size_log). // FakeStack has kNumberOfSizeClasses (11) size classes, each size class // is a power of two, starting from 64 bytes. Each size class occupies // stack_size bytes and thus can allocate // NumberOfFrames=(stack_size/BytesInSizeClass) fake frames (also a power of 2). // For each size class we have NumberOfFrames allocation flags, // each flag indicates whether the given frame is currently allocated. // All flags for size classes 0 .. 10 are stored in a single contiguous region // followed by another contiguous region which contains the actual memory for // size classes. The addresses are computed by GetFlags and GetFrame without // any memory accesses solely based on 'this' and stack_size_log. // Allocate() flips the appropriate allocation flag atomically, thus achieving // async-signal safety. // This allocator does not have quarantine per se, but it tries to allocate the // frames in round robin fasion to maximize the delay between a deallocation // and the next allocation. class FakeStack { static const uptr kMinStackFrameSizeLog = 6; // Min frame is 64B. static const uptr kMaxStackFrameSizeLog = 16; // Max stack frame is 64K. public: static const uptr kNumberOfSizeClasses = kMaxStackFrameSizeLog - kMinStackFrameSizeLog + 1; // CTOR: create the FakeStack as a single mmap-ed object. static FakeStack *Create(uptr stack_size_log); void Destroy(int tid); // stack_size_log is at least 15 (stack_size >= 32K). static uptr SizeRequiredForFlags(uptr stack_size_log) { - return 1UL << (stack_size_log + 1 - kMinStackFrameSizeLog); + return ((uptr)1) << (stack_size_log + 1 - kMinStackFrameSizeLog); } // Each size class occupies stack_size bytes. static uptr SizeRequiredForFrames(uptr stack_size_log) { - return (1ULL << stack_size_log) * kNumberOfSizeClasses; + return (((uptr)1) << stack_size_log) * kNumberOfSizeClasses; } // Number of bytes requires for the whole object. static uptr RequiredSize(uptr stack_size_log) { return kFlagsOffset + SizeRequiredForFlags(stack_size_log) + SizeRequiredForFrames(stack_size_log); } // Offset of the given flag from the first flag. // The flags for class 0 begin at offset 000000000 // The flags for class 1 begin at offset 100000000 // ....................2................ 110000000 // ....................3................ 111000000 // and so on. static uptr FlagsOffset(uptr stack_size_log, uptr class_id) { uptr t = kNumberOfSizeClasses - 1 - class_id; - const uptr all_ones = (1 << (kNumberOfSizeClasses - 1)) - 1; + const uptr all_ones = (((uptr)1) << (kNumberOfSizeClasses - 1)) - 1; return ((all_ones >> t) << t) << (stack_size_log - 15); } static uptr NumberOfFrames(uptr stack_size_log, uptr class_id) { - return 1UL << (stack_size_log - kMinStackFrameSizeLog - class_id); + return ((uptr)1) << (stack_size_log - kMinStackFrameSizeLog - class_id); } // Divide n by the numbe of frames in size class. static uptr ModuloNumberOfFrames(uptr stack_size_log, uptr class_id, uptr n) { return n & (NumberOfFrames(stack_size_log, class_id) - 1); } // The the pointer to the flags of the given class_id. u8 *GetFlags(uptr stack_size_log, uptr class_id) { return reinterpret_cast(this) + kFlagsOffset + FlagsOffset(stack_size_log, class_id); } // Get frame by class_id and pos. u8 *GetFrame(uptr stack_size_log, uptr class_id, uptr pos) { return reinterpret_cast(this) + kFlagsOffset + SizeRequiredForFlags(stack_size_log) + - (1 << stack_size_log) * class_id + BytesInSizeClass(class_id) * pos; + (((uptr)1) << stack_size_log) * class_id + + BytesInSizeClass(class_id) * pos; } // Allocate the fake frame. FakeFrame *Allocate(uptr stack_size_log, uptr class_id, uptr real_stack); // Deallocate the fake frame: read the saved flag address and write 0 there. static void Deallocate(uptr x, uptr class_id) { **SavedFlagPtr(x, class_id) = 0; } // Poison the entire FakeStack's shadow with the magic value. void PoisonAll(u8 magic); // Return the beginning of the FakeFrame or 0 if the address is not ours. uptr AddrIsInFakeStack(uptr addr, uptr *frame_beg, uptr *frame_end); USED uptr AddrIsInFakeStack(uptr addr) { uptr t1, t2; return AddrIsInFakeStack(addr, &t1, &t2); } // Number of bytes in a fake frame of this size class. static uptr BytesInSizeClass(uptr class_id) { - return 1UL << (class_id + kMinStackFrameSizeLog); + return ((uptr)1) << (class_id + kMinStackFrameSizeLog); } // The fake frame is guaranteed to have a right redzone. // We use the last word of that redzone to store the address of the flag // that corresponds to the current frame to make faster deallocation. static u8 **SavedFlagPtr(uptr x, uptr class_id) { return reinterpret_cast(x + BytesInSizeClass(class_id) - sizeof(x)); } uptr stack_size_log() const { return stack_size_log_; } void HandleNoReturn(); void GC(uptr real_stack); void ForEachFakeFrame(RangeIteratorCallback callback, void *arg); private: FakeStack() { } static const uptr kFlagsOffset = 4096; // This is were the flags begin. // Must match the number of uses of DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID COMPILER_CHECK(kNumberOfSizeClasses == 11); - static const uptr kMaxStackMallocSize = 1 << kMaxStackFrameSizeLog; + static const uptr kMaxStackMallocSize = ((uptr)1) << kMaxStackFrameSizeLog; uptr hint_position_[kNumberOfSizeClasses]; uptr stack_size_log_; // a bit is set if something was allocated from the corresponding size class. bool needs_gc_; }; FakeStack *GetTLSFakeStack(); void SetTLSFakeStack(FakeStack *fs); } // namespace __asan #endif // ASAN_FAKE_STACK_H Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_flags.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_flags.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_flags.cc (revision 305364) @@ -1,171 +1,179 @@ //===-- asan_flags.cc -------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // ASan flag parsing logic. //===----------------------------------------------------------------------===// #include "asan_activation.h" #include "asan_flags.h" #include "asan_interface_internal.h" #include "asan_stack.h" #include "lsan/lsan_common.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_flag_parser.h" #include "ubsan/ubsan_flags.h" #include "ubsan/ubsan_platform.h" namespace __asan { Flags asan_flags_dont_use_directly; // use via flags(). static const char *MaybeCallAsanDefaultOptions() { return (&__asan_default_options) ? __asan_default_options() : ""; } static const char *MaybeUseAsanDefaultOptionsCompileDefinition() { #ifdef ASAN_DEFAULT_OPTIONS // Stringize the macro value. # define ASAN_STRINGIZE(x) #x # define ASAN_STRINGIZE_OPTIONS(options) ASAN_STRINGIZE(options) return ASAN_STRINGIZE_OPTIONS(ASAN_DEFAULT_OPTIONS); #else return ""; #endif } void Flags::SetDefaults() { #define ASAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; #include "asan_flags.inc" #undef ASAN_FLAG } static void RegisterAsanFlags(FlagParser *parser, Flags *f) { #define ASAN_FLAG(Type, Name, DefaultValue, Description) \ RegisterFlag(parser, #Name, Description, &f->Name); #include "asan_flags.inc" #undef ASAN_FLAG } void InitializeFlags() { // Set the default values and prepare for parsing ASan and common flags. SetCommonFlagsDefaults(); { CommonFlags cf; cf.CopyFrom(*common_flags()); cf.detect_leaks = CAN_SANITIZE_LEAKS; cf.external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH"); cf.malloc_context_size = kDefaultMallocContextSize; cf.intercept_tls_get_addr = true; cf.exitcode = 1; OverrideCommonFlags(cf); } Flags *f = flags(); f->SetDefaults(); FlagParser asan_parser; RegisterAsanFlags(&asan_parser, f); RegisterCommonFlags(&asan_parser); // Set the default values and prepare for parsing LSan and UBSan flags // (which can also overwrite common flags). #if CAN_SANITIZE_LEAKS __lsan::Flags *lf = __lsan::flags(); lf->SetDefaults(); FlagParser lsan_parser; __lsan::RegisterLsanFlags(&lsan_parser, lf); RegisterCommonFlags(&lsan_parser); #endif #if CAN_SANITIZE_UB __ubsan::Flags *uf = __ubsan::flags(); uf->SetDefaults(); FlagParser ubsan_parser; __ubsan::RegisterUbsanFlags(&ubsan_parser, uf); RegisterCommonFlags(&ubsan_parser); #endif // Override from ASan compile definition. const char *asan_compile_def = MaybeUseAsanDefaultOptionsCompileDefinition(); asan_parser.ParseString(asan_compile_def); // Override from user-specified string. const char *asan_default_options = MaybeCallAsanDefaultOptions(); asan_parser.ParseString(asan_default_options); #if CAN_SANITIZE_UB const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions(); ubsan_parser.ParseString(ubsan_default_options); #endif // Override from command line. asan_parser.ParseString(GetEnv("ASAN_OPTIONS")); #if CAN_SANITIZE_LEAKS lsan_parser.ParseString(GetEnv("LSAN_OPTIONS")); #endif #if CAN_SANITIZE_UB ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS")); #endif - SetVerbosity(common_flags()->verbosity); + InitializeCommonFlags(); // TODO(eugenis): dump all flags at verbosity>=2? if (Verbosity()) ReportUnrecognizedFlags(); if (common_flags()->help) { // TODO(samsonov): print all of the flags (ASan, LSan, common). asan_parser.PrintFlagDescriptions(); } // Flag validation: if (!CAN_SANITIZE_LEAKS && common_flags()->detect_leaks) { Report("%s: detect_leaks is not supported on this platform.\n", SanitizerToolName); Die(); } // Make "strict_init_order" imply "check_initialization_order". // TODO(samsonov): Use a single runtime flag for an init-order checker. if (f->strict_init_order) { f->check_initialization_order = true; } CHECK_LE((uptr)common_flags()->malloc_context_size, kStackTraceMax); CHECK_LE(f->min_uar_stack_size_log, f->max_uar_stack_size_log); CHECK_GE(f->redzone, 16); CHECK_GE(f->max_redzone, f->redzone); CHECK_LE(f->max_redzone, 2048); CHECK(IsPowerOfTwo(f->redzone)); CHECK(IsPowerOfTwo(f->max_redzone)); // quarantine_size is deprecated but we still honor it. // quarantine_size can not be used together with quarantine_size_mb. if (f->quarantine_size >= 0 && f->quarantine_size_mb >= 0) { Report("%s: please use either 'quarantine_size' (deprecated) or " "quarantine_size_mb, but not both\n", SanitizerToolName); Die(); } if (f->quarantine_size >= 0) f->quarantine_size_mb = f->quarantine_size >> 20; if (f->quarantine_size_mb < 0) { const int kDefaultQuarantineSizeMb = (ASAN_LOW_MEMORY) ? 1UL << 6 : 1UL << 8; f->quarantine_size_mb = kDefaultQuarantineSizeMb; + } + if (!f->replace_str && common_flags()->intercept_strlen) { + Report("WARNING: strlen interceptor is enabled even though replace_str=0. " + "Use intercept_strlen=0 to disable it."); + } + if (!f->replace_str && common_flags()->intercept_strchr) { + Report("WARNING: strchr* interceptors are enabled even though " + "replace_str=0. Use intercept_strchr=0 to disable them."); } } } // namespace __asan #if !SANITIZER_SUPPORTS_WEAK_HOOKS extern "C" { SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE const char* __asan_default_options() { return ""; } } // extern "C" #endif Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_flags.inc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_flags.inc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_flags.inc (revision 305364) @@ -1,137 +1,141 @@ //===-- asan_flags.inc ------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // ASan runtime flags. // //===----------------------------------------------------------------------===// #ifndef ASAN_FLAG # error "Define ASAN_FLAG prior to including this file!" #endif // ASAN_FLAG(Type, Name, DefaultValue, Description) // See COMMON_FLAG in sanitizer_flags.inc for more details. ASAN_FLAG(int, quarantine_size, -1, "Deprecated, please use quarantine_size_mb.") ASAN_FLAG(int, quarantine_size_mb, -1, "Size (in Mb) of quarantine used to detect use-after-free " "errors. Lower value may reduce memory usage but increase the " "chance of false negatives.") ASAN_FLAG(int, redzone, 16, "Minimal size (in bytes) of redzones around heap objects. " "Requirement: redzone >= 16, is a power of two.") ASAN_FLAG(int, max_redzone, 2048, "Maximal size (in bytes) of redzones around heap objects.") ASAN_FLAG( bool, debug, false, "If set, prints some debugging information and does additional checks.") ASAN_FLAG( int, report_globals, 1, "Controls the way to handle globals (0 - don't detect buffer overflow on " "globals, 1 - detect buffer overflow, 2 - print data about registered " "globals).") ASAN_FLAG(bool, check_initialization_order, false, "If set, attempts to catch initialization order issues.") ASAN_FLAG( bool, replace_str, true, "If set, uses custom wrappers and replacements for libc string functions " "to find more errors.") ASAN_FLAG(bool, replace_intrin, true, - "If set, uses custom wrappers for memset/memcpy/memmove intinsics.") + "If set, uses custom wrappers for memset/memcpy/memmove intrinsics.") ASAN_FLAG(bool, detect_stack_use_after_return, false, "Enables stack-use-after-return checking at run-time.") ASAN_FLAG(int, min_uar_stack_size_log, 16, // We can't do smaller anyway. "Minimum fake stack size log.") ASAN_FLAG(int, max_uar_stack_size_log, 20, // 1Mb per size class, i.e. ~11Mb per thread "Maximum fake stack size log.") ASAN_FLAG(bool, uar_noreserve, false, "Use mmap with 'noreserve' flag to allocate fake stack.") ASAN_FLAG( int, max_malloc_fill_size, 0x1000, // By default, fill only the first 4K. "ASan allocator flag. max_malloc_fill_size is the maximal amount of " "bytes that will be filled with malloc_fill_byte on malloc.") ASAN_FLAG(int, malloc_fill_byte, 0xbe, "Value used to fill the newly allocated memory.") ASAN_FLAG(bool, allow_user_poisoning, true, "If set, user may manually mark memory regions as poisoned or " "unpoisoned.") ASAN_FLAG( int, sleep_before_dying, 0, "Number of seconds to sleep between printing an error report and " "terminating the program. Useful for debugging purposes (e.g. when one " "needs to attach gdb).") ASAN_FLAG(bool, check_malloc_usable_size, true, "Allows the users to work around the bug in Nvidia drivers prior to " "295.*.") ASAN_FLAG(bool, unmap_shadow_on_exit, false, "If set, explicitly unmaps the (huge) shadow at exit.") ASAN_FLAG(bool, protect_shadow_gap, true, "If set, mprotect the shadow gap") ASAN_FLAG(bool, print_stats, false, "Print various statistics after printing an error message or if " "atexit=1.") ASAN_FLAG(bool, print_legend, true, "Print the legend for the shadow bytes.") +ASAN_FLAG(bool, print_scariness, false, + "Print the scariness score. Experimental.") ASAN_FLAG(bool, atexit, false, "If set, prints ASan exit stats even after program terminates " "successfully.") ASAN_FLAG( bool, print_full_thread_history, true, "If set, prints thread creation stacks for the threads involved in the " "report and their ancestors up to the main thread.") ASAN_FLAG( bool, poison_heap, true, "Poison (or not) the heap memory on [de]allocation. Zero value is useful " "for benchmarking the allocator or instrumentator.") ASAN_FLAG(bool, poison_partial, true, "If true, poison partially addressable 8-byte aligned words " "(default=true). This flag affects heap and global buffers, but not " "stack buffers.") ASAN_FLAG(bool, poison_array_cookie, true, "Poison (or not) the array cookie after operator new[].") // Turn off alloc/dealloc mismatch checker on Mac and Windows for now. // https://github.com/google/sanitizers/issues/131 // https://github.com/google/sanitizers/issues/309 // TODO(glider,timurrrr): Fix known issues and enable this back. ASAN_FLAG(bool, alloc_dealloc_mismatch, (SANITIZER_MAC == 0) && (SANITIZER_WINDOWS == 0), "Report errors on malloc/delete, new/free, new/delete[], etc.") ASAN_FLAG(bool, new_delete_type_mismatch, true, - "Report errors on mismatch betwen size of new and delete.") + "Report errors on mismatch between size of new and delete.") ASAN_FLAG( bool, strict_init_order, false, "If true, assume that dynamic initializers can never access globals from " "other modules, even if the latter are already initialized.") ASAN_FLAG( bool, start_deactivated, false, "If true, ASan tweaks a bunch of other flags (quarantine, redzone, heap " "poisoning) to reduce memory consumption as much as possible, and " "restores them to original values when the first instrumented module is " "loaded into the process. This is mainly intended to be used on " "Android. ") ASAN_FLAG( int, detect_invalid_pointer_pairs, 0, "If non-zero, try to detect operations like <, <=, >, >= and - on " "invalid pointer pairs (e.g. when pointers belong to different objects). " "The bigger the value the harder we try.") ASAN_FLAG( bool, detect_container_overflow, true, "If true, honor the container overflow annotations. See " "https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow") ASAN_FLAG(int, detect_odr_violation, 2, "If >=2, detect violation of One-Definition-Rule (ODR); " "If ==1, detect ODR-violation only if the two variables " "have different sizes") ASAN_FLAG(bool, dump_instruction_bytes, false, "If true, dump 16 bytes starting at the instruction that caused SEGV") ASAN_FLAG(const char *, suppressions, "", "Suppressions file name.") ASAN_FLAG(bool, halt_on_error, true, "Crash the program after printing the first error report " "(WARNING: USE AT YOUR OWN RISK!)") +ASAN_FLAG(bool, use_odr_indicator, false, + "Use special ODR indicator symbol for ODR violation detection") Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_globals.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_globals.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_globals.cc (revision 305364) @@ -1,292 +1,383 @@ //===-- asan_globals.cc ---------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // Handle globals. //===----------------------------------------------------------------------===// #include "asan_interceptors.h" #include "asan_internal.h" #include "asan_mapping.h" #include "asan_poisoning.h" #include "asan_report.h" #include "asan_stack.h" #include "asan_stats.h" #include "asan_suppressions.h" #include "asan_thread.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_mutex.h" #include "sanitizer_common/sanitizer_placement_new.h" #include "sanitizer_common/sanitizer_stackdepot.h" namespace __asan { typedef __asan_global Global; struct ListOfGlobals { const Global *g; ListOfGlobals *next; }; static BlockingMutex mu_for_globals(LINKER_INITIALIZED); static LowLevelAllocator allocator_for_globals; static ListOfGlobals *list_of_all_globals; static const int kDynamicInitGlobalsInitialCapacity = 512; struct DynInitGlobal { Global g; bool initialized; }; typedef InternalMmapVector VectorOfGlobals; // Lazy-initialized and never deleted. static VectorOfGlobals *dynamic_init_globals; // We want to remember where a certain range of globals was registered. struct GlobalRegistrationSite { u32 stack_id; Global *g_first, *g_last; }; typedef InternalMmapVector GlobalRegistrationSiteVector; static GlobalRegistrationSiteVector *global_registration_site_vector; ALWAYS_INLINE void PoisonShadowForGlobal(const Global *g, u8 value) { FastPoisonShadow(g->beg, g->size_with_redzone, value); } ALWAYS_INLINE void PoisonRedZones(const Global &g) { uptr aligned_size = RoundUpTo(g.size, SHADOW_GRANULARITY); FastPoisonShadow(g.beg + aligned_size, g.size_with_redzone - aligned_size, kAsanGlobalRedzoneMagic); if (g.size != aligned_size) { FastPoisonShadowPartialRightRedzone( g.beg + RoundDownTo(g.size, SHADOW_GRANULARITY), g.size % SHADOW_GRANULARITY, SHADOW_GRANULARITY, kAsanGlobalRedzoneMagic); } } const uptr kMinimalDistanceFromAnotherGlobal = 64; static bool IsAddressNearGlobal(uptr addr, const __asan_global &g) { if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false; if (addr >= g.beg + g.size_with_redzone) return false; return true; } static void ReportGlobal(const Global &g, const char *prefix) { Report("%s Global[%p]: beg=%p size=%zu/%zu name=%s module=%s dyn_init=%zu\n", prefix, &g, (void *)g.beg, g.size, g.size_with_redzone, g.name, g.module_name, g.has_dynamic_init); if (g.location) { Report(" location (%p): name=%s[%p], %d %d\n", g.location, g.location->filename, g.location->filename, g.location->line_no, g.location->column_no); } } static u32 FindRegistrationSite(const Global *g) { mu_for_globals.CheckLocked(); CHECK(global_registration_site_vector); for (uptr i = 0, n = global_registration_site_vector->size(); i < n; i++) { GlobalRegistrationSite &grs = (*global_registration_site_vector)[i]; if (g >= grs.g_first && g <= grs.g_last) return grs.stack_id; } return 0; } int GetGlobalsForAddress(uptr addr, Global *globals, u32 *reg_sites, int max_globals) { if (!flags()->report_globals) return 0; BlockingMutexLock lock(&mu_for_globals); int res = 0; for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) { const Global &g = *l->g; if (flags()->report_globals >= 2) ReportGlobal(g, "Search"); if (IsAddressNearGlobal(addr, g)) { globals[res] = g; if (reg_sites) reg_sites[res] = FindRegistrationSite(&g); res++; if (res == max_globals) break; } } return res; } bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr) { Global g = {}; if (GetGlobalsForAddress(addr, &g, nullptr, 1)) { internal_strncpy(descr->name, g.name, descr->name_size); descr->region_address = g.beg; descr->region_size = g.size; descr->region_kind = "global"; return true; } return false; } +enum GlobalSymbolState { + UNREGISTERED = 0, + REGISTERED = 1 +}; + +// Check ODR violation for given global G via special ODR indicator. We use +// this method in case compiler instruments global variables through their +// local aliases. +static void CheckODRViolationViaIndicator(const Global *g) { + u8 *odr_indicator = reinterpret_cast(g->odr_indicator); + if (*odr_indicator == UNREGISTERED) { + *odr_indicator = REGISTERED; + return; + } + // If *odr_indicator is DEFINED, some module have already registered + // externally visible symbol with the same name. This is an ODR violation. + for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) { + if (g->odr_indicator == l->g->odr_indicator && + (flags()->detect_odr_violation >= 2 || g->size != l->g->size) && + !IsODRViolationSuppressed(g->name)) + ReportODRViolation(g, FindRegistrationSite(g), + l->g, FindRegistrationSite(l->g)); + } +} + +// Check ODR violation for given global G by checking if it's already poisoned. +// We use this method in case compiler doesn't use private aliases for global +// variables. +static void CheckODRViolationViaPoisoning(const Global *g) { + if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) { + // This check may not be enough: if the first global is much larger + // the entire redzone of the second global may be within the first global. + for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) { + if (g->beg == l->g->beg && + (flags()->detect_odr_violation >= 2 || g->size != l->g->size) && + !IsODRViolationSuppressed(g->name)) + ReportODRViolation(g, FindRegistrationSite(g), + l->g, FindRegistrationSite(l->g)); + } + } +} + +// Clang provides two different ways for global variables protection: +// it can poison the global itself or its private alias. In former +// case we may poison same symbol multiple times, that can help us to +// cheaply detect ODR violation: if we try to poison an already poisoned +// global, we have ODR violation error. +// In latter case, we poison each symbol exactly once, so we use special +// indicator symbol to perform similar check. +// In either case, compiler provides a special odr_indicator field to Global +// structure, that can contain two kinds of values: +// 1) Non-zero value. In this case, odr_indicator is an address of +// corresponding indicator variable for given global. +// 2) Zero. This means that we don't use private aliases for global variables +// and can freely check ODR violation with the first method. +// +// This routine chooses between two different methods of ODR violation +// detection. +static inline bool UseODRIndicator(const Global *g) { + // Use ODR indicator method iff use_odr_indicator flag is set and + // indicator symbol address is not 0. + return flags()->use_odr_indicator && g->odr_indicator > 0; +} + // Register a global variable. // This function may be called more than once for every global // so we store the globals in a map. static void RegisterGlobal(const Global *g) { CHECK(asan_inited); if (flags()->report_globals >= 2) ReportGlobal(*g, "Added"); CHECK(flags()->report_globals); CHECK(AddrIsInMem(g->beg)); - CHECK(AddrIsAlignedByGranularity(g->beg)); + if (!AddrIsAlignedByGranularity(g->beg)) { + Report("The following global variable is not properly aligned.\n"); + Report("This may happen if another global with the same name\n"); + Report("resides in another non-instrumented module.\n"); + Report("Or the global comes from a C file built w/o -fno-common.\n"); + Report("In either case this is likely an ODR violation bug,\n"); + Report("but AddressSanitizer can not provide more details.\n"); + ReportODRViolation(g, FindRegistrationSite(g), g, FindRegistrationSite(g)); + CHECK(AddrIsAlignedByGranularity(g->beg)); + } CHECK(AddrIsAlignedByGranularity(g->size_with_redzone)); if (flags()->detect_odr_violation) { // Try detecting ODR (One Definition Rule) violation, i.e. the situation // where two globals with the same name are defined in different modules. - if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) { - // This check may not be enough: if the first global is much larger - // the entire redzone of the second global may be within the first global. - for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) { - if (g->beg == l->g->beg && - (flags()->detect_odr_violation >= 2 || g->size != l->g->size) && - !IsODRViolationSuppressed(g->name)) - ReportODRViolation(g, FindRegistrationSite(g), - l->g, FindRegistrationSite(l->g)); - } - } + if (UseODRIndicator(g)) + CheckODRViolationViaIndicator(g); + else + CheckODRViolationViaPoisoning(g); } if (CanPoisonMemory()) PoisonRedZones(*g); ListOfGlobals *l = new(allocator_for_globals) ListOfGlobals; l->g = g; l->next = list_of_all_globals; list_of_all_globals = l; if (g->has_dynamic_init) { if (!dynamic_init_globals) { dynamic_init_globals = new(allocator_for_globals) VectorOfGlobals(kDynamicInitGlobalsInitialCapacity); } DynInitGlobal dyn_global = { *g, false }; dynamic_init_globals->push_back(dyn_global); } } static void UnregisterGlobal(const Global *g) { CHECK(asan_inited); if (flags()->report_globals >= 2) ReportGlobal(*g, "Removed"); CHECK(flags()->report_globals); CHECK(AddrIsInMem(g->beg)); CHECK(AddrIsAlignedByGranularity(g->beg)); CHECK(AddrIsAlignedByGranularity(g->size_with_redzone)); if (CanPoisonMemory()) PoisonShadowForGlobal(g, 0); // We unpoison the shadow memory for the global but we do not remove it from // the list because that would require O(n^2) time with the current list // implementation. It might not be worth doing anyway. + + // Release ODR indicator. + if (UseODRIndicator(g)) { + u8 *odr_indicator = reinterpret_cast(g->odr_indicator); + *odr_indicator = UNREGISTERED; + } } void StopInitOrderChecking() { BlockingMutexLock lock(&mu_for_globals); if (!flags()->check_initialization_order || !dynamic_init_globals) return; flags()->check_initialization_order = false; for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) { DynInitGlobal &dyn_g = (*dynamic_init_globals)[i]; const Global *g = &dyn_g.g; // Unpoison the whole global. PoisonShadowForGlobal(g, 0); // Poison redzones back. PoisonRedZones(*g); } } } // namespace __asan // ---------------------- Interface ---------------- {{{1 using namespace __asan; // NOLINT + + +// Apply __asan_register_globals to all globals found in the same loaded +// executable or shared library as `flag'. The flag tracks whether globals have +// already been registered or not for this image. +void __asan_register_image_globals(uptr *flag) { + if (*flag) + return; + AsanApplyToGlobals(__asan_register_globals, flag); + *flag = 1; +} + +// This mirrors __asan_register_image_globals. +void __asan_unregister_image_globals(uptr *flag) { + if (!*flag) + return; + AsanApplyToGlobals(__asan_unregister_globals, flag); + *flag = 0; +} // Register an array of globals. void __asan_register_globals(__asan_global *globals, uptr n) { if (!flags()->report_globals) return; GET_STACK_TRACE_MALLOC; u32 stack_id = StackDepotPut(stack); BlockingMutexLock lock(&mu_for_globals); if (!global_registration_site_vector) global_registration_site_vector = new(allocator_for_globals) GlobalRegistrationSiteVector(128); GlobalRegistrationSite site = {stack_id, &globals[0], &globals[n - 1]}; global_registration_site_vector->push_back(site); if (flags()->report_globals >= 2) { PRINT_CURRENT_STACK(); Printf("=== ID %d; %p %p\n", stack_id, &globals[0], &globals[n - 1]); } for (uptr i = 0; i < n; i++) { RegisterGlobal(&globals[i]); } } // Unregister an array of globals. // We must do this when a shared objects gets dlclosed. void __asan_unregister_globals(__asan_global *globals, uptr n) { if (!flags()->report_globals) return; BlockingMutexLock lock(&mu_for_globals); for (uptr i = 0; i < n; i++) { UnregisterGlobal(&globals[i]); } } // This method runs immediately prior to dynamic initialization in each TU, // when all dynamically initialized globals are unpoisoned. This method // poisons all global variables not defined in this TU, so that a dynamic // initializer can only touch global variables in the same TU. void __asan_before_dynamic_init(const char *module_name) { if (!flags()->check_initialization_order || !CanPoisonMemory()) return; bool strict_init_order = flags()->strict_init_order; CHECK(dynamic_init_globals); CHECK(module_name); CHECK(asan_inited); BlockingMutexLock lock(&mu_for_globals); if (flags()->report_globals >= 3) Printf("DynInitPoison module: %s\n", module_name); for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) { DynInitGlobal &dyn_g = (*dynamic_init_globals)[i]; const Global *g = &dyn_g.g; if (dyn_g.initialized) continue; if (g->module_name != module_name) PoisonShadowForGlobal(g, kAsanInitializationOrderMagic); else if (!strict_init_order) dyn_g.initialized = true; } } // This method runs immediately after dynamic initialization in each TU, when // all dynamically initialized globals except for those defined in the current // TU are poisoned. It simply unpoisons all dynamically initialized globals. void __asan_after_dynamic_init() { if (!flags()->check_initialization_order || !CanPoisonMemory()) return; CHECK(asan_inited); BlockingMutexLock lock(&mu_for_globals); // FIXME: Optionally report that we're unpoisoning globals from a module. for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) { DynInitGlobal &dyn_g = (*dynamic_init_globals)[i]; const Global *g = &dyn_g.g; if (!dyn_g.initialized) { // Unpoison the whole global. PoisonShadowForGlobal(g, 0); // Poison redzones back. PoisonRedZones(*g); } } } Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_init_version.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_init_version.h (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_init_version.h (revision 305364) @@ -1,34 +1,38 @@ //===-- asan_init_version.h -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // This header defines a versioned __asan_init function to be called at the // startup of the instrumented program. //===----------------------------------------------------------------------===// #ifndef ASAN_INIT_VERSION_H #define ASAN_INIT_VERSION_H extern "C" { // Every time the ASan ABI changes we also change the version number in the // __asan_init function name. Objects built with incompatible ASan ABI // versions will not link with run-time. + // // Changes between ABI versions: // v1=>v2: added 'module_name' to __asan_global // v2=>v3: stack frame description (created by the compiler) - // contains the function PC as the 3-rd field (see - // DescribeAddressIfStack). - // v3=>v4: added '__asan_global_source_location' to __asan_global. + // contains the function PC as the 3rd field (see + // DescribeAddressIfStack) + // v3=>v4: added '__asan_global_source_location' to __asan_global // v4=>v5: changed the semantics and format of __asan_stack_malloc_ and - // __asan_stack_free_ functions. + // __asan_stack_free_ functions // v5=>v6: changed the name of the version check symbol - #define __asan_version_mismatch_check __asan_version_mismatch_check_v6 + // v6=>v7: added 'odr_indicator' to __asan_global + // v7=>v8: added '__asan_(un)register_image_globals' functions for dead + // stripping support on Mach-O platforms + #define __asan_version_mismatch_check __asan_version_mismatch_check_v8 } #endif // ASAN_INIT_VERSION_H Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_interceptors.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_interceptors.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_interceptors.cc (revision 305364) @@ -1,822 +1,806 @@ //===-- asan_interceptors.cc ----------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // Intercept various libc functions. //===----------------------------------------------------------------------===// #include "asan_interceptors.h" #include "asan_allocator.h" #include "asan_internal.h" #include "asan_mapping.h" #include "asan_poisoning.h" #include "asan_report.h" #include "asan_stack.h" #include "asan_stats.h" #include "asan_suppressions.h" +#include "lsan/lsan_common.h" #include "sanitizer_common/sanitizer_libc.h" #if SANITIZER_POSIX #include "sanitizer_common/sanitizer_posix.h" #endif #if defined(__i386) && SANITIZER_LINUX #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1" #elif defined(__mips__) && SANITIZER_LINUX #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2" #endif namespace __asan { // Return true if we can quickly decide that the region is unpoisoned. static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) { if (size == 0) return true; if (size <= 32) return !AddressIsPoisoned(beg) && !AddressIsPoisoned(beg + size - 1) && !AddressIsPoisoned(beg + size / 2); return false; } struct AsanInterceptorContext { const char *interceptor_name; }; // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE, // and ASAN_WRITE_RANGE as macro instead of function so // that no extra frames are created, and stack trace contains // relevant information only. // We check all shadow bytes. #define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) do { \ uptr __offset = (uptr)(offset); \ uptr __size = (uptr)(size); \ uptr __bad = 0; \ if (__offset > __offset + __size) { \ GET_STACK_TRACE_FATAL_HERE; \ ReportStringFunctionSizeOverflow(__offset, __size, &stack); \ } \ if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \ (__bad = __asan_region_is_poisoned(__offset, __size))) { \ AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx; \ bool suppressed = false; \ if (_ctx) { \ suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \ if (!suppressed && HaveStackTraceBasedSuppressions()) { \ GET_STACK_TRACE_FATAL_HERE; \ suppressed = IsStackTraceSuppressed(&stack); \ } \ } \ if (!suppressed) { \ GET_CURRENT_PC_BP_SP; \ ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false);\ } \ } \ } while (0) #define ASAN_READ_RANGE(ctx, offset, size) \ ACCESS_MEMORY_RANGE(ctx, offset, size, false) #define ASAN_WRITE_RANGE(ctx, offset, size) \ ACCESS_MEMORY_RANGE(ctx, offset, size, true) #define ASAN_READ_STRING_OF_LEN(ctx, s, len, n) \ ASAN_READ_RANGE((ctx), (s), \ common_flags()->strict_string_checks ? (len) + 1 : (n)) #define ASAN_READ_STRING(ctx, s, n) \ ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n)) // Behavior of functions like "memcpy" or "strcpy" is undefined // if memory intervals overlap. We report error in this case. // Macro is used to avoid creation of new frames. static inline bool RangesOverlap(const char *offset1, uptr length1, const char *offset2, uptr length2) { return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1)); } #define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \ const char *offset1 = (const char*)_offset1; \ const char *offset2 = (const char*)_offset2; \ if (RangesOverlap(offset1, length1, offset2, length2)) { \ GET_STACK_TRACE_FATAL_HERE; \ ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \ offset2, length2, &stack); \ } \ } while (0) static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) { -#if ASAN_INTERCEPT_STRNLEN +#if SANITIZER_INTERCEPT_STRNLEN if (REAL(strnlen)) { return REAL(strnlen)(s, maxlen); } #endif return internal_strnlen(s, maxlen); } void SetThreadName(const char *name) { AsanThread *t = GetCurrentThread(); if (t) asanThreadRegistry().SetThreadName(t->tid(), name); } int OnExit() { // FIXME: ask frontend whether we need to return failure. return 0; } } // namespace __asan // ---------------------- Wrappers ---------------- {{{1 using namespace __asan; // NOLINT DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr) DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) #define ASAN_INTERCEPTOR_ENTER(ctx, func) \ AsanInterceptorContext _ctx = {#func}; \ ctx = (void *)&_ctx; \ (void) ctx; \ #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name) +#define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \ + ASAN_INTERCEPT_FUNC_VER(name, ver) #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ ASAN_WRITE_RANGE(ctx, ptr, size) #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \ ASAN_READ_RANGE(ctx, ptr, size) #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ ASAN_INTERCEPTOR_ENTER(ctx, func); \ do { \ if (asan_init_is_running) \ return REAL(func)(__VA_ARGS__); \ if (SANITIZER_MAC && UNLIKELY(!asan_inited)) \ return REAL(func)(__VA_ARGS__); \ ENSURE_ASAN_INITED(); \ } while (false) #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \ do { \ } while (false) #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \ do { \ } while (false) #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \ do { \ } while (false) #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \ do { \ } while (false) #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name) // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name) // But asan does not remember UserId's for threads (pthread_t); // and remembers all ever existed threads, so the linear search by UserId // can be slow. #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \ do { \ } while (false) #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) // Strict init-order checking is dlopen-hostile: // https://github.com/google/sanitizers/issues/178 #define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \ if (flags()->strict_init_order) { \ StopInitOrderChecking(); \ } #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \ CoverageUpdateMapping() #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CoverageUpdateMapping() #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited) #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \ if (AsanThread *t = GetCurrentThread()) { \ *begin = t->tls_begin(); \ *end = t->tls_end(); \ } else { \ *begin = *end = 0; \ } +// Asan needs custom handling of these: +#undef SANITIZER_INTERCEPT_MEMSET +#undef SANITIZER_INTERCEPT_MEMMOVE +#undef SANITIZER_INTERCEPT_MEMCPY #include "sanitizer_common/sanitizer_common_interceptors.inc" // Syscall interceptors don't have contexts, we don't support suppressions // for them. #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s) #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s) #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \ do { \ (void)(p); \ (void)(s); \ } while (false) #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \ do { \ (void)(p); \ (void)(s); \ } while (false) #include "sanitizer_common/sanitizer_common_syscalls.inc" struct ThreadStartParam { atomic_uintptr_t t; atomic_uintptr_t is_registered; }; +#if ASAN_INTERCEPT_PTHREAD_CREATE static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { ThreadStartParam *param = reinterpret_cast(arg); AsanThread *t = nullptr; while ((t = reinterpret_cast( atomic_load(¶m->t, memory_order_acquire))) == nullptr) internal_sched_yield(); SetCurrentThread(t); return t->ThreadStart(GetTid(), ¶m->is_registered); } -#if ASAN_INTERCEPT_PTHREAD_CREATE INTERCEPTOR(int, pthread_create, void *thread, void *attr, void *(*start_routine)(void*), void *arg) { EnsureMainThreadIDIsCorrect(); // Strict init-order checking is thread-hostile. if (flags()->strict_init_order) StopInitOrderChecking(); GET_STACK_TRACE_THREAD; int detached = 0; if (attr) REAL(pthread_attr_getdetachstate)(attr, &detached); ThreadStartParam param; atomic_store(¶m.t, 0, memory_order_relaxed); atomic_store(¶m.is_registered, 0, memory_order_relaxed); - int result = REAL(pthread_create)(thread, attr, asan_thread_start, ¶m); + int result; + { + // Ignore all allocations made by pthread_create: thread stack/TLS may be + // stored by pthread for future reuse even after thread destruction, and + // the linked list it's stored in doesn't even hold valid pointers to the + // objects, the latter are calculated by obscure pointer arithmetic. +#if CAN_SANITIZE_LEAKS + __lsan::ScopedInterceptorDisabler disabler; +#endif + result = REAL(pthread_create)(thread, attr, asan_thread_start, ¶m); + } if (result == 0) { u32 current_tid = GetCurrentTidOrInvalid(); AsanThread *t = AsanThread::Create(start_routine, arg, current_tid, &stack, detached); atomic_store(¶m.t, reinterpret_cast(t), memory_order_release); // Wait until the AsanThread object is initialized and the ThreadRegistry // entry is in "started" state. One reason for this is that after this // interceptor exits, the child thread's stack may be the only thing holding // the |arg| pointer. This may cause LSan to report a leak if leak checking // happens at a point when the interceptor has already exited, but the stack // range for the child thread is not yet known. while (atomic_load(¶m.is_registered, memory_order_acquire) == 0) internal_sched_yield(); } return result; } INTERCEPTOR(int, pthread_join, void *t, void **arg) { return real_pthread_join(t, arg); } DEFINE_REAL_PTHREAD_FUNCTIONS #endif // ASAN_INTERCEPT_PTHREAD_CREATE #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION #if SANITIZER_ANDROID INTERCEPTOR(void*, bsd_signal, int signum, void *handler) { - if (!IsDeadlySignal(signum) || common_flags()->allow_user_segv_handler) { + if (!IsHandledDeadlySignal(signum) || + common_flags()->allow_user_segv_handler) { return REAL(bsd_signal)(signum, handler); } return 0; } #endif INTERCEPTOR(void*, signal, int signum, void *handler) { - if (!IsDeadlySignal(signum) || common_flags()->allow_user_segv_handler) { + if (!IsHandledDeadlySignal(signum) || + common_flags()->allow_user_segv_handler) { return REAL(signal)(signum, handler); } return nullptr; } INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, struct sigaction *oldact) { - if (!IsDeadlySignal(signum) || common_flags()->allow_user_segv_handler) { + if (!IsHandledDeadlySignal(signum) || + common_flags()->allow_user_segv_handler) { return REAL(sigaction)(signum, act, oldact); } return 0; } namespace __sanitizer { int real_sigaction(int signum, const void *act, void *oldact) { return REAL(sigaction)(signum, (const struct sigaction *)act, (struct sigaction *)oldact); } } // namespace __sanitizer #elif SANITIZER_POSIX // We need to have defined REAL(sigaction) on posix systems. DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act, struct sigaction *oldact) #endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION #if ASAN_INTERCEPT_SWAPCONTEXT static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) { // Align to page size. uptr PageSize = GetPageSizeCached(); uptr bottom = stack & ~(PageSize - 1); ssize += stack - bottom; ssize = RoundUpTo(ssize, PageSize); static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) { PoisonShadow(bottom, ssize, 0); } } INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, struct ucontext_t *ucp) { static bool reported_warning = false; if (!reported_warning) { Report("WARNING: ASan doesn't fully support makecontext/swapcontext " "functions and may produce false positives in some cases!\n"); reported_warning = true; } // Clear shadow memory for new context (it may share stack // with current context). uptr stack, ssize; ReadContextStack(ucp, &stack, &ssize); ClearShadowMemoryForContextStack(stack, ssize); int res = REAL(swapcontext)(oucp, ucp); // swapcontext technically does not return, but program may swap context to // "oucp" later, that would look as if swapcontext() returned 0. // We need to clear shadow for ucp once again, as it may be in arbitrary // state. ClearShadowMemoryForContextStack(stack, ssize); return res; } #endif // ASAN_INTERCEPT_SWAPCONTEXT INTERCEPTOR(void, longjmp, void *env, int val) { __asan_handle_no_return(); REAL(longjmp)(env, val); } #if ASAN_INTERCEPT__LONGJMP INTERCEPTOR(void, _longjmp, void *env, int val) { __asan_handle_no_return(); REAL(_longjmp)(env, val); } #endif #if ASAN_INTERCEPT_SIGLONGJMP INTERCEPTOR(void, siglongjmp, void *env, int val) { __asan_handle_no_return(); REAL(siglongjmp)(env, val); } #endif #if ASAN_INTERCEPT___CXA_THROW INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { CHECK(REAL(__cxa_throw)); __asan_handle_no_return(); REAL(__cxa_throw)(a, b, c); } #endif // memcpy is called during __asan_init() from the internals of printf(...). // We do not treat memcpy with to==from as a bug. // See http://llvm.org/bugs/show_bug.cgi?id=11763. #define ASAN_MEMCPY_IMPL(ctx, to, from, size) do { \ if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size); \ if (asan_init_is_running) { \ return REAL(memcpy)(to, from, size); \ } \ ENSURE_ASAN_INITED(); \ if (flags()->replace_intrin) { \ if (to != from) { \ CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); \ } \ ASAN_READ_RANGE(ctx, from, size); \ ASAN_WRITE_RANGE(ctx, to, size); \ } \ return REAL(memcpy)(to, from, size); \ } while (0) void *__asan_memcpy(void *to, const void *from, uptr size) { ASAN_MEMCPY_IMPL(nullptr, to, from, size); } // memset is called inside Printf. #define ASAN_MEMSET_IMPL(ctx, block, c, size) do { \ if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size); \ if (asan_init_is_running) { \ return REAL(memset)(block, c, size); \ } \ ENSURE_ASAN_INITED(); \ if (flags()->replace_intrin) { \ ASAN_WRITE_RANGE(ctx, block, size); \ } \ return REAL(memset)(block, c, size); \ } while (0) void *__asan_memset(void *block, int c, uptr size) { ASAN_MEMSET_IMPL(nullptr, block, c, size); } #define ASAN_MEMMOVE_IMPL(ctx, to, from, size) do { \ if (UNLIKELY(!asan_inited)) \ return internal_memmove(to, from, size); \ ENSURE_ASAN_INITED(); \ if (flags()->replace_intrin) { \ ASAN_READ_RANGE(ctx, from, size); \ ASAN_WRITE_RANGE(ctx, to, size); \ } \ return internal_memmove(to, from, size); \ } while (0) void *__asan_memmove(void *to, const void *from, uptr size) { ASAN_MEMMOVE_IMPL(nullptr, to, from, size); } INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, memmove); ASAN_MEMMOVE_IMPL(ctx, to, from, size); } INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, memcpy); #if !SANITIZER_MAC ASAN_MEMCPY_IMPL(ctx, to, from, size); #else // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced // with WRAP(memcpy). As a result, false positives are reported for memmove() // calls. If we just disable error reporting with // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with // internal_memcpy(), which may lead to crashes, see // http://llvm.org/bugs/show_bug.cgi?id=16362. ASAN_MEMMOVE_IMPL(ctx, to, from, size); #endif // !SANITIZER_MAC } INTERCEPTOR(void*, memset, void *block, int c, uptr size) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, memset); ASAN_MEMSET_IMPL(ctx, block, c, size); } -INTERCEPTOR(char*, strchr, const char *str, int c) { - void *ctx; - ASAN_INTERCEPTOR_ENTER(ctx, strchr); - if (UNLIKELY(!asan_inited)) return internal_strchr(str, c); - // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is - // used. - if (asan_init_is_running) { - return REAL(strchr)(str, c); - } - ENSURE_ASAN_INITED(); - char *result = REAL(strchr)(str, c); - if (flags()->replace_str) { - uptr len = REAL(strlen)(str); - uptr bytes_read = (result ? result - str : len) + 1; - ASAN_READ_STRING_OF_LEN(ctx, str, len, bytes_read); - } - return result; -} - #if ASAN_INTERCEPT_INDEX # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX INTERCEPTOR(char*, index, const char *string, int c) ALIAS(WRAPPER_NAME(strchr)); # else # if SANITIZER_MAC DECLARE_REAL(char*, index, const char *string, int c) OVERRIDE_FUNCTION(index, strchr); # else DEFINE_REAL(char*, index, const char *string, int c) # endif # endif #endif // ASAN_INTERCEPT_INDEX // For both strcat() and strncat() we need to check the validity of |to| // argument irrespective of the |from| length. INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strcat); // NOLINT ENSURE_ASAN_INITED(); if (flags()->replace_str) { uptr from_length = REAL(strlen)(from); ASAN_READ_RANGE(ctx, from, from_length + 1); uptr to_length = REAL(strlen)(to); ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length); ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1); // If the copying actually happens, the |from| string should not overlap // with the resulting string starting at |to|, which has a length of // to_length + from_length + 1. if (from_length > 0) { CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from, from_length + 1); } } return REAL(strcat)(to, from); // NOLINT } INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strncat); ENSURE_ASAN_INITED(); if (flags()->replace_str) { uptr from_length = MaybeRealStrnlen(from, size); uptr copy_length = Min(size, from_length + 1); ASAN_READ_RANGE(ctx, from, copy_length); uptr to_length = REAL(strlen)(to); ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length); ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1); if (from_length > 0) { CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1, from, copy_length); } } return REAL(strncat)(to, from, size); } INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strcpy); // NOLINT #if SANITIZER_MAC if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from); // NOLINT #endif // strcpy is called from malloc_default_purgeable_zone() // in __asan::ReplaceSystemAlloc() on Mac. if (asan_init_is_running) { return REAL(strcpy)(to, from); // NOLINT } ENSURE_ASAN_INITED(); if (flags()->replace_str) { uptr from_size = REAL(strlen)(from) + 1; CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); ASAN_READ_RANGE(ctx, from, from_size); ASAN_WRITE_RANGE(ctx, to, from_size); } return REAL(strcpy)(to, from); // NOLINT } -#if ASAN_INTERCEPT_STRDUP INTERCEPTOR(char*, strdup, const char *s) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strdup); if (UNLIKELY(!asan_inited)) return internal_strdup(s); ENSURE_ASAN_INITED(); uptr length = REAL(strlen)(s); if (flags()->replace_str) { ASAN_READ_RANGE(ctx, s, length + 1); } GET_STACK_TRACE_MALLOC; void *new_mem = asan_malloc(length + 1, &stack); REAL(memcpy)(new_mem, s, length + 1); return reinterpret_cast(new_mem); } -#endif -INTERCEPTOR(SIZE_T, strlen, const char *s) { +#if ASAN_INTERCEPT___STRDUP +INTERCEPTOR(char*, __strdup, const char *s) { void *ctx; - ASAN_INTERCEPTOR_ENTER(ctx, strlen); - if (UNLIKELY(!asan_inited)) return internal_strlen(s); - // strlen is called from malloc_default_purgeable_zone() - // in __asan::ReplaceSystemAlloc() on Mac. - if (asan_init_is_running) { - return REAL(strlen)(s); - } + ASAN_INTERCEPTOR_ENTER(ctx, strdup); + if (UNLIKELY(!asan_inited)) return internal_strdup(s); ENSURE_ASAN_INITED(); - SIZE_T length = REAL(strlen)(s); + uptr length = REAL(strlen)(s); if (flags()->replace_str) { ASAN_READ_RANGE(ctx, s, length + 1); } - return length; + GET_STACK_TRACE_MALLOC; + void *new_mem = asan_malloc(length + 1, &stack); + REAL(memcpy)(new_mem, s, length + 1); + return reinterpret_cast(new_mem); } +#endif // ASAN_INTERCEPT___STRDUP INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, wcslen); - SIZE_T length = REAL(wcslen)(s); + SIZE_T length = internal_wcslen(s); if (!asan_init_is_running) { ENSURE_ASAN_INITED(); ASAN_READ_RANGE(ctx, s, (length + 1) * sizeof(wchar_t)); } return length; } INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strncpy); ENSURE_ASAN_INITED(); if (flags()->replace_str) { uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1); CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size); ASAN_READ_RANGE(ctx, from, from_size); ASAN_WRITE_RANGE(ctx, to, size); } return REAL(strncpy)(to, from, size); } -#if ASAN_INTERCEPT_STRNLEN -INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) { - void *ctx; - ASAN_INTERCEPTOR_ENTER(ctx, strnlen); - ENSURE_ASAN_INITED(); - uptr length = REAL(strnlen)(s, maxlen); - if (flags()->replace_str) { - ASAN_READ_RANGE(ctx, s, Min(length + 1, maxlen)); - } - return length; -} -#endif // ASAN_INTERCEPT_STRNLEN - INTERCEPTOR(long, strtol, const char *nptr, // NOLINT char **endptr, int base) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strtol); ENSURE_ASAN_INITED(); if (!flags()->replace_str) { return REAL(strtol)(nptr, endptr, base); } char *real_endptr; long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); return result; } INTERCEPTOR(int, atoi, const char *nptr) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, atoi); #if SANITIZER_MAC if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr); #endif ENSURE_ASAN_INITED(); if (!flags()->replace_str) { return REAL(atoi)(nptr); } char *real_endptr; // "man atoi" tells that behavior of atoi(nptr) is the same as // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the // parsed integer can't be stored in *long* type (even if it's // different from int). So, we just imitate this behavior. int result = REAL(strtol)(nptr, &real_endptr, 10); FixRealStrtolEndptr(nptr, &real_endptr); ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); return result; } INTERCEPTOR(long, atol, const char *nptr) { // NOLINT void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, atol); #if SANITIZER_MAC if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr); #endif ENSURE_ASAN_INITED(); if (!flags()->replace_str) { return REAL(atol)(nptr); } char *real_endptr; long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT FixRealStrtolEndptr(nptr, &real_endptr); ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); return result; } #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT char **endptr, int base) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strtoll); ENSURE_ASAN_INITED(); if (!flags()->replace_str) { return REAL(strtoll)(nptr, endptr, base); } char *real_endptr; long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); return result; } INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, atoll); ENSURE_ASAN_INITED(); if (!flags()->replace_str) { return REAL(atoll)(nptr); } char *real_endptr; long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT FixRealStrtolEndptr(nptr, &real_endptr); ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); return result; } #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL +#if ASAN_INTERCEPT___CXA_ATEXIT static void AtCxaAtexit(void *unused) { (void)unused; StopInitOrderChecking(); } -#if ASAN_INTERCEPT___CXA_ATEXIT INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, void *dso_handle) { #if SANITIZER_MAC if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle); #endif ENSURE_ASAN_INITED(); int res = REAL(__cxa_atexit)(func, arg, dso_handle); REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr); return res; } #endif // ASAN_INTERCEPT___CXA_ATEXIT #if ASAN_INTERCEPT_FORK INTERCEPTOR(int, fork, void) { ENSURE_ASAN_INITED(); if (common_flags()->coverage) CovBeforeFork(); int pid = REAL(fork)(); if (common_flags()->coverage) CovAfterFork(pid); return pid; } #endif // ASAN_INTERCEPT_FORK // ---------------------- InitializeAsanInterceptors ---------------- {{{1 namespace __asan { void InitializeAsanInterceptors() { static bool was_called_once; CHECK(was_called_once == false); was_called_once = true; InitializeCommonInterceptors(); // Intercept mem* functions. - ASAN_INTERCEPT_FUNC(memmove); + ASAN_INTERCEPT_FUNC(memcpy); ASAN_INTERCEPT_FUNC(memset); if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { - ASAN_INTERCEPT_FUNC(memcpy); + // In asan, REAL(memmove) is not used, but it is used in msan. + ASAN_INTERCEPT_FUNC(memmove); } + CHECK(REAL(memcpy)); // Intercept str* functions. ASAN_INTERCEPT_FUNC(strcat); // NOLINT - ASAN_INTERCEPT_FUNC(strchr); ASAN_INTERCEPT_FUNC(strcpy); // NOLINT - ASAN_INTERCEPT_FUNC(strlen); ASAN_INTERCEPT_FUNC(wcslen); ASAN_INTERCEPT_FUNC(strncat); ASAN_INTERCEPT_FUNC(strncpy); -#if ASAN_INTERCEPT_STRDUP ASAN_INTERCEPT_FUNC(strdup); -#endif -#if ASAN_INTERCEPT_STRNLEN - ASAN_INTERCEPT_FUNC(strnlen); +#if ASAN_INTERCEPT___STRDUP + ASAN_INTERCEPT_FUNC(__strdup); #endif #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX ASAN_INTERCEPT_FUNC(index); #endif ASAN_INTERCEPT_FUNC(atoi); ASAN_INTERCEPT_FUNC(atol); ASAN_INTERCEPT_FUNC(strtol); #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL ASAN_INTERCEPT_FUNC(atoll); ASAN_INTERCEPT_FUNC(strtoll); #endif // Intecept signal- and jump-related functions. ASAN_INTERCEPT_FUNC(longjmp); #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION ASAN_INTERCEPT_FUNC(sigaction); #if SANITIZER_ANDROID ASAN_INTERCEPT_FUNC(bsd_signal); #endif ASAN_INTERCEPT_FUNC(signal); #endif #if ASAN_INTERCEPT_SWAPCONTEXT ASAN_INTERCEPT_FUNC(swapcontext); #endif #if ASAN_INTERCEPT__LONGJMP ASAN_INTERCEPT_FUNC(_longjmp); #endif #if ASAN_INTERCEPT_SIGLONGJMP ASAN_INTERCEPT_FUNC(siglongjmp); #endif // Intercept exception handling functions. #if ASAN_INTERCEPT___CXA_THROW ASAN_INTERCEPT_FUNC(__cxa_throw); #endif // Intercept threading-related functions #if ASAN_INTERCEPT_PTHREAD_CREATE #if defined(ASAN_PTHREAD_CREATE_VERSION) ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION); #else ASAN_INTERCEPT_FUNC(pthread_create); #endif ASAN_INTERCEPT_FUNC(pthread_join); #endif // Intercept atexit function. #if ASAN_INTERCEPT___CXA_ATEXIT ASAN_INTERCEPT_FUNC(__cxa_atexit); #endif #if ASAN_INTERCEPT_FORK ASAN_INTERCEPT_FUNC(fork); #endif InitializePlatformInterceptors(); VReport(1, "AddressSanitizer: libc interceptors initialized\n"); } } // namespace __asan Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_interceptors.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_interceptors.h (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_interceptors.h (revision 305364) @@ -1,126 +1,124 @@ //===-- asan_interceptors.h -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // ASan-private header for asan_interceptors.cc //===----------------------------------------------------------------------===// #ifndef ASAN_INTERCEPTORS_H #define ASAN_INTERCEPTORS_H #include "asan_internal.h" #include "interception/interception.h" #include "sanitizer_common/sanitizer_platform_interceptors.h" // Use macro to describe if specific function should be // intercepted on a given platform. #if !SANITIZER_WINDOWS # define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 1 # define ASAN_INTERCEPT__LONGJMP 1 -# define ASAN_INTERCEPT_STRDUP 1 # define ASAN_INTERCEPT_INDEX 1 # define ASAN_INTERCEPT_PTHREAD_CREATE 1 # define ASAN_INTERCEPT_FORK 1 #else # define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 0 # define ASAN_INTERCEPT__LONGJMP 0 -# define ASAN_INTERCEPT_STRDUP 0 # define ASAN_INTERCEPT_INDEX 0 # define ASAN_INTERCEPT_PTHREAD_CREATE 0 # define ASAN_INTERCEPT_FORK 0 #endif #if SANITIZER_FREEBSD || SANITIZER_LINUX # define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 1 #else # define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 0 #endif -#if !SANITIZER_MAC -# define ASAN_INTERCEPT_STRNLEN 1 -#else -# define ASAN_INTERCEPT_STRNLEN 0 -#endif - #if SANITIZER_LINUX && !SANITIZER_ANDROID # define ASAN_INTERCEPT_SWAPCONTEXT 1 #else # define ASAN_INTERCEPT_SWAPCONTEXT 0 #endif #if !SANITIZER_WINDOWS # define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 1 #else # define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 0 #endif #if !SANITIZER_WINDOWS # define ASAN_INTERCEPT_SIGLONGJMP 1 #else # define ASAN_INTERCEPT_SIGLONGJMP 0 #endif // Android bug: https://code.google.com/p/android/issues/detail?id=61799 #if ASAN_HAS_EXCEPTIONS && !SANITIZER_WINDOWS && \ !(SANITIZER_ANDROID && defined(__i386)) # define ASAN_INTERCEPT___CXA_THROW 1 #else # define ASAN_INTERCEPT___CXA_THROW 0 #endif #if !SANITIZER_WINDOWS # define ASAN_INTERCEPT___CXA_ATEXIT 1 #else # define ASAN_INTERCEPT___CXA_ATEXIT 0 +#endif + +#if SANITIZER_LINUX && !SANITIZER_ANDROID +# define ASAN_INTERCEPT___STRDUP 1 +#else +# define ASAN_INTERCEPT___STRDUP 0 #endif DECLARE_REAL(int, memcmp, const void *a1, const void *a2, uptr size) DECLARE_REAL(void*, memcpy, void *to, const void *from, uptr size) DECLARE_REAL(void*, memset, void *block, int c, uptr size) DECLARE_REAL(char*, strchr, const char *str, int c) DECLARE_REAL(SIZE_T, strlen, const char *s) DECLARE_REAL(char*, strncpy, char *to, const char *from, uptr size) DECLARE_REAL(uptr, strnlen, const char *s, uptr maxlen) DECLARE_REAL(char*, strstr, const char *s1, const char *s2) struct sigaction; DECLARE_REAL(int, sigaction, int signum, const struct sigaction *act, struct sigaction *oldact) #if !SANITIZER_MAC #define ASAN_INTERCEPT_FUNC(name) \ do { \ if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \ VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \ } while (0) #define ASAN_INTERCEPT_FUNC_VER(name, ver) \ do { \ if ((!INTERCEPT_FUNCTION_VER(name, ver) || !REAL(name))) \ VReport( \ 1, "AddressSanitizer: failed to intercept '" #name "@@" #ver "'\n"); \ } while (0) #else // OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION. #define ASAN_INTERCEPT_FUNC(name) #endif // SANITIZER_MAC namespace __asan { void InitializeAsanInterceptors(); void InitializePlatformInterceptors(); #define ENSURE_ASAN_INITED() do { \ CHECK(!asan_init_is_running); \ if (UNLIKELY(!asan_inited)) { \ AsanInitFromRtl(); \ } \ } while (0) } // namespace __asan #endif // ASAN_INTERCEPTORS_H Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_interface_internal.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_interface_internal.h (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_interface_internal.h (revision 305364) @@ -1,219 +1,228 @@ //===-- asan_interface_internal.h -------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // This header declares the AddressSanitizer runtime interface functions. // The runtime library has to define these functions so the instrumented program // could call them. // // See also include/sanitizer/asan_interface.h //===----------------------------------------------------------------------===// #ifndef ASAN_INTERFACE_INTERNAL_H #define ASAN_INTERFACE_INTERNAL_H #include "sanitizer_common/sanitizer_internal_defs.h" #include "asan_init_version.h" using __sanitizer::uptr; extern "C" { // This function should be called at the very beginning of the process, // before any instrumented code is executed and before any call to malloc. SANITIZER_INTERFACE_ATTRIBUTE void __asan_init(); // This function exists purely to get a linker/loader error when using // incompatible versions of instrumentation and runtime library. Please note // that __asan_version_mismatch_check is a macro that is replaced with // __asan_version_mismatch_check_vXXX at compile-time. SANITIZER_INTERFACE_ATTRIBUTE void __asan_version_mismatch_check(); // This structure is used to describe the source location of a place where // global was defined. struct __asan_global_source_location { const char *filename; int line_no; int column_no; }; // This structure describes an instrumented global variable. struct __asan_global { uptr beg; // The address of the global. uptr size; // The original size of the global. uptr size_with_redzone; // The size with the redzone. const char *name; // Name as a C string. const char *module_name; // Module name as a C string. This pointer is a // unique identifier of a module. uptr has_dynamic_init; // Non-zero if the global has dynamic initializer. __asan_global_source_location *location; // Source location of a global, // or NULL if it is unknown. + uptr odr_indicator; // The address of the ODR indicator symbol. }; + + // These functions can be called on some platforms to find globals in the same + // loaded image as `flag' and apply __asan_(un)register_globals to them, + // filtering out redundant calls. + SANITIZER_INTERFACE_ATTRIBUTE + void __asan_register_image_globals(uptr *flag); + SANITIZER_INTERFACE_ATTRIBUTE + void __asan_unregister_image_globals(uptr *flag); // These two functions should be called by the instrumented code. // 'globals' is an array of structures describing 'n' globals. SANITIZER_INTERFACE_ATTRIBUTE void __asan_register_globals(__asan_global *globals, uptr n); SANITIZER_INTERFACE_ATTRIBUTE void __asan_unregister_globals(__asan_global *globals, uptr n); // These two functions should be called before and after dynamic initializers // of a single module run, respectively. SANITIZER_INTERFACE_ATTRIBUTE void __asan_before_dynamic_init(const char *module_name); SANITIZER_INTERFACE_ATTRIBUTE void __asan_after_dynamic_init(); // These two functions are used by instrumented code in the // use-after-scope mode. They mark memory for local variables as // unaddressable when they leave scope and addressable before the // function exits. SANITIZER_INTERFACE_ATTRIBUTE void __asan_poison_stack_memory(uptr addr, uptr size); SANITIZER_INTERFACE_ATTRIBUTE void __asan_unpoison_stack_memory(uptr addr, uptr size); // Performs cleanup before a NoReturn function. Must be called before things // like _exit and execl to avoid false positives on stack. SANITIZER_INTERFACE_ATTRIBUTE void __asan_handle_no_return(); SANITIZER_INTERFACE_ATTRIBUTE void __asan_poison_memory_region(void const volatile *addr, uptr size); SANITIZER_INTERFACE_ATTRIBUTE void __asan_unpoison_memory_region(void const volatile *addr, uptr size); SANITIZER_INTERFACE_ATTRIBUTE int __asan_address_is_poisoned(void const volatile *addr); SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_region_is_poisoned(uptr beg, uptr size); SANITIZER_INTERFACE_ATTRIBUTE void __asan_describe_address(uptr addr); SANITIZER_INTERFACE_ATTRIBUTE int __asan_report_present(); SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_report_pc(); SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_report_bp(); SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_report_sp(); SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_report_address(); SANITIZER_INTERFACE_ATTRIBUTE int __asan_get_report_access_type(); SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_report_access_size(); SANITIZER_INTERFACE_ATTRIBUTE const char * __asan_get_report_description(); SANITIZER_INTERFACE_ATTRIBUTE const char * __asan_locate_address(uptr addr, char *name, uptr name_size, uptr *region_address, uptr *region_size); SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_alloc_stack(uptr addr, uptr *trace, uptr size, u32 *thread_id); SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_free_stack(uptr addr, uptr *trace, uptr size, u32 *thread_id); SANITIZER_INTERFACE_ATTRIBUTE void __asan_get_shadow_mapping(uptr *shadow_scale, uptr *shadow_offset); SANITIZER_INTERFACE_ATTRIBUTE void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, uptr access_size, u32 exp); SANITIZER_INTERFACE_ATTRIBUTE void __asan_set_death_callback(void (*callback)(void)); SANITIZER_INTERFACE_ATTRIBUTE void __asan_set_error_report_callback(void (*callback)(const char*)); SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE /* OPTIONAL */ void __asan_on_error(); SANITIZER_INTERFACE_ATTRIBUTE void __asan_print_accumulated_stats(); SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE /* OPTIONAL */ const char* __asan_default_options(); // Global flag, copy of ASAN_OPTIONS=detect_stack_use_after_return SANITIZER_INTERFACE_ATTRIBUTE extern int __asan_option_detect_stack_use_after_return; SANITIZER_INTERFACE_ATTRIBUTE extern uptr *__asan_test_only_reported_buggy_pointer; SANITIZER_INTERFACE_ATTRIBUTE void __asan_load1(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_load2(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_load4(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_load8(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_load16(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_store1(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_store2(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_store4(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_store8(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_store16(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_loadN(uptr p, uptr size); SANITIZER_INTERFACE_ATTRIBUTE void __asan_storeN(uptr p, uptr size); SANITIZER_INTERFACE_ATTRIBUTE void __asan_load1_noabort(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_load2_noabort(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_load4_noabort(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_load8_noabort(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_load16_noabort(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_store1_noabort(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_store2_noabort(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_store4_noabort(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_store8_noabort(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_store16_noabort(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_loadN_noabort(uptr p, uptr size); SANITIZER_INTERFACE_ATTRIBUTE void __asan_storeN_noabort(uptr p, uptr size); SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load1(uptr p, u32 exp); SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load2(uptr p, u32 exp); SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load4(uptr p, u32 exp); SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load8(uptr p, u32 exp); SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load16(uptr p, u32 exp); SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store1(uptr p, u32 exp); SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store2(uptr p, u32 exp); SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store4(uptr p, u32 exp); SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store8(uptr p, u32 exp); SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store16(uptr p, u32 exp); SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_loadN(uptr p, uptr size, u32 exp); SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_storeN(uptr p, uptr size, u32 exp); SANITIZER_INTERFACE_ATTRIBUTE void* __asan_memcpy(void *dst, const void *src, uptr size); SANITIZER_INTERFACE_ATTRIBUTE void* __asan_memset(void *s, int c, uptr n); SANITIZER_INTERFACE_ATTRIBUTE void* __asan_memmove(void* dest, const void* src, uptr n); SANITIZER_INTERFACE_ATTRIBUTE void __asan_poison_cxx_array_cookie(uptr p); SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_load_cxx_array_cookie(uptr *p); SANITIZER_INTERFACE_ATTRIBUTE void __asan_poison_intra_object_redzone(uptr p, uptr size); SANITIZER_INTERFACE_ATTRIBUTE void __asan_unpoison_intra_object_redzone(uptr p, uptr size); SANITIZER_INTERFACE_ATTRIBUTE void __asan_alloca_poison(uptr addr, uptr size); SANITIZER_INTERFACE_ATTRIBUTE void __asan_allocas_unpoison(uptr top, uptr bottom); } // extern "C" #endif // ASAN_INTERFACE_INTERNAL_H Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_internal.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_internal.h (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_internal.h (revision 305364) @@ -1,141 +1,158 @@ //===-- asan_internal.h -----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // ASan-private header which defines various general utilities. //===----------------------------------------------------------------------===// #ifndef ASAN_INTERNAL_H #define ASAN_INTERNAL_H #include "asan_flags.h" #include "asan_interface_internal.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_internal_defs.h" #include "sanitizer_common/sanitizer_stacktrace.h" #include "sanitizer_common/sanitizer_libc.h" #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) # error "The AddressSanitizer run-time should not be" " instrumented by AddressSanitizer" #endif // Build-time configuration options. // If set, asan will intercept C++ exception api call(s). #ifndef ASAN_HAS_EXCEPTIONS # define ASAN_HAS_EXCEPTIONS 1 #endif // If set, values like allocator chunk size, as well as defaults for some flags // will be changed towards less memory overhead. #ifndef ASAN_LOW_MEMORY -#if SANITIZER_WORDSIZE == 32 +# if SANITIZER_IOS || (SANITIZER_WORDSIZE == 32) # define ASAN_LOW_MEMORY 1 -#else +# else # define ASAN_LOW_MEMORY 0 # endif #endif #ifndef ASAN_DYNAMIC # ifdef PIC # define ASAN_DYNAMIC 1 # else # define ASAN_DYNAMIC 0 # endif #endif // All internal functions in asan reside inside the __asan namespace // to avoid namespace collisions with the user programs. // Separate namespace also makes it simpler to distinguish the asan run-time // functions from the instrumented user code in a profile. namespace __asan { class AsanThread; using __sanitizer::StackTrace; void AsanInitFromRtl(); +// asan_win.cc +void InitializePlatformExceptionHandlers(); + // asan_rtl.cc void NORETURN ShowStatsAndAbort(); // asan_malloc_linux.cc / asan_malloc_mac.cc void ReplaceSystemMalloc(); // asan_linux.cc / asan_mac.cc / asan_win.cc void *AsanDoesNotSupportStaticLinkage(); void AsanCheckDynamicRTPrereqs(); void AsanCheckIncompatibleRT(); +// Support function for __asan_(un)register_image_globals. Searches for the +// loaded image containing `needle' and then enumerates all global metadata +// structures declared in that image, applying `op' (e.g., +// __asan_(un)register_globals) to them. +typedef void (*globals_op_fptr)(__asan_global *, uptr); +void AsanApplyToGlobals(globals_op_fptr op, const void *needle); + void AsanOnDeadlySignal(int, void *siginfo, void *context); void ReadContextStack(void *context, uptr *stack, uptr *ssize); void StopInitOrderChecking(); // Wrapper for TLS/TSD. void AsanTSDInit(void (*destructor)(void *tsd)); void *AsanTSDGet(); void AsanTSDSet(void *tsd); void PlatformTSDDtor(void *tsd); void AppendToErrorMessageBuffer(const char *buffer); void *AsanDlSymNext(const char *sym); void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name); // Platform-specific options. #if SANITIZER_MAC bool PlatformHasDifferentMemcpyAndMemmove(); # define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE \ (PlatformHasDifferentMemcpyAndMemmove()) +#elif SANITIZER_WINDOWS64 +# define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE false #else # define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE true #endif // SANITIZER_MAC // Add convenient macro for interface functions that may be represented as // weak hooks. -#define ASAN_MALLOC_HOOK(ptr, size) \ - if (&__sanitizer_malloc_hook) __sanitizer_malloc_hook(ptr, size) -#define ASAN_FREE_HOOK(ptr) \ - if (&__sanitizer_free_hook) __sanitizer_free_hook(ptr) +#define ASAN_MALLOC_HOOK(ptr, size) \ + do { \ + if (&__sanitizer_malloc_hook) __sanitizer_malloc_hook(ptr, size); \ + RunMallocHooks(ptr, size); \ + } while (false) +#define ASAN_FREE_HOOK(ptr) \ + do { \ + if (&__sanitizer_free_hook) __sanitizer_free_hook(ptr); \ + RunFreeHooks(ptr); \ + } while (false) #define ASAN_ON_ERROR() \ if (&__asan_on_error) __asan_on_error() extern int asan_inited; // Used to avoid infinite recursion in __asan_init(). extern bool asan_init_is_running; extern void (*death_callback)(void); - // These magic values are written to shadow for better error reporting. const int kAsanHeapLeftRedzoneMagic = 0xfa; const int kAsanHeapRightRedzoneMagic = 0xfb; const int kAsanHeapFreeMagic = 0xfd; const int kAsanStackLeftRedzoneMagic = 0xf1; const int kAsanStackMidRedzoneMagic = 0xf2; const int kAsanStackRightRedzoneMagic = 0xf3; const int kAsanStackPartialRedzoneMagic = 0xf4; const int kAsanStackAfterReturnMagic = 0xf5; const int kAsanInitializationOrderMagic = 0xf6; const int kAsanUserPoisonedMemoryMagic = 0xf7; const int kAsanContiguousContainerOOBMagic = 0xfc; const int kAsanStackUseAfterScopeMagic = 0xf8; const int kAsanGlobalRedzoneMagic = 0xf9; const int kAsanInternalHeapMagic = 0xfe; const int kAsanArrayCookieMagic = 0xac; const int kAsanIntraObjectRedzone = 0xbb; const int kAsanAllocaLeftMagic = 0xca; const int kAsanAllocaRightMagic = 0xcb; static const uptr kCurrentStackFrameMagic = 0x41B58AB3; static const uptr kRetiredStackFrameMagic = 0x45E0360E; } // namespace __asan #endif // ASAN_INTERNAL_H Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_linux.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_linux.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_linux.cc (revision 305364) @@ -1,171 +1,176 @@ //===-- asan_linux.cc -----------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // Linux-specific details. //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_FREEBSD || SANITIZER_LINUX #include "asan_interceptors.h" #include "asan_internal.h" #include "asan_thread.h" #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_freebsd.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_procmaps.h" #include #include #include #include #include #include #include #include #include #include #include #if SANITIZER_FREEBSD #include #endif #if SANITIZER_ANDROID || SANITIZER_FREEBSD #include extern "C" void* _DYNAMIC; #else #include #include #endif // x86-64 FreeBSD 9.2 and older define 'ucontext_t' incorrectly in // 32-bit mode. #if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) && \ __FreeBSD_version <= 902001 // v9.2 #define ucontext_t xucontext_t #endif typedef enum { ASAN_RT_VERSION_UNDEFINED = 0, ASAN_RT_VERSION_DYNAMIC, ASAN_RT_VERSION_STATIC, } asan_rt_version_t; // FIXME: perhaps also store abi version here? extern "C" { SANITIZER_INTERFACE_ATTRIBUTE asan_rt_version_t __asan_rt_version; } namespace __asan { void InitializePlatformInterceptors() {} +void InitializePlatformExceptionHandlers() {} void *AsanDoesNotSupportStaticLinkage() { // This will fail to link with -static. return &_DYNAMIC; // defined in link.h +} + +void AsanApplyToGlobals(globals_op_fptr op, const void *needle) { + UNIMPLEMENTED(); } #if SANITIZER_ANDROID // FIXME: should we do anything for Android? void AsanCheckDynamicRTPrereqs() {} void AsanCheckIncompatibleRT() {} #else static int FindFirstDSOCallback(struct dl_phdr_info *info, size_t size, void *data) { // Continue until the first dynamic library is found if (!info->dlpi_name || info->dlpi_name[0] == 0) return 0; // Ignore vDSO if (internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0) return 0; *(const char **)data = info->dlpi_name; return 1; } static bool IsDynamicRTName(const char *libname) { return internal_strstr(libname, "libclang_rt.asan") || internal_strstr(libname, "libasan.so"); } static void ReportIncompatibleRT() { Report("Your application is linked against incompatible ASan runtimes.\n"); Die(); } void AsanCheckDynamicRTPrereqs() { if (!ASAN_DYNAMIC) return; // Ensure that dynamic RT is the first DSO in the list const char *first_dso_name = nullptr; dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name); if (first_dso_name && !IsDynamicRTName(first_dso_name)) { Report("ASan runtime does not come first in initial library list; " "you should either link runtime to your application or " "manually preload it with LD_PRELOAD.\n"); Die(); } } void AsanCheckIncompatibleRT() { if (ASAN_DYNAMIC) { if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) { __asan_rt_version = ASAN_RT_VERSION_DYNAMIC; } else if (__asan_rt_version != ASAN_RT_VERSION_DYNAMIC) { ReportIncompatibleRT(); } } else { if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) { // Ensure that dynamic runtime is not present. We should detect it // as early as possible, otherwise ASan interceptors could bind to // the functions in dynamic ASan runtime instead of the functions in // system libraries, causing crashes later in ASan initialization. MemoryMappingLayout proc_maps(/*cache_enabled*/true); char filename[128]; while (proc_maps.Next(nullptr, nullptr, nullptr, filename, sizeof(filename), nullptr)) { if (IsDynamicRTName(filename)) { Report("Your application is linked against " "incompatible ASan runtimes.\n"); Die(); } } __asan_rt_version = ASAN_RT_VERSION_STATIC; } else if (__asan_rt_version != ASAN_RT_VERSION_STATIC) { ReportIncompatibleRT(); } } } #endif // SANITIZER_ANDROID #if !SANITIZER_ANDROID void ReadContextStack(void *context, uptr *stack, uptr *ssize) { ucontext_t *ucp = (ucontext_t*)context; *stack = (uptr)ucp->uc_stack.ss_sp; *ssize = ucp->uc_stack.ss_size; } #else void ReadContextStack(void *context, uptr *stack, uptr *ssize) { UNIMPLEMENTED(); } #endif void *AsanDlSymNext(const char *sym) { return dlsym(RTLD_NEXT, sym); } } // namespace __asan #endif // SANITIZER_FREEBSD || SANITIZER_LINUX Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_mac.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_mac.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_mac.cc (revision 305364) @@ -1,263 +1,296 @@ //===-- asan_mac.cc -------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // Mac-specific details. //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_MAC #include "asan_interceptors.h" #include "asan_internal.h" #include "asan_mapping.h" #include "asan_stack.h" #include "asan_thread.h" #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_mac.h" +#include #include #include #include +#include #include #include #include // for free() #include #include #include #include #include +// from , but we don't have that file on iOS +extern "C" { + extern char ***_NSGetArgv(void); + extern char ***_NSGetEnviron(void); +} + namespace __asan { void InitializePlatformInterceptors() {} +void InitializePlatformExceptionHandlers() {} bool PlatformHasDifferentMemcpyAndMemmove() { // On OS X 10.7 memcpy() and memmove() are both resolved // into memmove$VARIANT$sse42. // See also https://github.com/google/sanitizers/issues/34. // TODO(glider): need to check dynamically that memcpy() and memmove() are // actually the same function. return GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD; } // No-op. Mac does not support static linkage anyway. void *AsanDoesNotSupportStaticLinkage() { return 0; } // No-op. Mac does not support static linkage anyway. void AsanCheckDynamicRTPrereqs() {} // No-op. Mac does not support static linkage anyway. void AsanCheckIncompatibleRT() {} + +void AsanApplyToGlobals(globals_op_fptr op, const void *needle) { + // Find the Mach-O header for the image containing the needle + Dl_info info; + int err = dladdr(needle, &info); + if (err == 0) return; + +#if __LP64__ + const struct mach_header_64 *mh = (struct mach_header_64 *)info.dli_fbase; +#else + const struct mach_header *mh = (struct mach_header *)info.dli_fbase; +#endif + + // Look up the __asan_globals section in that image and register its globals + unsigned long size = 0; + __asan_global *globals = (__asan_global *)getsectiondata( + mh, + "__DATA", "__asan_globals", + &size); + + if (!globals) return; + if (size % sizeof(__asan_global) != 0) return; + op(globals, size / sizeof(__asan_global)); +} void ReadContextStack(void *context, uptr *stack, uptr *ssize) { UNIMPLEMENTED(); } // Support for the following functions from libdispatch on Mac OS: // dispatch_async_f() // dispatch_async() // dispatch_sync_f() // dispatch_sync() // dispatch_after_f() // dispatch_after() // dispatch_group_async_f() // dispatch_group_async() // TODO(glider): libdispatch API contains other functions that we don't support // yet. // // dispatch_sync() and dispatch_sync_f() are synchronous, although chances are // they can cause jobs to run on a thread different from the current one. // TODO(glider): if so, we need a test for this (otherwise we should remove // them). // // The following functions use dispatch_barrier_async_f() (which isn't a library // function but is exported) and are thus supported: // dispatch_source_set_cancel_handler_f() // dispatch_source_set_cancel_handler() // dispatch_source_set_event_handler_f() // dispatch_source_set_event_handler() // // The reference manual for Grand Central Dispatch is available at // http://developer.apple.com/library/mac/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html // The implementation details are at // http://libdispatch.macosforge.org/trac/browser/trunk/src/queue.c typedef void* dispatch_group_t; typedef void* dispatch_queue_t; typedef void* dispatch_source_t; typedef u64 dispatch_time_t; typedef void (*dispatch_function_t)(void *block); typedef void* (*worker_t)(void *block); // A wrapper for the ObjC blocks used to support libdispatch. typedef struct { void *block; dispatch_function_t func; u32 parent_tid; } asan_block_context_t; ALWAYS_INLINE void asan_register_worker_thread(int parent_tid, StackTrace *stack) { AsanThread *t = GetCurrentThread(); if (!t) { t = AsanThread::Create(/* start_routine */ nullptr, /* arg */ nullptr, parent_tid, stack, /* detached */ true); t->Init(); asanThreadRegistry().StartThread(t->tid(), 0, 0); SetCurrentThread(t); } } // For use by only those functions that allocated the context via // alloc_asan_context(). extern "C" void asan_dispatch_call_block_and_release(void *block) { GET_STACK_TRACE_THREAD; asan_block_context_t *context = (asan_block_context_t*)block; VReport(2, "asan_dispatch_call_block_and_release(): " "context: %p, pthread_self: %p\n", block, pthread_self()); asan_register_worker_thread(context->parent_tid, &stack); // Call the original dispatcher for the block. context->func(context->block); asan_free(context, &stack, FROM_MALLOC); } } // namespace __asan using namespace __asan; // NOLINT // Wrap |ctxt| and |func| into an asan_block_context_t. // The caller retains control of the allocated context. extern "C" asan_block_context_t *alloc_asan_context(void *ctxt, dispatch_function_t func, BufferedStackTrace *stack) { asan_block_context_t *asan_ctxt = (asan_block_context_t*) asan_malloc(sizeof(asan_block_context_t), stack); asan_ctxt->block = ctxt; asan_ctxt->func = func; asan_ctxt->parent_tid = GetCurrentTidOrInvalid(); return asan_ctxt; } // Define interceptor for dispatch_*_f function with the three most common // parameters: dispatch_queue_t, context, dispatch_function_t. #define INTERCEPT_DISPATCH_X_F_3(dispatch_x_f) \ INTERCEPTOR(void, dispatch_x_f, dispatch_queue_t dq, void *ctxt, \ dispatch_function_t func) { \ GET_STACK_TRACE_THREAD; \ asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); \ if (Verbosity() >= 2) { \ Report(#dispatch_x_f "(): context: %p, pthread_self: %p\n", \ asan_ctxt, pthread_self()); \ PRINT_CURRENT_STACK(); \ } \ return REAL(dispatch_x_f)(dq, (void*)asan_ctxt, \ asan_dispatch_call_block_and_release); \ } INTERCEPT_DISPATCH_X_F_3(dispatch_async_f) INTERCEPT_DISPATCH_X_F_3(dispatch_sync_f) INTERCEPT_DISPATCH_X_F_3(dispatch_barrier_async_f) INTERCEPTOR(void, dispatch_after_f, dispatch_time_t when, dispatch_queue_t dq, void *ctxt, dispatch_function_t func) { GET_STACK_TRACE_THREAD; asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); if (Verbosity() >= 2) { Report("dispatch_after_f: %p\n", asan_ctxt); PRINT_CURRENT_STACK(); } return REAL(dispatch_after_f)(when, dq, (void*)asan_ctxt, asan_dispatch_call_block_and_release); } INTERCEPTOR(void, dispatch_group_async_f, dispatch_group_t group, dispatch_queue_t dq, void *ctxt, dispatch_function_t func) { GET_STACK_TRACE_THREAD; asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); if (Verbosity() >= 2) { Report("dispatch_group_async_f(): context: %p, pthread_self: %p\n", asan_ctxt, pthread_self()); PRINT_CURRENT_STACK(); } REAL(dispatch_group_async_f)(group, dq, (void*)asan_ctxt, asan_dispatch_call_block_and_release); } #if !defined(MISSING_BLOCKS_SUPPORT) extern "C" { void dispatch_async(dispatch_queue_t dq, void(^work)(void)); void dispatch_group_async(dispatch_group_t dg, dispatch_queue_t dq, void(^work)(void)); void dispatch_after(dispatch_time_t when, dispatch_queue_t queue, void(^work)(void)); void dispatch_source_set_cancel_handler(dispatch_source_t ds, void(^work)(void)); void dispatch_source_set_event_handler(dispatch_source_t ds, void(^work)(void)); } #define GET_ASAN_BLOCK(work) \ void (^asan_block)(void); \ int parent_tid = GetCurrentTidOrInvalid(); \ asan_block = ^(void) { \ GET_STACK_TRACE_THREAD; \ asan_register_worker_thread(parent_tid, &stack); \ work(); \ } INTERCEPTOR(void, dispatch_async, dispatch_queue_t dq, void(^work)(void)) { ENABLE_FRAME_POINTER; GET_ASAN_BLOCK(work); REAL(dispatch_async)(dq, asan_block); } INTERCEPTOR(void, dispatch_group_async, dispatch_group_t dg, dispatch_queue_t dq, void(^work)(void)) { ENABLE_FRAME_POINTER; GET_ASAN_BLOCK(work); REAL(dispatch_group_async)(dg, dq, asan_block); } INTERCEPTOR(void, dispatch_after, dispatch_time_t when, dispatch_queue_t queue, void(^work)(void)) { ENABLE_FRAME_POINTER; GET_ASAN_BLOCK(work); REAL(dispatch_after)(when, queue, asan_block); } INTERCEPTOR(void, dispatch_source_set_cancel_handler, dispatch_source_t ds, void(^work)(void)) { if (!work) { REAL(dispatch_source_set_cancel_handler)(ds, work); return; } ENABLE_FRAME_POINTER; GET_ASAN_BLOCK(work); REAL(dispatch_source_set_cancel_handler)(ds, asan_block); } INTERCEPTOR(void, dispatch_source_set_event_handler, dispatch_source_t ds, void(^work)(void)) { ENABLE_FRAME_POINTER; GET_ASAN_BLOCK(work); REAL(dispatch_source_set_event_handler)(ds, asan_block); } #endif #endif // SANITIZER_MAC Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_malloc_linux.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_malloc_linux.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_malloc_linux.cc (revision 305364) @@ -1,203 +1,209 @@ //===-- asan_malloc_linux.cc ----------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // Linux-specific malloc interception. // We simply define functions like malloc, free, realloc, etc. // They will replace the corresponding libc functions automagically. //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_FREEBSD || SANITIZER_LINUX #include "sanitizer_common/sanitizer_tls_get_addr.h" #include "asan_allocator.h" #include "asan_interceptors.h" #include "asan_internal.h" #include "asan_stack.h" // ---------------------- Replacement functions ---------------- {{{1 using namespace __asan; // NOLINT -static const uptr kCallocPoolSize = 1024; -static uptr calloc_memory_for_dlsym[kCallocPoolSize]; +static uptr allocated_for_dlsym; +static const uptr kDlsymAllocPoolSize = 1024; +static uptr alloc_memory_for_dlsym[kDlsymAllocPoolSize]; -static bool IsInCallocPool(const void *ptr) { - sptr off = (sptr)ptr - (sptr)calloc_memory_for_dlsym; - return 0 <= off && off < (sptr)kCallocPoolSize; +static bool IsInDlsymAllocPool(const void *ptr) { + uptr off = (uptr)ptr - (uptr)alloc_memory_for_dlsym; + return off < sizeof(alloc_memory_for_dlsym); } +static void *AllocateFromLocalPool(uptr size_in_bytes) { + uptr size_in_words = RoundUpTo(size_in_bytes, kWordSize) / kWordSize; + void *mem = (void*)&alloc_memory_for_dlsym[allocated_for_dlsym]; + allocated_for_dlsym += size_in_words; + CHECK_LT(allocated_for_dlsym, kDlsymAllocPoolSize); + return mem; +} + INTERCEPTOR(void, free, void *ptr) { GET_STACK_TRACE_FREE; - if (UNLIKELY(IsInCallocPool(ptr))) + if (UNLIKELY(IsInDlsymAllocPool(ptr))) return; asan_free(ptr, &stack, FROM_MALLOC); } INTERCEPTOR(void, cfree, void *ptr) { GET_STACK_TRACE_FREE; - if (UNLIKELY(IsInCallocPool(ptr))) + if (UNLIKELY(IsInDlsymAllocPool(ptr))) return; asan_free(ptr, &stack, FROM_MALLOC); } INTERCEPTOR(void*, malloc, uptr size) { + if (UNLIKELY(!asan_inited)) + // Hack: dlsym calls malloc before REAL(malloc) is retrieved from dlsym. + return AllocateFromLocalPool(size); GET_STACK_TRACE_MALLOC; return asan_malloc(size, &stack); } INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { - if (UNLIKELY(!asan_inited)) { + if (UNLIKELY(!asan_inited)) // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. - static uptr allocated; - uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; - void *mem = (void*)&calloc_memory_for_dlsym[allocated]; - allocated += size_in_words; - CHECK(allocated < kCallocPoolSize); - return mem; - } + return AllocateFromLocalPool(nmemb * size); GET_STACK_TRACE_MALLOC; return asan_calloc(nmemb, size, &stack); } INTERCEPTOR(void*, realloc, void *ptr, uptr size) { GET_STACK_TRACE_MALLOC; - if (UNLIKELY(IsInCallocPool(ptr))) { - uptr offset = (uptr)ptr - (uptr)calloc_memory_for_dlsym; - uptr copy_size = Min(size, kCallocPoolSize - offset); + if (UNLIKELY(IsInDlsymAllocPool(ptr))) { + uptr offset = (uptr)ptr - (uptr)alloc_memory_for_dlsym; + uptr copy_size = Min(size, kDlsymAllocPoolSize - offset); void *new_ptr = asan_malloc(size, &stack); internal_memcpy(new_ptr, ptr, copy_size); return new_ptr; } return asan_realloc(ptr, size, &stack); } INTERCEPTOR(void*, memalign, uptr boundary, uptr size) { GET_STACK_TRACE_MALLOC; return asan_memalign(boundary, size, &stack, FROM_MALLOC); } INTERCEPTOR(void*, aligned_alloc, uptr boundary, uptr size) { GET_STACK_TRACE_MALLOC; return asan_memalign(boundary, size, &stack, FROM_MALLOC); } INTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) { GET_STACK_TRACE_MALLOC; void *res = asan_memalign(boundary, size, &stack, FROM_MALLOC); - DTLS_on_libc_memalign(res, size * boundary); + DTLS_on_libc_memalign(res, size); return res; } INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { GET_CURRENT_PC_BP_SP; (void)sp; return asan_malloc_usable_size(ptr, pc, bp); } // We avoid including malloc.h for portability reasons. // man mallinfo says the fields are "long", but the implementation uses int. // It doesn't matter much -- we just need to make sure that the libc's mallinfo // is not called. struct fake_mallinfo { int x[10]; }; INTERCEPTOR(struct fake_mallinfo, mallinfo, void) { struct fake_mallinfo res; REAL(memset)(&res, 0, sizeof(res)); return res; } INTERCEPTOR(int, mallopt, int cmd, int value) { return -1; } INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { GET_STACK_TRACE_MALLOC; // Printf("posix_memalign: %zx %zu\n", alignment, size); return asan_posix_memalign(memptr, alignment, size, &stack); } INTERCEPTOR(void*, valloc, uptr size) { GET_STACK_TRACE_MALLOC; return asan_valloc(size, &stack); } INTERCEPTOR(void*, pvalloc, uptr size) { GET_STACK_TRACE_MALLOC; return asan_pvalloc(size, &stack); } INTERCEPTOR(void, malloc_stats, void) { __asan_print_accumulated_stats(); } #if SANITIZER_ANDROID // Format of __libc_malloc_dispatch has changed in Android L. // While we are moving towards a solution that does not depend on bionic // internals, here is something to support both K* and L releases. struct MallocDebugK { void *(*malloc)(uptr bytes); void (*free)(void *mem); void *(*calloc)(uptr n_elements, uptr elem_size); void *(*realloc)(void *oldMem, uptr bytes); void *(*memalign)(uptr alignment, uptr bytes); uptr (*malloc_usable_size)(void *mem); }; struct MallocDebugL { void *(*calloc)(uptr n_elements, uptr elem_size); void (*free)(void *mem); fake_mallinfo (*mallinfo)(void); void *(*malloc)(uptr bytes); uptr (*malloc_usable_size)(void *mem); void *(*memalign)(uptr alignment, uptr bytes); int (*posix_memalign)(void **memptr, uptr alignment, uptr size); void* (*pvalloc)(uptr size); void *(*realloc)(void *oldMem, uptr bytes); void* (*valloc)(uptr size); }; ALIGNED(32) const MallocDebugK asan_malloc_dispatch_k = { WRAP(malloc), WRAP(free), WRAP(calloc), WRAP(realloc), WRAP(memalign), WRAP(malloc_usable_size)}; ALIGNED(32) const MallocDebugL asan_malloc_dispatch_l = { WRAP(calloc), WRAP(free), WRAP(mallinfo), WRAP(malloc), WRAP(malloc_usable_size), WRAP(memalign), WRAP(posix_memalign), WRAP(pvalloc), WRAP(realloc), WRAP(valloc)}; namespace __asan { void ReplaceSystemMalloc() { void **__libc_malloc_dispatch_p = (void **)AsanDlSymNext("__libc_malloc_dispatch"); if (__libc_malloc_dispatch_p) { // Decide on K vs L dispatch format by the presence of // __libc_malloc_default_dispatch export in libc. void *default_dispatch_p = AsanDlSymNext("__libc_malloc_default_dispatch"); if (default_dispatch_p) *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_k; else *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_l; } } } // namespace __asan #else // SANITIZER_ANDROID namespace __asan { void ReplaceSystemMalloc() { } } // namespace __asan #endif // SANITIZER_ANDROID #endif // SANITIZER_FREEBSD || SANITIZER_LINUX Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_malloc_win.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_malloc_win.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_malloc_win.cc (revision 305364) @@ -1,178 +1,251 @@ //===-- asan_malloc_win.cc ------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // Windows-specific malloc interception. //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_WINDOWS +#define WIN32_LEAN_AND_MEAN +#include #include "asan_allocator.h" #include "asan_interceptors.h" #include "asan_internal.h" #include "asan_stack.h" #include "interception/interception.h" #include using namespace __asan; // NOLINT // MT: Simply defining functions with the same signature in *.obj // files overrides the standard functions in the CRT. // MD: Memory allocation functions are defined in the CRT .dll, // so we have to intercept them before they are called for the first time. #if ASAN_DYNAMIC # define ALLOCATION_FUNCTION_ATTRIBUTE #else # define ALLOCATION_FUNCTION_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE #endif extern "C" { ALLOCATION_FUNCTION_ATTRIBUTE void free(void *ptr) { GET_STACK_TRACE_FREE; return asan_free(ptr, &stack, FROM_MALLOC); } ALLOCATION_FUNCTION_ATTRIBUTE void _free_dbg(void *ptr, int) { free(ptr); } ALLOCATION_FUNCTION_ATTRIBUTE +void _free_base(void *ptr) { + free(ptr); +} + +ALLOCATION_FUNCTION_ATTRIBUTE void cfree(void *ptr) { CHECK(!"cfree() should not be used on Windows"); } ALLOCATION_FUNCTION_ATTRIBUTE void *malloc(size_t size) { GET_STACK_TRACE_MALLOC; return asan_malloc(size, &stack); } ALLOCATION_FUNCTION_ATTRIBUTE +void *_malloc_base(size_t size) { + return malloc(size); +} + +ALLOCATION_FUNCTION_ATTRIBUTE void *_malloc_dbg(size_t size, int, const char *, int) { return malloc(size); } ALLOCATION_FUNCTION_ATTRIBUTE void *calloc(size_t nmemb, size_t size) { GET_STACK_TRACE_MALLOC; return asan_calloc(nmemb, size, &stack); } ALLOCATION_FUNCTION_ATTRIBUTE +void *_calloc_base(size_t nmemb, size_t size) { + return calloc(nmemb, size); +} + +ALLOCATION_FUNCTION_ATTRIBUTE void *_calloc_dbg(size_t nmemb, size_t size, int, const char *, int) { return calloc(nmemb, size); } ALLOCATION_FUNCTION_ATTRIBUTE void *_calloc_impl(size_t nmemb, size_t size, int *errno_tmp) { return calloc(nmemb, size); } ALLOCATION_FUNCTION_ATTRIBUTE void *realloc(void *ptr, size_t size) { GET_STACK_TRACE_MALLOC; return asan_realloc(ptr, size, &stack); } ALLOCATION_FUNCTION_ATTRIBUTE void *_realloc_dbg(void *ptr, size_t size, int) { CHECK(!"_realloc_dbg should not exist!"); return 0; } ALLOCATION_FUNCTION_ATTRIBUTE +void *_realloc_base(void *ptr, size_t size) { + return realloc(ptr, size); +} + +ALLOCATION_FUNCTION_ATTRIBUTE void *_recalloc(void *p, size_t n, size_t elem_size) { if (!p) return calloc(n, elem_size); const size_t size = n * elem_size; if (elem_size != 0 && size / elem_size != n) return 0; return realloc(p, size); } ALLOCATION_FUNCTION_ATTRIBUTE -size_t _msize(void *ptr) { +size_t _msize(const void *ptr) { GET_CURRENT_PC_BP_SP; (void)sp; return asan_malloc_usable_size(ptr, pc, bp); } ALLOCATION_FUNCTION_ATTRIBUTE void *_expand(void *memblock, size_t size) { // _expand is used in realloc-like functions to resize the buffer if possible. // We don't want memory to stand still while resizing buffers, so return 0. return 0; } ALLOCATION_FUNCTION_ATTRIBUTE void *_expand_dbg(void *memblock, size_t size) { return _expand(memblock, size); } // TODO(timurrrr): Might want to add support for _aligned_* allocation // functions to detect a bit more bugs. Those functions seem to wrap malloc(). int _CrtDbgReport(int, const char*, int, const char*, const char*, ...) { ShowStatsAndAbort(); } int _CrtDbgReportW(int reportType, const wchar_t*, int, const wchar_t*, const wchar_t*, ...) { ShowStatsAndAbort(); } int _CrtSetReportMode(int, int) { return 0; } } // extern "C" +INTERCEPTOR_WINAPI(LPVOID, HeapAlloc, HANDLE hHeap, DWORD dwFlags, + SIZE_T dwBytes) { + GET_STACK_TRACE_MALLOC; + void *p = asan_malloc(dwBytes, &stack); + // Reading MSDN suggests that the *entire* usable allocation is zeroed out. + // Otherwise it is difficult to HeapReAlloc with HEAP_ZERO_MEMORY. + // https://blogs.msdn.microsoft.com/oldnewthing/20120316-00/?p=8083 + if (dwFlags == HEAP_ZERO_MEMORY) + internal_memset(p, 0, asan_mz_size(p)); + else + CHECK(dwFlags == 0 && "unsupported heap flags"); + return p; +} + +INTERCEPTOR_WINAPI(BOOL, HeapFree, HANDLE hHeap, DWORD dwFlags, LPVOID lpMem) { + CHECK(dwFlags == 0 && "unsupported heap flags"); + GET_STACK_TRACE_FREE; + asan_free(lpMem, &stack, FROM_MALLOC); + return true; +} + +INTERCEPTOR_WINAPI(LPVOID, HeapReAlloc, HANDLE hHeap, DWORD dwFlags, + LPVOID lpMem, SIZE_T dwBytes) { + GET_STACK_TRACE_MALLOC; + // Realloc should never reallocate in place. + if (dwFlags & HEAP_REALLOC_IN_PLACE_ONLY) + return nullptr; + CHECK(dwFlags == 0 && "unsupported heap flags"); + return asan_realloc(lpMem, dwBytes, &stack); +} + +INTERCEPTOR_WINAPI(SIZE_T, HeapSize, HANDLE hHeap, DWORD dwFlags, + LPCVOID lpMem) { + CHECK(dwFlags == 0 && "unsupported heap flags"); + GET_CURRENT_PC_BP_SP; + (void)sp; + return asan_malloc_usable_size(lpMem, pc, bp); +} + namespace __asan { + +static void TryToOverrideFunction(const char *fname, uptr new_func) { + // Failure here is not fatal. The CRT may not be present, and different CRT + // versions use different symbols. + if (!__interception::OverrideFunction(fname, new_func)) + VPrintf(2, "Failed to override function %s\n", fname); +} + void ReplaceSystemMalloc() { #if defined(ASAN_DYNAMIC) - // We don't check the result because CRT might not be used in the process. - __interception::OverrideFunction("free", (uptr)free); - __interception::OverrideFunction("malloc", (uptr)malloc); - __interception::OverrideFunction("_malloc_crt", (uptr)malloc); - __interception::OverrideFunction("calloc", (uptr)calloc); - __interception::OverrideFunction("_calloc_crt", (uptr)calloc); - __interception::OverrideFunction("realloc", (uptr)realloc); - __interception::OverrideFunction("_realloc_crt", (uptr)realloc); - __interception::OverrideFunction("_recalloc", (uptr)_recalloc); - __interception::OverrideFunction("_recalloc_crt", (uptr)_recalloc); - __interception::OverrideFunction("_msize", (uptr)_msize); - __interception::OverrideFunction("_expand", (uptr)_expand); + TryToOverrideFunction("free", (uptr)free); + TryToOverrideFunction("_free_base", (uptr)free); + TryToOverrideFunction("malloc", (uptr)malloc); + TryToOverrideFunction("_malloc_base", (uptr)malloc); + TryToOverrideFunction("_malloc_crt", (uptr)malloc); + TryToOverrideFunction("calloc", (uptr)calloc); + TryToOverrideFunction("_calloc_base", (uptr)calloc); + TryToOverrideFunction("_calloc_crt", (uptr)calloc); + TryToOverrideFunction("realloc", (uptr)realloc); + TryToOverrideFunction("_realloc_base", (uptr)realloc); + TryToOverrideFunction("_realloc_crt", (uptr)realloc); + TryToOverrideFunction("_recalloc", (uptr)_recalloc); + TryToOverrideFunction("_recalloc_crt", (uptr)_recalloc); + TryToOverrideFunction("_msize", (uptr)_msize); + TryToOverrideFunction("_expand", (uptr)_expand); + TryToOverrideFunction("_expand_base", (uptr)_expand); - // Override different versions of 'operator new' and 'operator delete'. - // No need to override the nothrow versions as they just wrap the throw - // versions. - // FIXME: Unfortunately, MSVC miscompiles the statements that take the - // addresses of the array versions of these operators, - // see https://connect.microsoft.com/VisualStudio/feedbackdetail/view/946992 - // We might want to try to work around this by [inline] assembly or compiling - // parts of the RTL with Clang. - void *(*op_new)(size_t sz) = operator new; - void (*op_delete)(void *p) = operator delete; - void *(*op_array_new)(size_t sz) = operator new[]; - void (*op_array_delete)(void *p) = operator delete[]; - __interception::OverrideFunction("??2@YAPAXI@Z", (uptr)op_new); - __interception::OverrideFunction("??3@YAXPAX@Z", (uptr)op_delete); - __interception::OverrideFunction("??_U@YAPAXI@Z", (uptr)op_array_new); - __interception::OverrideFunction("??_V@YAXPAX@Z", (uptr)op_array_delete); + // Recent versions of ucrtbase.dll appear to be built with PGO and LTCG, which + // enable cross-module inlining. This means our _malloc_base hook won't catch + // all CRT allocations. This code here patches the import table of + // ucrtbase.dll so that all attempts to use the lower-level win32 heap + // allocation API will be directed to ASan's heap. We don't currently + // intercept all calls to HeapAlloc. If we did, we would have to check on + // HeapFree whether the pointer came from ASan of from the system. +#define INTERCEPT_UCRT_FUNCTION(func) \ + if (!INTERCEPT_FUNCTION_DLLIMPORT("ucrtbase.dll", \ + "api-ms-win-core-heap-l1-1-0.dll", func)) \ + VPrintf(2, "Failed to intercept ucrtbase.dll import %s\n", #func); + INTERCEPT_UCRT_FUNCTION(HeapAlloc); + INTERCEPT_UCRT_FUNCTION(HeapFree); + INTERCEPT_UCRT_FUNCTION(HeapReAlloc); + INTERCEPT_UCRT_FUNCTION(HeapSize); +#undef INTERCEPT_UCRT_FUNCTION #endif } } // namespace __asan #endif // _WIN32 Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_mapping.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_mapping.h (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_mapping.h (revision 305364) @@ -1,312 +1,336 @@ //===-- asan_mapping.h ------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // Defines ASan memory mapping. //===----------------------------------------------------------------------===// #ifndef ASAN_MAPPING_H #define ASAN_MAPPING_H #include "asan_internal.h" // The full explanation of the memory mapping could be found here: // https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm // // Typical shadow mapping on Linux/x86_64 with SHADOW_OFFSET == 0x00007fff8000: // || `[0x10007fff8000, 0x7fffffffffff]` || HighMem || // || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow || // || `[0x00008fff7000, 0x02008fff6fff]` || ShadowGap || // || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow || // || `[0x000000000000, 0x00007fff7fff]` || LowMem || // // When SHADOW_OFFSET is zero (-pie): // || `[0x100000000000, 0x7fffffffffff]` || HighMem || // || `[0x020000000000, 0x0fffffffffff]` || HighShadow || // || `[0x000000040000, 0x01ffffffffff]` || ShadowGap || // // Special case when something is already mapped between // 0x003000000000 and 0x005000000000 (e.g. when prelink is installed): // || `[0x10007fff8000, 0x7fffffffffff]` || HighMem || // || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow || // || `[0x005000000000, 0x02008fff6fff]` || ShadowGap3 || // || `[0x003000000000, 0x004fffffffff]` || MidMem || // || `[0x000a7fff8000, 0x002fffffffff]` || ShadowGap2 || // || `[0x00067fff8000, 0x000a7fff7fff]` || MidShadow || // || `[0x00008fff7000, 0x00067fff7fff]` || ShadowGap || // || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow || // || `[0x000000000000, 0x00007fff7fff]` || LowMem || // // Default Linux/i386 mapping on x86_64 machine: // || `[0x40000000, 0xffffffff]` || HighMem || // || `[0x28000000, 0x3fffffff]` || HighShadow || // || `[0x24000000, 0x27ffffff]` || ShadowGap || // || `[0x20000000, 0x23ffffff]` || LowShadow || // || `[0x00000000, 0x1fffffff]` || LowMem || // // Default Linux/i386 mapping on i386 machine // (addresses starting with 0xc0000000 are reserved // for kernel and thus not sanitized): // || `[0x38000000, 0xbfffffff]` || HighMem || // || `[0x27000000, 0x37ffffff]` || HighShadow || // || `[0x24000000, 0x26ffffff]` || ShadowGap || // || `[0x20000000, 0x23ffffff]` || LowShadow || // || `[0x00000000, 0x1fffffff]` || LowMem || // // Default Linux/MIPS32 mapping: // || `[0x2aaa0000, 0xffffffff]` || HighMem || // || `[0x0fff4000, 0x2aa9ffff]` || HighShadow || // || `[0x0bff4000, 0x0fff3fff]` || ShadowGap || // || `[0x0aaa0000, 0x0bff3fff]` || LowShadow || // || `[0x00000000, 0x0aa9ffff]` || LowMem || // // Default Linux/MIPS64 mapping: // || `[0x4000000000, 0xffffffffff]` || HighMem || // || `[0x2800000000, 0x3fffffffff]` || HighShadow || // || `[0x2400000000, 0x27ffffffff]` || ShadowGap || // || `[0x2000000000, 0x23ffffffff]` || LowShadow || // || `[0x0000000000, 0x1fffffffff]` || LowMem || // // Default Linux/AArch64 (39-bit VMA) mapping: // || `[0x2000000000, 0x7fffffffff]` || highmem || // || `[0x1400000000, 0x1fffffffff]` || highshadow || // || `[0x1200000000, 0x13ffffffff]` || shadowgap || // || `[0x1000000000, 0x11ffffffff]` || lowshadow || // || `[0x0000000000, 0x0fffffffff]` || lowmem || // // Default Linux/AArch64 (42-bit VMA) mapping: // || `[0x10000000000, 0x3ffffffffff]` || highmem || // || `[0x0a000000000, 0x0ffffffffff]` || highshadow || // || `[0x09000000000, 0x09fffffffff]` || shadowgap || // || `[0x08000000000, 0x08fffffffff]` || lowshadow || // || `[0x00000000000, 0x07fffffffff]` || lowmem || // +// Default Linux/S390 mapping: +// || `[0x30000000, 0x7fffffff]` || HighMem || +// || `[0x26000000, 0x2fffffff]` || HighShadow || +// || `[0x24000000, 0x25ffffff]` || ShadowGap || +// || `[0x20000000, 0x23ffffff]` || LowShadow || +// || `[0x00000000, 0x1fffffff]` || LowMem || +// +// Default Linux/SystemZ mapping: +// || `[0x14000000000000, 0x1fffffffffffff]` || HighMem || +// || `[0x12800000000000, 0x13ffffffffffff]` || HighShadow || +// || `[0x12000000000000, 0x127fffffffffff]` || ShadowGap || +// || `[0x10000000000000, 0x11ffffffffffff]` || LowShadow || +// || `[0x00000000000000, 0x0fffffffffffff]` || LowMem || +// // Shadow mapping on FreeBSD/x86-64 with SHADOW_OFFSET == 0x400000000000: // || `[0x500000000000, 0x7fffffffffff]` || HighMem || // || `[0x4a0000000000, 0x4fffffffffff]` || HighShadow || // || `[0x480000000000, 0x49ffffffffff]` || ShadowGap || // || `[0x400000000000, 0x47ffffffffff]` || LowShadow || // || `[0x000000000000, 0x3fffffffffff]` || LowMem || // // Shadow mapping on FreeBSD/i386 with SHADOW_OFFSET == 0x40000000: // || `[0x60000000, 0xffffffff]` || HighMem || // || `[0x4c000000, 0x5fffffff]` || HighShadow || // || `[0x48000000, 0x4bffffff]` || ShadowGap || // || `[0x40000000, 0x47ffffff]` || LowShadow || // || `[0x00000000, 0x3fffffff]` || LowMem || // // Default Windows/i386 mapping: // (the exact location of HighShadow/HighMem may vary depending // on WoW64, /LARGEADDRESSAWARE, etc). // || `[0x50000000, 0xffffffff]` || HighMem || // || `[0x3a000000, 0x4fffffff]` || HighShadow || // || `[0x36000000, 0x39ffffff]` || ShadowGap || // || `[0x30000000, 0x35ffffff]` || LowShadow || // || `[0x00000000, 0x2fffffff]` || LowMem || static const u64 kDefaultShadowScale = 3; static const u64 kDefaultShadowOffset32 = 1ULL << 29; // 0x20000000 static const u64 kDefaultShadowOffset64 = 1ULL << 44; static const u64 kDefaultShort64bitShadowOffset = 0x7FFF8000; // < 2G. static const u64 kIosShadowOffset32 = 1ULL << 30; // 0x40000000 -static const u64 kIosShadowOffset64 = 0x130000000; +static const u64 kIosShadowOffset64 = 0x120200000; static const u64 kIosSimShadowOffset32 = 1ULL << 30; static const u64 kIosSimShadowOffset64 = kDefaultShadowOffset64; static const u64 kAArch64_ShadowOffset64 = 1ULL << 36; static const u64 kMIPS32_ShadowOffset32 = 0x0aaa0000; static const u64 kMIPS64_ShadowOffset64 = 1ULL << 37; static const u64 kPPC64_ShadowOffset64 = 1ULL << 41; +static const u64 kSystemZ_ShadowOffset64 = 1ULL << 52; static const u64 kFreeBSD_ShadowOffset32 = 1ULL << 30; // 0x40000000 static const u64 kFreeBSD_ShadowOffset64 = 1ULL << 46; // 0x400000000000 static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000 +static const u64 kWindowsShadowOffset64 = 1ULL << 45; // 32TB #define SHADOW_SCALE kDefaultShadowScale #if SANITIZER_WORDSIZE == 32 # if SANITIZER_ANDROID # define SHADOW_OFFSET (0) # elif defined(__mips__) # define SHADOW_OFFSET kMIPS32_ShadowOffset32 # elif SANITIZER_FREEBSD # define SHADOW_OFFSET kFreeBSD_ShadowOffset32 # elif SANITIZER_WINDOWS # define SHADOW_OFFSET kWindowsShadowOffset32 -# elif SANITIZER_IOSSIM -# define SHADOW_OFFSET kIosSimShadowOffset32 # elif SANITIZER_IOS -# define SHADOW_OFFSET kIosShadowOffset32 +# if SANITIZER_IOSSIM +# define SHADOW_OFFSET kIosSimShadowOffset32 +# else +# define SHADOW_OFFSET kIosShadowOffset32 +# endif # else # define SHADOW_OFFSET kDefaultShadowOffset32 # endif #else -# if defined(__aarch64__) +# if SANITIZER_IOS +# if SANITIZER_IOSSIM +# define SHADOW_OFFSET kIosSimShadowOffset64 +# else +# define SHADOW_OFFSET kIosShadowOffset64 +# endif +# elif defined(__aarch64__) # define SHADOW_OFFSET kAArch64_ShadowOffset64 # elif defined(__powerpc64__) # define SHADOW_OFFSET kPPC64_ShadowOffset64 +# elif defined(__s390x__) +# define SHADOW_OFFSET kSystemZ_ShadowOffset64 # elif SANITIZER_FREEBSD # define SHADOW_OFFSET kFreeBSD_ShadowOffset64 # elif SANITIZER_MAC # define SHADOW_OFFSET kDefaultShadowOffset64 # elif defined(__mips64) # define SHADOW_OFFSET kMIPS64_ShadowOffset64 -# elif SANITIZER_IOSSIM -# define SHADOW_OFFSET kIosSimShadowOffset64 -# elif SANITIZER_IOS -# define SHADOW_OFFSET kIosShadowOffset64 +# elif SANITIZER_WINDOWS64 +# define SHADOW_OFFSET kWindowsShadowOffset64 # else # define SHADOW_OFFSET kDefaultShort64bitShadowOffset # endif #endif #define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE) #define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) + (SHADOW_OFFSET)) #define SHADOW_TO_MEM(shadow) (((shadow) - SHADOW_OFFSET) << SHADOW_SCALE) #define kLowMemBeg 0 #define kLowMemEnd (SHADOW_OFFSET ? SHADOW_OFFSET - 1 : 0) #define kLowShadowBeg SHADOW_OFFSET #define kLowShadowEnd MEM_TO_SHADOW(kLowMemEnd) #define kHighMemBeg (MEM_TO_SHADOW(kHighMemEnd) + 1) #define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg) #define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd) # define kMidShadowBeg MEM_TO_SHADOW(kMidMemBeg) # define kMidShadowEnd MEM_TO_SHADOW(kMidMemEnd) // With the zero shadow base we can not actually map pages starting from 0. // This constant is somewhat arbitrary. #define kZeroBaseShadowStart 0 #define kZeroBaseMaxShadowStart (1 << 18) #define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 \ : kZeroBaseShadowStart) #define kShadowGapEnd ((kMidMemBeg ? kMidShadowBeg : kHighShadowBeg) - 1) #define kShadowGap2Beg (kMidMemBeg ? kMidShadowEnd + 1 : 0) #define kShadowGap2End (kMidMemBeg ? kMidMemBeg - 1 : 0) #define kShadowGap3Beg (kMidMemBeg ? kMidMemEnd + 1 : 0) #define kShadowGap3End (kMidMemBeg ? kHighShadowBeg - 1 : 0) #define DO_ASAN_MAPPING_PROFILE 0 // Set to 1 to profile the functions below. #if DO_ASAN_MAPPING_PROFILE # define PROFILE_ASAN_MAPPING() AsanMappingProfile[__LINE__]++; #else # define PROFILE_ASAN_MAPPING() #endif // If 1, all shadow boundaries are constants. // Don't set to 1 other than for testing. #define ASAN_FIXED_MAPPING 0 namespace __asan { extern uptr AsanMappingProfile[]; #if ASAN_FIXED_MAPPING // Fixed mapping for 64-bit Linux. Mostly used for performance comparison // with non-fixed mapping. As of r175253 (Feb 2013) the performance // difference between fixed and non-fixed mapping is below the noise level. static uptr kHighMemEnd = 0x7fffffffffffULL; static uptr kMidMemBeg = 0x3000000000ULL; static uptr kMidMemEnd = 0x4fffffffffULL; #else extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; // Initialized in __asan_init. #endif static inline bool AddrIsInLowMem(uptr a) { PROFILE_ASAN_MAPPING(); return a < kLowMemEnd; } static inline bool AddrIsInLowShadow(uptr a) { PROFILE_ASAN_MAPPING(); return a >= kLowShadowBeg && a <= kLowShadowEnd; } static inline bool AddrIsInHighMem(uptr a) { PROFILE_ASAN_MAPPING(); return a >= kHighMemBeg && a <= kHighMemEnd; } static inline bool AddrIsInMidMem(uptr a) { PROFILE_ASAN_MAPPING(); return kMidMemBeg && a >= kMidMemBeg && a <= kMidMemEnd; } static inline bool AddrIsInMem(uptr a) { PROFILE_ASAN_MAPPING(); return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a); } static inline uptr MemToShadow(uptr p) { PROFILE_ASAN_MAPPING(); CHECK(AddrIsInMem(p)); return MEM_TO_SHADOW(p); } static inline bool AddrIsInHighShadow(uptr a) { PROFILE_ASAN_MAPPING(); return a >= kHighShadowBeg && a <= kHighMemEnd; } static inline bool AddrIsInMidShadow(uptr a) { PROFILE_ASAN_MAPPING(); return kMidMemBeg && a >= kMidShadowBeg && a <= kMidMemEnd; } static inline bool AddrIsInShadow(uptr a) { PROFILE_ASAN_MAPPING(); return AddrIsInLowShadow(a) || AddrIsInMidShadow(a) || AddrIsInHighShadow(a); } static inline bool AddrIsInShadowGap(uptr a) { PROFILE_ASAN_MAPPING(); if (kMidMemBeg) { if (a <= kShadowGapEnd) return SHADOW_OFFSET == 0 || a >= kShadowGapBeg; return (a >= kShadowGap2Beg && a <= kShadowGap2End) || (a >= kShadowGap3Beg && a <= kShadowGap3End); } // In zero-based shadow mode we treat addresses near zero as addresses // in shadow gap as well. if (SHADOW_OFFSET == 0) return a <= kShadowGapEnd; return a >= kShadowGapBeg && a <= kShadowGapEnd; } static inline bool AddrIsAlignedByGranularity(uptr a) { PROFILE_ASAN_MAPPING(); return (a & (SHADOW_GRANULARITY - 1)) == 0; } static inline bool AddressIsPoisoned(uptr a) { PROFILE_ASAN_MAPPING(); const uptr kAccessSize = 1; u8 *shadow_address = (u8*)MEM_TO_SHADOW(a); s8 shadow_value = *shadow_address; if (shadow_value) { u8 last_accessed_byte = (a & (SHADOW_GRANULARITY - 1)) + kAccessSize - 1; return (last_accessed_byte >= shadow_value); } return false; } // Must be after all calls to PROFILE_ASAN_MAPPING(). static const uptr kAsanMappingProfileSize = __LINE__; } // namespace __asan #endif // ASAN_MAPPING_H Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_memory_profile.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_memory_profile.cc (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_memory_profile.cc (revision 305364) @@ -0,0 +1,100 @@ +//===-- asan_memory_profile.cc.cc -----------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of AddressSanitizer, an address sanity checker. +// +// This file implements __sanitizer_print_memory_profile. +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_stackdepot.h" +#include "sanitizer_common/sanitizer_stacktrace.h" +#include "sanitizer_common/sanitizer_stoptheworld.h" +#include "lsan/lsan_common.h" +#include "asan/asan_allocator.h" + +#if CAN_SANITIZE_LEAKS + +namespace __asan { + +struct AllocationSite { + u32 id; + uptr total_size; + uptr count; +}; + +class HeapProfile { + public: + HeapProfile() : allocations_(1024) {} + void Insert(u32 id, uptr size) { + total_allocated_ += size; + total_count_++; + // Linear lookup will be good enough for most cases (although not all). + for (uptr i = 0; i < allocations_.size(); i++) { + if (allocations_[i].id == id) { + allocations_[i].total_size += size; + allocations_[i].count++; + return; + } + } + allocations_.push_back({id, size, 1}); + } + + void Print(uptr top_percent) { + InternalSort(&allocations_, allocations_.size(), + [](const AllocationSite &a, const AllocationSite &b) { + return a.total_size > b.total_size; + }); + CHECK(total_allocated_); + uptr total_shown = 0; + Printf("Live Heap Allocations: %zd bytes from %zd allocations; " + "showing top %zd%%\n", total_allocated_, total_count_, top_percent); + for (uptr i = 0; i < allocations_.size(); i++) { + auto &a = allocations_[i]; + Printf("%zd byte(s) (%zd%%) in %zd allocation(s)\n", a.total_size, + a.total_size * 100 / total_allocated_, a.count); + StackDepotGet(a.id).Print(); + total_shown += a.total_size; + if (total_shown * 100 / total_allocated_ > top_percent) + break; + } + } + + private: + uptr total_allocated_ = 0; + uptr total_count_ = 0; + InternalMmapVector allocations_; +}; + +static void ChunkCallback(uptr chunk, void *arg) { + HeapProfile *hp = reinterpret_cast(arg); + AsanChunkView cv = FindHeapChunkByAddress(chunk); + if (!cv.IsAllocated()) return; + u32 id = cv.GetAllocStackId(); + if (!id) return; + hp->Insert(id, cv.UsedSize()); +} + +static void MemoryProfileCB(const SuspendedThreadsList &suspended_threads_list, + void *argument) { + HeapProfile hp; + __lsan::ForEachChunk(ChunkCallback, &hp); + hp.Print(reinterpret_cast(argument)); +} + +} // namespace __asan + +extern "C" { +SANITIZER_INTERFACE_ATTRIBUTE +void __sanitizer_print_memory_profile(uptr top_percent) { + __sanitizer::StopTheWorld(__asan::MemoryProfileCB, (void*)top_percent); +} +} // extern "C" + +#endif // CAN_SANITIZE_LEAKS Property changes on: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_memory_profile.cc ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_new_delete.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_new_delete.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_new_delete.cc (revision 305364) @@ -1,132 +1,148 @@ //===-- asan_interceptors.cc ----------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // Interceptors for operators new and delete. //===----------------------------------------------------------------------===// #include "asan_allocator.h" #include "asan_internal.h" #include "asan_stack.h" #include "interception/interception.h" #include -// C++ operators can't have visibility attributes on Windows. +// C++ operators can't have dllexport attributes on Windows. We export them +// anyway by passing extra -export flags to the linker, which is exactly that +// dllexport would normally do. We need to export them in order to make the +// VS2015 dynamic CRT (MD) work. #if SANITIZER_WINDOWS # define CXX_OPERATOR_ATTRIBUTE +# ifdef _WIN64 +# pragma comment(linker, "/export:??2@YAPEAX_K@Z") // operator new +# pragma comment(linker, "/export:??3@YAXPEAX@Z") // operator delete +# pragma comment(linker, "/export:??3@YAXPEAX_K@Z") // sized operator delete +# pragma comment(linker, "/export:??_U@YAPEAX_K@Z") // operator new[] +# pragma comment(linker, "/export:??_V@YAXPEAX@Z") // operator delete[] +# else +# pragma comment(linker, "/export:??2@YAPAXI@Z") // operator new +# pragma comment(linker, "/export:??3@YAXPAX@Z") // operator delete +# pragma comment(linker, "/export:??3@YAXPAXI@Z") // sized operator delete +# pragma comment(linker, "/export:??_U@YAPAXI@Z") // operator new[] +# pragma comment(linker, "/export:??_V@YAXPAX@Z") // operator delete[] +# endif #else # define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE #endif using namespace __asan; // NOLINT // This code has issues on OSX. // See https://github.com/google/sanitizers/issues/131. // Fake std::nothrow_t to avoid including . namespace std { struct nothrow_t {}; } // namespace std #define OPERATOR_NEW_BODY(type) \ GET_STACK_TRACE_MALLOC;\ return asan_memalign(0, size, &stack, type); // On OS X it's not enough to just provide our own 'operator new' and // 'operator delete' implementations, because they're going to be in the // runtime dylib, and the main executable will depend on both the runtime // dylib and libstdc++, each of those'll have its implementation of new and // delete. // To make sure that C++ allocation/deallocation operators are overridden on // OS X we need to intercept them using their mangled names. #if !SANITIZER_MAC // FreeBSD prior v9.2 have wrong definition of 'size_t'. // http://svnweb.freebsd.org/base?view=revision&revision=232261 #if SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 32 #include #if __FreeBSD_version <= 902001 // v9.2 #define size_t unsigned #endif // __FreeBSD_version #endif // SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 32 CXX_OPERATOR_ATTRIBUTE void *operator new(size_t size) { OPERATOR_NEW_BODY(FROM_NEW); } CXX_OPERATOR_ATTRIBUTE void *operator new[](size_t size) { OPERATOR_NEW_BODY(FROM_NEW_BR); } CXX_OPERATOR_ATTRIBUTE void *operator new(size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY(FROM_NEW); } CXX_OPERATOR_ATTRIBUTE void *operator new[](size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY(FROM_NEW_BR); } #else // SANITIZER_MAC INTERCEPTOR(void *, _Znwm, size_t size) { OPERATOR_NEW_BODY(FROM_NEW); } INTERCEPTOR(void *, _Znam, size_t size) { OPERATOR_NEW_BODY(FROM_NEW_BR); } INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY(FROM_NEW); } INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY(FROM_NEW_BR); } #endif #define OPERATOR_DELETE_BODY(type) \ GET_STACK_TRACE_FREE;\ asan_free(ptr, &stack, type); #if !SANITIZER_MAC CXX_OPERATOR_ATTRIBUTE void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY(FROM_NEW); } CXX_OPERATOR_ATTRIBUTE void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY(FROM_NEW_BR); } CXX_OPERATOR_ATTRIBUTE void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY(FROM_NEW); } CXX_OPERATOR_ATTRIBUTE void operator delete[](void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY(FROM_NEW_BR); } CXX_OPERATOR_ATTRIBUTE void operator delete(void *ptr, size_t size) NOEXCEPT { GET_STACK_TRACE_FREE; asan_sized_free(ptr, size, &stack, FROM_NEW); } CXX_OPERATOR_ATTRIBUTE void operator delete[](void *ptr, size_t size) NOEXCEPT { GET_STACK_TRACE_FREE; asan_sized_free(ptr, size, &stack, FROM_NEW_BR); } #else // SANITIZER_MAC INTERCEPTOR(void, _ZdlPv, void *ptr) { OPERATOR_DELETE_BODY(FROM_NEW); } INTERCEPTOR(void, _ZdaPv, void *ptr) { OPERATOR_DELETE_BODY(FROM_NEW_BR); } INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY(FROM_NEW); } INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY(FROM_NEW_BR); } #endif Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_poisoning.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_poisoning.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_poisoning.cc (revision 305364) @@ -1,434 +1,434 @@ //===-- asan_poisoning.cc -------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // Shadow memory poisoning by ASan RTL and by user application. //===----------------------------------------------------------------------===// #include "asan_poisoning.h" #include "asan_report.h" #include "asan_stack.h" #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_flags.h" namespace __asan { static atomic_uint8_t can_poison_memory; void SetCanPoisonMemory(bool value) { atomic_store(&can_poison_memory, value, memory_order_release); } bool CanPoisonMemory() { return atomic_load(&can_poison_memory, memory_order_acquire); } void PoisonShadow(uptr addr, uptr size, u8 value) { if (!CanPoisonMemory()) return; CHECK(AddrIsAlignedByGranularity(addr)); CHECK(AddrIsInMem(addr)); CHECK(AddrIsAlignedByGranularity(addr + size)); CHECK(AddrIsInMem(addr + size - SHADOW_GRANULARITY)); CHECK(REAL(memset)); FastPoisonShadow(addr, size, value); } void PoisonShadowPartialRightRedzone(uptr addr, uptr size, uptr redzone_size, u8 value) { if (!CanPoisonMemory()) return; CHECK(AddrIsAlignedByGranularity(addr)); CHECK(AddrIsInMem(addr)); FastPoisonShadowPartialRightRedzone(addr, size, redzone_size, value); } struct ShadowSegmentEndpoint { u8 *chunk; s8 offset; // in [0, SHADOW_GRANULARITY) s8 value; // = *chunk; explicit ShadowSegmentEndpoint(uptr address) { chunk = (u8*)MemToShadow(address); offset = address & (SHADOW_GRANULARITY - 1); value = *chunk; } }; void FlushUnneededASanShadowMemory(uptr p, uptr size) { // Since asan's mapping is compacting, the shadow chunk may be // not page-aligned, so we only flush the page-aligned portion. uptr page_size = GetPageSizeCached(); uptr shadow_beg = RoundUpTo(MemToShadow(p), page_size); uptr shadow_end = RoundDownTo(MemToShadow(p + size), page_size); FlushUnneededShadowMemory(shadow_beg, shadow_end - shadow_beg); } void AsanPoisonOrUnpoisonIntraObjectRedzone(uptr ptr, uptr size, bool poison) { uptr end = ptr + size; if (Verbosity()) { Printf("__asan_%spoison_intra_object_redzone [%p,%p) %zd\n", poison ? "" : "un", ptr, end, size); if (Verbosity() >= 2) PRINT_CURRENT_STACK(); } CHECK(size); CHECK_LE(size, 4096); CHECK(IsAligned(end, SHADOW_GRANULARITY)); if (!IsAligned(ptr, SHADOW_GRANULARITY)) { *(u8 *)MemToShadow(ptr) = poison ? static_cast(ptr % SHADOW_GRANULARITY) : 0; ptr |= SHADOW_GRANULARITY - 1; ptr++; } for (; ptr < end; ptr += SHADOW_GRANULARITY) *(u8*)MemToShadow(ptr) = poison ? kAsanIntraObjectRedzone : 0; } } // namespace __asan // ---------------------- Interface ---------------- {{{1 using namespace __asan; // NOLINT // Current implementation of __asan_(un)poison_memory_region doesn't check // that user program (un)poisons the memory it owns. It poisons memory // conservatively, and unpoisons progressively to make sure asan shadow // mapping invariant is preserved (see detailed mapping description here: // https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm). // // * if user asks to poison region [left, right), the program poisons // at least [left, AlignDown(right)). // * if user asks to unpoison region [left, right), the program unpoisons // at most [AlignDown(left), right). void __asan_poison_memory_region(void const volatile *addr, uptr size) { if (!flags()->allow_user_poisoning || size == 0) return; uptr beg_addr = (uptr)addr; uptr end_addr = beg_addr + size; VPrintf(3, "Trying to poison memory region [%p, %p)\n", (void *)beg_addr, (void *)end_addr); ShadowSegmentEndpoint beg(beg_addr); ShadowSegmentEndpoint end(end_addr); if (beg.chunk == end.chunk) { CHECK(beg.offset < end.offset); s8 value = beg.value; CHECK(value == end.value); // We can only poison memory if the byte in end.offset is unaddressable. // No need to re-poison memory if it is poisoned already. if (value > 0 && value <= end.offset) { if (beg.offset > 0) { *beg.chunk = Min(value, beg.offset); } else { *beg.chunk = kAsanUserPoisonedMemoryMagic; } } return; } CHECK(beg.chunk < end.chunk); if (beg.offset > 0) { // Mark bytes from beg.offset as unaddressable. if (beg.value == 0) { *beg.chunk = beg.offset; } else { *beg.chunk = Min(beg.value, beg.offset); } beg.chunk++; } REAL(memset)(beg.chunk, kAsanUserPoisonedMemoryMagic, end.chunk - beg.chunk); // Poison if byte in end.offset is unaddressable. if (end.value > 0 && end.value <= end.offset) { *end.chunk = kAsanUserPoisonedMemoryMagic; } } void __asan_unpoison_memory_region(void const volatile *addr, uptr size) { if (!flags()->allow_user_poisoning || size == 0) return; uptr beg_addr = (uptr)addr; uptr end_addr = beg_addr + size; VPrintf(3, "Trying to unpoison memory region [%p, %p)\n", (void *)beg_addr, (void *)end_addr); ShadowSegmentEndpoint beg(beg_addr); ShadowSegmentEndpoint end(end_addr); if (beg.chunk == end.chunk) { CHECK(beg.offset < end.offset); s8 value = beg.value; CHECK(value == end.value); // We unpoison memory bytes up to enbytes up to end.offset if it is not // unpoisoned already. if (value != 0) { *beg.chunk = Max(value, end.offset); } return; } CHECK(beg.chunk < end.chunk); if (beg.offset > 0) { *beg.chunk = 0; beg.chunk++; } REAL(memset)(beg.chunk, 0, end.chunk - beg.chunk); if (end.offset > 0 && end.value != 0) { *end.chunk = Max(end.value, end.offset); } } int __asan_address_is_poisoned(void const volatile *addr) { return __asan::AddressIsPoisoned((uptr)addr); } uptr __asan_region_is_poisoned(uptr beg, uptr size) { if (!size) return 0; uptr end = beg + size; if (!AddrIsInMem(beg)) return beg; if (!AddrIsInMem(end)) return end; CHECK_LT(beg, end); uptr aligned_b = RoundUpTo(beg, SHADOW_GRANULARITY); uptr aligned_e = RoundDownTo(end, SHADOW_GRANULARITY); uptr shadow_beg = MemToShadow(aligned_b); uptr shadow_end = MemToShadow(aligned_e); // First check the first and the last application bytes, // then check the SHADOW_GRANULARITY-aligned region by calling // mem_is_zero on the corresponding shadow. if (!__asan::AddressIsPoisoned(beg) && !__asan::AddressIsPoisoned(end - 1) && (shadow_end <= shadow_beg || __sanitizer::mem_is_zero((const char *)shadow_beg, shadow_end - shadow_beg))) return 0; // The fast check failed, so we have a poisoned byte somewhere. // Find it slowly. for (; beg < end; beg++) if (__asan::AddressIsPoisoned(beg)) return beg; UNREACHABLE("mem_is_zero returned false, but poisoned byte was not found"); return 0; } #define CHECK_SMALL_REGION(p, size, isWrite) \ do { \ uptr __p = reinterpret_cast(p); \ uptr __size = size; \ if (UNLIKELY(__asan::AddressIsPoisoned(__p) || \ __asan::AddressIsPoisoned(__p + __size - 1))) { \ GET_CURRENT_PC_BP_SP; \ uptr __bad = __asan_region_is_poisoned(__p, __size); \ __asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0);\ } \ } while (false); \ extern "C" SANITIZER_INTERFACE_ATTRIBUTE u16 __sanitizer_unaligned_load16(const uu16 *p) { CHECK_SMALL_REGION(p, sizeof(*p), false); return *p; } extern "C" SANITIZER_INTERFACE_ATTRIBUTE u32 __sanitizer_unaligned_load32(const uu32 *p) { CHECK_SMALL_REGION(p, sizeof(*p), false); return *p; } extern "C" SANITIZER_INTERFACE_ATTRIBUTE u64 __sanitizer_unaligned_load64(const uu64 *p) { CHECK_SMALL_REGION(p, sizeof(*p), false); return *p; } extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_unaligned_store16(uu16 *p, u16 x) { CHECK_SMALL_REGION(p, sizeof(*p), true); *p = x; } extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_unaligned_store32(uu32 *p, u32 x) { CHECK_SMALL_REGION(p, sizeof(*p), true); *p = x; } extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_unaligned_store64(uu64 *p, u64 x) { CHECK_SMALL_REGION(p, sizeof(*p), true); *p = x; } extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __asan_poison_cxx_array_cookie(uptr p) { if (SANITIZER_WORDSIZE != 64) return; if (!flags()->poison_array_cookie) return; uptr s = MEM_TO_SHADOW(p); *reinterpret_cast(s) = kAsanArrayCookieMagic; } extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_load_cxx_array_cookie(uptr *p) { if (SANITIZER_WORDSIZE != 64) return *p; if (!flags()->poison_array_cookie) return *p; uptr s = MEM_TO_SHADOW(reinterpret_cast(p)); u8 sval = *reinterpret_cast(s); if (sval == kAsanArrayCookieMagic) return *p; // If sval is not kAsanArrayCookieMagic it can only be freed memory, // which means that we are going to get double-free. So, return 0 to avoid // infinite loop of destructors. We don't want to report a double-free here // though, so print a warning just in case. // CHECK_EQ(sval, kAsanHeapFreeMagic); if (sval == kAsanHeapFreeMagic) { Report("AddressSanitizer: loaded array cookie from free-d memory; " "expect a double-free report\n"); return 0; } // The cookie may remain unpoisoned if e.g. it comes from a custom // operator new defined inside a class. return *p; } // This is a simplified version of __asan_(un)poison_memory_region, which // assumes that left border of region to be poisoned is properly aligned. static void PoisonAlignedStackMemory(uptr addr, uptr size, bool do_poison) { if (size == 0) return; uptr aligned_size = size & ~(SHADOW_GRANULARITY - 1); PoisonShadow(addr, aligned_size, do_poison ? kAsanStackUseAfterScopeMagic : 0); if (size == aligned_size) return; s8 end_offset = (s8)(size - aligned_size); s8* shadow_end = (s8*)MemToShadow(addr + aligned_size); s8 end_value = *shadow_end; if (do_poison) { // If possible, mark all the bytes mapping to last shadow byte as // unaddressable. if (end_value > 0 && end_value <= end_offset) *shadow_end = (s8)kAsanStackUseAfterScopeMagic; } else { // If necessary, mark few first bytes mapping to last shadow byte // as addressable if (end_value != 0) *shadow_end = Max(end_value, end_offset); } } void __asan_poison_stack_memory(uptr addr, uptr size) { VReport(1, "poisoning: %p %zx\n", (void *)addr, size); PoisonAlignedStackMemory(addr, size, true); } void __asan_unpoison_stack_memory(uptr addr, uptr size) { VReport(1, "unpoisoning: %p %zx\n", (void *)addr, size); PoisonAlignedStackMemory(addr, size, false); } void __sanitizer_annotate_contiguous_container(const void *beg_p, const void *end_p, const void *old_mid_p, const void *new_mid_p) { if (!flags()->detect_container_overflow) return; VPrintf(2, "contiguous_container: %p %p %p %p\n", beg_p, end_p, old_mid_p, new_mid_p); uptr beg = reinterpret_cast(beg_p); uptr end = reinterpret_cast(end_p); uptr old_mid = reinterpret_cast(old_mid_p); uptr new_mid = reinterpret_cast(new_mid_p); uptr granularity = SHADOW_GRANULARITY; if (!(beg <= old_mid && beg <= new_mid && old_mid <= end && new_mid <= end && IsAligned(beg, granularity))) { GET_STACK_TRACE_FATAL_HERE; ReportBadParamsToAnnotateContiguousContainer(beg, end, old_mid, new_mid, &stack); } CHECK_LE(end - beg, - FIRST_32_SECOND_64(1UL << 30, 1UL << 34)); // Sanity check. + FIRST_32_SECOND_64(1UL << 30, 1ULL << 34)); // Sanity check. uptr a = RoundDownTo(Min(old_mid, new_mid), granularity); uptr c = RoundUpTo(Max(old_mid, new_mid), granularity); uptr d1 = RoundDownTo(old_mid, granularity); // uptr d2 = RoundUpTo(old_mid, granularity); // Currently we should be in this state: // [a, d1) is good, [d2, c) is bad, [d1, d2) is partially good. // Make a quick sanity check that we are indeed in this state. // // FIXME: Two of these three checks are disabled until we fix // https://github.com/google/sanitizers/issues/258. // if (d1 != d2) // CHECK_EQ(*(u8*)MemToShadow(d1), old_mid - d1); if (a + granularity <= d1) CHECK_EQ(*(u8*)MemToShadow(a), 0); // if (d2 + granularity <= c && c <= end) // CHECK_EQ(*(u8 *)MemToShadow(c - granularity), // kAsanContiguousContainerOOBMagic); uptr b1 = RoundDownTo(new_mid, granularity); uptr b2 = RoundUpTo(new_mid, granularity); // New state: // [a, b1) is good, [b2, c) is bad, [b1, b2) is partially good. PoisonShadow(a, b1 - a, 0); PoisonShadow(b2, c - b2, kAsanContiguousContainerOOBMagic); if (b1 != b2) { CHECK_EQ(b2 - b1, granularity); *(u8*)MemToShadow(b1) = static_cast(new_mid - b1); } } const void *__sanitizer_contiguous_container_find_bad_address( const void *beg_p, const void *mid_p, const void *end_p) { if (!flags()->detect_container_overflow) return nullptr; uptr beg = reinterpret_cast(beg_p); uptr end = reinterpret_cast(end_p); uptr mid = reinterpret_cast(mid_p); CHECK_LE(beg, mid); CHECK_LE(mid, end); // Check some bytes starting from beg, some bytes around mid, and some bytes // ending with end. uptr kMaxRangeToCheck = 32; uptr r1_beg = beg; uptr r1_end = Min(end + kMaxRangeToCheck, mid); uptr r2_beg = Max(beg, mid - kMaxRangeToCheck); uptr r2_end = Min(end, mid + kMaxRangeToCheck); uptr r3_beg = Max(end - kMaxRangeToCheck, mid); uptr r3_end = end; for (uptr i = r1_beg; i < r1_end; i++) if (AddressIsPoisoned(i)) return reinterpret_cast(i); for (uptr i = r2_beg; i < mid; i++) if (AddressIsPoisoned(i)) return reinterpret_cast(i); for (uptr i = mid; i < r2_end; i++) if (!AddressIsPoisoned(i)) return reinterpret_cast(i); for (uptr i = r3_beg; i < r3_end; i++) if (!AddressIsPoisoned(i)) return reinterpret_cast(i); return nullptr; } int __sanitizer_verify_contiguous_container(const void *beg_p, const void *mid_p, const void *end_p) { return __sanitizer_contiguous_container_find_bad_address(beg_p, mid_p, end_p) == nullptr; } extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __asan_poison_intra_object_redzone(uptr ptr, uptr size) { AsanPoisonOrUnpoisonIntraObjectRedzone(ptr, size, true); } extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __asan_unpoison_intra_object_redzone(uptr ptr, uptr size) { AsanPoisonOrUnpoisonIntraObjectRedzone(ptr, size, false); } // --- Implementation of LSan-specific functions --- {{{1 namespace __lsan { bool WordIsPoisoned(uptr addr) { return (__asan_region_is_poisoned(addr, sizeof(uptr)) != 0); } } Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_posix.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_posix.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_posix.cc (revision 305364) @@ -1,117 +1,126 @@ //===-- asan_posix.cc -----------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // Posix-specific details. //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_POSIX #include "asan_internal.h" #include "asan_interceptors.h" #include "asan_mapping.h" #include "asan_report.h" #include "asan_stack.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_posix.h" #include "sanitizer_common/sanitizer_procmaps.h" #include #include #include #include #include #include namespace __asan { void AsanOnDeadlySignal(int signo, void *siginfo, void *context) { ScopedDeadlySignal signal_scope(GetCurrentThread()); int code = (int)((siginfo_t*)siginfo)->si_code; - // Write the first message using the bullet-proof write. - if (18 != internal_write(2, "ASAN:DEADLYSIGNAL\n", 18)) Die(); + // Write the first message using fd=2, just in case. + // It may actually fail to write in case stderr is closed. + internal_write(2, "ASAN:DEADLYSIGNAL\n", 18); SignalContext sig = SignalContext::Create(siginfo, context); // Access at a reasonable offset above SP, or slightly below it (to account // for x86_64 or PowerPC redzone, ARM push of multiple registers, etc) is // probably a stack overflow. +#ifdef __s390__ + // On s390, the fault address in siginfo points to start of the page, not + // to the precise word that was accessed. Mask off the low bits of sp to + // take it into account. + bool IsStackAccess = sig.addr >= (sig.sp & ~0xFFF) && + sig.addr < sig.sp + 0xFFFF; +#else bool IsStackAccess = sig.addr + 512 > sig.sp && sig.addr < sig.sp + 0xFFFF; +#endif #if __powerpc__ // Large stack frames can be allocated with e.g. // lis r0,-10000 // stdux r1,r1,r0 # store sp to [sp-10000] and update sp by -10000 // If the store faults then sp will not have been updated, so test above // will not work, becase the fault address will be more than just "slightly" // below sp. if (!IsStackAccess && IsAccessibleMemoryRange(sig.pc, 4)) { u32 inst = *(unsigned *)sig.pc; u32 ra = (inst >> 16) & 0x1F; u32 opcd = inst >> 26; u32 xo = (inst >> 1) & 0x3FF; // Check for store-with-update to sp. The instructions we accept are: // stbu rs,d(ra) stbux rs,ra,rb // sthu rs,d(ra) sthux rs,ra,rb // stwu rs,d(ra) stwux rs,ra,rb // stdu rs,ds(ra) stdux rs,ra,rb // where ra is r1 (the stack pointer). if (ra == 1 && (opcd == 39 || opcd == 45 || opcd == 37 || opcd == 62 || (opcd == 31 && (xo == 247 || xo == 439 || xo == 183 || xo == 181)))) IsStackAccess = true; } #endif // __powerpc__ // We also check si_code to filter out SEGV caused by something else other // then hitting the guard page or unmapped memory, like, for example, // unaligned memory access. if (IsStackAccess && (code == si_SEGV_MAPERR || code == si_SEGV_ACCERR)) ReportStackOverflow(sig); else if (signo == SIGFPE) ReportDeadlySignal("FPE", sig); else if (signo == SIGILL) ReportDeadlySignal("ILL", sig); else ReportDeadlySignal("SEGV", sig); } // ---------------------- TSD ---------------- {{{1 static pthread_key_t tsd_key; static bool tsd_key_inited = false; void AsanTSDInit(void (*destructor)(void *tsd)) { CHECK(!tsd_key_inited); tsd_key_inited = true; CHECK_EQ(0, pthread_key_create(&tsd_key, destructor)); } void *AsanTSDGet() { CHECK(tsd_key_inited); return pthread_getspecific(tsd_key); } void AsanTSDSet(void *tsd) { CHECK(tsd_key_inited); pthread_setspecific(tsd_key, tsd); } void PlatformTSDDtor(void *tsd) { AsanThreadContext *context = (AsanThreadContext*)tsd; if (context->destructor_iterations > 1) { context->destructor_iterations--; CHECK_EQ(0, pthread_setspecific(tsd_key, tsd)); return; } AsanThread::TSDDtor(tsd); } } // namespace __asan #endif // SANITIZER_POSIX Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_report.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_report.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_report.cc (revision 305364) @@ -1,1185 +1,1273 @@ //===-- asan_report.cc ----------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // This file contains error reporting code. //===----------------------------------------------------------------------===// #include "asan_flags.h" #include "asan_internal.h" #include "asan_mapping.h" #include "asan_report.h" +#include "asan_scariness_score.h" #include "asan_stack.h" #include "asan_thread.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_report_decorator.h" #include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_symbolizer.h" namespace __asan { // -------------------- User-specified callbacks ----------------- {{{1 static void (*error_report_callback)(const char*); static char *error_message_buffer = nullptr; static uptr error_message_buffer_pos = 0; static BlockingMutex error_message_buf_mutex(LINKER_INITIALIZED); static const unsigned kAsanBuggyPcPoolSize = 25; static __sanitizer::atomic_uintptr_t AsanBuggyPcPool[kAsanBuggyPcPoolSize]; struct ReportData { uptr pc; uptr sp; uptr bp; uptr addr; bool is_write; uptr access_size; const char *description; }; static bool report_happened = false; static ReportData report_data = {}; void AppendToErrorMessageBuffer(const char *buffer) { BlockingMutexLock l(&error_message_buf_mutex); if (!error_message_buffer) { error_message_buffer = (char*)MmapOrDieQuietly(kErrorMessageBufferSize, __func__); error_message_buffer_pos = 0; } uptr length = internal_strlen(buffer); RAW_CHECK(kErrorMessageBufferSize >= error_message_buffer_pos); uptr remaining = kErrorMessageBufferSize - error_message_buffer_pos; internal_strncpy(error_message_buffer + error_message_buffer_pos, buffer, remaining); error_message_buffer[kErrorMessageBufferSize - 1] = '\0'; // FIXME: reallocate the buffer instead of truncating the message. error_message_buffer_pos += Min(remaining, length); } // ---------------------- Decorator ------------------------------ {{{1 class Decorator: public __sanitizer::SanitizerCommonDecorator { public: Decorator() : SanitizerCommonDecorator() { } const char *Access() { return Blue(); } const char *EndAccess() { return Default(); } const char *Location() { return Green(); } const char *EndLocation() { return Default(); } const char *Allocation() { return Magenta(); } const char *EndAllocation() { return Default(); } const char *ShadowByte(u8 byte) { switch (byte) { case kAsanHeapLeftRedzoneMagic: case kAsanHeapRightRedzoneMagic: case kAsanArrayCookieMagic: return Red(); case kAsanHeapFreeMagic: return Magenta(); case kAsanStackLeftRedzoneMagic: case kAsanStackMidRedzoneMagic: case kAsanStackRightRedzoneMagic: case kAsanStackPartialRedzoneMagic: return Red(); case kAsanStackAfterReturnMagic: return Magenta(); case kAsanInitializationOrderMagic: return Cyan(); case kAsanUserPoisonedMemoryMagic: case kAsanContiguousContainerOOBMagic: case kAsanAllocaLeftMagic: case kAsanAllocaRightMagic: return Blue(); case kAsanStackUseAfterScopeMagic: return Magenta(); case kAsanGlobalRedzoneMagic: return Red(); case kAsanInternalHeapMagic: return Yellow(); case kAsanIntraObjectRedzone: return Yellow(); default: return Default(); } } const char *EndShadowByte() { return Default(); } const char *MemoryByte() { return Magenta(); } const char *EndMemoryByte() { return Default(); } }; // ---------------------- Helper functions ----------------------- {{{1 static void PrintMemoryByte(InternalScopedString *str, const char *before, u8 byte, bool in_shadow, const char *after = "\n") { Decorator d; str->append("%s%s%x%x%s%s", before, in_shadow ? d.ShadowByte(byte) : d.MemoryByte(), byte >> 4, byte & 15, in_shadow ? d.EndShadowByte() : d.EndMemoryByte(), after); } static void PrintShadowByte(InternalScopedString *str, const char *before, u8 byte, const char *after = "\n") { PrintMemoryByte(str, before, byte, /*in_shadow*/true, after); } static void PrintShadowBytes(InternalScopedString *str, const char *before, u8 *bytes, u8 *guilty, uptr n) { Decorator d; if (before) str->append("%s%p:", before, bytes); for (uptr i = 0; i < n; i++) { u8 *p = bytes + i; const char *before = p == guilty ? "[" : (p - 1 == guilty && i != 0) ? "" : " "; const char *after = p == guilty ? "]" : ""; PrintShadowByte(str, before, *p, after); } str->append("\n"); } static void PrintLegend(InternalScopedString *str) { str->append( "Shadow byte legend (one shadow byte represents %d " "application bytes):\n", (int)SHADOW_GRANULARITY); PrintShadowByte(str, " Addressable: ", 0); str->append(" Partially addressable: "); for (u8 i = 1; i < SHADOW_GRANULARITY; i++) PrintShadowByte(str, "", i, " "); str->append("\n"); PrintShadowByte(str, " Heap left redzone: ", kAsanHeapLeftRedzoneMagic); PrintShadowByte(str, " Heap right redzone: ", kAsanHeapRightRedzoneMagic); PrintShadowByte(str, " Freed heap region: ", kAsanHeapFreeMagic); PrintShadowByte(str, " Stack left redzone: ", kAsanStackLeftRedzoneMagic); PrintShadowByte(str, " Stack mid redzone: ", kAsanStackMidRedzoneMagic); PrintShadowByte(str, " Stack right redzone: ", kAsanStackRightRedzoneMagic); PrintShadowByte(str, " Stack partial redzone: ", kAsanStackPartialRedzoneMagic); PrintShadowByte(str, " Stack after return: ", kAsanStackAfterReturnMagic); PrintShadowByte(str, " Stack use after scope: ", kAsanStackUseAfterScopeMagic); PrintShadowByte(str, " Global redzone: ", kAsanGlobalRedzoneMagic); PrintShadowByte(str, " Global init order: ", kAsanInitializationOrderMagic); PrintShadowByte(str, " Poisoned by user: ", kAsanUserPoisonedMemoryMagic); PrintShadowByte(str, " Container overflow: ", kAsanContiguousContainerOOBMagic); PrintShadowByte(str, " Array cookie: ", kAsanArrayCookieMagic); PrintShadowByte(str, " Intra object redzone: ", kAsanIntraObjectRedzone); PrintShadowByte(str, " ASan internal: ", kAsanInternalHeapMagic); PrintShadowByte(str, " Left alloca redzone: ", kAsanAllocaLeftMagic); PrintShadowByte(str, " Right alloca redzone: ", kAsanAllocaRightMagic); } void MaybeDumpInstructionBytes(uptr pc) { if (!flags()->dump_instruction_bytes || (pc < GetPageSizeCached())) return; InternalScopedString str(1024); str.append("First 16 instruction bytes at pc: "); if (IsAccessibleMemoryRange(pc, 16)) { for (int i = 0; i < 16; ++i) { PrintMemoryByte(&str, "", ((u8 *)pc)[i], /*in_shadow*/false, " "); } str.append("\n"); } else { str.append("unaccessible\n"); } Report("%s", str.data()); } static void PrintShadowMemoryForAddress(uptr addr) { if (!AddrIsInMem(addr)) return; uptr shadow_addr = MemToShadow(addr); const uptr n_bytes_per_row = 16; uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1); InternalScopedString str(4096 * 8); str.append("Shadow bytes around the buggy address:\n"); for (int i = -5; i <= 5; i++) { const char *prefix = (i == 0) ? "=>" : " "; PrintShadowBytes(&str, prefix, (u8 *)(aligned_shadow + i * n_bytes_per_row), (u8 *)shadow_addr, n_bytes_per_row); } if (flags()->print_legend) PrintLegend(&str); Printf("%s", str.data()); } static void PrintZoneForPointer(uptr ptr, uptr zone_ptr, const char *zone_name) { if (zone_ptr) { if (zone_name) { Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n", ptr, zone_ptr, zone_name); } else { Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n", ptr, zone_ptr); } } else { Printf("malloc_zone_from_ptr(%p) = 0\n", ptr); } } static void DescribeThread(AsanThread *t) { if (t) DescribeThread(t->context()); } // ---------------------- Address Descriptions ------------------- {{{1 static bool IsASCII(unsigned char c) { return /*0x00 <= c &&*/ c <= 0x7F; } static const char *MaybeDemangleGlobalName(const char *name) { // We can spoil names of globals with C linkage, so use an heuristic // approach to check if the name should be demangled. bool should_demangle = false; if (name[0] == '_' && name[1] == 'Z') should_demangle = true; else if (SANITIZER_WINDOWS && name[0] == '\01' && name[1] == '?') should_demangle = true; return should_demangle ? Symbolizer::GetOrInit()->Demangle(name) : name; } // Check if the global is a zero-terminated ASCII string. If so, print it. static void PrintGlobalNameIfASCII(InternalScopedString *str, const __asan_global &g) { for (uptr p = g.beg; p < g.beg + g.size - 1; p++) { unsigned char c = *(unsigned char*)p; if (c == '\0' || !IsASCII(c)) return; } if (*(char*)(g.beg + g.size - 1) != '\0') return; str->append(" '%s' is ascii string '%s'\n", MaybeDemangleGlobalName(g.name), (char *)g.beg); } static const char *GlobalFilename(const __asan_global &g) { const char *res = g.module_name; // Prefer the filename from source location, if is available. if (g.location) res = g.location->filename; CHECK(res); return res; } static void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g) { str->append("%s", GlobalFilename(g)); if (!g.location) return; if (g.location->line_no) str->append(":%d", g.location->line_no); if (g.location->column_no) str->append(":%d", g.location->column_no); } static void DescribeAddressRelativeToGlobal(uptr addr, uptr size, const __asan_global &g) { InternalScopedString str(4096); Decorator d; str.append("%s", d.Location()); if (addr < g.beg) { str.append("%p is located %zd bytes to the left", (void *)addr, g.beg - addr); } else if (addr + size > g.beg + g.size) { if (addr < g.beg + g.size) addr = g.beg + g.size; str.append("%p is located %zd bytes to the right", (void *)addr, addr - (g.beg + g.size)); } else { // Can it happen? str.append("%p is located %zd bytes inside", (void *)addr, addr - g.beg); } str.append(" of global variable '%s' defined in '", MaybeDemangleGlobalName(g.name)); PrintGlobalLocation(&str, g); str.append("' (0x%zx) of size %zu\n", g.beg, g.size); str.append("%s", d.EndLocation()); PrintGlobalNameIfASCII(&str, g); Printf("%s", str.data()); } static bool DescribeAddressIfGlobal(uptr addr, uptr size, const char *bug_type) { // Assume address is close to at most four globals. const int kMaxGlobalsInReport = 4; __asan_global globals[kMaxGlobalsInReport]; u32 reg_sites[kMaxGlobalsInReport]; int globals_num = GetGlobalsForAddress(addr, globals, reg_sites, ARRAY_SIZE(globals)); if (globals_num == 0) return false; for (int i = 0; i < globals_num; i++) { DescribeAddressRelativeToGlobal(addr, size, globals[i]); if (0 == internal_strcmp(bug_type, "initialization-order-fiasco") && reg_sites[i]) { Printf(" registered at:\n"); StackDepotGet(reg_sites[i]).Print(); } } return true; } bool DescribeAddressIfShadow(uptr addr, AddressDescription *descr, bool print) { if (AddrIsInMem(addr)) return false; const char *area_type = nullptr; if (AddrIsInShadowGap(addr)) area_type = "shadow gap"; else if (AddrIsInHighShadow(addr)) area_type = "high shadow"; else if (AddrIsInLowShadow(addr)) area_type = "low shadow"; if (area_type != nullptr) { if (print) { Printf("Address %p is located in the %s area.\n", addr, area_type); } else { CHECK(descr); descr->region_kind = area_type; } return true; } CHECK(0 && "Address is not in memory and not in shadow?"); return false; } // Return " (thread_name) " or an empty string if the name is empty. const char *ThreadNameWithParenthesis(AsanThreadContext *t, char buff[], uptr buff_len) { const char *name = t->name; if (name[0] == '\0') return ""; buff[0] = 0; internal_strncat(buff, " (", 3); internal_strncat(buff, name, buff_len - 4); internal_strncat(buff, ")", 2); return buff; } const char *ThreadNameWithParenthesis(u32 tid, char buff[], uptr buff_len) { if (tid == kInvalidTid) return ""; asanThreadRegistry().CheckLocked(); AsanThreadContext *t = GetThreadContextByTidLocked(tid); return ThreadNameWithParenthesis(t, buff, buff_len); } static void PrintAccessAndVarIntersection(const StackVarDescr &var, uptr addr, uptr access_size, uptr prev_var_end, uptr next_var_beg) { uptr var_end = var.beg + var.size; uptr addr_end = addr + access_size; const char *pos_descr = nullptr; // If the variable [var.beg, var_end) is the nearest variable to the // current memory access, indicate it in the log. if (addr >= var.beg) { if (addr_end <= var_end) pos_descr = "is inside"; // May happen if this is a use-after-return. else if (addr < var_end) pos_descr = "partially overflows"; else if (addr_end <= next_var_beg && next_var_beg - addr_end >= addr - var_end) pos_descr = "overflows"; } else { if (addr_end > var.beg) pos_descr = "partially underflows"; else if (addr >= prev_var_end && addr - prev_var_end >= var.beg - addr_end) pos_descr = "underflows"; } InternalScopedString str(1024); str.append(" [%zd, %zd)", var.beg, var_end); // Render variable name. str.append(" '"); for (uptr i = 0; i < var.name_len; ++i) { str.append("%c", var.name_pos[i]); } str.append("'"); if (pos_descr) { Decorator d; // FIXME: we may want to also print the size of the access here, // but in case of accesses generated by memset it may be confusing. str.append("%s <== Memory access at offset %zd %s this variable%s\n", d.Location(), addr, pos_descr, d.EndLocation()); } else { str.append("\n"); } Printf("%s", str.data()); } bool ParseFrameDescription(const char *frame_descr, InternalMmapVector *vars) { CHECK(frame_descr); char *p; // This string is created by the compiler and has the following form: // "n alloc_1 alloc_2 ... alloc_n" // where alloc_i looks like "offset size len ObjectName". uptr n_objects = (uptr)internal_simple_strtoll(frame_descr, &p, 10); if (n_objects == 0) return false; for (uptr i = 0; i < n_objects; i++) { uptr beg = (uptr)internal_simple_strtoll(p, &p, 10); uptr size = (uptr)internal_simple_strtoll(p, &p, 10); uptr len = (uptr)internal_simple_strtoll(p, &p, 10); if (beg == 0 || size == 0 || *p != ' ') { return false; } p++; StackVarDescr var = {beg, size, p, len}; vars->push_back(var); p += len; } return true; } bool DescribeAddressIfStack(uptr addr, uptr access_size) { AsanThread *t = FindThreadByStackAddress(addr); if (!t) return false; Decorator d; char tname[128]; Printf("%s", d.Location()); Printf("Address %p is located in stack of thread T%d%s", addr, t->tid(), ThreadNameWithParenthesis(t->tid(), tname, sizeof(tname))); // Try to fetch precise stack frame for this access. AsanThread::StackFrameAccess access; if (!t->GetStackFrameAccessByAddr(addr, &access)) { Printf("%s\n", d.EndLocation()); return true; } Printf(" at offset %zu in frame%s\n", access.offset, d.EndLocation()); // Now we print the frame where the alloca has happened. // We print this frame as a stack trace with one element. // The symbolizer may print more than one frame if inlining was involved. // The frame numbers may be different than those in the stack trace printed // previously. That's unfortunate, but I have no better solution, // especially given that the alloca may be from entirely different place // (e.g. use-after-scope, or different thread's stack). -#if defined(__powerpc64__) && defined(__BIG_ENDIAN__) +#if SANITIZER_PPC64V1 // On PowerPC64 ELFv1, the address of a function actually points to a // three-doubleword data structure with the first field containing // the address of the function's code. access.frame_pc = *reinterpret_cast(access.frame_pc); #endif access.frame_pc += 16; Printf("%s", d.EndLocation()); StackTrace alloca_stack(&access.frame_pc, 1); alloca_stack.Print(); InternalMmapVector vars(16); if (!ParseFrameDescription(access.frame_descr, &vars)) { Printf("AddressSanitizer can't parse the stack frame " "descriptor: |%s|\n", access.frame_descr); // 'addr' is a stack address, so return true even if we can't parse frame return true; } uptr n_objects = vars.size(); // Report the number of stack objects. Printf(" This frame has %zu object(s):\n", n_objects); // Report all objects in this frame. for (uptr i = 0; i < n_objects; i++) { uptr prev_var_end = i ? vars[i - 1].beg + vars[i - 1].size : 0; uptr next_var_beg = i + 1 < n_objects ? vars[i + 1].beg : ~(0UL); PrintAccessAndVarIntersection(vars[i], access.offset, access_size, prev_var_end, next_var_beg); } Printf("HINT: this may be a false positive if your program uses " "some custom stack unwind mechanism or swapcontext\n"); if (SANITIZER_WINDOWS) Printf(" (longjmp, SEH and C++ exceptions *are* supported)\n"); else Printf(" (longjmp and C++ exceptions *are* supported)\n"); DescribeThread(t); return true; } static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr, uptr access_size) { sptr offset; Decorator d; InternalScopedString str(4096); str.append("%s", d.Location()); if (chunk.AddrIsAtLeft(addr, access_size, &offset)) { str.append("%p is located %zd bytes to the left of", (void *)addr, offset); } else if (chunk.AddrIsAtRight(addr, access_size, &offset)) { if (offset < 0) { addr -= offset; offset = 0; } str.append("%p is located %zd bytes to the right of", (void *)addr, offset); } else if (chunk.AddrIsInside(addr, access_size, &offset)) { str.append("%p is located %zd bytes inside of", (void*)addr, offset); } else { str.append("%p is located somewhere around (this is AddressSanitizer bug!)", (void *)addr); } str.append(" %zu-byte region [%p,%p)\n", chunk.UsedSize(), (void *)(chunk.Beg()), (void *)(chunk.End())); str.append("%s", d.EndLocation()); Printf("%s", str.data()); } void DescribeHeapAddress(uptr addr, uptr access_size) { AsanChunkView chunk = FindHeapChunkByAddress(addr); if (!chunk.IsValid()) { Printf("AddressSanitizer can not describe address in more detail " "(wild memory access suspected).\n"); return; } DescribeAccessToHeapChunk(chunk, addr, access_size); CHECK(chunk.AllocTid() != kInvalidTid); asanThreadRegistry().CheckLocked(); AsanThreadContext *alloc_thread = GetThreadContextByTidLocked(chunk.AllocTid()); StackTrace alloc_stack = chunk.GetAllocStack(); char tname[128]; Decorator d; AsanThreadContext *free_thread = nullptr; if (chunk.FreeTid() != kInvalidTid) { free_thread = GetThreadContextByTidLocked(chunk.FreeTid()); Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(), free_thread->tid, ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)), d.EndAllocation()); StackTrace free_stack = chunk.GetFreeStack(); free_stack.Print(); Printf("%spreviously allocated by thread T%d%s here:%s\n", d.Allocation(), alloc_thread->tid, ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)), d.EndAllocation()); } else { Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(), alloc_thread->tid, ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)), d.EndAllocation()); } alloc_stack.Print(); DescribeThread(GetCurrentThread()); if (free_thread) DescribeThread(free_thread); DescribeThread(alloc_thread); } static void DescribeAddress(uptr addr, uptr access_size, const char *bug_type) { // Check if this is shadow or shadow gap. if (DescribeAddressIfShadow(addr)) return; CHECK(AddrIsInMem(addr)); if (DescribeAddressIfGlobal(addr, access_size, bug_type)) return; if (DescribeAddressIfStack(addr, access_size)) return; // Assume it is a heap address. DescribeHeapAddress(addr, access_size); } // ------------------- Thread description -------------------- {{{1 void DescribeThread(AsanThreadContext *context) { CHECK(context); asanThreadRegistry().CheckLocked(); // No need to announce the main thread. if (context->tid == 0 || context->announced) { return; } context->announced = true; char tname[128]; InternalScopedString str(1024); str.append("Thread T%d%s", context->tid, ThreadNameWithParenthesis(context->tid, tname, sizeof(tname))); if (context->parent_tid == kInvalidTid) { str.append(" created by unknown thread\n"); Printf("%s", str.data()); return; } str.append( " created by T%d%s here:\n", context->parent_tid, ThreadNameWithParenthesis(context->parent_tid, tname, sizeof(tname))); Printf("%s", str.data()); StackDepotGet(context->stack_id).Print(); // Recursively described parent thread if needed. if (flags()->print_full_thread_history) { AsanThreadContext *parent_context = GetThreadContextByTidLocked(context->parent_tid); DescribeThread(parent_context); } } // -------------------- Different kinds of reports ----------------- {{{1 // Use ScopedInErrorReport to run common actions just before and // immediately after printing error report. class ScopedInErrorReport { public: explicit ScopedInErrorReport(ReportData *report = nullptr, bool fatal = false) { halt_on_error_ = fatal || flags()->halt_on_error; if (lock_.TryLock()) { StartReporting(report); return; } // ASan found two bugs in different threads simultaneously. u32 current_tid = GetCurrentTidOrInvalid(); if (reporting_thread_tid_ == current_tid || reporting_thread_tid_ == kInvalidTid) { // This is either asynch signal or nested error during error reporting. // Fail simple to avoid deadlocks in Report(). // Can't use Report() here because of potential deadlocks // in nested signal handlers. const char msg[] = "AddressSanitizer: nested bug in the same thread, " "aborting.\n"; WriteToFile(kStderrFd, msg, sizeof(msg)); internal__exit(common_flags()->exitcode); } if (halt_on_error_) { // Do not print more than one report, otherwise they will mix up. // Error reporting functions shouldn't return at this situation, as // they are effectively no-returns. Report("AddressSanitizer: while reporting a bug found another one. " "Ignoring.\n"); // Sleep long enough to make sure that the thread which started // to print an error report will finish doing it. SleepForSeconds(Max(100, flags()->sleep_before_dying + 1)); // If we're still not dead for some reason, use raw _exit() instead of // Die() to bypass any additional checks. internal__exit(common_flags()->exitcode); } else { // The other thread will eventually finish reporting // so it's safe to wait lock_.Lock(); } StartReporting(report); } ~ScopedInErrorReport() { // Make sure the current thread is announced. DescribeThread(GetCurrentThread()); // We may want to grab this lock again when printing stats. asanThreadRegistry().Unlock(); // Print memory stats. if (flags()->print_stats) __asan_print_accumulated_stats(); + if (common_flags()->print_cmdline) + PrintCmdline(); + // Copy the message buffer so that we could start logging without holding a // lock that gets aquired during printing. InternalScopedBuffer buffer_copy(kErrorMessageBufferSize); { BlockingMutexLock l(&error_message_buf_mutex); internal_memcpy(buffer_copy.data(), error_message_buffer, kErrorMessageBufferSize); } LogFullErrorReport(buffer_copy.data()); if (error_report_callback) { error_report_callback(buffer_copy.data()); } CommonSanitizerReportMutex.Unlock(); reporting_thread_tid_ = kInvalidTid; lock_.Unlock(); if (halt_on_error_) { Report("ABORTING\n"); Die(); } } private: void StartReporting(ReportData *report) { if (report) report_data = *report; report_happened = true; ASAN_ON_ERROR(); // Make sure the registry and sanitizer report mutexes are locked while // we're printing an error report. // We can lock them only here to avoid self-deadlock in case of // recursive reports. asanThreadRegistry().Lock(); CommonSanitizerReportMutex.Lock(); reporting_thread_tid_ = GetCurrentTidOrInvalid(); Printf("====================================================" "=============\n"); } static StaticSpinMutex lock_; static u32 reporting_thread_tid_; bool halt_on_error_; }; StaticSpinMutex ScopedInErrorReport::lock_; -u32 ScopedInErrorReport::reporting_thread_tid_; +u32 ScopedInErrorReport::reporting_thread_tid_ = kInvalidTid; void ReportStackOverflow(const SignalContext &sig) { - ScopedInErrorReport in_report; + ScopedInErrorReport in_report(/*report*/ nullptr, /*fatal*/ true); Decorator d; Printf("%s", d.Warning()); Report( "ERROR: AddressSanitizer: stack-overflow on address %p" " (pc %p bp %p sp %p T%d)\n", (void *)sig.addr, (void *)sig.pc, (void *)sig.bp, (void *)sig.sp, GetCurrentTidOrInvalid()); Printf("%s", d.EndWarning()); + ScarinessScore::PrintSimple(10, "stack-overflow"); GET_STACK_TRACE_SIGNAL(sig); stack.Print(); ReportErrorSummary("stack-overflow", &stack); } void ReportDeadlySignal(const char *description, const SignalContext &sig) { - ScopedInErrorReport in_report(/*report*/nullptr, /*fatal*/true); + ScopedInErrorReport in_report(/*report*/ nullptr, /*fatal*/ true); Decorator d; Printf("%s", d.Warning()); Report( "ERROR: AddressSanitizer: %s on unknown address %p" " (pc %p bp %p sp %p T%d)\n", description, (void *)sig.addr, (void *)sig.pc, (void *)sig.bp, (void *)sig.sp, GetCurrentTidOrInvalid()); - if (sig.pc < GetPageSizeCached()) { + Printf("%s", d.EndWarning()); + ScarinessScore SS; + if (sig.pc < GetPageSizeCached()) Report("Hint: pc points to the zero page.\n"); + if (sig.is_memory_access) { + const char *access_type = + sig.write_flag == SignalContext::WRITE + ? "WRITE" + : (sig.write_flag == SignalContext::READ ? "READ" : "UNKNOWN"); + Report("The signal is caused by a %s memory access.\n", access_type); + if (sig.addr < GetPageSizeCached()) { + Report("Hint: address points to the zero page.\n"); + SS.Scare(10, "null-deref"); + } else if (sig.addr == sig.pc) { + SS.Scare(60, "wild-jump"); + } else if (sig.write_flag == SignalContext::WRITE) { + SS.Scare(30, "wild-addr-write"); + } else if (sig.write_flag == SignalContext::READ) { + SS.Scare(20, "wild-addr-read"); + } else { + SS.Scare(25, "wild-addr"); + } + } else { + SS.Scare(10, "signal"); } - Printf("%s", d.EndWarning()); + SS.Print(); GET_STACK_TRACE_SIGNAL(sig); stack.Print(); MaybeDumpInstructionBytes(sig.pc); Printf("AddressSanitizer can not provide additional info.\n"); ReportErrorSummary(description, &stack); } void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) { ScopedInErrorReport in_report; Decorator d; Printf("%s", d.Warning()); char tname[128]; u32 curr_tid = GetCurrentTidOrInvalid(); Report("ERROR: AddressSanitizer: attempting double-free on %p in " "thread T%d%s:\n", addr, curr_tid, ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname))); Printf("%s", d.EndWarning()); CHECK_GT(free_stack->size, 0); + ScarinessScore::PrintSimple(42, "double-free"); GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp); stack.Print(); DescribeHeapAddress(addr, 1); ReportErrorSummary("double-free", &stack); } -void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size, +void ReportNewDeleteSizeMismatch(uptr addr, uptr alloc_size, uptr delete_size, BufferedStackTrace *free_stack) { ScopedInErrorReport in_report; Decorator d; Printf("%s", d.Warning()); char tname[128]; u32 curr_tid = GetCurrentTidOrInvalid(); Report("ERROR: AddressSanitizer: new-delete-type-mismatch on %p in " "thread T%d%s:\n", addr, curr_tid, ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname))); Printf("%s object passed to delete has wrong type:\n", d.EndWarning()); Printf(" size of the allocated type: %zd bytes;\n" " size of the deallocated type: %zd bytes.\n", - asan_mz_size(reinterpret_cast(addr)), delete_size); + alloc_size, delete_size); CHECK_GT(free_stack->size, 0); + ScarinessScore::PrintSimple(10, "new-delete-type-mismatch"); GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp); stack.Print(); DescribeHeapAddress(addr, 1); ReportErrorSummary("new-delete-type-mismatch", &stack); Report("HINT: if you don't care about these errors you may set " "ASAN_OPTIONS=new_delete_type_mismatch=0\n"); } void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack) { ScopedInErrorReport in_report; Decorator d; Printf("%s", d.Warning()); char tname[128]; u32 curr_tid = GetCurrentTidOrInvalid(); Report("ERROR: AddressSanitizer: attempting free on address " "which was not malloc()-ed: %p in thread T%d%s\n", addr, curr_tid, ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname))); Printf("%s", d.EndWarning()); CHECK_GT(free_stack->size, 0); + ScarinessScore::PrintSimple(40, "bad-free"); GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp); stack.Print(); DescribeHeapAddress(addr, 1); ReportErrorSummary("bad-free", &stack); } void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack, AllocType alloc_type, AllocType dealloc_type) { static const char *alloc_names[] = {"INVALID", "malloc", "operator new", "operator new []"}; static const char *dealloc_names[] = {"INVALID", "free", "operator delete", "operator delete []"}; CHECK_NE(alloc_type, dealloc_type); ScopedInErrorReport in_report; Decorator d; Printf("%s", d.Warning()); Report("ERROR: AddressSanitizer: alloc-dealloc-mismatch (%s vs %s) on %p\n", alloc_names[alloc_type], dealloc_names[dealloc_type], addr); Printf("%s", d.EndWarning()); CHECK_GT(free_stack->size, 0); + ScarinessScore::PrintSimple(10, "alloc-dealloc-mismatch"); GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp); stack.Print(); DescribeHeapAddress(addr, 1); ReportErrorSummary("alloc-dealloc-mismatch", &stack); Report("HINT: if you don't care about these errors you may set " "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n"); } void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack) { ScopedInErrorReport in_report; Decorator d; Printf("%s", d.Warning()); Report("ERROR: AddressSanitizer: attempting to call " "malloc_usable_size() for pointer which is " "not owned: %p\n", addr); Printf("%s", d.EndWarning()); stack->Print(); DescribeHeapAddress(addr, 1); ReportErrorSummary("bad-malloc_usable_size", stack); } void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr, BufferedStackTrace *stack) { ScopedInErrorReport in_report; Decorator d; Printf("%s", d.Warning()); Report("ERROR: AddressSanitizer: attempting to call " "__sanitizer_get_allocated_size() for pointer which is " "not owned: %p\n", addr); Printf("%s", d.EndWarning()); stack->Print(); DescribeHeapAddress(addr, 1); ReportErrorSummary("bad-__sanitizer_get_allocated_size", stack); } void ReportStringFunctionMemoryRangesOverlap(const char *function, const char *offset1, uptr length1, const char *offset2, uptr length2, BufferedStackTrace *stack) { ScopedInErrorReport in_report; Decorator d; char bug_type[100]; internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function); Printf("%s", d.Warning()); Report("ERROR: AddressSanitizer: %s: " "memory ranges [%p,%p) and [%p, %p) overlap\n", \ bug_type, offset1, offset1 + length1, offset2, offset2 + length2); Printf("%s", d.EndWarning()); + ScarinessScore::PrintSimple(10, bug_type); stack->Print(); DescribeAddress((uptr)offset1, length1, bug_type); DescribeAddress((uptr)offset2, length2, bug_type); ReportErrorSummary(bug_type, stack); } void ReportStringFunctionSizeOverflow(uptr offset, uptr size, BufferedStackTrace *stack) { ScopedInErrorReport in_report; Decorator d; const char *bug_type = "negative-size-param"; Printf("%s", d.Warning()); Report("ERROR: AddressSanitizer: %s: (size=%zd)\n", bug_type, size); Printf("%s", d.EndWarning()); + ScarinessScore::PrintSimple(10, bug_type); stack->Print(); DescribeAddress(offset, size, bug_type); ReportErrorSummary(bug_type, stack); } void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end, uptr old_mid, uptr new_mid, BufferedStackTrace *stack) { ScopedInErrorReport in_report; Report("ERROR: AddressSanitizer: bad parameters to " "__sanitizer_annotate_contiguous_container:\n" " beg : %p\n" " end : %p\n" " old_mid : %p\n" " new_mid : %p\n", beg, end, old_mid, new_mid); uptr granularity = SHADOW_GRANULARITY; if (!IsAligned(beg, granularity)) Report("ERROR: beg is not aligned by %d\n", granularity); stack->Print(); ReportErrorSummary("bad-__sanitizer_annotate_contiguous_container", stack); } void ReportODRViolation(const __asan_global *g1, u32 stack_id1, const __asan_global *g2, u32 stack_id2) { ScopedInErrorReport in_report; Decorator d; Printf("%s", d.Warning()); Report("ERROR: AddressSanitizer: odr-violation (%p):\n", g1->beg); Printf("%s", d.EndWarning()); InternalScopedString g1_loc(256), g2_loc(256); PrintGlobalLocation(&g1_loc, *g1); PrintGlobalLocation(&g2_loc, *g2); Printf(" [1] size=%zd '%s' %s\n", g1->size, MaybeDemangleGlobalName(g1->name), g1_loc.data()); Printf(" [2] size=%zd '%s' %s\n", g2->size, MaybeDemangleGlobalName(g2->name), g2_loc.data()); if (stack_id1 && stack_id2) { Printf("These globals were registered at these points:\n"); Printf(" [1]:\n"); StackDepotGet(stack_id1).Print(); Printf(" [2]:\n"); StackDepotGet(stack_id2).Print(); } Report("HINT: if you don't care about these errors you may set " "ASAN_OPTIONS=detect_odr_violation=0\n"); InternalScopedString error_msg(256); error_msg.append("odr-violation: global '%s' at %s", MaybeDemangleGlobalName(g1->name), g1_loc.data()); ReportErrorSummary(error_msg.data()); } // ----------------------- CheckForInvalidPointerPair ----------- {{{1 static NOINLINE void ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp, uptr a1, uptr a2) { ScopedInErrorReport in_report; const char *bug_type = "invalid-pointer-pair"; Decorator d; Printf("%s", d.Warning()); Report("ERROR: AddressSanitizer: invalid-pointer-pair: %p %p\n", a1, a2); Printf("%s", d.EndWarning()); GET_STACK_TRACE_FATAL(pc, bp); stack.Print(); DescribeAddress(a1, 1, bug_type); DescribeAddress(a2, 1, bug_type); ReportErrorSummary(bug_type, &stack); } static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) { if (!flags()->detect_invalid_pointer_pairs) return; uptr a1 = reinterpret_cast(p1); uptr a2 = reinterpret_cast(p2); AsanChunkView chunk1 = FindHeapChunkByAddress(a1); AsanChunkView chunk2 = FindHeapChunkByAddress(a2); - bool valid1 = chunk1.IsValid(); - bool valid2 = chunk2.IsValid(); - if ((valid1 != valid2) || (valid1 && valid2 && !chunk1.Eq(chunk2))) { - GET_CALLER_PC_BP_SP; \ + bool valid1 = chunk1.IsAllocated(); + bool valid2 = chunk2.IsAllocated(); + if (!valid1 || !valid2 || !chunk1.Eq(chunk2)) { + GET_CALLER_PC_BP_SP; return ReportInvalidPointerPair(pc, bp, sp, a1, a2); } } // ----------------------- Mac-specific reports ----------------- {{{1 void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name, BufferedStackTrace *stack) { ScopedInErrorReport in_report; Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n" "This is an unrecoverable problem, exiting now.\n", addr); PrintZoneForPointer(addr, zone_ptr, zone_name); stack->Print(); DescribeHeapAddress(addr, 1); } // -------------- SuppressErrorReport -------------- {{{1 // Avoid error reports duplicating for ASan recover mode. static bool SuppressErrorReport(uptr pc) { if (!common_flags()->suppress_equal_pcs) return false; for (unsigned i = 0; i < kAsanBuggyPcPoolSize; i++) { uptr cmp = atomic_load_relaxed(&AsanBuggyPcPool[i]); if (cmp == 0 && atomic_compare_exchange_strong(&AsanBuggyPcPool[i], &cmp, pc, memory_order_relaxed)) return false; if (cmp == pc) return true; } Die(); } +static void PrintContainerOverflowHint() { + Printf("HINT: if you don't care about these errors you may set " + "ASAN_OPTIONS=detect_container_overflow=0.\n" + "If you suspect a false positive see also: " + "https://github.com/google/sanitizers/wiki/" + "AddressSanitizerContainerOverflow.\n"); +} + +static bool AdjacentShadowValuesAreFullyPoisoned(u8 *s) { + return s[-1] > 127 && s[1] > 127; +} + void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write, uptr access_size, u32 exp, bool fatal) { if (!fatal && SuppressErrorReport(pc)) return; ENABLE_FRAME_POINTER; + ScarinessScore SS; + if (access_size) { + if (access_size <= 9) { + char desr[] = "?-byte"; + desr[0] = '0' + access_size; + SS.Scare(access_size + access_size / 2, desr); + } else if (access_size >= 10) { + SS.Scare(15, "multi-byte"); + } + is_write ? SS.Scare(20, "write") : SS.Scare(1, "read"); + } + // Optimization experiments. // The experiments can be used to evaluate potential optimizations that remove // instrumentation (assess false negatives). Instead of completely removing // some instrumentation, compiler can emit special calls into runtime // (e.g. __asan_report_exp_load1 instead of __asan_report_load1) and pass // mask of experiments (exp). // The reaction to a non-zero value of exp is to be defined. (void)exp; // Determine the error type. const char *bug_descr = "unknown-crash"; + u8 shadow_val = 0; if (AddrIsInMem(addr)) { u8 *shadow_addr = (u8*)MemToShadow(addr); // If we are accessing 16 bytes, look at the second shadow byte. if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY) shadow_addr++; // If we are in the partial right redzone, look at the next shadow byte. if (*shadow_addr > 0 && *shadow_addr < 128) shadow_addr++; - switch (*shadow_addr) { + bool far_from_bounds = false; + shadow_val = *shadow_addr; + int bug_type_score = 0; + // For use-after-frees reads are almost as bad as writes. + int read_after_free_bonus = 0; + switch (shadow_val) { case kAsanHeapLeftRedzoneMagic: case kAsanHeapRightRedzoneMagic: case kAsanArrayCookieMagic: bug_descr = "heap-buffer-overflow"; + bug_type_score = 10; + far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr); break; case kAsanHeapFreeMagic: bug_descr = "heap-use-after-free"; + bug_type_score = 20; + if (!is_write) read_after_free_bonus = 18; break; case kAsanStackLeftRedzoneMagic: bug_descr = "stack-buffer-underflow"; + bug_type_score = 25; + far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr); break; case kAsanInitializationOrderMagic: bug_descr = "initialization-order-fiasco"; + bug_type_score = 1; break; case kAsanStackMidRedzoneMagic: case kAsanStackRightRedzoneMagic: case kAsanStackPartialRedzoneMagic: bug_descr = "stack-buffer-overflow"; + bug_type_score = 25; + far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr); break; case kAsanStackAfterReturnMagic: bug_descr = "stack-use-after-return"; + bug_type_score = 30; + if (!is_write) read_after_free_bonus = 18; break; case kAsanUserPoisonedMemoryMagic: bug_descr = "use-after-poison"; + bug_type_score = 20; break; case kAsanContiguousContainerOOBMagic: bug_descr = "container-overflow"; + bug_type_score = 10; break; case kAsanStackUseAfterScopeMagic: bug_descr = "stack-use-after-scope"; + bug_type_score = 10; break; case kAsanGlobalRedzoneMagic: bug_descr = "global-buffer-overflow"; + bug_type_score = 10; + far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr); break; case kAsanIntraObjectRedzone: bug_descr = "intra-object-overflow"; + bug_type_score = 10; break; case kAsanAllocaLeftMagic: case kAsanAllocaRightMagic: bug_descr = "dynamic-stack-buffer-overflow"; + bug_type_score = 25; + far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr); break; } + SS.Scare(bug_type_score + read_after_free_bonus, bug_descr); + if (far_from_bounds) + SS.Scare(10, "far-from-bounds"); } ReportData report = { pc, sp, bp, addr, (bool)is_write, access_size, bug_descr }; ScopedInErrorReport in_report(&report, fatal); Decorator d; Printf("%s", d.Warning()); Report("ERROR: AddressSanitizer: %s on address " "%p at pc %p bp %p sp %p\n", bug_descr, (void*)addr, pc, bp, sp); Printf("%s", d.EndWarning()); u32 curr_tid = GetCurrentTidOrInvalid(); char tname[128]; Printf("%s%s of size %zu at %p thread T%d%s%s\n", d.Access(), access_size ? (is_write ? "WRITE" : "READ") : "ACCESS", access_size, (void*)addr, curr_tid, ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)), d.EndAccess()); + SS.Print(); GET_STACK_TRACE_FATAL(pc, bp); stack.Print(); DescribeAddress(addr, access_size, bug_descr); + if (shadow_val == kAsanContiguousContainerOOBMagic) + PrintContainerOverflowHint(); ReportErrorSummary(bug_descr, &stack); PrintShadowMemoryForAddress(addr); } } // namespace __asan // --------------------------- Interface --------------------- {{{1 using namespace __asan; // NOLINT void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, uptr access_size, u32 exp) { ENABLE_FRAME_POINTER; bool fatal = flags()->halt_on_error; ReportGenericError(pc, bp, sp, addr, is_write, access_size, exp, fatal); } void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) { BlockingMutexLock l(&error_message_buf_mutex); error_report_callback = callback; } void __asan_describe_address(uptr addr) { // Thread registry must be locked while we're describing an address. asanThreadRegistry().Lock(); DescribeAddress(addr, 1, ""); asanThreadRegistry().Unlock(); } int __asan_report_present() { return report_happened ? 1 : 0; } uptr __asan_get_report_pc() { return report_data.pc; } uptr __asan_get_report_bp() { return report_data.bp; } uptr __asan_get_report_sp() { return report_data.sp; } uptr __asan_get_report_address() { return report_data.addr; } int __asan_get_report_access_type() { return report_data.is_write ? 1 : 0; } uptr __asan_get_report_access_size() { return report_data.access_size; } const char *__asan_get_report_description() { return report_data.description; } extern "C" { SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_ptr_sub(void *a, void *b) { CheckForInvalidPointerPair(a, b); } SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_ptr_cmp(void *a, void *b) { CheckForInvalidPointerPair(a, b); } } // extern "C" #if !SANITIZER_SUPPORTS_WEAK_HOOKS // Provide default implementation of __asan_on_error that does nothing // and may be overriden by user. SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE NOINLINE void __asan_on_error() {} #endif Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_report.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_report.h (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_report.h (revision 305364) @@ -1,87 +1,87 @@ //===-- asan_report.h -------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // ASan-private header for error reporting functions. //===----------------------------------------------------------------------===// #include "asan_allocator.h" #include "asan_internal.h" #include "asan_thread.h" namespace __asan { struct StackVarDescr { uptr beg; uptr size; const char *name_pos; uptr name_len; }; struct AddressDescription { char *name; uptr name_size; uptr region_address; uptr region_size; const char *region_kind; }; // Returns the number of globals close to the provided address and copies // them to "globals" array. int GetGlobalsForAddress(uptr addr, __asan_global *globals, u32 *reg_sites, int max_globals); bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr); // The following functions prints address description depending // on the memory type (shadow/heap/stack/global). void DescribeHeapAddress(uptr addr, uptr access_size); bool DescribeAddressIfShadow(uptr addr, AddressDescription *descr = nullptr, bool print = true); bool ParseFrameDescription(const char *frame_descr, InternalMmapVector *vars); bool DescribeAddressIfStack(uptr addr, uptr access_size); void DescribeThread(AsanThreadContext *context); // Different kinds of error reports. void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write, uptr access_size, u32 exp, bool fatal); void ReportStackOverflow(const SignalContext &sig); void ReportDeadlySignal(const char *description, const SignalContext &sig); -void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size, +void ReportNewDeleteSizeMismatch(uptr addr, uptr alloc_size, uptr delete_size, BufferedStackTrace *free_stack); void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack); void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack); void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack, AllocType alloc_type, AllocType dealloc_type); void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack); void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr, BufferedStackTrace *stack); void ReportStringFunctionMemoryRangesOverlap(const char *function, const char *offset1, uptr length1, const char *offset2, uptr length2, BufferedStackTrace *stack); void ReportStringFunctionSizeOverflow(uptr offset, uptr size, BufferedStackTrace *stack); void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end, uptr old_mid, uptr new_mid, BufferedStackTrace *stack); void ReportODRViolation(const __asan_global *g1, u32 stack_id1, const __asan_global *g2, u32 stack_id2); // Mac-specific errors and warnings. void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name, BufferedStackTrace *stack); void ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name, BufferedStackTrace *stack); } // namespace __asan Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_rtl.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_rtl.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_rtl.cc (revision 305364) @@ -1,630 +1,648 @@ //===-- asan_rtl.cc -------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // Main file of the ASan run-time library. //===----------------------------------------------------------------------===// #include "asan_activation.h" #include "asan_allocator.h" #include "asan_interceptors.h" #include "asan_interface_internal.h" #include "asan_internal.h" #include "asan_mapping.h" #include "asan_poisoning.h" #include "asan_report.h" #include "asan_stack.h" #include "asan_stats.h" #include "asan_suppressions.h" #include "asan_thread.h" #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_symbolizer.h" #include "lsan/lsan_common.h" #include "ubsan/ubsan_init.h" #include "ubsan/ubsan_platform.h" int __asan_option_detect_stack_use_after_return; // Global interface symbol. uptr *__asan_test_only_reported_buggy_pointer; // Used only for testing asan. namespace __asan { uptr AsanMappingProfile[kAsanMappingProfileSize]; static void AsanDie() { static atomic_uint32_t num_calls; if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) { // Don't die twice - run a busy loop. while (1) { } } if (flags()->sleep_before_dying) { Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying); SleepForSeconds(flags()->sleep_before_dying); } if (flags()->unmap_shadow_on_exit) { if (kMidMemBeg) { UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg); UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd); } else { UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); } } } static void AsanCheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2) { Report("AddressSanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n", file, line, cond, (uptr)v1, (uptr)v2); // FIXME: check for infinite recursion without a thread-local counter here. PRINT_CURRENT_STACK_CHECK(); Die(); } // -------------------------- Globals --------------------- {{{1 int asan_inited; bool asan_init_is_running; #if !ASAN_FIXED_MAPPING uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; #endif // -------------------------- Misc ---------------- {{{1 void ShowStatsAndAbort() { __asan_print_accumulated_stats(); Die(); } // ---------------------- mmap -------------------- {{{1 // Reserve memory range [beg, end]. // We need to use inclusive range because end+1 may not be representable. void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name) { - CHECK_EQ((beg % GetPageSizeCached()), 0); - CHECK_EQ(((end + 1) % GetPageSizeCached()), 0); + CHECK_EQ((beg % GetMmapGranularity()), 0); + CHECK_EQ(((end + 1) % GetMmapGranularity()), 0); uptr size = end - beg + 1; DecreaseTotalMmap(size); // Don't count the shadow against mmap_limit_mb. void *res = MmapFixedNoReserve(beg, size, name); if (res != (void*)beg) { Report("ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. " "Perhaps you're using ulimit -v\n", size); Abort(); } if (common_flags()->no_huge_pages_for_shadow) NoHugePagesInRegion(beg, size); if (common_flags()->use_madv_dontdump) DontDumpShadowMemory(beg, size); } // --------------- LowLevelAllocateCallbac ---------- {{{1 static void OnLowLevelAllocate(uptr ptr, uptr size) { PoisonShadow(ptr, size, kAsanInternalHeapMagic); } // -------------------------- Run-time entry ------------------- {{{1 // exported functions #define ASAN_REPORT_ERROR(type, is_write, size) \ extern "C" NOINLINE INTERFACE_ATTRIBUTE \ void __asan_report_ ## type ## size(uptr addr) { \ GET_CALLER_PC_BP_SP; \ ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \ } \ extern "C" NOINLINE INTERFACE_ATTRIBUTE \ void __asan_report_exp_ ## type ## size(uptr addr, u32 exp) { \ GET_CALLER_PC_BP_SP; \ ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \ } \ extern "C" NOINLINE INTERFACE_ATTRIBUTE \ void __asan_report_ ## type ## size ## _noabort(uptr addr) { \ GET_CALLER_PC_BP_SP; \ ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \ } \ ASAN_REPORT_ERROR(load, false, 1) ASAN_REPORT_ERROR(load, false, 2) ASAN_REPORT_ERROR(load, false, 4) ASAN_REPORT_ERROR(load, false, 8) ASAN_REPORT_ERROR(load, false, 16) ASAN_REPORT_ERROR(store, true, 1) ASAN_REPORT_ERROR(store, true, 2) ASAN_REPORT_ERROR(store, true, 4) ASAN_REPORT_ERROR(store, true, 8) ASAN_REPORT_ERROR(store, true, 16) #define ASAN_REPORT_ERROR_N(type, is_write) \ extern "C" NOINLINE INTERFACE_ATTRIBUTE \ void __asan_report_ ## type ## _n(uptr addr, uptr size) { \ GET_CALLER_PC_BP_SP; \ ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \ } \ extern "C" NOINLINE INTERFACE_ATTRIBUTE \ void __asan_report_exp_ ## type ## _n(uptr addr, uptr size, u32 exp) { \ GET_CALLER_PC_BP_SP; \ ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \ } \ extern "C" NOINLINE INTERFACE_ATTRIBUTE \ void __asan_report_ ## type ## _n_noabort(uptr addr, uptr size) { \ GET_CALLER_PC_BP_SP; \ ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \ } \ ASAN_REPORT_ERROR_N(load, false) ASAN_REPORT_ERROR_N(store, true) #define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg, fatal) \ uptr sp = MEM_TO_SHADOW(addr); \ uptr s = size <= SHADOW_GRANULARITY ? *reinterpret_cast(sp) \ : *reinterpret_cast(sp); \ if (UNLIKELY(s)) { \ if (UNLIKELY(size >= SHADOW_GRANULARITY || \ ((s8)((addr & (SHADOW_GRANULARITY - 1)) + size - 1)) >= \ (s8)s)) { \ if (__asan_test_only_reported_buggy_pointer) { \ *__asan_test_only_reported_buggy_pointer = addr; \ } else { \ GET_CALLER_PC_BP_SP; \ ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, \ fatal); \ } \ } \ } #define ASAN_MEMORY_ACCESS_CALLBACK(type, is_write, size) \ extern "C" NOINLINE INTERFACE_ATTRIBUTE \ void __asan_##type##size(uptr addr) { \ ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, true) \ } \ extern "C" NOINLINE INTERFACE_ATTRIBUTE \ void __asan_exp_##type##size(uptr addr, u32 exp) { \ ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp, true) \ } \ extern "C" NOINLINE INTERFACE_ATTRIBUTE \ void __asan_##type##size ## _noabort(uptr addr) { \ ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, false) \ } \ ASAN_MEMORY_ACCESS_CALLBACK(load, false, 1) ASAN_MEMORY_ACCESS_CALLBACK(load, false, 2) ASAN_MEMORY_ACCESS_CALLBACK(load, false, 4) ASAN_MEMORY_ACCESS_CALLBACK(load, false, 8) ASAN_MEMORY_ACCESS_CALLBACK(load, false, 16) ASAN_MEMORY_ACCESS_CALLBACK(store, true, 1) ASAN_MEMORY_ACCESS_CALLBACK(store, true, 2) ASAN_MEMORY_ACCESS_CALLBACK(store, true, 4) ASAN_MEMORY_ACCESS_CALLBACK(store, true, 8) ASAN_MEMORY_ACCESS_CALLBACK(store, true, 16) extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_loadN(uptr addr, uptr size) { if (__asan_region_is_poisoned(addr, size)) { GET_CALLER_PC_BP_SP; ReportGenericError(pc, bp, sp, addr, false, size, 0, true); } } extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_exp_loadN(uptr addr, uptr size, u32 exp) { if (__asan_region_is_poisoned(addr, size)) { GET_CALLER_PC_BP_SP; ReportGenericError(pc, bp, sp, addr, false, size, exp, true); } } extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_loadN_noabort(uptr addr, uptr size) { if (__asan_region_is_poisoned(addr, size)) { GET_CALLER_PC_BP_SP; ReportGenericError(pc, bp, sp, addr, false, size, 0, false); } } extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_storeN(uptr addr, uptr size) { if (__asan_region_is_poisoned(addr, size)) { GET_CALLER_PC_BP_SP; ReportGenericError(pc, bp, sp, addr, true, size, 0, true); } } extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_exp_storeN(uptr addr, uptr size, u32 exp) { if (__asan_region_is_poisoned(addr, size)) { GET_CALLER_PC_BP_SP; ReportGenericError(pc, bp, sp, addr, true, size, exp, true); } } extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_storeN_noabort(uptr addr, uptr size) { if (__asan_region_is_poisoned(addr, size)) { GET_CALLER_PC_BP_SP; ReportGenericError(pc, bp, sp, addr, true, size, 0, false); } } // Force the linker to keep the symbols for various ASan interface functions. // We want to keep those in the executable in order to let the instrumented // dynamic libraries access the symbol even if it is not used by the executable // itself. This should help if the build system is removing dead code at link // time. static NOINLINE void force_interface_symbols() { volatile int fake_condition = 0; // prevent dead condition elimination. // __asan_report_* functions are noreturn, so we need a switch to prevent // the compiler from removing any of them. switch (fake_condition) { case 1: __asan_report_load1(0); break; case 2: __asan_report_load2(0); break; case 3: __asan_report_load4(0); break; case 4: __asan_report_load8(0); break; case 5: __asan_report_load16(0); break; case 6: __asan_report_load_n(0, 0); break; case 7: __asan_report_store1(0); break; case 8: __asan_report_store2(0); break; case 9: __asan_report_store4(0); break; case 10: __asan_report_store8(0); break; case 11: __asan_report_store16(0); break; case 12: __asan_report_store_n(0, 0); break; case 13: __asan_report_exp_load1(0, 0); break; case 14: __asan_report_exp_load2(0, 0); break; case 15: __asan_report_exp_load4(0, 0); break; case 16: __asan_report_exp_load8(0, 0); break; case 17: __asan_report_exp_load16(0, 0); break; case 18: __asan_report_exp_load_n(0, 0, 0); break; case 19: __asan_report_exp_store1(0, 0); break; case 20: __asan_report_exp_store2(0, 0); break; case 21: __asan_report_exp_store4(0, 0); break; case 22: __asan_report_exp_store8(0, 0); break; case 23: __asan_report_exp_store16(0, 0); break; case 24: __asan_report_exp_store_n(0, 0, 0); break; case 25: __asan_register_globals(nullptr, 0); break; case 26: __asan_unregister_globals(nullptr, 0); break; case 27: __asan_set_death_callback(nullptr); break; case 28: __asan_set_error_report_callback(nullptr); break; case 29: __asan_handle_no_return(); break; case 30: __asan_address_is_poisoned(nullptr); break; case 31: __asan_poison_memory_region(nullptr, 0); break; case 32: __asan_unpoison_memory_region(nullptr, 0); break; case 34: __asan_before_dynamic_init(nullptr); break; case 35: __asan_after_dynamic_init(); break; case 36: __asan_poison_stack_memory(0, 0); break; case 37: __asan_unpoison_stack_memory(0, 0); break; case 38: __asan_region_is_poisoned(0, 0); break; case 39: __asan_describe_address(0); break; } } static void asan_atexit() { Printf("AddressSanitizer exit stats:\n"); __asan_print_accumulated_stats(); // Print AsanMappingProfile. for (uptr i = 0; i < kAsanMappingProfileSize; i++) { if (AsanMappingProfile[i] == 0) continue; Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]); } } static void InitializeHighMemEnd() { #if !ASAN_FIXED_MAPPING kHighMemEnd = GetMaxVirtualAddress(); // Increase kHighMemEnd to make sure it's properly // aligned together with kHighMemBeg: - kHighMemEnd |= SHADOW_GRANULARITY * GetPageSizeCached() - 1; + kHighMemEnd |= SHADOW_GRANULARITY * GetMmapGranularity() - 1; #endif // !ASAN_FIXED_MAPPING - CHECK_EQ((kHighMemBeg % GetPageSizeCached()), 0); + CHECK_EQ((kHighMemBeg % GetMmapGranularity()), 0); } static void ProtectGap(uptr addr, uptr size) { if (!flags()->protect_shadow_gap) return; - void *res = MmapNoAccess(addr, size, "shadow gap"); + void *res = MmapFixedNoAccess(addr, size, "shadow gap"); if (addr == (uptr)res) return; // A few pages at the start of the address space can not be protected. // But we really want to protect as much as possible, to prevent this memory // being returned as a result of a non-FIXED mmap(). if (addr == kZeroBaseShadowStart) { - uptr step = GetPageSizeCached(); + uptr step = GetMmapGranularity(); while (size > step && addr < kZeroBaseMaxShadowStart) { addr += step; size -= step; - void *res = MmapNoAccess(addr, size, "shadow gap"); + void *res = MmapFixedNoAccess(addr, size, "shadow gap"); if (addr == (uptr)res) return; } } Report("ERROR: Failed to protect the shadow gap. " "ASan cannot proceed correctly. ABORTING.\n"); DumpProcessMap(); Die(); } static void PrintAddressSpaceLayout() { Printf("|| `[%p, %p]` || HighMem ||\n", (void*)kHighMemBeg, (void*)kHighMemEnd); Printf("|| `[%p, %p]` || HighShadow ||\n", (void*)kHighShadowBeg, (void*)kHighShadowEnd); if (kMidMemBeg) { Printf("|| `[%p, %p]` || ShadowGap3 ||\n", (void*)kShadowGap3Beg, (void*)kShadowGap3End); Printf("|| `[%p, %p]` || MidMem ||\n", (void*)kMidMemBeg, (void*)kMidMemEnd); Printf("|| `[%p, %p]` || ShadowGap2 ||\n", (void*)kShadowGap2Beg, (void*)kShadowGap2End); Printf("|| `[%p, %p]` || MidShadow ||\n", (void*)kMidShadowBeg, (void*)kMidShadowEnd); } Printf("|| `[%p, %p]` || ShadowGap ||\n", (void*)kShadowGapBeg, (void*)kShadowGapEnd); if (kLowShadowBeg) { Printf("|| `[%p, %p]` || LowShadow ||\n", (void*)kLowShadowBeg, (void*)kLowShadowEnd); Printf("|| `[%p, %p]` || LowMem ||\n", (void*)kLowMemBeg, (void*)kLowMemEnd); } Printf("MemToShadow(shadow): %p %p %p %p", (void*)MEM_TO_SHADOW(kLowShadowBeg), (void*)MEM_TO_SHADOW(kLowShadowEnd), (void*)MEM_TO_SHADOW(kHighShadowBeg), (void*)MEM_TO_SHADOW(kHighShadowEnd)); if (kMidMemBeg) { Printf(" %p %p", (void*)MEM_TO_SHADOW(kMidShadowBeg), (void*)MEM_TO_SHADOW(kMidShadowEnd)); } Printf("\n"); Printf("redzone=%zu\n", (uptr)flags()->redzone); Printf("max_redzone=%zu\n", (uptr)flags()->max_redzone); Printf("quarantine_size_mb=%zuM\n", (uptr)flags()->quarantine_size_mb); Printf("malloc_context_size=%zu\n", (uptr)common_flags()->malloc_context_size); Printf("SHADOW_SCALE: %d\n", (int)SHADOW_SCALE); Printf("SHADOW_GRANULARITY: %d\n", (int)SHADOW_GRANULARITY); Printf("SHADOW_OFFSET: 0x%zx\n", (uptr)SHADOW_OFFSET); CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7); if (kMidMemBeg) CHECK(kMidShadowBeg > kLowShadowEnd && kMidMemBeg > kMidShadowEnd && kHighShadowBeg > kMidMemEnd); } static void AsanInitInternal() { if (LIKELY(asan_inited)) return; SanitizerToolName = "AddressSanitizer"; CHECK(!asan_init_is_running && "ASan init calls itself!"); asan_init_is_running = true; CacheBinaryName(); // Initialize flags. This must be done early, because most of the // initialization steps look at flags(). InitializeFlags(); AsanCheckIncompatibleRT(); AsanCheckDynamicRTPrereqs(); + AvoidCVE_2016_2143(); SetCanPoisonMemory(flags()->poison_heap); SetMallocContextSize(common_flags()->malloc_context_size); + InitializePlatformExceptionHandlers(); + InitializeHighMemEnd(); // Make sure we are not statically linked. AsanDoesNotSupportStaticLinkage(); // Install tool-specific callbacks in sanitizer_common. AddDieCallback(AsanDie); SetCheckFailedCallback(AsanCheckFailed); SetPrintfAndReportCallback(AppendToErrorMessageBuffer); __sanitizer_set_report_path(common_flags()->log_path); // Enable UAR detection, if required. __asan_option_detect_stack_use_after_return = flags()->detect_stack_use_after_return; // Re-exec ourselves if we need to set additional env or command line args. MaybeReexec(); // Setup internal allocator callback. SetLowLevelAllocateCallback(OnLowLevelAllocate); InitializeAsanInterceptors(); // Enable system log ("adb logcat") on Android. // Doing this before interceptors are initialized crashes in: // AsanInitInternal -> android_log_write -> __interceptor_strcmp AndroidLogInit(); ReplaceSystemMalloc(); uptr shadow_start = kLowShadowBeg; if (kLowShadowBeg) shadow_start -= GetMmapGranularity(); bool full_shadow_is_available = MemoryRangeIsAvailable(shadow_start, kHighShadowEnd); #if SANITIZER_LINUX && defined(__x86_64__) && defined(_LP64) && \ !ASAN_FIXED_MAPPING if (!full_shadow_is_available) { kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0; kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0; } +#elif SANITIZER_WINDOWS64 + // Disable the "mid mem" shadow layout. + if (!full_shadow_is_available) { + kMidMemBeg = 0; + kMidMemEnd = 0; + } #endif if (Verbosity()) PrintAddressSpaceLayout(); DisableCoreDumperIfNecessary(); if (full_shadow_is_available) { // mmap the low shadow plus at least one page at the left. if (kLowShadowBeg) ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow"); // mmap the high shadow. ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow"); // protect the gap. ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1); } else if (kMidMemBeg && MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) && MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) { CHECK(kLowShadowBeg != kLowShadowEnd); // mmap the low shadow plus at least one page at the left. ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow"); // mmap the mid shadow. ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd, "mid shadow"); // mmap the high shadow. ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow"); // protect the gaps. ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1); ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1); } else { Report("Shadow memory range interleaves with an existing memory mapping. " "ASan cannot proceed correctly. ABORTING.\n"); Report("ASan shadow was supposed to be located in the [%p-%p] range.\n", shadow_start, kHighShadowEnd); DumpProcessMap(); Die(); } AsanTSDInit(PlatformTSDDtor); InstallDeadlySignalHandlers(AsanOnDeadlySignal); AllocatorOptions allocator_options; allocator_options.SetFrom(flags(), common_flags()); InitializeAllocator(allocator_options); MaybeStartBackgroudThread(); SetSoftRssLimitExceededCallback(AsanSoftRssLimitExceededCallback); // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited // should be set to 1 prior to initializing the threads. asan_inited = 1; asan_init_is_running = false; if (flags()->atexit) Atexit(asan_atexit); InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir); // Now that ASan runtime is (mostly) initialized, deactivate it if // necessary, so that it can be re-activated when requested. if (flags()->start_deactivated) AsanDeactivate(); // interceptors InitTlsSize(); // Create main thread. AsanThread *main_thread = AsanThread::Create( /* start_routine */ nullptr, /* arg */ nullptr, /* parent_tid */ 0, /* stack */ nullptr, /* detached */ true); CHECK_EQ(0, main_thread->tid()); SetCurrentThread(main_thread); main_thread->ThreadStart(internal_getpid(), /* signal_thread_is_registered */ nullptr); force_interface_symbols(); // no-op. SanitizerInitializeUnwinder(); -#if CAN_SANITIZE_LEAKS - __lsan::InitCommonLsan(); - if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) { - Atexit(__lsan::DoLeakCheck); + if (CAN_SANITIZE_LEAKS) { + __lsan::InitCommonLsan(); + if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) { + Atexit(__lsan::DoLeakCheck); + } } -#endif // CAN_SANITIZE_LEAKS #if CAN_SANITIZE_UB __ubsan::InitAsPlugin(); #endif InitializeSuppressions(); + + if (CAN_SANITIZE_LEAKS) { + // LateInitialize() calls dlsym, which can allocate an error string buffer + // in the TLS. Let's ignore the allocation to avoid reporting a leak. + __lsan::ScopedInterceptorDisabler disabler; + Symbolizer::LateInitialize(); + } else { + Symbolizer::LateInitialize(); + } VReport(1, "AddressSanitizer Init done\n"); } // Initialize as requested from some part of ASan runtime library (interceptors, // allocator, etc). void AsanInitFromRtl() { AsanInitInternal(); } #if ASAN_DYNAMIC // Initialize runtime in case it's LD_PRELOAD-ed into unsanitized executable // (and thus normal initializers from .preinit_array or modules haven't run). class AsanInitializer { public: // NOLINT AsanInitializer() { AsanInitFromRtl(); } }; static AsanInitializer asan_initializer; #endif // ASAN_DYNAMIC } // namespace __asan // ---------------------- Interface ---------------- {{{1 using namespace __asan; // NOLINT void NOINLINE __asan_handle_no_return() { int local_stack; AsanThread *curr_thread = GetCurrentThread(); uptr PageSize = GetPageSizeCached(); uptr top, bottom; if (curr_thread) { top = curr_thread->stack_top(); bottom = ((uptr)&local_stack - PageSize) & ~(PageSize - 1); } else { // If we haven't seen this thread, try asking the OS for stack bounds. uptr tls_addr, tls_size, stack_size; GetThreadStackAndTls(/*main=*/false, &bottom, &stack_size, &tls_addr, &tls_size); top = bottom + stack_size; } static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M if (top - bottom > kMaxExpectedCleanupSize) { static bool reported_warning = false; if (reported_warning) return; reported_warning = true; Report("WARNING: ASan is ignoring requested __asan_handle_no_return: " "stack top: %p; bottom %p; size: %p (%zd)\n" "False positive error reports may follow\n" "For details see " "https://github.com/google/sanitizers/issues/189\n", top, bottom, top - bottom, top - bottom); return; } PoisonShadow(bottom, top - bottom, 0); if (curr_thread && curr_thread->has_fake_stack()) curr_thread->fake_stack()->HandleNoReturn(); } void NOINLINE __asan_set_death_callback(void (*callback)(void)) { SetUserDieCallback(callback); } // Initialize as requested from instrumented application code. // We use this call as a trigger to wake up ASan from deactivated state. void __asan_init() { AsanActivate(); AsanInitInternal(); } void __asan_version_mismatch_check() { // Do nothing. } Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_scariness_score.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_scariness_score.h (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_scariness_score.h (revision 305364) @@ -0,0 +1,67 @@ +//===-- asan_scariness_score.h ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of AddressSanitizer, an address sanity checker. +// +// Compute the level of scariness of the error message. +// Don't expect any deep science here, just a set of heuristics that suggest +// that e.g. 1-byte-read-global-buffer-overflow is less scary than +// 8-byte-write-stack-use-after-return. +// +// Every error report has one or more features, such as memory access size, +// type (read or write), type of accessed memory (e.g. free-d heap, or a global +// redzone), etc. Every such feature has an int score and a string description. +// The overall score is the sum of all feature scores and the description +// is a concatenation of feature descriptions. +// Examples: +// 17 (4-byte-read-heap-buffer-overflow) +// 65 (multi-byte-write-stack-use-after-return) +// 10 (null-deref) +// +//===----------------------------------------------------------------------===// + +#ifndef ASAN_SCARINESS_SCORE_H +#define ASAN_SCARINESS_SCORE_H + +#include "asan_flags.h" +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_libc.h" + +namespace __asan { +class ScarinessScore { + public: + ScarinessScore() { + descr[0] = 0; + } + void Scare(int add_to_score, const char *reason) { + if (descr[0]) + internal_strlcat(descr, "-", sizeof(descr)); + internal_strlcat(descr, reason, sizeof(descr)); + score += add_to_score; + }; + int GetScore() const { return score; } + const char *GetDescription() const { return descr; } + void Print() { + if (score && flags()->print_scariness) + Printf("SCARINESS: %d (%s)\n", score, descr); + } + static void PrintSimple(int score, const char *descr) { + ScarinessScore SS; + SS.Scare(score, descr); + SS.Print(); + } + + private: + int score = 0; + char descr[1024]; +}; + +} // namespace __asan + +#endif // ASAN_SCARINESS_SCORE_H Property changes on: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_scariness_score.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_stack.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_stack.h (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_stack.h (revision 305364) @@ -1,119 +1,122 @@ //===-- asan_stack.h --------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // ASan-private header for asan_stack.cc. //===----------------------------------------------------------------------===// #ifndef ASAN_STACK_H #define ASAN_STACK_H #include "asan_flags.h" #include "asan_thread.h" #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_stacktrace.h" namespace __asan { static const u32 kDefaultMallocContextSize = 30; void SetMallocContextSize(u32 size); u32 GetMallocContextSize(); // Get the stack trace with the given pc and bp. // The pc will be in the position 0 of the resulting stack trace. // The bp may refer to the current frame or to the caller's frame. ALWAYS_INLINE void GetStackTraceWithPcBpAndContext(BufferedStackTrace *stack, uptr max_depth, uptr pc, uptr bp, void *context, bool fast) { #if SANITIZER_WINDOWS stack->Unwind(max_depth, pc, bp, context, 0, 0, fast); #else AsanThread *t; stack->size = 0; if (LIKELY(asan_inited)) { if ((t = GetCurrentThread()) && !t->isUnwinding()) { // On FreeBSD the slow unwinding that leverages _Unwind_Backtrace() // yields the call stack of the signal's handler and not of the code // that raised the signal (as it does on Linux). if (SANITIZER_FREEBSD && t->isInDeadlySignal()) fast = true; uptr stack_top = t->stack_top(); uptr stack_bottom = t->stack_bottom(); ScopedUnwinding unwind_scope(t); - stack->Unwind(max_depth, pc, bp, context, stack_top, stack_bottom, fast); + if (!SANITIZER_MIPS || IsValidFrame(bp, stack_top, stack_bottom)) { + stack->Unwind(max_depth, pc, bp, context, stack_top, stack_bottom, + fast); + } } else if (!t && !fast) { /* If GetCurrentThread() has failed, try to do slow unwind anyways. */ stack->Unwind(max_depth, pc, bp, context, 0, 0, false); } } #endif // SANITIZER_WINDOWS } } // namespace __asan // NOTE: A Rule of thumb is to retrieve stack trace in the interceptors // as early as possible (in functions exposed to the user), as we generally // don't want stack trace to contain functions from ASan internals. #define GET_STACK_TRACE(max_size, fast) \ BufferedStackTrace stack; \ if (max_size <= 2) { \ stack.size = max_size; \ if (max_size > 0) { \ stack.top_frame_bp = GET_CURRENT_FRAME(); \ stack.trace_buffer[0] = StackTrace::GetCurrentPc(); \ if (max_size > 1) \ stack.trace_buffer[1] = GET_CALLER_PC(); \ } \ } else { \ GetStackTraceWithPcBpAndContext(&stack, max_size, \ StackTrace::GetCurrentPc(), \ GET_CURRENT_FRAME(), 0, fast); \ } #define GET_STACK_TRACE_FATAL(pc, bp) \ BufferedStackTrace stack; \ GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, 0, \ common_flags()->fast_unwind_on_fatal) #define GET_STACK_TRACE_SIGNAL(sig) \ BufferedStackTrace stack; \ GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, \ (sig).pc, (sig).bp, (sig).context, \ common_flags()->fast_unwind_on_fatal) #define GET_STACK_TRACE_FATAL_HERE \ GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_fatal) #define GET_STACK_TRACE_CHECK_HERE \ GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_check) #define GET_STACK_TRACE_THREAD \ GET_STACK_TRACE(kStackTraceMax, true) #define GET_STACK_TRACE_MALLOC \ GET_STACK_TRACE(GetMallocContextSize(), common_flags()->fast_unwind_on_malloc) #define GET_STACK_TRACE_FREE GET_STACK_TRACE_MALLOC #define PRINT_CURRENT_STACK() \ { \ GET_STACK_TRACE_FATAL_HERE; \ stack.Print(); \ } #define PRINT_CURRENT_STACK_CHECK() \ { \ GET_STACK_TRACE_CHECK_HERE; \ stack.Print(); \ } #endif // ASAN_STACK_H Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_suppressions.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_suppressions.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_suppressions.cc (revision 305364) @@ -1,110 +1,111 @@ //===-- asan_suppressions.cc ----------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // Issue suppression and suppression-related functions. //===----------------------------------------------------------------------===// #include "asan_suppressions.h" #include "asan_stack.h" #include "sanitizer_common/sanitizer_placement_new.h" #include "sanitizer_common/sanitizer_suppressions.h" #include "sanitizer_common/sanitizer_symbolizer.h" namespace __asan { ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)]; static SuppressionContext *suppression_ctx = nullptr; static const char kInterceptorName[] = "interceptor_name"; static const char kInterceptorViaFunction[] = "interceptor_via_fun"; static const char kInterceptorViaLibrary[] = "interceptor_via_lib"; static const char kODRViolation[] = "odr_violation"; static const char *kSuppressionTypes[] = { kInterceptorName, kInterceptorViaFunction, kInterceptorViaLibrary, kODRViolation}; extern "C" { #if SANITIZER_SUPPORTS_WEAK_HOOKS SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE const char *__asan_default_suppressions(); #else // No week hooks, provide empty implementation. const char *__asan_default_suppressions() { return ""; } #endif // SANITIZER_SUPPORTS_WEAK_HOOKS } // extern "C" void InitializeSuppressions() { CHECK_EQ(nullptr, suppression_ctx); suppression_ctx = new (suppression_placeholder) // NOLINT SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes)); suppression_ctx->ParseFromFile(flags()->suppressions); if (&__asan_default_suppressions) suppression_ctx->Parse(__asan_default_suppressions()); } bool IsInterceptorSuppressed(const char *interceptor_name) { CHECK(suppression_ctx); Suppression *s; // Match "interceptor_name" suppressions. return suppression_ctx->Match(interceptor_name, kInterceptorName, &s); } bool HaveStackTraceBasedSuppressions() { CHECK(suppression_ctx); return suppression_ctx->HasSuppressionType(kInterceptorViaFunction) || suppression_ctx->HasSuppressionType(kInterceptorViaLibrary); } bool IsODRViolationSuppressed(const char *global_var_name) { CHECK(suppression_ctx); Suppression *s; // Match "odr_violation" suppressions. return suppression_ctx->Match(global_var_name, kODRViolation, &s); } bool IsStackTraceSuppressed(const StackTrace *stack) { if (!HaveStackTraceBasedSuppressions()) return false; CHECK(suppression_ctx); Symbolizer *symbolizer = Symbolizer::GetOrInit(); Suppression *s; for (uptr i = 0; i < stack->size && stack->trace[i]; i++) { uptr addr = stack->trace[i]; if (suppression_ctx->HasSuppressionType(kInterceptorViaLibrary)) { // Match "interceptor_via_lib" suppressions. if (const char *module_name = symbolizer->GetModuleNameForPc(addr)) if (suppression_ctx->Match(module_name, kInterceptorViaLibrary, &s)) return true; } if (suppression_ctx->HasSuppressionType(kInterceptorViaFunction)) { SymbolizedStack *frames = symbolizer->SymbolizePC(addr); + CHECK(frames); for (SymbolizedStack *cur = frames; cur; cur = cur->next) { const char *function_name = cur->info.function; if (!function_name) { continue; } // Match "interceptor_via_fun" suppressions. if (suppression_ctx->Match(function_name, kInterceptorViaFunction, &s)) { frames->ClearAll(); return true; } } frames->ClearAll(); } } return false; } } // namespace __asan Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_thread.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_thread.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_thread.cc (revision 305364) @@ -1,357 +1,458 @@ //===-- asan_thread.cc ----------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // Thread-related code. //===----------------------------------------------------------------------===// #include "asan_allocator.h" #include "asan_interceptors.h" #include "asan_poisoning.h" #include "asan_stack.h" #include "asan_thread.h" #include "asan_mapping.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_placement_new.h" #include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_tls_get_addr.h" #include "lsan/lsan_common.h" namespace __asan { // AsanThreadContext implementation. struct CreateThreadContextArgs { AsanThread *thread; StackTrace *stack; }; void AsanThreadContext::OnCreated(void *arg) { CreateThreadContextArgs *args = static_cast(arg); if (args->stack) stack_id = StackDepotPut(*args->stack); thread = args->thread; thread->set_context(this); } void AsanThreadContext::OnFinished() { // Drop the link to the AsanThread object. thread = nullptr; } // MIPS requires aligned address static ALIGNED(16) char thread_registry_placeholder[sizeof(ThreadRegistry)]; static ThreadRegistry *asan_thread_registry; static BlockingMutex mu_for_thread_context(LINKER_INITIALIZED); static LowLevelAllocator allocator_for_thread_context; static ThreadContextBase *GetAsanThreadContext(u32 tid) { BlockingMutexLock lock(&mu_for_thread_context); return new(allocator_for_thread_context) AsanThreadContext(tid); } ThreadRegistry &asanThreadRegistry() { static bool initialized; // Don't worry about thread_safety - this should be called when there is // a single thread. if (!initialized) { // Never reuse ASan threads: we store pointer to AsanThreadContext // in TSD and can't reliably tell when no more TSD destructors will // be called. It would be wrong to reuse AsanThreadContext for another // thread before all TSD destructors will be called for it. asan_thread_registry = new(thread_registry_placeholder) ThreadRegistry( GetAsanThreadContext, kMaxNumberOfThreads, kMaxNumberOfThreads); initialized = true; } return *asan_thread_registry; } AsanThreadContext *GetThreadContextByTidLocked(u32 tid) { return static_cast( asanThreadRegistry().GetThreadLocked(tid)); } // AsanThread implementation. AsanThread *AsanThread::Create(thread_callback_t start_routine, void *arg, u32 parent_tid, StackTrace *stack, bool detached) { uptr PageSize = GetPageSizeCached(); uptr size = RoundUpTo(sizeof(AsanThread), PageSize); AsanThread *thread = (AsanThread*)MmapOrDie(size, __func__); thread->start_routine_ = start_routine; thread->arg_ = arg; CreateThreadContextArgs args = { thread, stack }; asanThreadRegistry().CreateThread(*reinterpret_cast(thread), detached, parent_tid, &args); return thread; } void AsanThread::TSDDtor(void *tsd) { AsanThreadContext *context = (AsanThreadContext*)tsd; VReport(1, "T%d TSDDtor\n", context->tid); if (context->thread) context->thread->Destroy(); } void AsanThread::Destroy() { int tid = this->tid(); VReport(1, "T%d exited\n", tid); malloc_storage().CommitBack(); if (common_flags()->use_sigaltstack) UnsetAlternateSignalStack(); asanThreadRegistry().FinishThread(tid); FlushToDeadThreadStats(&stats_); // We also clear the shadow on thread destruction because // some code may still be executing in later TSD destructors // and we don't want it to have any poisoned stack. ClearShadowForThreadStackAndTLS(); DeleteFakeStack(tid); uptr size = RoundUpTo(sizeof(AsanThread), GetPageSizeCached()); UnmapOrDie(this, size); DTLS_Destroy(); } +void AsanThread::StartSwitchFiber(FakeStack **fake_stack_save, uptr bottom, + uptr size) { + if (atomic_load(&stack_switching_, memory_order_relaxed)) { + Report("ERROR: starting fiber switch while in fiber switch\n"); + Die(); + } + + next_stack_bottom_ = bottom; + next_stack_top_ = bottom + size; + atomic_store(&stack_switching_, 1, memory_order_release); + + FakeStack *current_fake_stack = fake_stack_; + if (fake_stack_save) + *fake_stack_save = fake_stack_; + fake_stack_ = nullptr; + SetTLSFakeStack(nullptr); + // if fake_stack_save is null, the fiber will die, delete the fakestack + if (!fake_stack_save && current_fake_stack) + current_fake_stack->Destroy(this->tid()); +} + +void AsanThread::FinishSwitchFiber(FakeStack *fake_stack_save) { + if (!atomic_load(&stack_switching_, memory_order_relaxed)) { + Report("ERROR: finishing a fiber switch that has not started\n"); + Die(); + } + + if (fake_stack_save) { + SetTLSFakeStack(fake_stack_save); + fake_stack_ = fake_stack_save; + } + + stack_bottom_ = next_stack_bottom_; + stack_top_ = next_stack_top_; + atomic_store(&stack_switching_, 0, memory_order_release); + next_stack_top_ = 0; + next_stack_bottom_ = 0; +} + +inline AsanThread::StackBounds AsanThread::GetStackBounds() const { + if (!atomic_load(&stack_switching_, memory_order_acquire)) + return StackBounds{stack_bottom_, stack_top_}; // NOLINT + char local; + const uptr cur_stack = (uptr)&local; + // Note: need to check next stack first, because FinishSwitchFiber + // may be in process of overwriting stack_top_/bottom_. But in such case + // we are already on the next stack. + if (cur_stack >= next_stack_bottom_ && cur_stack < next_stack_top_) + return StackBounds{next_stack_bottom_, next_stack_top_}; // NOLINT + return StackBounds{stack_bottom_, stack_top_}; // NOLINT +} + +uptr AsanThread::stack_top() { + return GetStackBounds().top; +} + +uptr AsanThread::stack_bottom() { + return GetStackBounds().bottom; +} + +uptr AsanThread::stack_size() { + const auto bounds = GetStackBounds(); + return bounds.top - bounds.bottom; +} + // We want to create the FakeStack lazyly on the first use, but not eralier // than the stack size is known and the procedure has to be async-signal safe. FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() { uptr stack_size = this->stack_size(); if (stack_size == 0) // stack_size is not yet available, don't use FakeStack. return nullptr; uptr old_val = 0; // fake_stack_ has 3 states: // 0 -- not initialized // 1 -- being initialized // ptr -- initialized // This CAS checks if the state was 0 and if so changes it to state 1, // if that was successful, it initializes the pointer. if (atomic_compare_exchange_strong( reinterpret_cast(&fake_stack_), &old_val, 1UL, memory_order_relaxed)) { uptr stack_size_log = Log2(RoundUpToPowerOfTwo(stack_size)); CHECK_LE(flags()->min_uar_stack_size_log, flags()->max_uar_stack_size_log); stack_size_log = Min(stack_size_log, static_cast(flags()->max_uar_stack_size_log)); stack_size_log = Max(stack_size_log, static_cast(flags()->min_uar_stack_size_log)); fake_stack_ = FakeStack::Create(stack_size_log); SetTLSFakeStack(fake_stack_); return fake_stack_; } return nullptr; } void AsanThread::Init() { + next_stack_top_ = next_stack_bottom_ = 0; + atomic_store(&stack_switching_, false, memory_order_release); fake_stack_ = nullptr; // Will be initialized lazily if needed. CHECK_EQ(this->stack_size(), 0U); SetThreadStackAndTls(); CHECK_GT(this->stack_size(), 0U); CHECK(AddrIsInMem(stack_bottom_)); CHECK(AddrIsInMem(stack_top_ - 1)); ClearShadowForThreadStackAndTLS(); int local = 0; VReport(1, "T%d: stack [%p,%p) size 0x%zx; local=%p\n", tid(), (void *)stack_bottom_, (void *)stack_top_, stack_top_ - stack_bottom_, &local); } thread_return_t AsanThread::ThreadStart( uptr os_id, atomic_uintptr_t *signal_thread_is_registered) { Init(); asanThreadRegistry().StartThread(tid(), os_id, nullptr); if (signal_thread_is_registered) atomic_store(signal_thread_is_registered, 1, memory_order_release); if (common_flags()->use_sigaltstack) SetAlternateSignalStack(); if (!start_routine_) { // start_routine_ == 0 if we're on the main thread or on one of the // OS X libdispatch worker threads. But nobody is supposed to call // ThreadStart() for the worker threads. CHECK_EQ(tid(), 0); return 0; } thread_return_t res = start_routine_(arg_); // On POSIX systems we defer this to the TSD destructor. LSan will consider // the thread's memory as non-live from the moment we call Destroy(), even // though that memory might contain pointers to heap objects which will be // cleaned up by a user-defined TSD destructor. Thus, calling Destroy() before // the TSD destructors have run might cause false positives in LSan. if (!SANITIZER_POSIX) this->Destroy(); return res; } void AsanThread::SetThreadStackAndTls() { uptr tls_size = 0; - GetThreadStackAndTls(tid() == 0, &stack_bottom_, &stack_size_, &tls_begin_, - &tls_size); - stack_top_ = stack_bottom_ + stack_size_; + uptr stack_size = 0; + GetThreadStackAndTls(tid() == 0, const_cast(&stack_bottom_), + const_cast(&stack_size), &tls_begin_, &tls_size); + stack_top_ = stack_bottom_ + stack_size; tls_end_ = tls_begin_ + tls_size; + dtls_ = DTLS_Get(); int local; CHECK(AddrIsInStack((uptr)&local)); } void AsanThread::ClearShadowForThreadStackAndTLS() { PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0); if (tls_begin_ != tls_end_) PoisonShadow(tls_begin_, tls_end_ - tls_begin_, 0); } bool AsanThread::GetStackFrameAccessByAddr(uptr addr, StackFrameAccess *access) { uptr bottom = 0; if (AddrIsInStack(addr)) { bottom = stack_bottom(); } else if (has_fake_stack()) { bottom = fake_stack()->AddrIsInFakeStack(addr); CHECK(bottom); access->offset = addr - bottom; access->frame_pc = ((uptr*)bottom)[2]; access->frame_descr = (const char *)((uptr*)bottom)[1]; return true; } uptr aligned_addr = addr & ~(SANITIZER_WORDSIZE/8 - 1); // align addr. u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr); u8 *shadow_bottom = (u8*)MemToShadow(bottom); while (shadow_ptr >= shadow_bottom && *shadow_ptr != kAsanStackLeftRedzoneMagic) { shadow_ptr--; } while (shadow_ptr >= shadow_bottom && *shadow_ptr == kAsanStackLeftRedzoneMagic) { shadow_ptr--; } if (shadow_ptr < shadow_bottom) { return false; } uptr* ptr = (uptr*)SHADOW_TO_MEM((uptr)(shadow_ptr + 1)); CHECK(ptr[0] == kCurrentStackFrameMagic); access->offset = addr - (uptr)ptr; access->frame_pc = ptr[2]; access->frame_descr = (const char*)ptr[1]; return true; } +bool AsanThread::AddrIsInStack(uptr addr) { + const auto bounds = GetStackBounds(); + return addr >= bounds.bottom && addr < bounds.top; +} + static bool ThreadStackContainsAddress(ThreadContextBase *tctx_base, void *addr) { AsanThreadContext *tctx = static_cast(tctx_base); AsanThread *t = tctx->thread; if (!t) return false; if (t->AddrIsInStack((uptr)addr)) return true; if (t->has_fake_stack() && t->fake_stack()->AddrIsInFakeStack((uptr)addr)) return true; return false; } AsanThread *GetCurrentThread() { AsanThreadContext *context = reinterpret_cast(AsanTSDGet()); if (!context) { if (SANITIZER_ANDROID) { // On Android, libc constructor is called _after_ asan_init, and cleans up // TSD. Try to figure out if this is still the main thread by the stack // address. We are not entirely sure that we have correct main thread // limits, so only do this magic on Android, and only if the found thread // is the main thread. AsanThreadContext *tctx = GetThreadContextByTidLocked(0); if (ThreadStackContainsAddress(tctx, &context)) { SetCurrentThread(tctx->thread); return tctx->thread; } } return nullptr; } return context->thread; } void SetCurrentThread(AsanThread *t) { CHECK(t->context()); VReport(2, "SetCurrentThread: %p for thread %p\n", t->context(), (void *)GetThreadSelf()); // Make sure we do not reset the current AsanThread. CHECK_EQ(0, AsanTSDGet()); AsanTSDSet(t->context()); CHECK_EQ(t->context(), AsanTSDGet()); } u32 GetCurrentTidOrInvalid() { AsanThread *t = GetCurrentThread(); return t ? t->tid() : kInvalidTid; } AsanThread *FindThreadByStackAddress(uptr addr) { asanThreadRegistry().CheckLocked(); AsanThreadContext *tctx = static_cast( asanThreadRegistry().FindThreadContextLocked(ThreadStackContainsAddress, (void *)addr)); return tctx ? tctx->thread : nullptr; } void EnsureMainThreadIDIsCorrect() { AsanThreadContext *context = reinterpret_cast(AsanTSDGet()); if (context && (context->tid == 0)) context->os_id = GetTid(); } __asan::AsanThread *GetAsanThreadByOsIDLocked(uptr os_id) { __asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>( __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id)); if (!context) return nullptr; return context->thread; } } // namespace __asan // --- Implementation of LSan-specific functions --- {{{1 namespace __lsan { bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end, - uptr *tls_begin, uptr *tls_end, - uptr *cache_begin, uptr *cache_end) { + uptr *tls_begin, uptr *tls_end, uptr *cache_begin, + uptr *cache_end, DTLS **dtls) { __asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id); if (!t) return false; *stack_begin = t->stack_bottom(); *stack_end = t->stack_top(); *tls_begin = t->tls_begin(); *tls_end = t->tls_end(); // ASan doesn't keep allocator caches in TLS, so these are unused. *cache_begin = 0; *cache_end = 0; + *dtls = t->dtls(); return true; } void ForEachExtraStackRange(uptr os_id, RangeIteratorCallback callback, void *arg) { __asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id); if (t && t->has_fake_stack()) t->fake_stack()->ForEachFakeFrame(callback, arg); } void LockThreadRegistry() { __asan::asanThreadRegistry().Lock(); } void UnlockThreadRegistry() { __asan::asanThreadRegistry().Unlock(); } void EnsureMainThreadIDIsCorrect() { __asan::EnsureMainThreadIDIsCorrect(); } } // namespace __lsan + +// ---------------------- Interface ---------------- {{{1 +using namespace __asan; // NOLINT + +extern "C" { +SANITIZER_INTERFACE_ATTRIBUTE +void __sanitizer_start_switch_fiber(void **fakestacksave, const void *bottom, + uptr size) { + AsanThread *t = GetCurrentThread(); + if (!t) { + VReport(1, "__asan_start_switch_fiber called from unknown thread\n"); + return; + } + t->StartSwitchFiber((FakeStack**)fakestacksave, (uptr)bottom, size); +} + +SANITIZER_INTERFACE_ATTRIBUTE +void __sanitizer_finish_switch_fiber(void* fakestack) { + AsanThread *t = GetCurrentThread(); + if (!t) { + VReport(1, "__asan_finish_switch_fiber called from unknown thread\n"); + return; + } + t->FinishSwitchFiber((FakeStack*)fakestack); +} +} Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_thread.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_thread.h (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_thread.h (revision 305364) @@ -1,185 +1,205 @@ //===-- asan_thread.h -------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // ASan-private header for asan_thread.cc. //===----------------------------------------------------------------------===// #ifndef ASAN_THREAD_H #define ASAN_THREAD_H #include "asan_allocator.h" #include "asan_internal.h" #include "asan_fake_stack.h" #include "asan_stats.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_thread_registry.h" +namespace __sanitizer { +struct DTLS; +} // namespace __sanitizer + namespace __asan { const u32 kInvalidTid = 0xffffff; // Must fit into 24 bits. const u32 kMaxNumberOfThreads = (1 << 22); // 4M class AsanThread; // These objects are created for every thread and are never deleted, // so we can find them by tid even if the thread is long dead. class AsanThreadContext : public ThreadContextBase { public: explicit AsanThreadContext(int tid) : ThreadContextBase(tid), announced(false), destructor_iterations(GetPthreadDestructorIterations()), stack_id(0), thread(nullptr) {} bool announced; u8 destructor_iterations; u32 stack_id; AsanThread *thread; void OnCreated(void *arg) override; void OnFinished() override; }; // AsanThreadContext objects are never freed, so we need many of them. COMPILER_CHECK(sizeof(AsanThreadContext) <= 256); // AsanThread are stored in TSD and destroyed when the thread dies. class AsanThread { public: static AsanThread *Create(thread_callback_t start_routine, void *arg, u32 parent_tid, StackTrace *stack, bool detached); static void TSDDtor(void *tsd); void Destroy(); void Init(); // Should be called from the thread itself. thread_return_t ThreadStart(uptr os_id, atomic_uintptr_t *signal_thread_is_registered); - uptr stack_top() { return stack_top_; } - uptr stack_bottom() { return stack_bottom_; } - uptr stack_size() { return stack_size_; } + uptr stack_top(); + uptr stack_bottom(); + uptr stack_size(); uptr tls_begin() { return tls_begin_; } uptr tls_end() { return tls_end_; } + DTLS *dtls() { return dtls_; } u32 tid() { return context_->tid; } AsanThreadContext *context() { return context_; } void set_context(AsanThreadContext *context) { context_ = context; } struct StackFrameAccess { uptr offset; uptr frame_pc; const char *frame_descr; }; bool GetStackFrameAccessByAddr(uptr addr, StackFrameAccess *access); - bool AddrIsInStack(uptr addr) { - return addr >= stack_bottom_ && addr < stack_top_; - } + bool AddrIsInStack(uptr addr); void DeleteFakeStack(int tid) { if (!fake_stack_) return; FakeStack *t = fake_stack_; fake_stack_ = nullptr; SetTLSFakeStack(nullptr); t->Destroy(tid); } + void StartSwitchFiber(FakeStack **fake_stack_save, uptr bottom, uptr size); + void FinishSwitchFiber(FakeStack *fake_stack_save); + bool has_fake_stack() { - return (reinterpret_cast(fake_stack_) > 1); + return !atomic_load(&stack_switching_, memory_order_relaxed) && + (reinterpret_cast(fake_stack_) > 1); } FakeStack *fake_stack() { if (!__asan_option_detect_stack_use_after_return) return nullptr; + if (atomic_load(&stack_switching_, memory_order_relaxed)) + return nullptr; if (!has_fake_stack()) return AsyncSignalSafeLazyInitFakeStack(); return fake_stack_; } // True is this thread is currently unwinding stack (i.e. collecting a stack // trace). Used to prevent deadlocks on platforms where libc unwinder calls // malloc internally. See PR17116 for more details. bool isUnwinding() const { return unwinding_; } void setUnwinding(bool b) { unwinding_ = b; } // True if we are in a deadly signal handler. bool isInDeadlySignal() const { return in_deadly_signal_; } void setInDeadlySignal(bool b) { in_deadly_signal_ = b; } AsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; } AsanStats &stats() { return stats_; } private: // NOTE: There is no AsanThread constructor. It is allocated // via mmap() and *must* be valid in zero-initialized state. void SetThreadStackAndTls(); void ClearShadowForThreadStackAndTLS(); FakeStack *AsyncSignalSafeLazyInitFakeStack(); + struct StackBounds { + uptr bottom; + uptr top; + }; + StackBounds GetStackBounds() const; + AsanThreadContext *context_; thread_callback_t start_routine_; void *arg_; + uptr stack_top_; uptr stack_bottom_; - // stack_size_ == stack_top_ - stack_bottom_; - // It needs to be set in a async-signal-safe manner. - uptr stack_size_; + // these variables are used when the thread is about to switch stack + uptr next_stack_top_; + uptr next_stack_bottom_; + // true if switching is in progress + atomic_uint8_t stack_switching_; + uptr tls_begin_; uptr tls_end_; + DTLS *dtls_; FakeStack *fake_stack_; AsanThreadLocalMallocStorage malloc_storage_; AsanStats stats_; bool unwinding_; bool in_deadly_signal_; }; // ScopedUnwinding is a scope for stacktracing member of a context class ScopedUnwinding { public: explicit ScopedUnwinding(AsanThread *t) : thread(t) { t->setUnwinding(true); } ~ScopedUnwinding() { thread->setUnwinding(false); } private: AsanThread *thread; }; // ScopedDeadlySignal is a scope for handling deadly signals. class ScopedDeadlySignal { public: explicit ScopedDeadlySignal(AsanThread *t) : thread(t) { if (thread) thread->setInDeadlySignal(true); } ~ScopedDeadlySignal() { if (thread) thread->setInDeadlySignal(false); } private: AsanThread *thread; }; // Returns a single instance of registry. ThreadRegistry &asanThreadRegistry(); // Must be called under ThreadRegistryLock. AsanThreadContext *GetThreadContextByTidLocked(u32 tid); // Get the current thread. May return 0. AsanThread *GetCurrentThread(); void SetCurrentThread(AsanThread *t); u32 GetCurrentTidOrInvalid(); AsanThread *FindThreadByStackAddress(uptr addr); // Used to handle fork(). void EnsureMainThreadIDIsCorrect(); } // namespace __asan #endif // ASAN_THREAD_H Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_win.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_win.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_win.cc (revision 305364) @@ -1,254 +1,340 @@ //===-- asan_win.cc -------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // Windows-specific details. //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_WINDOWS #define WIN32_LEAN_AND_MEAN #include #include #include "asan_interceptors.h" #include "asan_internal.h" #include "asan_report.h" #include "asan_stack.h" #include "asan_thread.h" +#include "asan_mapping.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_mutex.h" using namespace __asan; // NOLINT extern "C" { SANITIZER_INTERFACE_ATTRIBUTE int __asan_should_detect_stack_use_after_return() { __asan_init(); return __asan_option_detect_stack_use_after_return; } // -------------------- A workaround for the abscence of weak symbols ----- {{{ // We don't have a direct equivalent of weak symbols when using MSVC, but we can // use the /alternatename directive to tell the linker to default a specific // symbol to a specific value, which works nicely for allocator hooks and // __asan_default_options(). void __sanitizer_default_malloc_hook(void *ptr, uptr size) { } void __sanitizer_default_free_hook(void *ptr) { } const char* __asan_default_default_options() { return ""; } const char* __asan_default_default_suppressions() { return ""; } void __asan_default_on_error() {} +// 64-bit msvc will not prepend an underscore for symbols. +#ifdef _WIN64 +#pragma comment(linker, "/alternatename:__sanitizer_malloc_hook=__sanitizer_default_malloc_hook") // NOLINT +#pragma comment(linker, "/alternatename:__sanitizer_free_hook=__sanitizer_default_free_hook") // NOLINT +#pragma comment(linker, "/alternatename:__asan_default_options=__asan_default_default_options") // NOLINT +#pragma comment(linker, "/alternatename:__asan_default_suppressions=__asan_default_default_suppressions") // NOLINT +#pragma comment(linker, "/alternatename:__asan_on_error=__asan_default_on_error") // NOLINT +#else #pragma comment(linker, "/alternatename:___sanitizer_malloc_hook=___sanitizer_default_malloc_hook") // NOLINT #pragma comment(linker, "/alternatename:___sanitizer_free_hook=___sanitizer_default_free_hook") // NOLINT #pragma comment(linker, "/alternatename:___asan_default_options=___asan_default_default_options") // NOLINT #pragma comment(linker, "/alternatename:___asan_default_suppressions=___asan_default_default_suppressions") // NOLINT #pragma comment(linker, "/alternatename:___asan_on_error=___asan_default_on_error") // NOLINT +#endif // }}} } // extern "C" // ---------------------- Windows-specific inteceptors ---------------- {{{ INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) { CHECK(REAL(RaiseException)); __asan_handle_no_return(); REAL(RaiseException)(a, b, c, d); } + +#ifdef _WIN64 + +INTERCEPTOR_WINAPI(int, __C_specific_handler, void *a, void *b, void *c, void *d) { // NOLINT + CHECK(REAL(__C_specific_handler)); + __asan_handle_no_return(); + return REAL(__C_specific_handler)(a, b, c, d); +} + +#else + INTERCEPTOR(int, _except_handler3, void *a, void *b, void *c, void *d) { CHECK(REAL(_except_handler3)); __asan_handle_no_return(); return REAL(_except_handler3)(a, b, c, d); } #if ASAN_DYNAMIC // This handler is named differently in -MT and -MD CRTs. #define _except_handler4 _except_handler4_common #endif INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) { CHECK(REAL(_except_handler4)); __asan_handle_no_return(); return REAL(_except_handler4)(a, b, c, d); } +#endif static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { AsanThread *t = (AsanThread*)arg; SetCurrentThread(t); return t->ThreadStart(GetTid(), /* signal_thread_is_registered */ nullptr); } INTERCEPTOR_WINAPI(DWORD, CreateThread, void* security, uptr stack_size, DWORD (__stdcall *start_routine)(void*), void* arg, DWORD thr_flags, void* tid) { // Strict init-order checking is thread-hostile. if (flags()->strict_init_order) StopInitOrderChecking(); GET_STACK_TRACE_THREAD; // FIXME: The CreateThread interceptor is not the same as a pthread_create // one. This is a bandaid fix for PR22025. bool detached = false; // FIXME: how can we determine it on Windows? u32 current_tid = GetCurrentTidOrInvalid(); AsanThread *t = AsanThread::Create(start_routine, arg, current_tid, &stack, detached); return REAL(CreateThread)(security, stack_size, asan_thread_start, t, thr_flags, tid); } namespace { BlockingMutex mu_for_thread_tracking(LINKER_INITIALIZED); void EnsureWorkerThreadRegistered() { // FIXME: GetCurrentThread relies on TSD, which might not play well with // system thread pools. We might want to use something like reference // counting to zero out GetCurrentThread() underlying storage when the last // work item finishes? Or can we disable reclaiming of threads in the pool? BlockingMutexLock l(&mu_for_thread_tracking); if (__asan::GetCurrentThread()) return; AsanThread *t = AsanThread::Create( /* start_routine */ nullptr, /* arg */ nullptr, /* parent_tid */ -1, /* stack */ nullptr, /* detached */ true); t->Init(); asanThreadRegistry().StartThread(t->tid(), 0, 0); SetCurrentThread(t); } } // namespace INTERCEPTOR_WINAPI(DWORD, NtWaitForWorkViaWorkerFactory, DWORD a, DWORD b) { // NtWaitForWorkViaWorkerFactory is called from system worker pool threads to // query work scheduled by BindIoCompletionCallback, QueueUserWorkItem, etc. // System worker pool threads are created at arbitraty point in time and // without using CreateThread, so we wrap NtWaitForWorkViaWorkerFactory // instead and don't register a specific parent_tid/stack. EnsureWorkerThreadRegistered(); return REAL(NtWaitForWorkViaWorkerFactory)(a, b); } // }}} namespace __asan { void InitializePlatformInterceptors() { ASAN_INTERCEPT_FUNC(CreateThread); ASAN_INTERCEPT_FUNC(RaiseException); + +#ifdef _WIN64 + ASAN_INTERCEPT_FUNC(__C_specific_handler); +#else ASAN_INTERCEPT_FUNC(_except_handler3); ASAN_INTERCEPT_FUNC(_except_handler4); +#endif // NtWaitForWorkViaWorkerFactory is always linked dynamically. CHECK(::__interception::OverrideFunction( "NtWaitForWorkViaWorkerFactory", (uptr)WRAP(NtWaitForWorkViaWorkerFactory), (uptr *)&REAL(NtWaitForWorkViaWorkerFactory))); } +void AsanApplyToGlobals(globals_op_fptr op, const void *needle) { + UNIMPLEMENTED(); +} + // ---------------------- TSD ---------------- {{{ static bool tsd_key_inited = false; static __declspec(thread) void *fake_tsd = 0; void AsanTSDInit(void (*destructor)(void *tsd)) { // FIXME: we're ignoring the destructor for now. tsd_key_inited = true; } void *AsanTSDGet() { CHECK(tsd_key_inited); return fake_tsd; } void AsanTSDSet(void *tsd) { CHECK(tsd_key_inited); fake_tsd = tsd; } void PlatformTSDDtor(void *tsd) { AsanThread::TSDDtor(tsd); } // }}} // ---------------------- Various stuff ---------------- {{{ void *AsanDoesNotSupportStaticLinkage() { #if defined(_DEBUG) #error Please build the runtime with a non-debug CRT: /MD or /MT #endif return 0; } void AsanCheckDynamicRTPrereqs() {} void AsanCheckIncompatibleRT() {} void ReadContextStack(void *context, uptr *stack, uptr *ssize) { UNIMPLEMENTED(); } void AsanOnDeadlySignal(int, void *siginfo, void *context) { UNIMPLEMENTED(); } +#if SANITIZER_WINDOWS64 +// Exception handler for dealing with shadow memory. +static LONG CALLBACK +ShadowExceptionHandler(PEXCEPTION_POINTERS exception_pointers) { + static uptr page_size = GetPageSizeCached(); + static uptr alloc_granularity = GetMmapGranularity(); + // Only handle access violations. + if (exception_pointers->ExceptionRecord->ExceptionCode != + EXCEPTION_ACCESS_VIOLATION) { + return EXCEPTION_CONTINUE_SEARCH; + } + + // Only handle access violations that land within the shadow memory. + uptr addr = + (uptr)(exception_pointers->ExceptionRecord->ExceptionInformation[1]); + + // Check valid shadow range. + if (!AddrIsInShadow(addr)) return EXCEPTION_CONTINUE_SEARCH; + + // This is an access violation while trying to read from the shadow. Commit + // the relevant page and let execution continue. + + // Determine the address of the page that is being accessed. + uptr page = RoundDownTo(addr, page_size); + + // Query the existing page. + MEMORY_BASIC_INFORMATION mem_info = {}; + if (::VirtualQuery((LPVOID)page, &mem_info, sizeof(mem_info)) == 0) + return EXCEPTION_CONTINUE_SEARCH; + + // Commit the page. + uptr result = + (uptr)::VirtualAlloc((LPVOID)page, page_size, MEM_COMMIT, PAGE_READWRITE); + if (result != page) return EXCEPTION_CONTINUE_SEARCH; + + // The page mapping succeeded, so continue execution as usual. + return EXCEPTION_CONTINUE_EXECUTION; +} + +#endif + +void InitializePlatformExceptionHandlers() { +#if SANITIZER_WINDOWS64 + // On Win64, we map memory on demand with access violation handler. + // Install our exception handler. + CHECK(AddVectoredExceptionHandler(TRUE, &ShadowExceptionHandler)); +#endif +} + static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler; static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) { EXCEPTION_RECORD *exception_record = info->ExceptionRecord; CONTEXT *context = info->ContextRecord; if (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION || exception_record->ExceptionCode == EXCEPTION_IN_PAGE_ERROR) { const char *description = (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) ? "access-violation" : "in-page-error"; SignalContext sig = SignalContext::Create(exception_record, context); ReportDeadlySignal(description, sig); } // FIXME: Handle EXCEPTION_STACK_OVERFLOW here. return default_seh_handler(info); } // We want to install our own exception handler (EH) to print helpful reports // on access violations and whatnot. Unfortunately, the CRT initializers assume // they are run before any user code and drop any previously-installed EHs on // the floor, so we can't install our handler inside __asan_init. // (See crt0dat.c in the CRT sources for the details) // // Things get even more complicated with the dynamic runtime, as it finishes its // initialization before the .exe module CRT begins to initialize. // // For the static runtime (-MT), it's enough to put a callback to // __asan_set_seh_filter in the last section for C initializers. // // For the dynamic runtime (-MD), we want link the same // asan_dynamic_runtime_thunk.lib to all the modules, thus __asan_set_seh_filter // will be called for each instrumented module. This ensures that at least one // __asan_set_seh_filter call happens after the .exe module CRT is initialized. extern "C" SANITIZER_INTERFACE_ATTRIBUTE int __asan_set_seh_filter() { // We should only store the previous handler if it's not our own handler in // order to avoid loops in the EH chain. auto prev_seh_handler = SetUnhandledExceptionFilter(SEHHandler); if (prev_seh_handler != &SEHHandler) default_seh_handler = prev_seh_handler; return 0; } #if !ASAN_DYNAMIC -// Put a pointer to __asan_set_seh_filter at the end of the global list -// of C initializers, after the default EH is set by the CRT. -#pragma section(".CRT$XIZ", long, read) // NOLINT -__declspec(allocate(".CRT$XIZ")) +// The CRT runs initializers in this order: +// - C initializers, from XIA to XIZ +// - C++ initializers, from XCA to XCZ +// Prior to 2015, the CRT set the unhandled exception filter at priority XIY, +// near the end of C initialization. Starting in 2015, it was moved to the +// beginning of C++ initialization. We set our priority to XCAB to run +// immediately after the CRT runs. This way, our exception filter is called +// first and we can delegate to their filter if appropriate. +#pragma section(".CRT$XCAB", long, read) // NOLINT +__declspec(allocate(".CRT$XCAB")) int (*__intercept_seh)() = __asan_set_seh_filter; #endif // }}} } // namespace __asan #endif // _WIN32 Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_win_dll_thunk.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_win_dll_thunk.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_win_dll_thunk.cc (revision 305364) @@ -1,427 +1,447 @@ //===-- asan_win_dll_thunk.cc ---------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // This file defines a family of thunks that should be statically linked into // the DLLs that have ASan instrumentation in order to delegate the calls to the // shared runtime that lives in the main binary. // See https://github.com/google/sanitizers/issues/209 for the details. //===----------------------------------------------------------------------===// // Only compile this code when buidling asan_dll_thunk.lib // Using #ifdef rather than relying on Makefiles etc. // simplifies the build procedure. #ifdef ASAN_DLL_THUNK #include "asan_init_version.h" #include "interception/interception.h" +#include "sanitizer_common/sanitizer_platform_interceptors.h" // ---------- Function interception helper functions and macros ----------- {{{1 extern "C" { void *__stdcall GetModuleHandleA(const char *module_name); void *__stdcall GetProcAddress(void *module, const char *proc_name); void abort(); } static uptr getRealProcAddressOrDie(const char *name) { uptr ret = __interception::InternalGetProcAddress((void *)GetModuleHandleA(0), name); if (!ret) abort(); return ret; } // We need to intercept some functions (e.g. ASan interface, memory allocator -- // let's call them "hooks") exported by the DLL thunk and forward the hooks to // the runtime in the main module. // However, we don't want to keep two lists of these hooks. // To avoid that, the list of hooks should be defined using the // INTERCEPT_WHEN_POSSIBLE macro. Then, all these hooks can be intercepted // at once by calling INTERCEPT_HOOKS(). // Use macro+template magic to automatically generate the list of hooks. // Each hook at line LINE defines a template class with a static // FunctionInterceptor::Execute() method intercepting the hook. // The default implementation of FunctionInterceptor is to call // the Execute() method corresponding to the previous line. template struct FunctionInterceptor { static void Execute() { FunctionInterceptor::Execute(); } }; // There shouldn't be any hooks with negative definition line number. template<> struct FunctionInterceptor<0> { static void Execute() {} }; #define INTERCEPT_WHEN_POSSIBLE(main_function, dll_function) \ template <> struct FunctionInterceptor<__LINE__> { \ static void Execute() { \ uptr wrapper = getRealProcAddressOrDie(main_function); \ if (!__interception::OverrideFunction((uptr)dll_function, wrapper, 0)) \ abort(); \ FunctionInterceptor<__LINE__ - 1>::Execute(); \ } \ }; // Special case of hooks -- ASan own interface functions. Those are only called // after __asan_init, thus an empty implementation is sufficient. #define INTERFACE_FUNCTION(name) \ extern "C" __declspec(noinline) void name() { \ volatile int prevent_icf = (__LINE__ << 8); (void)prevent_icf; \ __debugbreak(); \ } \ INTERCEPT_WHEN_POSSIBLE(#name, name) // INTERCEPT_HOOKS must be used after the last INTERCEPT_WHEN_POSSIBLE. #define INTERCEPT_HOOKS FunctionInterceptor<__LINE__>::Execute // We can't define our own version of strlen etc. because that would lead to // link-time or even type mismatch errors. Instead, we can declare a function // just to be able to get its address. Me may miss the first few calls to the // functions since it can be called before __asan_init, but that would lead to // false negatives in the startup code before user's global initializers, which // isn't a big deal. #define INTERCEPT_LIBRARY_FUNCTION(name) \ extern "C" void name(); \ INTERCEPT_WHEN_POSSIBLE(WRAPPER_NAME(name), name) // Disable compiler warnings that show up if we declare our own version // of a compiler intrinsic (e.g. strlen). #pragma warning(disable: 4391) #pragma warning(disable: 4392) static void InterceptHooks(); // }}} // ---------- Function wrapping helpers ----------------------------------- {{{1 #define WRAP_V_V(name) \ extern "C" void name() { \ typedef void (*fntype)(); \ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ fn(); \ } \ INTERCEPT_WHEN_POSSIBLE(#name, name); #define WRAP_V_W(name) \ extern "C" void name(void *arg) { \ typedef void (*fntype)(void *arg); \ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ fn(arg); \ } \ INTERCEPT_WHEN_POSSIBLE(#name, name); #define WRAP_V_WW(name) \ extern "C" void name(void *arg1, void *arg2) { \ typedef void (*fntype)(void *, void *); \ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ fn(arg1, arg2); \ } \ INTERCEPT_WHEN_POSSIBLE(#name, name); #define WRAP_V_WWW(name) \ extern "C" void name(void *arg1, void *arg2, void *arg3) { \ typedef void *(*fntype)(void *, void *, void *); \ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ fn(arg1, arg2, arg3); \ } \ INTERCEPT_WHEN_POSSIBLE(#name, name); #define WRAP_W_V(name) \ extern "C" void *name() { \ typedef void *(*fntype)(); \ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ return fn(); \ } \ INTERCEPT_WHEN_POSSIBLE(#name, name); #define WRAP_W_W(name) \ extern "C" void *name(void *arg) { \ typedef void *(*fntype)(void *arg); \ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ return fn(arg); \ } \ INTERCEPT_WHEN_POSSIBLE(#name, name); #define WRAP_W_WW(name) \ extern "C" void *name(void *arg1, void *arg2) { \ typedef void *(*fntype)(void *, void *); \ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ return fn(arg1, arg2); \ } \ INTERCEPT_WHEN_POSSIBLE(#name, name); #define WRAP_W_WWW(name) \ extern "C" void *name(void *arg1, void *arg2, void *arg3) { \ typedef void *(*fntype)(void *, void *, void *); \ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ return fn(arg1, arg2, arg3); \ } \ INTERCEPT_WHEN_POSSIBLE(#name, name); #define WRAP_W_WWWW(name) \ extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4) { \ typedef void *(*fntype)(void *, void *, void *, void *); \ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ return fn(arg1, arg2, arg3, arg4); \ } \ INTERCEPT_WHEN_POSSIBLE(#name, name); #define WRAP_W_WWWWW(name) \ extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \ void *arg5) { \ typedef void *(*fntype)(void *, void *, void *, void *, void *); \ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ return fn(arg1, arg2, arg3, arg4, arg5); \ } \ INTERCEPT_WHEN_POSSIBLE(#name, name); #define WRAP_W_WWWWWW(name) \ extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \ void *arg5, void *arg6) { \ typedef void *(*fntype)(void *, void *, void *, void *, void *, void *); \ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ return fn(arg1, arg2, arg3, arg4, arg5, arg6); \ } \ INTERCEPT_WHEN_POSSIBLE(#name, name); // }}} // ----------------- ASan own interface functions -------------------- // Don't use the INTERFACE_FUNCTION machinery for this function as we actually // want to call it in the __asan_init interceptor. WRAP_W_V(__asan_should_detect_stack_use_after_return) extern "C" { int __asan_option_detect_stack_use_after_return; // Manually wrap __asan_init as we need to initialize // __asan_option_detect_stack_use_after_return afterwards. void __asan_init() { typedef void (*fntype)(); static fntype fn = 0; // __asan_init is expected to be called by only one thread. if (fn) return; fn = (fntype)getRealProcAddressOrDie("__asan_init"); fn(); __asan_option_detect_stack_use_after_return = (__asan_should_detect_stack_use_after_return() != 0); InterceptHooks(); } } extern "C" void __asan_version_mismatch_check() { // Do nothing. } INTERFACE_FUNCTION(__asan_handle_no_return) INTERFACE_FUNCTION(__asan_report_store1) INTERFACE_FUNCTION(__asan_report_store2) INTERFACE_FUNCTION(__asan_report_store4) INTERFACE_FUNCTION(__asan_report_store8) INTERFACE_FUNCTION(__asan_report_store16) INTERFACE_FUNCTION(__asan_report_store_n) INTERFACE_FUNCTION(__asan_report_load1) INTERFACE_FUNCTION(__asan_report_load2) INTERFACE_FUNCTION(__asan_report_load4) INTERFACE_FUNCTION(__asan_report_load8) INTERFACE_FUNCTION(__asan_report_load16) INTERFACE_FUNCTION(__asan_report_load_n) INTERFACE_FUNCTION(__asan_store1) INTERFACE_FUNCTION(__asan_store2) INTERFACE_FUNCTION(__asan_store4) INTERFACE_FUNCTION(__asan_store8) INTERFACE_FUNCTION(__asan_store16) INTERFACE_FUNCTION(__asan_storeN) INTERFACE_FUNCTION(__asan_load1) INTERFACE_FUNCTION(__asan_load2) INTERFACE_FUNCTION(__asan_load4) INTERFACE_FUNCTION(__asan_load8) INTERFACE_FUNCTION(__asan_load16) INTERFACE_FUNCTION(__asan_loadN) INTERFACE_FUNCTION(__asan_memcpy); INTERFACE_FUNCTION(__asan_memset); INTERFACE_FUNCTION(__asan_memmove); INTERFACE_FUNCTION(__asan_alloca_poison); INTERFACE_FUNCTION(__asan_allocas_unpoison); INTERFACE_FUNCTION(__asan_register_globals) INTERFACE_FUNCTION(__asan_unregister_globals) INTERFACE_FUNCTION(__asan_before_dynamic_init) INTERFACE_FUNCTION(__asan_after_dynamic_init) INTERFACE_FUNCTION(__asan_poison_stack_memory) INTERFACE_FUNCTION(__asan_unpoison_stack_memory) INTERFACE_FUNCTION(__asan_poison_memory_region) INTERFACE_FUNCTION(__asan_unpoison_memory_region) INTERFACE_FUNCTION(__asan_address_is_poisoned) INTERFACE_FUNCTION(__asan_region_is_poisoned) INTERFACE_FUNCTION(__asan_get_current_fake_stack) INTERFACE_FUNCTION(__asan_addr_is_in_fake_stack) INTERFACE_FUNCTION(__asan_stack_malloc_0) INTERFACE_FUNCTION(__asan_stack_malloc_1) INTERFACE_FUNCTION(__asan_stack_malloc_2) INTERFACE_FUNCTION(__asan_stack_malloc_3) INTERFACE_FUNCTION(__asan_stack_malloc_4) INTERFACE_FUNCTION(__asan_stack_malloc_5) INTERFACE_FUNCTION(__asan_stack_malloc_6) INTERFACE_FUNCTION(__asan_stack_malloc_7) INTERFACE_FUNCTION(__asan_stack_malloc_8) INTERFACE_FUNCTION(__asan_stack_malloc_9) INTERFACE_FUNCTION(__asan_stack_malloc_10) INTERFACE_FUNCTION(__asan_stack_free_0) INTERFACE_FUNCTION(__asan_stack_free_1) INTERFACE_FUNCTION(__asan_stack_free_2) INTERFACE_FUNCTION(__asan_stack_free_4) INTERFACE_FUNCTION(__asan_stack_free_5) INTERFACE_FUNCTION(__asan_stack_free_6) INTERFACE_FUNCTION(__asan_stack_free_7) INTERFACE_FUNCTION(__asan_stack_free_8) INTERFACE_FUNCTION(__asan_stack_free_9) INTERFACE_FUNCTION(__asan_stack_free_10) // FIXME: we might want to have a sanitizer_win_dll_thunk? INTERFACE_FUNCTION(__sanitizer_annotate_contiguous_container) INTERFACE_FUNCTION(__sanitizer_contiguous_container_find_bad_address) INTERFACE_FUNCTION(__sanitizer_cov) INTERFACE_FUNCTION(__sanitizer_cov_dump) INTERFACE_FUNCTION(__sanitizer_cov_indir_call16) INTERFACE_FUNCTION(__sanitizer_cov_init) INTERFACE_FUNCTION(__sanitizer_cov_module_init) INTERFACE_FUNCTION(__sanitizer_cov_trace_basic_block) INTERFACE_FUNCTION(__sanitizer_cov_trace_func_enter) INTERFACE_FUNCTION(__sanitizer_cov_trace_cmp) INTERFACE_FUNCTION(__sanitizer_cov_trace_switch) INTERFACE_FUNCTION(__sanitizer_cov_with_check) INTERFACE_FUNCTION(__sanitizer_get_allocated_size) INTERFACE_FUNCTION(__sanitizer_get_coverage_guards) INTERFACE_FUNCTION(__sanitizer_get_coverage_pc_buffer) INTERFACE_FUNCTION(__sanitizer_get_current_allocated_bytes) INTERFACE_FUNCTION(__sanitizer_get_estimated_allocated_size) INTERFACE_FUNCTION(__sanitizer_get_free_bytes) INTERFACE_FUNCTION(__sanitizer_get_heap_size) INTERFACE_FUNCTION(__sanitizer_get_ownership) INTERFACE_FUNCTION(__sanitizer_get_total_unique_caller_callee_pairs) INTERFACE_FUNCTION(__sanitizer_get_total_unique_coverage) INTERFACE_FUNCTION(__sanitizer_get_unmapped_bytes) INTERFACE_FUNCTION(__sanitizer_maybe_open_cov_file) INTERFACE_FUNCTION(__sanitizer_print_stack_trace) INTERFACE_FUNCTION(__sanitizer_ptr_cmp) INTERFACE_FUNCTION(__sanitizer_ptr_sub) INTERFACE_FUNCTION(__sanitizer_report_error_summary) INTERFACE_FUNCTION(__sanitizer_reset_coverage) INTERFACE_FUNCTION(__sanitizer_get_number_of_counters) INTERFACE_FUNCTION(__sanitizer_update_counter_bitset_and_clear_counters) INTERFACE_FUNCTION(__sanitizer_sandbox_on_notify) INTERFACE_FUNCTION(__sanitizer_set_death_callback) INTERFACE_FUNCTION(__sanitizer_set_report_path) +INTERFACE_FUNCTION(__sanitizer_set_report_fd) INTERFACE_FUNCTION(__sanitizer_unaligned_load16) INTERFACE_FUNCTION(__sanitizer_unaligned_load32) INTERFACE_FUNCTION(__sanitizer_unaligned_load64) INTERFACE_FUNCTION(__sanitizer_unaligned_store16) INTERFACE_FUNCTION(__sanitizer_unaligned_store32) INTERFACE_FUNCTION(__sanitizer_unaligned_store64) INTERFACE_FUNCTION(__sanitizer_verify_contiguous_container) +INTERFACE_FUNCTION(__sanitizer_install_malloc_and_free_hooks) +INTERFACE_FUNCTION(__sanitizer_start_switch_fiber) +INTERFACE_FUNCTION(__sanitizer_finish_switch_fiber) // TODO(timurrrr): Add more interface functions on the as-needed basis. // ----------------- Memory allocation functions --------------------- WRAP_V_W(free) +WRAP_V_W(_free_base) WRAP_V_WW(_free_dbg) WRAP_W_W(malloc) +WRAP_W_W(_malloc_base) WRAP_W_WWWW(_malloc_dbg) WRAP_W_WW(calloc) +WRAP_W_WW(_calloc_base) WRAP_W_WWWWW(_calloc_dbg) WRAP_W_WWW(_calloc_impl) WRAP_W_WW(realloc) +WRAP_W_WW(_realloc_base) WRAP_W_WWW(_realloc_dbg) WRAP_W_WWW(_recalloc) WRAP_W_W(_msize) WRAP_W_W(_expand) WRAP_W_W(_expand_dbg) // TODO(timurrrr): Might want to add support for _aligned_* allocation // functions to detect a bit more bugs. Those functions seem to wrap malloc(). // TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cc). INTERCEPT_LIBRARY_FUNCTION(atoi); INTERCEPT_LIBRARY_FUNCTION(atol); + +#ifdef _WIN64 +INTERCEPT_LIBRARY_FUNCTION(__C_specific_handler); +#else INTERCEPT_LIBRARY_FUNCTION(_except_handler3); // _except_handler4 checks -GS cookie which is different for each module, so we // can't use INTERCEPT_LIBRARY_FUNCTION(_except_handler4). INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) { __asan_handle_no_return(); return REAL(_except_handler4)(a, b, c, d); } +#endif INTERCEPT_LIBRARY_FUNCTION(frexp); INTERCEPT_LIBRARY_FUNCTION(longjmp); +#if SANITIZER_INTERCEPT_MEMCHR INTERCEPT_LIBRARY_FUNCTION(memchr); +#endif INTERCEPT_LIBRARY_FUNCTION(memcmp); INTERCEPT_LIBRARY_FUNCTION(memcpy); INTERCEPT_LIBRARY_FUNCTION(memmove); INTERCEPT_LIBRARY_FUNCTION(memset); INTERCEPT_LIBRARY_FUNCTION(strcat); // NOLINT INTERCEPT_LIBRARY_FUNCTION(strchr); INTERCEPT_LIBRARY_FUNCTION(strcmp); INTERCEPT_LIBRARY_FUNCTION(strcpy); // NOLINT INTERCEPT_LIBRARY_FUNCTION(strcspn); +INTERCEPT_LIBRARY_FUNCTION(strdup); INTERCEPT_LIBRARY_FUNCTION(strlen); INTERCEPT_LIBRARY_FUNCTION(strncat); INTERCEPT_LIBRARY_FUNCTION(strncmp); INTERCEPT_LIBRARY_FUNCTION(strncpy); INTERCEPT_LIBRARY_FUNCTION(strnlen); INTERCEPT_LIBRARY_FUNCTION(strpbrk); +INTERCEPT_LIBRARY_FUNCTION(strrchr); INTERCEPT_LIBRARY_FUNCTION(strspn); INTERCEPT_LIBRARY_FUNCTION(strstr); INTERCEPT_LIBRARY_FUNCTION(strtol); INTERCEPT_LIBRARY_FUNCTION(wcslen); // Must be after all the interceptor declarations due to the way INTERCEPT_HOOKS // is defined. void InterceptHooks() { INTERCEPT_HOOKS(); +#ifndef _WIN64 INTERCEPT_FUNCTION(_except_handler4); +#endif } // We want to call __asan_init before C/C++ initializers/constructors are // executed, otherwise functions like memset might be invoked. // For some strange reason, merely linking in asan_preinit.cc doesn't work // as the callback is never called... Is link.exe doing something too smart? // In DLLs, the callbacks are expected to return 0, // otherwise CRT initialization fails. static int call_asan_init() { __asan_init(); return 0; } #pragma section(".CRT$XIB", long, read) // NOLINT __declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = call_asan_init; #endif // ASAN_DLL_THUNK Index: projects/clang390-import/contrib/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cc (revision 305364) @@ -1,99 +1,100 @@ //===-- asan_win_uar_thunk.cc ---------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // This file defines things that need to be present in the application modules // to interact with the ASan DLL runtime correctly and can't be implemented // using the default "import library" generated when linking the DLL RTL. // // This includes: // - forwarding the detect_stack_use_after_return runtime option // - working around deficiencies of the MD runtime // - installing a custom SEH handlerx // //===----------------------------------------------------------------------===// // Only compile this code when buidling asan_dynamic_runtime_thunk.lib // Using #ifdef rather than relying on Makefiles etc. // simplifies the build procedure. #ifdef ASAN_DYNAMIC_RUNTIME_THUNK #define WIN32_LEAN_AND_MEAN #include // First, declare CRT sections we'll be using in this file #pragma section(".CRT$XID", long, read) // NOLINT -#pragma section(".CRT$XIZ", long, read) // NOLINT +#pragma section(".CRT$XCAB", long, read) // NOLINT #pragma section(".CRT$XTW", long, read) // NOLINT #pragma section(".CRT$XTY", long, read) // NOLINT //////////////////////////////////////////////////////////////////////////////// // Define a copy of __asan_option_detect_stack_use_after_return that should be // used when linking an MD runtime with a set of object files on Windows. // // The ASan MD runtime dllexports '__asan_option_detect_stack_use_after_return', // so normally we would just dllimport it. Unfortunately, the dllimport // attribute adds __imp_ prefix to the symbol name of a variable. // Since in general we don't know if a given TU is going to be used // with a MT or MD runtime and we don't want to use ugly __imp_ names on Windows // just to work around this issue, let's clone the a variable that is // constant after initialization anyways. extern "C" { __declspec(dllimport) int __asan_should_detect_stack_use_after_return(); int __asan_option_detect_stack_use_after_return = __asan_should_detect_stack_use_after_return(); } //////////////////////////////////////////////////////////////////////////////// // For some reason, the MD CRT doesn't call the C/C++ terminators during on DLL // unload or on exit. ASan relies on LLVM global_dtors to call // __asan_unregister_globals on these events, which unfortunately doesn't work // with the MD runtime, see PR22545 for the details. // To work around this, for each DLL we schedule a call to UnregisterGlobals // using atexit() that calls a small subset of C terminators // where LLVM global_dtors is placed. Fingers crossed, no other C terminators // are there. extern "C" int __cdecl atexit(void (__cdecl *f)(void)); extern "C" void __cdecl _initterm(void *a, void *b); namespace { __declspec(allocate(".CRT$XTW")) void* before_global_dtors = 0; __declspec(allocate(".CRT$XTY")) void* after_global_dtors = 0; void UnregisterGlobals() { _initterm(&before_global_dtors, &after_global_dtors); } int ScheduleUnregisterGlobals() { return atexit(UnregisterGlobals); } // We need to call 'atexit(UnregisterGlobals);' as early as possible, but after // atexit() is initialized (.CRT$XIC). As this is executed before C++ // initializers (think ctors for globals), UnregisterGlobals gets executed after // dtors for C++ globals. __declspec(allocate(".CRT$XID")) int (*__asan_schedule_unregister_globals)() = ScheduleUnregisterGlobals; } // namespace //////////////////////////////////////////////////////////////////////////////// // ASan SEH handling. // We need to set the ASan-specific SEH handler at the end of CRT initialization // of each module (see also asan_win.cc). extern "C" { __declspec(dllimport) int __asan_set_seh_filter(); static int SetSEHFilter() { return __asan_set_seh_filter(); } // Unfortunately, putting a pointer to __asan_set_seh_filter into // __asan_intercept_seh gets optimized out, so we have to use an extra function. -__declspec(allocate(".CRT$XIZ")) int (*__asan_seh_interceptor)() = SetSEHFilter; +__declspec(allocate(".CRT$XCAB")) int (*__asan_seh_interceptor)() = + SetSEHFilter; } #endif // ASAN_DYNAMIC_RUNTIME_THUNK Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/adddf3vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/adddf3vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/adddf3vfp.S (revision 305364) @@ -1,26 +1,29 @@ //===-- adddf3vfp.S - Implement adddf3vfp ---------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // double __adddf3vfp(double a, double b) { return a + b; } // // Adds two double precision floating point numbers using the Darwin // calling convention where double arguments are passsed in GPR pairs // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__adddf3vfp) vmov d6, r0, r1 // move first param from r0/r1 pair into d6 vmov d7, r2, r3 // move second param from r2/r3 pair into d7 vadd.f64 d6, d6, d7 vmov r0, r1, d6 // move result back to r0/r1 pair bx lr END_COMPILERRT_FUNCTION(__adddf3vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/addsf3vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/addsf3vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/addsf3vfp.S (revision 305364) @@ -1,26 +1,29 @@ //===-- addsf3vfp.S - Implement addsf3vfp ---------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern float __addsf3vfp(float a, float b); // // Adds two single precision floating point numbers using the Darwin // calling convention where single arguments are passsed in GPRs // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__addsf3vfp) vmov s14, r0 // move first param from r0 into float register vmov s15, r1 // move second param from r1 into float register vadd.f32 s14, s14, s15 vmov r0, s14 // move result back to r0 bx lr END_COMPILERRT_FUNCTION(__addsf3vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_cdcmp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_cdcmp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_cdcmp.S (revision 305364) @@ -1,96 +1,98 @@ //===-- aeabi_cdcmp.S - EABI cdcmp* implementation ------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ #error big endian support not implemented #endif #define APSR_Z (1 << 30) #define APSR_C (1 << 29) // void __aeabi_cdcmpeq(double a, double b) { // if (isnan(a) || isnan(b)) { // Z = 0; C = 1; // } else { // __aeabi_cdcmple(a, b); // } // } .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmpeq) push {r0-r3, lr} bl __aeabi_cdcmpeq_check_nan cmp r0, #1 pop {r0-r3, lr} // NaN has been ruled out, so __aeabi_cdcmple can't trap bne __aeabi_cdcmple msr CPSR_f, #APSR_C JMP(lr) END_COMPILERRT_FUNCTION(__aeabi_cdcmpeq) // void __aeabi_cdcmple(double a, double b) { // if (__aeabi_dcmplt(a, b)) { // Z = 0; C = 0; // } else if (__aeabi_dcmpeq(a, b)) { // Z = 1; C = 1; // } else { // Z = 0; C = 1; // } // } .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmple) // Per the RTABI, this function must preserve r0-r11. // Save lr in the same instruction for compactness push {r0-r3, lr} bl __aeabi_dcmplt cmp r0, #1 moveq ip, #0 beq 1f ldm sp, {r0-r3} bl __aeabi_dcmpeq cmp r0, #1 moveq ip, #(APSR_C | APSR_Z) movne ip, #(APSR_C) 1: msr CPSR_f, ip pop {r0-r3} POP_PC() END_COMPILERRT_FUNCTION(__aeabi_cdcmple) // int __aeabi_cdrcmple(double a, double b) { // return __aeabi_cdcmple(b, a); // } .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__aeabi_cdrcmple) // Swap r0 and r2 mov ip, r0 mov r0, r2 mov r2, ip // Swap r1 and r3 mov ip, r1 mov r1, r3 mov r3, ip b __aeabi_cdcmple END_COMPILERRT_FUNCTION(__aeabi_cdrcmple) +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_cfcmp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_cfcmp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_cfcmp.S (revision 305364) @@ -1,91 +1,93 @@ //===-- aeabi_cfcmp.S - EABI cfcmp* implementation ------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ #error big endian support not implemented #endif #define APSR_Z (1 << 30) #define APSR_C (1 << 29) // void __aeabi_cfcmpeq(float a, float b) { // if (isnan(a) || isnan(b)) { // Z = 0; C = 1; // } else { // __aeabi_cfcmple(a, b); // } // } .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__aeabi_cfcmpeq) push {r0-r3, lr} bl __aeabi_cfcmpeq_check_nan cmp r0, #1 pop {r0-r3, lr} // NaN has been ruled out, so __aeabi_cfcmple can't trap bne __aeabi_cfcmple msr CPSR_f, #APSR_C JMP(lr) END_COMPILERRT_FUNCTION(__aeabi_cfcmpeq) // void __aeabi_cfcmple(float a, float b) { // if (__aeabi_fcmplt(a, b)) { // Z = 0; C = 0; // } else if (__aeabi_fcmpeq(a, b)) { // Z = 1; C = 1; // } else { // Z = 0; C = 1; // } // } .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__aeabi_cfcmple) // Per the RTABI, this function must preserve r0-r11. // Save lr in the same instruction for compactness push {r0-r3, lr} bl __aeabi_fcmplt cmp r0, #1 moveq ip, #0 beq 1f ldm sp, {r0-r3} bl __aeabi_fcmpeq cmp r0, #1 moveq ip, #(APSR_C | APSR_Z) movne ip, #(APSR_C) 1: msr CPSR_f, ip pop {r0-r3} POP_PC() END_COMPILERRT_FUNCTION(__aeabi_cfcmple) // int __aeabi_cfrcmple(float a, float b) { // return __aeabi_cfcmple(b, a); // } .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__aeabi_cfrcmple) // Swap r0 and r1 mov ip, r0 mov r0, r1 mov r1, ip b __aeabi_cfcmple END_COMPILERRT_FUNCTION(__aeabi_cfrcmple) +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_dcmp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_dcmp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_dcmp.S (revision 305364) @@ -1,40 +1,43 @@ //===-- aeabi_dcmp.S - EABI dcmp* implementation ---------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // int __aeabi_dcmp{eq,lt,le,ge,gt}(double a, double b) { // int result = __{eq,lt,le,ge,gt}df2(a, b); // if (result {==,<,<=,>=,>} 0) { // return 1; // } else { // return 0; // } // } #define DEFINE_AEABI_DCMP(cond) \ .syntax unified SEPARATOR \ .p2align 2 SEPARATOR \ DEFINE_COMPILERRT_FUNCTION(__aeabi_dcmp ## cond) \ push { r4, lr } SEPARATOR \ bl SYMBOL_NAME(__ ## cond ## df2) SEPARATOR \ cmp r0, #0 SEPARATOR \ b ## cond 1f SEPARATOR \ mov r0, #0 SEPARATOR \ pop { r4, pc } SEPARATOR \ 1: SEPARATOR \ mov r0, #1 SEPARATOR \ pop { r4, pc } SEPARATOR \ END_COMPILERRT_FUNCTION(__aeabi_dcmp ## cond) DEFINE_AEABI_DCMP(eq) DEFINE_AEABI_DCMP(lt) DEFINE_AEABI_DCMP(le) DEFINE_AEABI_DCMP(ge) DEFINE_AEABI_DCMP(gt) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_fcmp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_fcmp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_fcmp.S (revision 305364) @@ -1,40 +1,43 @@ //===-- aeabi_fcmp.S - EABI fcmp* implementation ---------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // int __aeabi_fcmp{eq,lt,le,ge,gt}(float a, float b) { // int result = __{eq,lt,le,ge,gt}sf2(a, b); // if (result {==,<,<=,>=,>} 0) { // return 1; // } else { // return 0; // } // } #define DEFINE_AEABI_FCMP(cond) \ .syntax unified SEPARATOR \ .p2align 2 SEPARATOR \ DEFINE_COMPILERRT_FUNCTION(__aeabi_fcmp ## cond) \ push { r4, lr } SEPARATOR \ bl SYMBOL_NAME(__ ## cond ## sf2) SEPARATOR \ cmp r0, #0 SEPARATOR \ b ## cond 1f SEPARATOR \ mov r0, #0 SEPARATOR \ pop { r4, pc } SEPARATOR \ 1: SEPARATOR \ mov r0, #1 SEPARATOR \ pop { r4, pc } SEPARATOR \ END_COMPILERRT_FUNCTION(__aeabi_fcmp ## cond) DEFINE_AEABI_FCMP(eq) DEFINE_AEABI_FCMP(lt) DEFINE_AEABI_FCMP(le) DEFINE_AEABI_FCMP(ge) DEFINE_AEABI_FCMP(gt) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_idivmod.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_idivmod.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_idivmod.S (revision 305364) @@ -1,28 +1,31 @@ //===-- aeabi_idivmod.S - EABI idivmod implementation ---------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // struct { int quot, int rem} __aeabi_idivmod(int numerator, int denominator) { // int rem, quot; // quot = __divmodsi4(numerator, denominator, &rem); // return {quot, rem}; // } .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__aeabi_idivmod) push { lr } sub sp, sp, #4 mov r2, sp bl SYMBOL_NAME(__divmodsi4) ldr r1, [sp] add sp, sp, #4 pop { pc } END_COMPILERRT_FUNCTION(__aeabi_idivmod) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_ldivmod.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_ldivmod.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_ldivmod.S (revision 305364) @@ -1,31 +1,34 @@ //===-- aeabi_ldivmod.S - EABI ldivmod implementation ---------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // struct { int64_t quot, int64_t rem} // __aeabi_ldivmod(int64_t numerator, int64_t denominator) { // int64_t rem, quot; // quot = __divmoddi4(numerator, denominator, &rem); // return {quot, rem}; // } .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__aeabi_ldivmod) push {r11, lr} sub sp, sp, #16 add r12, sp, #8 str r12, [sp] bl SYMBOL_NAME(__divmoddi4) ldr r2, [sp, #8] ldr r3, [sp, #12] add sp, sp, #16 pop {r11, pc} END_COMPILERRT_FUNCTION(__aeabi_ldivmod) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_memcmp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_memcmp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_memcmp.S (revision 305364) @@ -1,22 +1,24 @@ //===-- aeabi_memcmp.S - EABI memcmp implementation -----------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // void __aeabi_memcmp(void *dest, void *src, size_t n) { memcmp(dest, src, n); } + .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__aeabi_memcmp) b memcmp END_COMPILERRT_FUNCTION(__aeabi_memcmp) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcmp4, __aeabi_memcmp) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcmp8, __aeabi_memcmp) - .section .note.GNU-stack,"",%progbits +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_memcpy.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_memcpy.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_memcpy.S (revision 305364) @@ -1,22 +1,24 @@ //===-- aeabi_memcpy.S - EABI memcpy implementation -----------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // void __aeabi_memcpy(void *dest, void *src, size_t n) { memcpy(dest, src, n); } + .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__aeabi_memcpy) b memcpy END_COMPILERRT_FUNCTION(__aeabi_memcpy) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcpy4, __aeabi_memcpy) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcpy8, __aeabi_memcpy) - .section .note.GNU-stack,"",%progbits +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_memmove.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_memmove.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_memmove.S (revision 305364) @@ -1,22 +1,23 @@ //===-- aeabi_memmove.S - EABI memmove implementation --------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===---------------------------------------------------------------------===// #include "../assembly.h" // void __aeabi_memmove(void *dest, void *src, size_t n) { memmove(dest, src, n); } .p2align 2 DEFINE_COMPILERRT_FUNCTION(__aeabi_memmove) b memmove END_COMPILERRT_FUNCTION(__aeabi_memmove) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memmove4, __aeabi_memmove) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memmove8, __aeabi_memmove) - .section .note.GNU-stack,"",%progbits +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_memset.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_memset.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_memset.S (revision 305364) @@ -1,35 +1,37 @@ //===-- aeabi_memset.S - EABI memset implementation -----------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // void __aeabi_memset(void *dest, size_t n, int c) { memset(dest, c, n); } // void __aeabi_memclr(void *dest, size_t n) { __aeabi_memset(dest, n, 0); } + .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__aeabi_memset) mov r3, r1 mov r1, r2 mov r2, r3 b memset END_COMPILERRT_FUNCTION(__aeabi_memset) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memset4, __aeabi_memset) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memset8, __aeabi_memset) DEFINE_COMPILERRT_FUNCTION(__aeabi_memclr) mov r2, r1 mov r1, #0 b memset END_COMPILERRT_FUNCTION(__aeabi_memclr) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memclr4, __aeabi_memclr) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memclr8, __aeabi_memclr) - .section .note.GNU-stack,"",%progbits +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S (revision 305364) @@ -1,29 +1,32 @@ //===-- aeabi_uidivmod.S - EABI uidivmod implementation -------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // struct { unsigned quot, unsigned rem} // __aeabi_uidivmod(unsigned numerator, unsigned denominator) { // unsigned rem, quot; // quot = __udivmodsi4(numerator, denominator, &rem); // return {quot, rem}; // } .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__aeabi_uidivmod) push { lr } sub sp, sp, #4 mov r2, sp bl SYMBOL_NAME(__udivmodsi4) ldr r1, [sp] add sp, sp, #4 pop { pc } END_COMPILERRT_FUNCTION(__aeabi_uidivmod) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_uldivmod.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_uldivmod.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/aeabi_uldivmod.S (revision 305364) @@ -1,31 +1,34 @@ //===-- aeabi_uldivmod.S - EABI uldivmod implementation -------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // struct { uint64_t quot, uint64_t rem} // __aeabi_uldivmod(uint64_t numerator, uint64_t denominator) { // uint64_t rem, quot; // quot = __udivmoddi4(numerator, denominator, &rem); // return {quot, rem}; // } .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__aeabi_uldivmod) push {r11, lr} sub sp, sp, #16 add r12, sp, #8 str r12, [sp] bl SYMBOL_NAME(__udivmoddi4) ldr r2, [sp, #8] ldr r3, [sp, #12] add sp, sp, #16 pop {r11, pc} END_COMPILERRT_FUNCTION(__aeabi_uldivmod) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/bswapdi2.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/bswapdi2.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/bswapdi2.S (revision 305364) @@ -1,47 +1,50 @@ //===------- bswapdi2 - Implement bswapdi2 --------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" .syntax unified .text #if __ARM_ARCH_ISA_THUMB == 2 .thumb #endif // // extern uint64_t __bswapdi2(uint64_t); // // Reverse all the bytes in a 64-bit integer. // .p2align 2 #if __ARM_ARCH_ISA_THUMB == 2 DEFINE_COMPILERRT_THUMB_FUNCTION(__bswapdi2) #else DEFINE_COMPILERRT_FUNCTION(__bswapdi2) #endif #if __ARM_ARCH < 6 // before armv6 does not have "rev" instruction // r2 = rev(r0) eor r2, r0, r0, ror #16 bic r2, r2, #0xff0000 mov r2, r2, lsr #8 eor r2, r2, r0, ror #8 // r0 = rev(r1) eor r0, r1, r1, ror #16 bic r0, r0, #0xff0000 mov r0, r0, lsr #8 eor r0, r0, r1, ror #8 #else rev r2, r0 // r2 = rev(r0) rev r0, r1 // r0 = rev(r1) #endif mov r1, r2 // r1 = r2 = rev(r0) JMP(lr) END_COMPILERRT_FUNCTION(__bswapdi2) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/bswapsi2.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/bswapsi2.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/bswapsi2.S (revision 305364) @@ -1,39 +1,42 @@ //===------- bswapsi2 - Implement bswapsi2 --------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" .syntax unified .text #if __ARM_ARCH_ISA_THUMB == 2 .thumb #endif // // extern uint32_t __bswapsi2(uint32_t); // // Reverse all the bytes in a 32-bit integer. // .p2align 2 #if __ARM_ARCH_ISA_THUMB == 2 DEFINE_COMPILERRT_THUMB_FUNCTION(__bswapsi2) #else DEFINE_COMPILERRT_FUNCTION(__bswapsi2) #endif #if __ARM_ARCH < 6 // before armv6 does not have "rev" instruction eor r1, r0, r0, ror #16 bic r1, r1, #0xff0000 mov r1, r1, lsr #8 eor r0, r1, r0, ror #8 #else rev r0, r0 #endif JMP(lr) END_COMPILERRT_FUNCTION(__bswapsi2) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/clzdi2.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/clzdi2.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/clzdi2.S (revision 305364) @@ -1,97 +1,100 @@ /* ===-- clzdi2.c - Implement __clzdi2 -------------------------------------=== * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== * * This file implements count leading zeros for 64bit arguments. * * ===----------------------------------------------------------------------=== */ #include "../assembly.h" .syntax unified .text #if __ARM_ARCH_ISA_THUMB == 2 .thumb #endif .p2align 2 #if __ARM_ARCH_ISA_THUMB == 2 DEFINE_COMPILERRT_THUMB_FUNCTION(__clzdi2) #else DEFINE_COMPILERRT_FUNCTION(__clzdi2) #endif #ifdef __ARM_FEATURE_CLZ #ifdef __ARMEB__ cmp r0, 0 itee ne clzne r0, r0 clzeq r0, r1 addeq r0, r0, 32 #else cmp r1, 0 itee ne clzne r0, r1 clzeq r0, r0 addeq r0, r0, 32 #endif JMP(lr) #else /* Assumption: n != 0 */ /* * r0: n * r1: upper half of n, overwritten after check * r1: count of leading zeros in n + 1 * r2: scratch register for shifted r0 */ #ifdef __ARMEB__ cmp r0, 0 moveq r0, r1 #else cmp r1, 0 movne r0, r1 #endif movne r1, 1 moveq r1, 33 /* * Basic block: * if ((r0 >> SHIFT) == 0) * r1 += SHIFT; * else * r0 >>= SHIFT; * for descending powers of two as SHIFT. */ #define BLOCK(shift) \ lsrs r2, r0, shift; \ movne r0, r2; \ addeq r1, shift \ BLOCK(16) BLOCK(8) BLOCK(4) BLOCK(2) /* * The basic block invariants at this point are (r0 >> 2) == 0 and * r0 != 0. This means 1 <= r0 <= 3 and 0 <= (r0 >> 1) <= 1. * * r0 | (r0 >> 1) == 0 | (r0 >> 1) == 1 | -(r0 >> 1) | 1 - (r0 >> 1) * ---+----------------+----------------+------------+-------------- * 1 | 1 | 0 | 0 | 1 * 2 | 0 | 1 | -1 | 0 * 3 | 0 | 1 | -1 | 0 * * The r1's initial value of 1 compensates for the 1 here. */ sub r0, r1, r0, lsr #1 JMP(lr) #endif // __ARM_FEATURE_CLZ END_COMPILERRT_FUNCTION(__clzdi2) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/clzsi2.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/clzsi2.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/clzsi2.S (revision 305364) @@ -1,76 +1,79 @@ /* ===-- clzsi2.c - Implement __clzsi2 -------------------------------------=== * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== * * This file implements count leading zeros for 32bit arguments. * * ===----------------------------------------------------------------------=== */ #include "../assembly.h" .syntax unified .text #if __ARM_ARCH_ISA_THUMB == 2 .thumb #endif .p2align 2 #if __ARM_ARCH_ISA_THUMB == 2 DEFINE_COMPILERRT_THUMB_FUNCTION(__clzsi2) #else DEFINE_COMPILERRT_FUNCTION(__clzsi2) #endif #ifdef __ARM_FEATURE_CLZ clz r0, r0 JMP(lr) #else /* Assumption: n != 0 */ /* * r0: n * r1: count of leading zeros in n + 1 * r2: scratch register for shifted r0 */ mov r1, 1 /* * Basic block: * if ((r0 >> SHIFT) == 0) * r1 += SHIFT; * else * r0 >>= SHIFT; * for descending powers of two as SHIFT. */ #define BLOCK(shift) \ lsrs r2, r0, shift; \ movne r0, r2; \ addeq r1, shift \ BLOCK(16) BLOCK(8) BLOCK(4) BLOCK(2) /* * The basic block invariants at this point are (r0 >> 2) == 0 and * r0 != 0. This means 1 <= r0 <= 3 and 0 <= (r0 >> 1) <= 1. * * r0 | (r0 >> 1) == 0 | (r0 >> 1) == 1 | -(r0 >> 1) | 1 - (r0 >> 1) * ---+----------------+----------------+------------+-------------- * 1 | 1 | 0 | 0 | 1 * 2 | 0 | 1 | -1 | 0 * 3 | 0 | 1 | -1 | 0 * * The r1's initial value of 1 compensates for the 1 here. */ sub r0, r1, r0, lsr #1 JMP(lr) #endif // __ARM_FEATURE_CLZ END_COMPILERRT_FUNCTION(__clzsi2) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/comparesf2.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/comparesf2.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/comparesf2.S (revision 305364) @@ -1,148 +1,151 @@ //===-- comparesf2.S - Implement single-precision soft-float comparisons --===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the following soft-fp_t comparison routines: // // __eqsf2 __gesf2 __unordsf2 // __lesf2 __gtsf2 // __ltsf2 // __nesf2 // // The semantics of the routines grouped in each column are identical, so there // is a single implementation for each, with multiple names. // // The routines behave as follows: // // __lesf2(a,b) returns -1 if a < b // 0 if a == b // 1 if a > b // 1 if either a or b is NaN // // __gesf2(a,b) returns -1 if a < b // 0 if a == b // 1 if a > b // -1 if either a or b is NaN // // __unordsf2(a,b) returns 0 if both a and b are numbers // 1 if either a or b is NaN // // Note that __lesf2( ) and __gesf2( ) are identical except in their handling of // NaN values. // //===----------------------------------------------------------------------===// #include "../assembly.h" .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__eqsf2) // Make copies of a and b with the sign bit shifted off the top. These will // be used to detect zeros and NaNs. mov r2, r0, lsl #1 mov r3, r1, lsl #1 // We do the comparison in three stages (ignoring NaN values for the time // being). First, we orr the absolute values of a and b; this sets the Z // flag if both a and b are zero (of either sign). The shift of r3 doesn't // effect this at all, but it *does* make sure that the C flag is clear for // the subsequent operations. orrs r12, r2, r3, lsr #1 // Next, we check if a and b have the same or different signs. If they have // opposite signs, this eor will set the N flag. it ne eorsne r12, r0, r1 // If a and b are equal (either both zeros or bit identical; again, we're // ignoring NaNs for now), this subtract will zero out r0. If they have the // same sign, the flags are updated as they would be for a comparison of the // absolute values of a and b. it pl subspl r0, r2, r3 // If a is smaller in magnitude than b and both have the same sign, place // the negation of the sign of b in r0. Thus, if both are negative and // a > b, this sets r0 to 0; if both are positive and a < b, this sets // r0 to -1. // // This is also done if a and b have opposite signs and are not both zero, // because in that case the subtract was not performed and the C flag is // still clear from the shift argument in orrs; if a is positive and b // negative, this places 0 in r0; if a is negative and b positive, -1 is // placed in r0. it lo mvnlo r0, r1, asr #31 // If a is greater in magnitude than b and both have the same sign, place // the sign of b in r0. Thus, if both are negative and a < b, -1 is placed // in r0, which is the desired result. Conversely, if both are positive // and a > b, zero is placed in r0. it hi movhi r0, r1, asr #31 // If you've been keeping track, at this point r0 contains -1 if a < b and // 0 if a >= b. All that remains to be done is to set it to 1 if a > b. // If a == b, then the Z flag is set, so we can get the correct final value // into r0 by simply or'ing with 1 if Z is clear. it ne orrne r0, r0, #1 // Finally, we need to deal with NaNs. If either argument is NaN, replace // the value in r0 with 1. cmp r2, #0xff000000 ite ls cmpls r3, #0xff000000 movhi r0, #1 JMP(lr) END_COMPILERRT_FUNCTION(__eqsf2) DEFINE_COMPILERRT_FUNCTION_ALIAS(__lesf2, __eqsf2) DEFINE_COMPILERRT_FUNCTION_ALIAS(__ltsf2, __eqsf2) DEFINE_COMPILERRT_FUNCTION_ALIAS(__nesf2, __eqsf2) .p2align 2 DEFINE_COMPILERRT_FUNCTION(__gtsf2) // Identical to the preceding except in that we return -1 for NaN values. // Given that the two paths share so much code, one might be tempted to // unify them; however, the extra code needed to do so makes the code size // to performance tradeoff very hard to justify for such small functions. mov r2, r0, lsl #1 mov r3, r1, lsl #1 orrs r12, r2, r3, lsr #1 it ne eorsne r12, r0, r1 it pl subspl r0, r2, r3 it lo mvnlo r0, r1, asr #31 it hi movhi r0, r1, asr #31 it ne orrne r0, r0, #1 cmp r2, #0xff000000 ite ls cmpls r3, #0xff000000 movhi r0, #-1 JMP(lr) END_COMPILERRT_FUNCTION(__gtsf2) DEFINE_COMPILERRT_FUNCTION_ALIAS(__gesf2, __gtsf2) .p2align 2 DEFINE_COMPILERRT_FUNCTION(__unordsf2) // Return 1 for NaN values, 0 otherwise. mov r2, r0, lsl #1 mov r3, r1, lsl #1 mov r0, #0 cmp r2, #0xff000000 ite ls cmpls r3, #0xff000000 movhi r0, #1 JMP(lr) END_COMPILERRT_FUNCTION(__unordsf2) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_fcmpun, __unordsf2) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/divdf3vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/divdf3vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/divdf3vfp.S (revision 305364) @@ -1,26 +1,29 @@ //===-- divdf3vfp.S - Implement divdf3vfp ---------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern double __divdf3vfp(double a, double b); // // Divides two double precision floating point numbers using the Darwin // calling convention where double arguments are passsed in GPR pairs // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__divdf3vfp) vmov d6, r0, r1 // move first param from r0/r1 pair into d6 vmov d7, r2, r3 // move second param from r2/r3 pair into d7 vdiv.f64 d5, d6, d7 vmov r0, r1, d5 // move result back to r0/r1 pair bx lr END_COMPILERRT_FUNCTION(__divdf3vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/divmodsi4.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/divmodsi4.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/divmodsi4.S (revision 305364) @@ -1,74 +1,77 @@ /*===-- divmodsi4.S - 32-bit signed integer divide and modulus ------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __divmodsi4 (32-bit signed integer divide and * modulus) function for the ARM architecture. A naive digit-by-digit * computation is employed for simplicity. * *===----------------------------------------------------------------------===*/ #include "../assembly.h" #define ESTABLISH_FRAME \ push {r4-r7, lr} ;\ add r7, sp, #12 #define CLEAR_FRAME_AND_RETURN \ pop {r4-r7, pc} .syntax unified .text #if __ARM_ARCH_ISA_THUMB == 2 .thumb #endif @ int __divmodsi4(int divident, int divisor, int *remainder) @ Calculate the quotient and remainder of the (signed) division. The return @ value is the quotient, the remainder is placed in the variable. .p2align 3 #if __ARM_ARCH_ISA_THUMB == 2 DEFINE_COMPILERRT_THUMB_FUNCTION(__divmodsi4) #else DEFINE_COMPILERRT_FUNCTION(__divmodsi4) #endif #if __ARM_ARCH_EXT_IDIV__ tst r1, r1 beq LOCAL_LABEL(divzero) mov r3, r0 sdiv r0, r3, r1 mls r1, r0, r1, r3 str r1, [r2] bx lr LOCAL_LABEL(divzero): mov r0, #0 bx lr #else ESTABLISH_FRAME // Set aside the sign of the quotient and modulus, and the address for the // modulus. eor r4, r0, r1 mov r5, r0 mov r6, r2 // Take the absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31). eor ip, r0, r0, asr #31 eor lr, r1, r1, asr #31 sub r0, ip, r0, asr #31 sub r1, lr, r1, asr #31 // Unsigned divmod: bl SYMBOL_NAME(__udivmodsi4) // Apply the sign of quotient and modulus ldr r1, [r6] eor r0, r0, r4, asr #31 eor r1, r1, r5, asr #31 sub r0, r0, r4, asr #31 sub r1, r1, r5, asr #31 str r1, [r6] CLEAR_FRAME_AND_RETURN #endif END_COMPILERRT_FUNCTION(__divmodsi4) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/divsf3vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/divsf3vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/divsf3vfp.S (revision 305364) @@ -1,26 +1,29 @@ //===-- divsf3vfp.S - Implement divsf3vfp ---------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern float __divsf3vfp(float a, float b); // // Divides two single precision floating point numbers using the Darwin // calling convention where single arguments are passsed like 32-bit ints. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__divsf3vfp) vmov s14, r0 // move first param from r0 into float register vmov s15, r1 // move second param from r1 into float register vdiv.f32 s13, s14, s15 vmov r0, s13 // move result back to r0 bx lr END_COMPILERRT_FUNCTION(__divsf3vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/divsi3.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/divsi3.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/divsi3.S (revision 305364) @@ -1,65 +1,68 @@ /*===-- divsi3.S - 32-bit signed integer divide ---------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __divsi3 (32-bit signed integer divide) function * for the ARM architecture as a wrapper around the unsigned routine. * *===----------------------------------------------------------------------===*/ #include "../assembly.h" #define ESTABLISH_FRAME \ push {r4, r7, lr} ;\ add r7, sp, #4 #define CLEAR_FRAME_AND_RETURN \ pop {r4, r7, pc} .syntax unified .text #if __ARM_ARCH_ISA_THUMB == 2 .thumb #endif .p2align 3 // Ok, APCS and AAPCS agree on 32 bit args, so it's safe to use the same routine. DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_idiv, __divsi3) @ int __divsi3(int divident, int divisor) @ Calculate and return the quotient of the (signed) division. #if __ARM_ARCH_ISA_THUMB == 2 DEFINE_COMPILERRT_THUMB_FUNCTION(__divsi3) #else DEFINE_COMPILERRT_FUNCTION(__divsi3) #endif #if __ARM_ARCH_EXT_IDIV__ tst r1,r1 beq LOCAL_LABEL(divzero) sdiv r0, r0, r1 bx lr LOCAL_LABEL(divzero): mov r0,#0 bx lr #else ESTABLISH_FRAME // Set aside the sign of the quotient. eor r4, r0, r1 // Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31). eor r2, r0, r0, asr #31 eor r3, r1, r1, asr #31 sub r0, r2, r0, asr #31 sub r1, r3, r1, asr #31 // abs(a) / abs(b) bl SYMBOL_NAME(__udivsi3) // Apply sign of quotient to result and return. eor r0, r0, r4, asr #31 sub r0, r0, r4, asr #31 CLEAR_FRAME_AND_RETURN #endif END_COMPILERRT_FUNCTION(__divsi3) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/eqdf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/eqdf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/eqdf2vfp.S (revision 305364) @@ -1,29 +1,32 @@ //===-- eqdf2vfp.S - Implement eqdf2vfp -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern int __eqdf2vfp(double a, double b); // // Returns one iff a == b and neither is NaN. // Uses Darwin calling convention where double precision arguments are passsed // like in GPR pairs. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__eqdf2vfp) vmov d6, r0, r1 // load r0/r1 pair in double register vmov d7, r2, r3 // load r2/r3 pair in double register vcmp.f64 d6, d7 vmrs apsr_nzcv, fpscr moveq r0, #1 // set result register to 1 if equal movne r0, #0 bx lr END_COMPILERRT_FUNCTION(__eqdf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/eqsf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/eqsf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/eqsf2vfp.S (revision 305364) @@ -1,29 +1,32 @@ //===-- eqsf2vfp.S - Implement eqsf2vfp -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern int __eqsf2vfp(float a, float b); // // Returns one iff a == b and neither is NaN. // Uses Darwin calling convention where single precision arguments are passsed // like 32-bit ints // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__eqsf2vfp) vmov s14, r0 // move from GPR 0 to float register vmov s15, r1 // move from GPR 1 to float register vcmp.f32 s14, s15 vmrs apsr_nzcv, fpscr moveq r0, #1 // set result register to 1 if equal movne r0, #0 bx lr END_COMPILERRT_FUNCTION(__eqsf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/extendsfdf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/extendsfdf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/extendsfdf2vfp.S (revision 305364) @@ -1,26 +1,29 @@ //===-- extendsfdf2vfp.S - Implement extendsfdf2vfp -----------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern double __extendsfdf2vfp(float a); // // Converts single precision float to double precision result. // Uses Darwin calling convention where a single precision parameter is // passed in a GPR and a double precision result is returned in R0/R1 pair. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__extendsfdf2vfp) vmov s15, r0 // load float register from R0 vcvt.f64.f32 d7, s15 // convert single to double vmov r0, r1, d7 // return result in r0/r1 pair bx lr END_COMPILERRT_FUNCTION(__extendsfdf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/fixdfsivfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/fixdfsivfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/fixdfsivfp.S (revision 305364) @@ -1,26 +1,29 @@ //===-- fixdfsivfp.S - Implement fixdfsivfp -----------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern int __fixdfsivfp(double a); // // Converts double precision float to a 32-bit int rounding towards zero. // Uses Darwin calling convention where a double precision parameter is // passed in GPR register pair. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__fixdfsivfp) vmov d7, r0, r1 // load double register from R0/R1 vcvt.s32.f64 s15, d7 // convert double to 32-bit int into s15 vmov r0, s15 // move s15 to result register bx lr END_COMPILERRT_FUNCTION(__fixdfsivfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/fixsfsivfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/fixsfsivfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/fixsfsivfp.S (revision 305364) @@ -1,26 +1,29 @@ //===-- fixsfsivfp.S - Implement fixsfsivfp -----------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern int __fixsfsivfp(float a); // // Converts single precision float to a 32-bit int rounding towards zero. // Uses Darwin calling convention where a single precision parameter is // passed in a GPR.. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__fixsfsivfp) vmov s15, r0 // load float register from R0 vcvt.s32.f32 s15, s15 // convert single to 32-bit int into s15 vmov r0, s15 // move s15 to result register bx lr END_COMPILERRT_FUNCTION(__fixsfsivfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/fixunsdfsivfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/fixunsdfsivfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/fixunsdfsivfp.S (revision 305364) @@ -1,27 +1,30 @@ //===-- fixunsdfsivfp.S - Implement fixunsdfsivfp -------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern unsigned int __fixunsdfsivfp(double a); // // Converts double precision float to a 32-bit unsigned int rounding towards // zero. All negative values become zero. // Uses Darwin calling convention where a double precision parameter is // passed in GPR register pair. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__fixunsdfsivfp) vmov d7, r0, r1 // load double register from R0/R1 vcvt.u32.f64 s15, d7 // convert double to 32-bit int into s15 vmov r0, s15 // move s15 to result register bx lr END_COMPILERRT_FUNCTION(__fixunsdfsivfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/fixunssfsivfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/fixunssfsivfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/fixunssfsivfp.S (revision 305364) @@ -1,27 +1,30 @@ //===-- fixunssfsivfp.S - Implement fixunssfsivfp -------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern unsigned int __fixunssfsivfp(float a); // // Converts single precision float to a 32-bit unsigned int rounding towards // zero. All negative values become zero. // Uses Darwin calling convention where a single precision parameter is // passed in a GPR.. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__fixunssfsivfp) vmov s15, r0 // load float register from R0 vcvt.u32.f32 s15, s15 // convert single to 32-bit unsigned into s15 vmov r0, s15 // move s15 to result register bx lr END_COMPILERRT_FUNCTION(__fixunssfsivfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/floatsidfvfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/floatsidfvfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/floatsidfvfp.S (revision 305364) @@ -1,26 +1,29 @@ //===-- floatsidfvfp.S - Implement floatsidfvfp ---------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern double __floatsidfvfp(int a); // // Converts a 32-bit int to a double precision float. // Uses Darwin calling convention where a double precision result is // return in GPR register pair. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__floatsidfvfp) vmov s15, r0 // move int to float register s15 vcvt.f64.s32 d7, s15 // convert 32-bit int in s15 to double in d7 vmov r0, r1, d7 // move d7 to result register pair r0/r1 bx lr END_COMPILERRT_FUNCTION(__floatsidfvfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/floatsisfvfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/floatsisfvfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/floatsisfvfp.S (revision 305364) @@ -1,26 +1,29 @@ //===-- floatsisfvfp.S - Implement floatsisfvfp ---------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern float __floatsisfvfp(int a); // // Converts single precision float to a 32-bit int rounding towards zero. // Uses Darwin calling convention where a single precision result is // return in a GPR.. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__floatsisfvfp) vmov s15, r0 // move int to float register s15 vcvt.f32.s32 s15, s15 // convert 32-bit int in s15 to float in s15 vmov r0, s15 // move s15 to result register bx lr END_COMPILERRT_FUNCTION(__floatsisfvfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/floatunssidfvfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/floatunssidfvfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/floatunssidfvfp.S (revision 305364) @@ -1,26 +1,29 @@ //===-- floatunssidfvfp.S - Implement floatunssidfvfp ---------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern double __floatunssidfvfp(unsigned int a); // // Converts a 32-bit int to a double precision float. // Uses Darwin calling convention where a double precision result is // return in GPR register pair. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__floatunssidfvfp) vmov s15, r0 // move int to float register s15 vcvt.f64.u32 d7, s15 // convert 32-bit int in s15 to double in d7 vmov r0, r1, d7 // move d7 to result register pair r0/r1 bx lr END_COMPILERRT_FUNCTION(__floatunssidfvfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/floatunssisfvfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/floatunssisfvfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/floatunssisfvfp.S (revision 305364) @@ -1,26 +1,29 @@ //===-- floatunssisfvfp.S - Implement floatunssisfvfp ---------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern float __floatunssisfvfp(unsigned int a); // // Converts single precision float to a 32-bit int rounding towards zero. // Uses Darwin calling convention where a single precision result is // return in a GPR.. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__floatunssisfvfp) vmov s15, r0 // move int to float register s15 vcvt.f32.u32 s15, s15 // convert 32-bit int in s15 to float in s15 vmov r0, s15 // move s15 to result register bx lr END_COMPILERRT_FUNCTION(__floatunssisfvfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/gedf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/gedf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/gedf2vfp.S (revision 305364) @@ -1,29 +1,32 @@ //===-- gedf2vfp.S - Implement gedf2vfp -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern int __gedf2vfp(double a, double b); // // Returns one iff a >= b and neither is NaN. // Uses Darwin calling convention where double precision arguments are passsed // like in GPR pairs. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__gedf2vfp) vmov d6, r0, r1 // load r0/r1 pair in double register vmov d7, r2, r3 // load r2/r3 pair in double register vcmp.f64 d6, d7 vmrs apsr_nzcv, fpscr movge r0, #1 // set result register to 1 if greater than or equal movlt r0, #0 bx lr END_COMPILERRT_FUNCTION(__gedf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/gesf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/gesf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/gesf2vfp.S (revision 305364) @@ -1,29 +1,32 @@ //===-- gesf2vfp.S - Implement gesf2vfp -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern int __gesf2vfp(float a, float b); // // Returns one iff a >= b and neither is NaN. // Uses Darwin calling convention where single precision arguments are passsed // like 32-bit ints // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__gesf2vfp) vmov s14, r0 // move from GPR 0 to float register vmov s15, r1 // move from GPR 1 to float register vcmp.f32 s14, s15 vmrs apsr_nzcv, fpscr movge r0, #1 // set result register to 1 if greater than or equal movlt r0, #0 bx lr END_COMPILERRT_FUNCTION(__gesf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/gtdf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/gtdf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/gtdf2vfp.S (revision 305364) @@ -1,29 +1,32 @@ //===-- gtdf2vfp.S - Implement gtdf2vfp -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern double __gtdf2vfp(double a, double b); // // Returns one iff a > b and neither is NaN. // Uses Darwin calling convention where double precision arguments are passsed // like in GPR pairs. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__gtdf2vfp) vmov d6, r0, r1 // load r0/r1 pair in double register vmov d7, r2, r3 // load r2/r3 pair in double register vcmp.f64 d6, d7 vmrs apsr_nzcv, fpscr movgt r0, #1 // set result register to 1 if equal movle r0, #0 bx lr END_COMPILERRT_FUNCTION(__gtdf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/gtsf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/gtsf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/gtsf2vfp.S (revision 305364) @@ -1,29 +1,32 @@ //===-- gtsf2vfp.S - Implement gtsf2vfp -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern int __gtsf2vfp(float a, float b); // // Returns one iff a > b and neither is NaN. // Uses Darwin calling convention where single precision arguments are passsed // like 32-bit ints // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__gtsf2vfp) vmov s14, r0 // move from GPR 0 to float register vmov s15, r1 // move from GPR 1 to float register vcmp.f32 s14, s15 vmrs apsr_nzcv, fpscr movgt r0, #1 // set result register to 1 if equal movle r0, #0 bx lr END_COMPILERRT_FUNCTION(__gtsf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/ledf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/ledf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/ledf2vfp.S (revision 305364) @@ -1,29 +1,32 @@ //===-- ledf2vfp.S - Implement ledf2vfp -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern double __ledf2vfp(double a, double b); // // Returns one iff a <= b and neither is NaN. // Uses Darwin calling convention where double precision arguments are passsed // like in GPR pairs. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__ledf2vfp) vmov d6, r0, r1 // load r0/r1 pair in double register vmov d7, r2, r3 // load r2/r3 pair in double register vcmp.f64 d6, d7 vmrs apsr_nzcv, fpscr movls r0, #1 // set result register to 1 if equal movhi r0, #0 bx lr END_COMPILERRT_FUNCTION(__ledf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/lesf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/lesf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/lesf2vfp.S (revision 305364) @@ -1,29 +1,32 @@ //===-- lesf2vfp.S - Implement lesf2vfp -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern int __lesf2vfp(float a, float b); // // Returns one iff a <= b and neither is NaN. // Uses Darwin calling convention where single precision arguments are passsed // like 32-bit ints // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__lesf2vfp) vmov s14, r0 // move from GPR 0 to float register vmov s15, r1 // move from GPR 1 to float register vcmp.f32 s14, s15 vmrs apsr_nzcv, fpscr movls r0, #1 // set result register to 1 if equal movhi r0, #0 bx lr END_COMPILERRT_FUNCTION(__lesf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/ltdf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/ltdf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/ltdf2vfp.S (revision 305364) @@ -1,29 +1,32 @@ //===-- ltdf2vfp.S - Implement ltdf2vfp -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern double __ltdf2vfp(double a, double b); // // Returns one iff a < b and neither is NaN. // Uses Darwin calling convention where double precision arguments are passsed // like in GPR pairs. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__ltdf2vfp) vmov d6, r0, r1 // load r0/r1 pair in double register vmov d7, r2, r3 // load r2/r3 pair in double register vcmp.f64 d6, d7 vmrs apsr_nzcv, fpscr movmi r0, #1 // set result register to 1 if equal movpl r0, #0 bx lr END_COMPILERRT_FUNCTION(__ltdf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/ltsf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/ltsf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/ltsf2vfp.S (revision 305364) @@ -1,29 +1,32 @@ //===-- ltsf2vfp.S - Implement ltsf2vfp -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern int __ltsf2vfp(float a, float b); // // Returns one iff a < b and neither is NaN. // Uses Darwin calling convention where single precision arguments are passsed // like 32-bit ints // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__ltsf2vfp) vmov s14, r0 // move from GPR 0 to float register vmov s15, r1 // move from GPR 1 to float register vcmp.f32 s14, s15 vmrs apsr_nzcv, fpscr movmi r0, #1 // set result register to 1 if equal movpl r0, #0 bx lr END_COMPILERRT_FUNCTION(__ltsf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/modsi3.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/modsi3.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/modsi3.S (revision 305364) @@ -1,63 +1,66 @@ /*===-- modsi3.S - 32-bit signed integer modulus --------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __modsi3 (32-bit signed integer modulus) function * for the ARM architecture as a wrapper around the unsigned routine. * *===----------------------------------------------------------------------===*/ #include "../assembly.h" #define ESTABLISH_FRAME \ push {r4, r7, lr} ;\ add r7, sp, #4 #define CLEAR_FRAME_AND_RETURN \ pop {r4, r7, pc} .syntax unified .text #if __ARM_ARCH_ISA_THUMB == 2 .thumb #endif @ int __modsi3(int divident, int divisor) @ Calculate and return the remainder of the (signed) division. .p2align 3 #if __ARM_ARCH_ISA_THUMB == 2 DEFINE_COMPILERRT_THUMB_FUNCTION(__modsi3) #else DEFINE_COMPILERRT_FUNCTION(__modsi3) #endif #if __ARM_ARCH_EXT_IDIV__ tst r1, r1 beq LOCAL_LABEL(divzero) sdiv r2, r0, r1 mls r0, r2, r1, r0 bx lr LOCAL_LABEL(divzero): mov r0, #0 bx lr #else ESTABLISH_FRAME // Set aside the sign of the dividend. mov r4, r0 // Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31). eor r2, r0, r0, asr #31 eor r3, r1, r1, asr #31 sub r0, r2, r0, asr #31 sub r1, r3, r1, asr #31 // abs(a) % abs(b) bl SYMBOL_NAME(__umodsi3) // Apply sign of dividend to result and return. eor r0, r0, r4, asr #31 sub r0, r0, r4, asr #31 CLEAR_FRAME_AND_RETURN #endif END_COMPILERRT_FUNCTION(__modsi3) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/muldf3vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/muldf3vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/muldf3vfp.S (revision 305364) @@ -1,26 +1,29 @@ //===-- muldf3vfp.S - Implement muldf3vfp ---------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern double __muldf3vfp(double a, double b); // // Multiplies two double precision floating point numbers using the Darwin // calling convention where double arguments are passsed in GPR pairs // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__muldf3vfp) vmov d6, r0, r1 // move first param from r0/r1 pair into d6 vmov d7, r2, r3 // move second param from r2/r3 pair into d7 vmul.f64 d6, d6, d7 vmov r0, r1, d6 // move result back to r0/r1 pair bx lr END_COMPILERRT_FUNCTION(__muldf3vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/mulsf3vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/mulsf3vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/mulsf3vfp.S (revision 305364) @@ -1,26 +1,29 @@ //===-- mulsf3vfp.S - Implement mulsf3vfp ---------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern float __mulsf3vfp(float a, float b); // // Multiplies two single precision floating point numbers using the Darwin // calling convention where single arguments are passsed like 32-bit ints. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__mulsf3vfp) vmov s14, r0 // move first param from r0 into float register vmov s15, r1 // move second param from r1 into float register vmul.f32 s13, s14, s15 vmov r0, s13 // move result back to r0 bx lr END_COMPILERRT_FUNCTION(__mulsf3vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/nedf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/nedf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/nedf2vfp.S (revision 305364) @@ -1,29 +1,32 @@ //===-- nedf2vfp.S - Implement nedf2vfp -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern double __nedf2vfp(double a, double b); // // Returns zero if a and b are unequal and neither is NaN. // Uses Darwin calling convention where double precision arguments are passsed // like in GPR pairs. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__nedf2vfp) vmov d6, r0, r1 // load r0/r1 pair in double register vmov d7, r2, r3 // load r2/r3 pair in double register vcmp.f64 d6, d7 vmrs apsr_nzcv, fpscr movne r0, #1 // set result register to 0 if unequal moveq r0, #0 bx lr END_COMPILERRT_FUNCTION(__nedf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/negdf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/negdf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/negdf2vfp.S (revision 305364) @@ -1,23 +1,26 @@ //===-- negdf2vfp.S - Implement negdf2vfp ---------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern double __negdf2vfp(double a, double b); // // Returns the negation a double precision floating point numbers using the // Darwin calling convention where double arguments are passsed in GPR pairs. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__negdf2vfp) eor r1, r1, #-2147483648 // flip sign bit on double in r0/r1 pair bx lr END_COMPILERRT_FUNCTION(__negdf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/negsf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/negsf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/negsf2vfp.S (revision 305364) @@ -1,23 +1,26 @@ //===-- negsf2vfp.S - Implement negsf2vfp ---------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern float __negsf2vfp(float a); // // Returns the negation of a single precision floating point numbers using the // Darwin calling convention where single arguments are passsed like 32-bit ints // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__negsf2vfp) eor r0, r0, #-2147483648 // flip sign bit on float in r0 bx lr END_COMPILERRT_FUNCTION(__negsf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/nesf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/nesf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/nesf2vfp.S (revision 305364) @@ -1,29 +1,32 @@ //===-- nesf2vfp.S - Implement nesf2vfp -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern int __nesf2vfp(float a, float b); // // Returns one iff a != b and neither is NaN. // Uses Darwin calling convention where single precision arguments are passsed // like 32-bit ints // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__nesf2vfp) vmov s14, r0 // move from GPR 0 to float register vmov s15, r1 // move from GPR 1 to float register vcmp.f32 s14, s15 vmrs apsr_nzcv, fpscr movne r0, #1 // set result register to 1 if unequal moveq r0, #0 bx lr END_COMPILERRT_FUNCTION(__nesf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/restore_vfp_d8_d15_regs.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/restore_vfp_d8_d15_regs.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/restore_vfp_d8_d15_regs.S (revision 305364) @@ -1,33 +1,35 @@ //===-- save_restore_regs.S - Implement save/restore* ---------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // When compiling C++ functions that need to handle thrown exceptions the // compiler is required to save all registers and call __Unwind_SjLj_Register // in the function prolog. But when compiling for thumb1, there are // no instructions to access the floating point registers, so the // compiler needs to add a call to the helper function _save_vfp_d8_d15_regs // written in ARM to save the float registers. In the epilog, the compiler // must also add a call to __restore_vfp_d8_d15_regs to restore those registers. // .text .syntax unified // // Restore registers d8-d15 from stack // .p2align 2 DEFINE_COMPILERRT_PRIVATE_FUNCTION(__restore_vfp_d8_d15_regs) vldmia sp!, {d8-d15} // pop registers d8-d15 off stack bx lr // return to prolog END_COMPILERRT_FUNCTION(__restore_vfp_d8_d15_regs) +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/save_vfp_d8_d15_regs.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/save_vfp_d8_d15_regs.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/save_vfp_d8_d15_regs.S (revision 305364) @@ -1,33 +1,35 @@ //===-- save_restore_regs.S - Implement save/restore* ---------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // When compiling C++ functions that need to handle thrown exceptions the // compiler is required to save all registers and call __Unwind_SjLj_Register // in the function prolog. But when compiling for thumb1, there are // no instructions to access the floating point registers, so the // compiler needs to add a call to the helper function _save_vfp_d8_d15_regs // written in ARM to save the float registers. In the epilog, the compiler // must also add a call to __restore_vfp_d8_d15_regs to restore those registers. // .text .syntax unified // // Save registers d8-d15 onto stack // .p2align 2 DEFINE_COMPILERRT_PRIVATE_FUNCTION(__save_vfp_d8_d15_regs) vstmdb sp!, {d8-d15} // push registers d8-d15 onto stack bx lr // return to prolog END_COMPILERRT_FUNCTION(__save_vfp_d8_d15_regs) +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/subdf3vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/subdf3vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/subdf3vfp.S (revision 305364) @@ -1,26 +1,29 @@ //===-- subdf3vfp.S - Implement subdf3vfp ---------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern double __subdf3vfp(double a, double b); // // Returns difference between two double precision floating point numbers using // the Darwin calling convention where double arguments are passsed in GPR pairs // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__subdf3vfp) vmov d6, r0, r1 // move first param from r0/r1 pair into d6 vmov d7, r2, r3 // move second param from r2/r3 pair into d7 vsub.f64 d6, d6, d7 vmov r0, r1, d6 // move result back to r0/r1 pair bx lr END_COMPILERRT_FUNCTION(__subdf3vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/subsf3vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/subsf3vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/subsf3vfp.S (revision 305364) @@ -1,27 +1,30 @@ //===-- subsf3vfp.S - Implement subsf3vfp ---------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern float __subsf3vfp(float a, float b); // // Returns the difference between two single precision floating point numbers // using the Darwin calling convention where single arguments are passsed // like 32-bit ints. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__subsf3vfp) vmov s14, r0 // move first param from r0 into float register vmov s15, r1 // move second param from r1 into float register vsub.f32 s14, s14, s15 vmov r0, s14 // move result back to r0 bx lr END_COMPILERRT_FUNCTION(__subsf3vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/switch16.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/switch16.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/switch16.S (revision 305364) @@ -1,44 +1,46 @@ //===-- switch.S - Implement switch* --------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // When compiling switch statements in thumb mode, the compiler // can use these __switch* helper functions The compiler emits a blx to // the __switch* function followed by a table of displacements for each // case statement. On entry, R0 is the index into the table. The __switch* // function uses the return address in lr to find the start of the table. // The first entry in the table is the count of the entries in the table. // It then uses R0 to index into the table and get the displacement of the // address to jump to. If R0 is greater than the size of the table, it jumps // to the last entry in the table. Each displacement in the table is actually // the distance from lr to the label, thus making the tables PIC. .text .syntax unified // // The table contains signed 2-byte sized elements which are 1/2 the distance // from lr to the target label. // .p2align 2 DEFINE_COMPILERRT_PRIVATE_FUNCTION(__switch16) ldrh ip, [lr, #-1] // get first 16-bit word in table cmp r0, ip // compare with index add r0, lr, r0, lsl #1 // compute address of element in table add ip, lr, ip, lsl #1 // compute address of last element in table ite lo ldrshlo r0, [r0, #1] // load 16-bit element if r0 is in range ldrshhs r0, [ip, #1] // load 16-bit element if r0 out of range add ip, lr, r0, lsl #1 // compute label = lr + element*2 bx ip // jump to computed label END_COMPILERRT_FUNCTION(__switch16) +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/switch32.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/switch32.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/switch32.S (revision 305364) @@ -1,44 +1,46 @@ //===-- switch.S - Implement switch* --------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // When compiling switch statements in thumb mode, the compiler // can use these __switch* helper functions The compiler emits a blx to // the __switch* function followed by a table of displacements for each // case statement. On entry, R0 is the index into the table. The __switch* // function uses the return address in lr to find the start of the table. // The first entry in the table is the count of the entries in the table. // It then uses R0 to index into the table and get the displacement of the // address to jump to. If R0 is greater than the size of the table, it jumps // to the last entry in the table. Each displacement in the table is actually // the distance from lr to the label, thus making the tables PIC. .text .syntax unified // // The table contains signed 4-byte sized elements which are the distance // from lr to the target label. // .p2align 2 DEFINE_COMPILERRT_PRIVATE_FUNCTION(__switch32) ldr ip, [lr, #-1] // get first 32-bit word in table cmp r0, ip // compare with index add r0, lr, r0, lsl #2 // compute address of element in table add ip, lr, ip, lsl #2 // compute address of last element in table ite lo ldrlo r0, [r0, #3] // load 32-bit element if r0 is in range ldrhs r0, [ip, #3] // load 32-bit element if r0 out of range add ip, lr, r0 // compute label = lr + element bx ip // jump to computed label END_COMPILERRT_FUNCTION(__switch32) +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/switch8.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/switch8.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/switch8.S (revision 305364) @@ -1,42 +1,44 @@ //===-- switch.S - Implement switch* --------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // When compiling switch statements in thumb mode, the compiler // can use these __switch* helper functions The compiler emits a blx to // the __switch* function followed by a table of displacements for each // case statement. On entry, R0 is the index into the table. The __switch* // function uses the return address in lr to find the start of the table. // The first entry in the table is the count of the entries in the table. // It then uses R0 to index into the table and get the displacement of the // address to jump to. If R0 is greater than the size of the table, it jumps // to the last entry in the table. Each displacement in the table is actually // the distance from lr to the label, thus making the tables PIC. .text .syntax unified // // The table contains signed byte sized elements which are 1/2 the distance // from lr to the target label. // .p2align 2 DEFINE_COMPILERRT_PRIVATE_FUNCTION(__switch8) ldrb ip, [lr, #-1] // get first byte in table cmp r0, ip // signed compare with index ite lo ldrsblo r0, [lr, r0] // get indexed byte out of table ldrsbhs r0, [lr, ip] // if out of range, use last entry in table add ip, lr, r0, lsl #1 // compute label = lr + element*2 bx ip // jump to computed label END_COMPILERRT_FUNCTION(__switch8) +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/switchu8.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/switchu8.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/switchu8.S (revision 305364) @@ -1,42 +1,44 @@ //===-- switch.S - Implement switch* --------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // When compiling switch statements in thumb mode, the compiler // can use these __switch* helper functions The compiler emits a blx to // the __switch* function followed by a table of displacements for each // case statement. On entry, R0 is the index into the table. The __switch* // function uses the return address in lr to find the start of the table. // The first entry in the table is the count of the entries in the table. // It then uses R0 to index into the table and get the displacement of the // address to jump to. If R0 is greater than the size of the table, it jumps // to the last entry in the table. Each displacement in the table is actually // the distance from lr to the label, thus making the tables PIC. .text .syntax unified // // The table contains unsigned byte sized elements which are 1/2 the distance // from lr to the target label. // .p2align 2 DEFINE_COMPILERRT_PRIVATE_FUNCTION(__switchu8) ldrb ip, [lr, #-1] // get first byte in table cmp r0, ip // compare with index ite lo ldrblo r0, [lr, r0] // get indexed byte out of table ldrbhs r0, [lr, ip] // if out of range, use last entry in table add ip, lr, r0, lsl #1 // compute label = lr + element*2 bx ip // jump to computed label END_COMPILERRT_FUNCTION(__switchu8) +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_add_4.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_add_4.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_add_4.S (revision 305364) @@ -1,21 +1,23 @@ /*===-- sync_fetch_and_add_4.S - ------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_add_4 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" /* "adds" is 2 bytes shorter than "add". */ #define add_4(rD, rN, rM) add rD, rN, rM SYNC_OP_4(add_4) +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_add_8.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_add_8.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_add_8.S (revision 305364) @@ -1,24 +1,26 @@ /*===-- sync_fetch_and_add_8.S - ------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_add_8 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #if __ARM_ARCH_PROFILE != 'M' #define add_8(rD_LO, rD_HI, rN_LO, rN_HI, rM_LO, rM_HI) \ adds rD_LO, rN_LO, rM_LO ; \ adc rD_HI, rN_HI, rM_HI SYNC_OP_8(add_8) #endif +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_and_4.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_and_4.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_and_4.S (revision 305364) @@ -1,19 +1,22 @@ /*===-- sync_fetch_and_and_4.S - ------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_and_4 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #define and_4(rD, rN, rM) and rD, rN, rM SYNC_OP_4(and_4) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_and_8.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_and_8.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_and_8.S (revision 305364) @@ -1,23 +1,26 @@ /*===-- sync_fetch_and_and_8.S - ------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_and_8 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #if __ARM_ARCH_PROFILE != 'M' #define and_8(rD_LO, rD_HI, rN_LO, rN_HI, rM_LO, rM_HI) \ and rD_LO, rN_LO, rM_LO ; \ and rD_HI, rN_HI, rM_HI SYNC_OP_8(and_8) #endif + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_max_4.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_max_4.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_max_4.S (revision 305364) @@ -1,20 +1,22 @@ /*===-- sync_fetch_and_max_4.S - ------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_max_4 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #define max_4(rD, rN, rM) MINMAX_4(rD, rN, rM, gt) SYNC_OP_4(max_4) +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_max_8.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_max_8.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_max_8.S (revision 305364) @@ -1,21 +1,24 @@ /*===-- sync_fetch_and_max_8.S - ------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_max_8 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #if __ARM_ARCH_PROFILE != 'M' #define max_8(rD_LO, rD_HI, rN_LO, rN_HI, rM_LO, rM_HI) MINMAX_8(rD_LO, rD_HI, rN_LO, rN_HI, rM_LO, rM_HI, gt) SYNC_OP_8(max_8) #endif + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_min_4.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_min_4.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_min_4.S (revision 305364) @@ -1,20 +1,22 @@ /*===-- sync_fetch_and_min_4.S - ------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_min_4 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #define min_4(rD, rN, rM) MINMAX_4(rD, rN, rM, lt) SYNC_OP_4(min_4) +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_min_8.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_min_8.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_min_8.S (revision 305364) @@ -1,21 +1,24 @@ /*===-- sync_fetch_and_min_8.S - ------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_min_8 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #if __ARM_ARCH_PROFILE != 'M' #define min_8(rD_LO, rD_HI, rN_LO, rN_HI, rM_LO, rM_HI) MINMAX_8(rD_LO, rD_HI, rN_LO, rN_HI, rM_LO, rM_HI, lt) SYNC_OP_8(min_8) #endif + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_4.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_4.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_4.S (revision 305364) @@ -1,20 +1,22 @@ /*===-- sync_fetch_and_nand_4.S - -----------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_nand_4 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #define nand_4(rD, rN, rM) bic rD, rN, rM SYNC_OP_4(nand_4) +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_8.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_8.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_8.S (revision 305364) @@ -1,24 +1,26 @@ /*===-- sync_fetch_and_nand_8.S - ------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_nand_8 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #if __ARM_ARCH_PROFILE != 'M' #define nand_8(rD_LO, rD_HI, rN_LO, rN_HI, rM_LO, rM_HI) \ bic rD_LO, rN_LO, rM_LO ; \ bic rD_HI, rN_HI, rM_HI SYNC_OP_8(nand_8) #endif +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_or_4.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_or_4.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_or_4.S (revision 305364) @@ -1,20 +1,22 @@ /*===-- sync_fetch_and_or_4.S - -------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_or_4 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #define or_4(rD, rN, rM) orr rD, rN, rM SYNC_OP_4(or_4) +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_or_8.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_or_8.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_or_8.S (revision 305364) @@ -1,24 +1,26 @@ /*===-- sync_fetch_and_or_8.S - -------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_or_8 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #if __ARM_ARCH_PROFILE != 'M' #define or_8(rD_LO, rD_HI, rN_LO, rN_HI, rM_LO, rM_HI) \ orr rD_LO, rN_LO, rM_LO ; \ orr rD_HI, rN_HI, rM_HI SYNC_OP_8(or_8) #endif +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_4.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_4.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_4.S (revision 305364) @@ -1,21 +1,23 @@ /*===-- sync_fetch_and_sub_4.S - ------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_sub_4 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" /* "subs" is 2 bytes shorter than "sub". */ #define sub_4(rD, rN, rM) sub rD, rN, rM SYNC_OP_4(sub_4) +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_8.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_8.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_8.S (revision 305364) @@ -1,24 +1,26 @@ /*===-- sync_fetch_and_sub_8.S - ------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_sub_8 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #if __ARM_ARCH_PROFILE != 'M' #define sub_8(rD_LO, rD_HI, rN_LO, rN_HI, rM_LO, rM_HI) \ subs rD_LO, rN_LO, rM_LO ; \ sbc rD_HI, rN_HI, rM_HI SYNC_OP_8(sub_8) #endif +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_4.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_4.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_4.S (revision 305364) @@ -1,20 +1,22 @@ /*===-- sync_fetch_and_umax_4.S - ------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_umax_4 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #define umax_4(rD, rN, rM) MINMAX_4(rD, rN, rM, hi) SYNC_OP_4(umax_4) +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_8.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_8.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_8.S (revision 305364) @@ -1,21 +1,24 @@ /*===-- sync_fetch_and_umax_8.S - ------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_umax_8 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #if __ARM_ARCH_PROFILE != 'M' #define umax_8(rD_LO, rD_HI, rN_LO, rN_HI, rM_LO, rM_HI) MINMAX_8(rD_LO, rD_HI, rN_LO, rN_HI, rM_LO, rM_HI, hi) SYNC_OP_8(umax_8) #endif + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_4.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_4.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_4.S (revision 305364) @@ -1,20 +1,22 @@ /*===-- sync_fetch_and_umin_4.S - ------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_umin_4 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #define umin_4(rD, rN, rM) MINMAX_4(rD, rN, rM, lo) SYNC_OP_4(umin_4) +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_8.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_8.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_8.S (revision 305364) @@ -1,21 +1,24 @@ /*===-- sync_fetch_and_umin_8.S - ------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_umin_8 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #if __ARM_ARCH_PROFILE != 'M' #define umin_8(rD_LO, rD_HI, rN_LO, rN_HI, rM_LO, rM_HI) MINMAX_8(rD_LO, rD_HI, rN_LO, rN_HI, rM_LO, rM_HI, lo) SYNC_OP_8(umin_8) #endif + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_4.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_4.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_4.S (revision 305364) @@ -1,20 +1,22 @@ /*===-- sync_fetch_and_xor_4.S - ------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_xor_4 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #define xor_4(rD, rN, rM) eor rD, rN, rM SYNC_OP_4(xor_4) +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_8.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_8.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_8.S (revision 305364) @@ -1,24 +1,26 @@ /*===-- sync_fetch_and_xor_8.S - ------------------------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __sync_fetch_and_xor_8 function for the ARM * architecture. * *===----------------------------------------------------------------------===*/ #include "sync-ops.h" #if __ARM_ARCH_PROFILE != 'M' #define xor_8(rD_LO, rD_HI, rN_LO, rN_HI, rM_LO, rM_HI) \ eor rD_LO, rN_LO, rM_LO ; \ eor rD_HI, rN_HI, rM_HI SYNC_OP_8(xor_8) #endif +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_synchronize.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_synchronize.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/sync_synchronize.S (revision 305364) @@ -1,35 +1,38 @@ //===-- sync_synchronize - Implement memory barrier * ----------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // When compiling a use of the gcc built-in __sync_synchronize() in thumb1 mode // the compiler may emit a call to __sync_synchronize. // On Darwin the implementation jumps to an OS supplied function named // OSMemoryBarrier // .text .syntax unified #if __APPLE__ .p2align 2 DEFINE_COMPILERRT_PRIVATE_FUNCTION(__sync_synchronize) stmfd sp!, {r7, lr} add r7, sp, #0 bl _OSMemoryBarrier ldmfd sp!, {r7, pc} END_COMPILERRT_FUNCTION(__sync_synchronize) // tell linker it can break up file at label boundaries .subsections_via_symbols #endif + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/truncdfsf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/truncdfsf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/truncdfsf2vfp.S (revision 305364) @@ -1,26 +1,29 @@ //===-- truncdfsf2vfp.S - Implement truncdfsf2vfp -------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern float __truncdfsf2vfp(double a); // // Converts double precision float to signle precision result. // Uses Darwin calling convention where a double precision parameter is // passed in a R0/R1 pair and a signle precision result is returned in R0. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__truncdfsf2vfp) vmov d7, r0, r1 // load double from r0/r1 pair vcvt.f32.f64 s15, d7 // convert double to single (trucate precision) vmov r0, s15 // return result in r0 bx lr END_COMPILERRT_FUNCTION(__truncdfsf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/udivmodsi4.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/udivmodsi4.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/udivmodsi4.S (revision 305364) @@ -1,184 +1,187 @@ /*===-- udivmodsi4.S - 32-bit unsigned integer divide and modulus ---------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __udivmodsi4 (32-bit unsigned integer divide and * modulus) function for the ARM 32-bit architecture. * *===----------------------------------------------------------------------===*/ #include "../assembly.h" .syntax unified .text #if __ARM_ARCH_ISA_THUMB == 2 .thumb #endif @ unsigned int __udivmodsi4(unsigned int divident, unsigned int divisor, @ unsigned int *remainder) @ Calculate the quotient and remainder of the (unsigned) division. The return @ value is the quotient, the remainder is placed in the variable. .p2align 2 #if __ARM_ARCH_ISA_THUMB == 2 DEFINE_COMPILERRT_THUMB_FUNCTION(__udivmodsi4) #else DEFINE_COMPILERRT_FUNCTION(__udivmodsi4) #endif #if __ARM_ARCH_EXT_IDIV__ tst r1, r1 beq LOCAL_LABEL(divby0) mov r3, r0 udiv r0, r3, r1 mls r1, r0, r1, r3 str r1, [r2] bx lr #else cmp r1, #1 bcc LOCAL_LABEL(divby0) beq LOCAL_LABEL(divby1) cmp r0, r1 bcc LOCAL_LABEL(quotient0) /* * Implement division using binary long division algorithm. * * r0 is the numerator, r1 the denominator. * * The code before JMP computes the correct shift I, so that * r0 and (r1 << I) have the highest bit set in the same position. * At the time of JMP, ip := .Ldiv0block - 12 * I. * This depends on the fixed instruction size of block. * For ARM mode, this is 12 Bytes, for THUMB mode 14 Bytes. * * block(shift) implements the test-and-update-quotient core. * It assumes (r0 << shift) can be computed without overflow and * that (r0 << shift) < 2 * r1. The quotient is stored in r3. */ # ifdef __ARM_FEATURE_CLZ clz ip, r0 clz r3, r1 /* r0 >= r1 implies clz(r0) <= clz(r1), so ip <= r3. */ sub r3, r3, ip # if __ARM_ARCH_ISA_THUMB == 2 adr ip, LOCAL_LABEL(div0block) + 1 sub ip, ip, r3, lsl #1 # else adr ip, LOCAL_LABEL(div0block) # endif sub ip, ip, r3, lsl #2 sub ip, ip, r3, lsl #3 mov r3, #0 bx ip # else # if __ARM_ARCH_ISA_THUMB == 2 # error THUMB mode requires CLZ or UDIV # endif str r4, [sp, #-8]! mov r4, r0 adr ip, LOCAL_LABEL(div0block) lsr r3, r4, #16 cmp r3, r1 movhs r4, r3 subhs ip, ip, #(16 * 12) lsr r3, r4, #8 cmp r3, r1 movhs r4, r3 subhs ip, ip, #(8 * 12) lsr r3, r4, #4 cmp r3, r1 movhs r4, r3 subhs ip, #(4 * 12) lsr r3, r4, #2 cmp r3, r1 movhs r4, r3 subhs ip, ip, #(2 * 12) /* Last block, no need to update r3 or r4. */ cmp r1, r4, lsr #1 subls ip, ip, #(1 * 12) ldr r4, [sp], #8 /* restore r4, we are done with it. */ mov r3, #0 JMP(ip) # endif #define IMM # #define block(shift) \ cmp r0, r1, lsl IMM shift; \ ITT(hs); \ WIDE(addhs) r3, r3, IMM (1 << shift); \ WIDE(subhs) r0, r0, r1, lsl IMM shift block(31) block(30) block(29) block(28) block(27) block(26) block(25) block(24) block(23) block(22) block(21) block(20) block(19) block(18) block(17) block(16) block(15) block(14) block(13) block(12) block(11) block(10) block(9) block(8) block(7) block(6) block(5) block(4) block(3) block(2) block(1) LOCAL_LABEL(div0block): block(0) str r0, [r2] mov r0, r3 JMP(lr) LOCAL_LABEL(quotient0): str r0, [r2] mov r0, #0 JMP(lr) LOCAL_LABEL(divby1): mov r3, #0 str r3, [r2] JMP(lr) #endif /* __ARM_ARCH_EXT_IDIV__ */ LOCAL_LABEL(divby0): mov r0, #0 #ifdef __ARM_EABI__ b __aeabi_idiv0 #else JMP(lr) #endif END_COMPILERRT_FUNCTION(__udivmodsi4) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/udivsi3.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/udivsi3.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/udivsi3.S (revision 305364) @@ -1,170 +1,173 @@ /*===-- udivsi3.S - 32-bit unsigned integer divide ------------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __udivsi3 (32-bit unsigned integer divide) * function for the ARM 32-bit architecture. * *===----------------------------------------------------------------------===*/ #include "../assembly.h" .syntax unified .text #if __ARM_ARCH_ISA_THUMB == 2 .thumb #endif .p2align 2 DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_uidiv, __udivsi3) @ unsigned int __udivsi3(unsigned int divident, unsigned int divisor) @ Calculate and return the quotient of the (unsigned) division. #if __ARM_ARCH_ISA_THUMB == 2 DEFINE_COMPILERRT_THUMB_FUNCTION(__udivsi3) #else DEFINE_COMPILERRT_FUNCTION(__udivsi3) #endif #if __ARM_ARCH_EXT_IDIV__ tst r1, r1 beq LOCAL_LABEL(divby0) udiv r0, r0, r1 bx lr #else cmp r1, #1 bcc LOCAL_LABEL(divby0) IT(eq) JMPc(lr, eq) cmp r0, r1 ITT(cc) movcc r0, #0 JMPc(lr, cc) /* * Implement division using binary long division algorithm. * * r0 is the numerator, r1 the denominator. * * The code before JMP computes the correct shift I, so that * r0 and (r1 << I) have the highest bit set in the same position. * At the time of JMP, ip := .Ldiv0block - 12 * I. * This depends on the fixed instruction size of block. * For ARM mode, this is 12 Bytes, for THUMB mode 14 Bytes. * * block(shift) implements the test-and-update-quotient core. * It assumes (r0 << shift) can be computed without overflow and * that (r0 << shift) < 2 * r1. The quotient is stored in r3. */ # ifdef __ARM_FEATURE_CLZ clz ip, r0 clz r3, r1 /* r0 >= r1 implies clz(r0) <= clz(r1), so ip <= r3. */ sub r3, r3, ip # if __ARM_ARCH_ISA_THUMB == 2 adr ip, LOCAL_LABEL(div0block) + 1 sub ip, ip, r3, lsl #1 # else adr ip, LOCAL_LABEL(div0block) # endif sub ip, ip, r3, lsl #2 sub ip, ip, r3, lsl #3 mov r3, #0 bx ip # else # if __ARM_ARCH_ISA_THUMB == 2 # error THUMB mode requires CLZ or UDIV # endif mov r2, r0 adr ip, LOCAL_LABEL(div0block) lsr r3, r2, #16 cmp r3, r1 movhs r2, r3 subhs ip, ip, #(16 * 12) lsr r3, r2, #8 cmp r3, r1 movhs r2, r3 subhs ip, ip, #(8 * 12) lsr r3, r2, #4 cmp r3, r1 movhs r2, r3 subhs ip, #(4 * 12) lsr r3, r2, #2 cmp r3, r1 movhs r2, r3 subhs ip, ip, #(2 * 12) /* Last block, no need to update r2 or r3. */ cmp r1, r2, lsr #1 subls ip, ip, #(1 * 12) mov r3, #0 JMP(ip) # endif #define IMM # #define block(shift) \ cmp r0, r1, lsl IMM shift; \ ITT(hs); \ WIDE(addhs) r3, r3, IMM (1 << shift); \ WIDE(subhs) r0, r0, r1, lsl IMM shift block(31) block(30) block(29) block(28) block(27) block(26) block(25) block(24) block(23) block(22) block(21) block(20) block(19) block(18) block(17) block(16) block(15) block(14) block(13) block(12) block(11) block(10) block(9) block(8) block(7) block(6) block(5) block(4) block(3) block(2) block(1) LOCAL_LABEL(div0block): block(0) mov r0, r3 JMP(lr) #endif /* __ARM_ARCH_EXT_IDIV__ */ LOCAL_LABEL(divby0): mov r0, #0 #ifdef __ARM_EABI__ b __aeabi_idiv0 #else JMP(lr) #endif END_COMPILERRT_FUNCTION(__udivsi3) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/umodsi3.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/umodsi3.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/umodsi3.S (revision 305364) @@ -1,161 +1,164 @@ /*===-- umodsi3.S - 32-bit unsigned integer modulus -----------------------===// * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------===// * * This file implements the __umodsi3 (32-bit unsigned integer modulus) * function for the ARM 32-bit architecture. * *===----------------------------------------------------------------------===*/ #include "../assembly.h" .syntax unified .text #if __ARM_ARCH_ISA_THUMB == 2 .thumb #endif @ unsigned int __umodsi3(unsigned int divident, unsigned int divisor) @ Calculate and return the remainder of the (unsigned) division. .p2align 2 #if __ARM_ARCH_ISA_THUMB == 2 DEFINE_COMPILERRT_THUMB_FUNCTION(__umodsi3) #else DEFINE_COMPILERRT_FUNCTION(__umodsi3) #endif #if __ARM_ARCH_EXT_IDIV__ tst r1, r1 beq LOCAL_LABEL(divby0) udiv r2, r0, r1 mls r0, r2, r1, r0 bx lr #else cmp r1, #1 bcc LOCAL_LABEL(divby0) ITT(eq) moveq r0, #0 JMPc(lr, eq) cmp r0, r1 IT(cc) JMPc(lr, cc) /* * Implement division using binary long division algorithm. * * r0 is the numerator, r1 the denominator. * * The code before JMP computes the correct shift I, so that * r0 and (r1 << I) have the highest bit set in the same position. * At the time of JMP, ip := .Ldiv0block - 8 * I. * This depends on the fixed instruction size of block. * For ARM mode, this is 8 Bytes, for THUMB mode 10 Bytes. * * block(shift) implements the test-and-update-quotient core. * It assumes (r0 << shift) can be computed without overflow and * that (r0 << shift) < 2 * r1. The quotient is stored in r3. */ # ifdef __ARM_FEATURE_CLZ clz ip, r0 clz r3, r1 /* r0 >= r1 implies clz(r0) <= clz(r1), so ip <= r3. */ sub r3, r3, ip # if __ARM_ARCH_ISA_THUMB == 2 adr ip, LOCAL_LABEL(div0block) + 1 sub ip, ip, r3, lsl #1 # else adr ip, LOCAL_LABEL(div0block) # endif sub ip, ip, r3, lsl #3 bx ip # else # if __ARM_ARCH_ISA_THUMB == 2 # error THUMB mode requires CLZ or UDIV # endif mov r2, r0 adr ip, LOCAL_LABEL(div0block) lsr r3, r2, #16 cmp r3, r1 movhs r2, r3 subhs ip, ip, #(16 * 8) lsr r3, r2, #8 cmp r3, r1 movhs r2, r3 subhs ip, ip, #(8 * 8) lsr r3, r2, #4 cmp r3, r1 movhs r2, r3 subhs ip, #(4 * 8) lsr r3, r2, #2 cmp r3, r1 movhs r2, r3 subhs ip, ip, #(2 * 8) /* Last block, no need to update r2 or r3. */ cmp r1, r2, lsr #1 subls ip, ip, #(1 * 8) JMP(ip) # endif #define IMM # #define block(shift) \ cmp r0, r1, lsl IMM shift; \ IT(hs); \ WIDE(subhs) r0, r0, r1, lsl IMM shift block(31) block(30) block(29) block(28) block(27) block(26) block(25) block(24) block(23) block(22) block(21) block(20) block(19) block(18) block(17) block(16) block(15) block(14) block(13) block(12) block(11) block(10) block(9) block(8) block(7) block(6) block(5) block(4) block(3) block(2) block(1) LOCAL_LABEL(div0block): block(0) JMP(lr) #endif /* __ARM_ARCH_EXT_IDIV__ */ LOCAL_LABEL(divby0): mov r0, #0 #ifdef __ARM_EABI__ b __aeabi_idiv0 #else JMP(lr) #endif END_COMPILERRT_FUNCTION(__umodsi3) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/unorddf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/unorddf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/unorddf2vfp.S (revision 305364) @@ -1,29 +1,32 @@ //===-- unorddf2vfp.S - Implement unorddf2vfp ------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern int __unorddf2vfp(double a, double b); // // Returns one iff a or b is NaN // Uses Darwin calling convention where double precision arguments are passsed // like in GPR pairs. // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__unorddf2vfp) vmov d6, r0, r1 // load r0/r1 pair in double register vmov d7, r2, r3 // load r2/r3 pair in double register vcmp.f64 d6, d7 vmrs apsr_nzcv, fpscr movvs r0, #1 // set result register to 1 if "overflow" (any NaNs) movvc r0, #0 bx lr END_COMPILERRT_FUNCTION(__unorddf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/unordsf2vfp.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/unordsf2vfp.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/arm/unordsf2vfp.S (revision 305364) @@ -1,29 +1,32 @@ //===-- unordsf2vfp.S - Implement unordsf2vfp -----------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // extern int __unordsf2vfp(float a, float b); // // Returns one iff a or b is NaN // Uses Darwin calling convention where single precision arguments are passsed // like 32-bit ints // .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__unordsf2vfp) vmov s14, r0 // move from GPR 0 to float register vmov s15, r1 // move from GPR 1 to float register vcmp.f32 s14, s15 vmrs apsr_nzcv, fpscr movvs r0, #1 // set result register to 1 if "overflow" (any NaNs) movvc r0, #0 bx lr END_COMPILERRT_FUNCTION(__unordsf2vfp) + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/assembly.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/assembly.h (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/assembly.h (revision 305364) @@ -1,158 +1,168 @@ /* ===-- assembly.h - compiler-rt assembler support macros -----------------=== * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== * * This file defines macros for use in compiler-rt assembler source. * This file is not part of the interface of this library. * * ===----------------------------------------------------------------------=== */ #ifndef COMPILERRT_ASSEMBLY_H #define COMPILERRT_ASSEMBLY_H #if defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__) #define SEPARATOR @ #else #define SEPARATOR ; #endif #if defined(__APPLE__) #define HIDDEN(name) .private_extern name #define LOCAL_LABEL(name) L_##name // tell linker it can break up file at label boundaries #define FILE_LEVEL_DIRECTIVE .subsections_via_symbols #define SYMBOL_IS_FUNC(name) #define CONST_SECTION .const +#define NO_EXEC_STACK_DIRECTIVE + #elif defined(__ELF__) #define HIDDEN(name) .hidden name #define LOCAL_LABEL(name) .L_##name #define FILE_LEVEL_DIRECTIVE #if defined(__arm__) #define SYMBOL_IS_FUNC(name) .type name,%function #else #define SYMBOL_IS_FUNC(name) .type name,@function #endif #define CONST_SECTION .section .rodata +#if defined(__GNU__) || defined(__ANDROID__) || defined(__FreeBSD__) +#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits +#else +#define NO_EXEC_STACK_DIRECTIVE +#endif + #else // !__APPLE__ && !__ELF__ #define HIDDEN(name) #define LOCAL_LABEL(name) .L ## name #define FILE_LEVEL_DIRECTIVE #define SYMBOL_IS_FUNC(name) \ .def name SEPARATOR \ .scl 2 SEPARATOR \ .type 32 SEPARATOR \ .endef #define CONST_SECTION .section .rdata,"rd" + +#define NO_EXEC_STACK_DIRECTIVE #endif #if defined(__arm__) #if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5 #define ARM_HAS_BX #endif #if !defined(__ARM_FEATURE_CLZ) && \ (__ARM_ARCH >= 6 || (__ARM_ARCH == 5 && !defined(__ARM_ARCH_5__))) #define __ARM_FEATURE_CLZ #endif #ifdef ARM_HAS_BX #define JMP(r) bx r #define JMPc(r, c) bx##c r #else #define JMP(r) mov pc, r #define JMPc(r, c) mov##c pc, r #endif // pop {pc} can't switch Thumb mode on ARMv4T #if __ARM_ARCH >= 5 #define POP_PC() pop {pc} #else #define POP_PC() \ pop {ip}; \ JMP(ip) #endif #if __ARM_ARCH_ISA_THUMB == 2 #define IT(cond) it cond #define ITT(cond) itt cond #else #define IT(cond) #define ITT(cond) #endif #if __ARM_ARCH_ISA_THUMB == 2 #define WIDE(op) op.w #else #define WIDE(op) op #endif #endif #define GLUE2(a, b) a##b #define GLUE(a, b) GLUE2(a, b) #define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name) #ifdef VISIBILITY_HIDDEN #define DECLARE_SYMBOL_VISIBILITY(name) \ HIDDEN(SYMBOL_NAME(name)) SEPARATOR #else #define DECLARE_SYMBOL_VISIBILITY(name) #endif #define DEFINE_COMPILERRT_FUNCTION(name) \ FILE_LEVEL_DIRECTIVE SEPARATOR \ .globl SYMBOL_NAME(name) SEPARATOR \ SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ DECLARE_SYMBOL_VISIBILITY(name) \ SYMBOL_NAME(name): #define DEFINE_COMPILERRT_THUMB_FUNCTION(name) \ FILE_LEVEL_DIRECTIVE SEPARATOR \ .globl SYMBOL_NAME(name) SEPARATOR \ SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \ .thumb_func SEPARATOR \ SYMBOL_NAME(name): #define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \ FILE_LEVEL_DIRECTIVE SEPARATOR \ .globl SYMBOL_NAME(name) SEPARATOR \ SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ HIDDEN(SYMBOL_NAME(name)) SEPARATOR \ SYMBOL_NAME(name): #define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name) \ .globl name SEPARATOR \ SYMBOL_IS_FUNC(name) SEPARATOR \ HIDDEN(name) SEPARATOR \ name: #define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target) \ .globl SYMBOL_NAME(name) SEPARATOR \ SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ .set SYMBOL_NAME(name), SYMBOL_NAME(target) SEPARATOR #if defined(__ARM_EABI__) #define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) \ DEFINE_COMPILERRT_FUNCTION_ALIAS(aeabi_name, name) #else #define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) #endif #ifdef __ELF__ #define END_COMPILERRT_FUNCTION(name) \ .size SYMBOL_NAME(name), . - SYMBOL_NAME(name) #else #define END_COMPILERRT_FUNCTION(name) #endif #endif /* COMPILERRT_ASSEMBLY_H */ Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/clear_cache.c =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/clear_cache.c (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/clear_cache.c (revision 305364) @@ -1,159 +1,170 @@ /* ===-- clear_cache.c - Implement __clear_cache ---------------------------=== * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== */ #include "int_lib.h" #include #if __APPLE__ #include #endif + +#if defined(_WIN32) +/* Forward declare Win32 APIs since the GCC mode driver does not handle the + newer SDKs as well as needed. */ +uint32_t FlushInstructionCache(uintptr_t hProcess, void *lpBaseAddress, + uintptr_t dwSize); +uintptr_t GetCurrentProcess(void); +#endif + #if (defined(__FreeBSD__) || defined(__Bitrig__)) && defined(__arm__) #include #include #endif #if defined(__NetBSD__) && defined(__arm__) #include #endif #if defined(__mips__) && !defined(__FreeBSD__) #include #include #include #if defined(__ANDROID__) && defined(__LP64__) /* * clear_mips_cache - Invalidates instruction cache for Mips. */ static void clear_mips_cache(const void* Addr, size_t Size) { asm volatile ( ".set push\n" ".set noreorder\n" ".set noat\n" "beq %[Size], $zero, 20f\n" /* If size == 0, branch around. */ "nop\n" "daddu %[Size], %[Addr], %[Size]\n" /* Calculate end address + 1 */ "rdhwr $v0, $1\n" /* Get step size for SYNCI. $1 is $HW_SYNCI_Step */ "beq $v0, $zero, 20f\n" /* If no caches require synchronization, branch around. */ "nop\n" "10:\n" "synci 0(%[Addr])\n" /* Synchronize all caches around address. */ "daddu %[Addr], %[Addr], $v0\n" /* Add step size. */ "sltu $at, %[Addr], %[Size]\n" /* Compare current with end address. */ "bne $at, $zero, 10b\n" /* Branch if more to do. */ "nop\n" "sync\n" /* Clear memory hazards. */ "20:\n" "bal 30f\n" "nop\n" "30:\n" "daddiu $ra, $ra, 12\n" /* $ra has a value of $pc here. Add offset of 12 to point to the instruction after the last nop. */ "jr.hb $ra\n" /* Return, clearing instruction hazards. */ "nop\n" ".set pop\n" : [Addr] "+r"(Addr), [Size] "+r"(Size) :: "at", "ra", "v0", "memory" ); } #endif #endif -#if defined(__ANDROID__) && defined(__arm__) +#if defined(__linux__) && defined(__arm__) #include #endif /* * The compiler generates calls to __clear_cache() when creating * trampoline functions on the stack for use with nested functions. * It is expected to invalidate the instruction cache for the * specified range. */ void __clear_cache(void *start, void *end) { #if __i386__ || __x86_64__ /* * Intel processors have a unified instruction and data cache * so there is nothing to do */ #elif defined(__arm__) && !defined(__APPLE__) #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__Bitrig__) struct arm_sync_icache_args arg; arg.addr = (uintptr_t)start; arg.len = (uintptr_t)end - (uintptr_t)start; sysarch(ARM_SYNC_ICACHE, &arg); - #elif defined(__ANDROID__) + #elif defined(__linux__) register int start_reg __asm("r0") = (int) (intptr_t) start; const register int end_reg __asm("r1") = (int) (intptr_t) end; - const register int flags __asm("r2") = 0; const register int syscall_nr __asm("r7") = __ARM_NR_cacheflush; - __asm __volatile("svc 0x0" : "=r"(start_reg) - : "r"(syscall_nr), "r"(start_reg), "r"(end_reg), "r"(flags) : "r0"); + __asm __volatile("svc 0x0" + : "=r"(start_reg) + : "r"(syscall_nr), "r"(start_reg), "r"(end_reg)); if (start_reg != 0) { compilerrt_abort(); } + #elif defined(_WIN32) + FlushInstructionCache(GetCurrentProcess(), start, end - start); #else compilerrt_abort(); #endif #elif defined(__mips__) && !defined(__FreeBSD__) const uintptr_t start_int = (uintptr_t) start; const uintptr_t end_int = (uintptr_t) end; #if defined(__ANDROID__) && defined(__LP64__) // Call synci implementation for short address range. const uintptr_t address_range_limit = 256; if ((end_int - start_int) <= address_range_limit) { clear_mips_cache(start, (end_int - start_int)); } else { syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE); } #else syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE); #endif #elif defined(__aarch64__) && !defined(__APPLE__) uint64_t xstart = (uint64_t)(uintptr_t) start; uint64_t xend = (uint64_t)(uintptr_t) end; uint64_t addr; // Get Cache Type Info uint64_t ctr_el0; __asm __volatile("mrs %0, ctr_el0" : "=r"(ctr_el0)); /* * dc & ic instructions must use 64bit registers so we don't use * uintptr_t in case this runs in an IPL32 environment. */ const size_t dcache_line_size = 4 << ((ctr_el0 >> 16) & 15); for (addr = xstart; addr < xend; addr += dcache_line_size) __asm __volatile("dc cvau, %0" :: "r"(addr)); __asm __volatile("dsb ish"); const size_t icache_line_size = 4 << ((ctr_el0 >> 0) & 15); for (addr = xstart; addr < xend; addr += icache_line_size) __asm __volatile("ic ivau, %0" :: "r"(addr)); __asm __volatile("isb sy"); #else #if __APPLE__ /* On Darwin, sys_icache_invalidate() provides this functionality */ sys_icache_invalidate(start, end-start); #else compilerrt_abort(); #endif #endif } Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/cpu_model.c =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/cpu_model.c (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/cpu_model.c (revision 305364) @@ -0,0 +1,797 @@ +//===-- cpu_model.c - Support for __cpu_model builtin ------------*- C -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is based on LLVM's lib/Support/Host.cpp. +// It implements the operating system Host concept and builtin +// __cpu_model for the compiler_rt library, for x86 only. +// +//===----------------------------------------------------------------------===// + +#if (defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64__) || defined(_M_X64)) && \ + (defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)) + +#include + +#define bool int +#define true 1 +#define false 0 + +#ifdef _MSC_VER +#include +#endif + +enum VendorSignatures { + SIG_INTEL = 0x756e6547 /* Genu */, + SIG_AMD = 0x68747541 /* Auth */ +}; + +enum ProcessorVendors { + VENDOR_INTEL = 1, + VENDOR_AMD, + VENDOR_OTHER, + VENDOR_MAX +}; + +enum ProcessorTypes { + INTEL_ATOM = 1, + INTEL_CORE2, + INTEL_COREI7, + AMDFAM10H, + AMDFAM15H, + INTEL_i386, + INTEL_i486, + INTEL_PENTIUM, + INTEL_PENTIUM_PRO, + INTEL_PENTIUM_II, + INTEL_PENTIUM_III, + INTEL_PENTIUM_IV, + INTEL_PENTIUM_M, + INTEL_CORE_DUO, + INTEL_XEONPHI, + INTEL_X86_64, + INTEL_NOCONA, + INTEL_PRESCOTT, + AMD_i486, + AMDPENTIUM, + AMDATHLON, + AMDFAM14H, + AMDFAM16H, + CPU_TYPE_MAX +}; + +enum ProcessorSubtypes { + INTEL_COREI7_NEHALEM = 1, + INTEL_COREI7_WESTMERE, + INTEL_COREI7_SANDYBRIDGE, + AMDFAM10H_BARCELONA, + AMDFAM10H_SHANGHAI, + AMDFAM10H_ISTANBUL, + AMDFAM15H_BDVER1, + AMDFAM15H_BDVER2, + INTEL_PENTIUM_MMX, + INTEL_CORE2_65, + INTEL_CORE2_45, + INTEL_COREI7_IVYBRIDGE, + INTEL_COREI7_HASWELL, + INTEL_COREI7_BROADWELL, + INTEL_COREI7_SKYLAKE, + INTEL_COREI7_SKYLAKE_AVX512, + INTEL_ATOM_BONNELL, + INTEL_ATOM_SILVERMONT, + INTEL_KNIGHTS_LANDING, + AMDPENTIUM_K6, + AMDPENTIUM_K62, + AMDPENTIUM_K63, + AMDPENTIUM_GEODE, + AMDATHLON_TBIRD, + AMDATHLON_MP, + AMDATHLON_XP, + AMDATHLON_K8SSE3, + AMDATHLON_OPTERON, + AMDATHLON_FX, + AMDATHLON_64, + AMD_BTVER1, + AMD_BTVER2, + AMDFAM15H_BDVER3, + AMDFAM15H_BDVER4, + CPU_SUBTYPE_MAX +}; + +enum ProcessorFeatures { + FEATURE_CMOV = 0, + FEATURE_MMX, + FEATURE_POPCNT, + FEATURE_SSE, + FEATURE_SSE2, + FEATURE_SSE3, + FEATURE_SSSE3, + FEATURE_SSE4_1, + FEATURE_SSE4_2, + FEATURE_AVX, + FEATURE_AVX2, + FEATURE_AVX512, + FEATURE_AVX512SAVE, + FEATURE_MOVBE, + FEATURE_ADX, + FEATURE_EM64T +}; + +// The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max). +// Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID +// support. Consequently, for i386, the presence of CPUID is checked first +// via the corresponding eflags bit. +static bool isCpuIdSupported() { +#if defined(__GNUC__) || defined(__clang__) +#if defined(__i386__) + int __cpuid_supported; + __asm__(" pushfl\n" + " popl %%eax\n" + " movl %%eax,%%ecx\n" + " xorl $0x00200000,%%eax\n" + " pushl %%eax\n" + " popfl\n" + " pushfl\n" + " popl %%eax\n" + " movl $0,%0\n" + " cmpl %%eax,%%ecx\n" + " je 1f\n" + " movl $1,%0\n" + "1:" + : "=r"(__cpuid_supported) + : + : "eax", "ecx"); + if (!__cpuid_supported) + return false; +#endif + return true; +#endif + return true; +} + +// This code is copied from lib/Support/Host.cpp. +// Changes to either file should be mirrored in the other. + +/// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in +/// the specified arguments. If we can't run cpuid on the host, return true. +static void getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX, + unsigned *rECX, unsigned *rEDX) { +#if defined(__GNUC__) || defined(__clang__) +#if defined(__x86_64__) + // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. + __asm__("movq\t%%rbx, %%rsi\n\t" + "cpuid\n\t" + "xchgq\t%%rbx, %%rsi\n\t" + : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) + : "a"(value)); +#elif defined(__i386__) + __asm__("movl\t%%ebx, %%esi\n\t" + "cpuid\n\t" + "xchgl\t%%ebx, %%esi\n\t" + : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) + : "a"(value)); +// pedantic #else returns to appease -Wunreachable-code (so we don't generate +// postprocessed code that looks like "return true; return false;") +#else + assert(0 && "This method is defined only for x86."); +#endif +#elif defined(_MSC_VER) + // The MSVC intrinsic is portable across x86 and x64. + int registers[4]; + __cpuid(registers, value); + *rEAX = registers[0]; + *rEBX = registers[1]; + *rECX = registers[2]; + *rEDX = registers[3]; +#else + assert(0 && "This method is defined only for GNUC, Clang or MSVC."); +#endif +} + +/// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return +/// the 4 values in the specified arguments. If we can't run cpuid on the host, +/// return true. +static void getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf, + unsigned *rEAX, unsigned *rEBX, unsigned *rECX, + unsigned *rEDX) { +#if defined(__x86_64__) || defined(_M_X64) +#if defined(__GNUC__) || defined(__clang__) + // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually. + // FIXME: should we save this for Clang? + __asm__("movq\t%%rbx, %%rsi\n\t" + "cpuid\n\t" + "xchgq\t%%rbx, %%rsi\n\t" + : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) + : "a"(value), "c"(subleaf)); +#elif defined(_MSC_VER) + int registers[4]; + __cpuidex(registers, value, subleaf); + *rEAX = registers[0]; + *rEBX = registers[1]; + *rECX = registers[2]; + *rEDX = registers[3]; +#else + assert(0 && "This method is defined only for GNUC, Clang or MSVC."); +#endif +#elif defined(__i386__) || defined(_M_IX86) +#if defined(__GNUC__) || defined(__clang__) + __asm__("movl\t%%ebx, %%esi\n\t" + "cpuid\n\t" + "xchgl\t%%ebx, %%esi\n\t" + : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) + : "a"(value), "c"(subleaf)); +#elif defined(_MSC_VER) + __asm { + mov eax,value + mov ecx,subleaf + cpuid + mov esi,rEAX + mov dword ptr [esi],eax + mov esi,rEBX + mov dword ptr [esi],ebx + mov esi,rECX + mov dword ptr [esi],ecx + mov esi,rEDX + mov dword ptr [esi],edx + } +#else + assert(0 && "This method is defined only for GNUC, Clang or MSVC."); +#endif +#else + assert(0 && "This method is defined only for x86."); +#endif +} + +// Read control register 0 (XCR0). Used to detect features such as AVX. +static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) { +#if defined(__GNUC__) || defined(__clang__) + // Check xgetbv; this uses a .byte sequence instead of the instruction + // directly because older assemblers do not include support for xgetbv and + // there is no easy way to conditionally compile based on the assembler used. + __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0)); + return false; +#elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK) + unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK); + *rEAX = Result; + *rEDX = Result >> 32; + return false; +#else + return true; +#endif +} + +static void detectX86FamilyModel(unsigned EAX, unsigned *Family, + unsigned *Model) { + *Family = (EAX >> 8) & 0xf; // Bits 8 - 11 + *Model = (EAX >> 4) & 0xf; // Bits 4 - 7 + if (*Family == 6 || *Family == 0xf) { + if (*Family == 0xf) + // Examine extended family ID if family ID is F. + *Family += (EAX >> 20) & 0xff; // Bits 20 - 27 + // Examine extended model ID if family ID is 6 or F. + *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19 + } +} + +static void getIntelProcessorTypeAndSubtype(unsigned int Family, + unsigned int Model, + unsigned int Brand_id, + unsigned int Features, + unsigned *Type, unsigned *Subtype) { + if (Brand_id != 0) + return; + switch (Family) { + case 3: + *Type = INTEL_i386; + break; + case 4: + switch (Model) { + case 0: // Intel486 DX processors + case 1: // Intel486 DX processors + case 2: // Intel486 SX processors + case 3: // Intel487 processors, IntelDX2 OverDrive processors, + // IntelDX2 processors + case 4: // Intel486 SL processor + case 5: // IntelSX2 processors + case 7: // Write-Back Enhanced IntelDX2 processors + case 8: // IntelDX4 OverDrive processors, IntelDX4 processors + default: + *Type = INTEL_i486; + break; + } + case 5: + switch (Model) { + case 1: // Pentium OverDrive processor for Pentium processor (60, 66), + // Pentium processors (60, 66) + case 2: // Pentium OverDrive processor for Pentium processor (75, 90, + // 100, 120, 133), Pentium processors (75, 90, 100, 120, 133, + // 150, 166, 200) + case 3: // Pentium OverDrive processors for Intel486 processor-based + // systems + *Type = INTEL_PENTIUM; + break; + case 4: // Pentium OverDrive processor with MMX technology for Pentium + // processor (75, 90, 100, 120, 133), Pentium processor with + // MMX technology (166, 200) + *Type = INTEL_PENTIUM; + *Subtype = INTEL_PENTIUM_MMX; + break; + default: + *Type = INTEL_PENTIUM; + break; + } + case 6: + switch (Model) { + case 0x01: // Pentium Pro processor + *Type = INTEL_PENTIUM_PRO; + break; + case 0x03: // Intel Pentium II OverDrive processor, Pentium II processor, + // model 03 + case 0x05: // Pentium II processor, model 05, Pentium II Xeon processor, + // model 05, and Intel Celeron processor, model 05 + case 0x06: // Celeron processor, model 06 + *Type = INTEL_PENTIUM_II; + break; + case 0x07: // Pentium III processor, model 07, and Pentium III Xeon + // processor, model 07 + case 0x08: // Pentium III processor, model 08, Pentium III Xeon processor, + // model 08, and Celeron processor, model 08 + case 0x0a: // Pentium III Xeon processor, model 0Ah + case 0x0b: // Pentium III processor, model 0Bh + *Type = INTEL_PENTIUM_III; + break; + case 0x09: // Intel Pentium M processor, Intel Celeron M processor model 09. + case 0x0d: // Intel Pentium M processor, Intel Celeron M processor, model + // 0Dh. All processors are manufactured using the 90 nm process. + case 0x15: // Intel EP80579 Integrated Processor and Intel EP80579 + // Integrated Processor with Intel QuickAssist Technology + *Type = INTEL_PENTIUM_M; + break; + case 0x0e: // Intel Core Duo processor, Intel Core Solo processor, model + // 0Eh. All processors are manufactured using the 65 nm process. + *Type = INTEL_CORE_DUO; + break; // yonah + case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile + // processor, Intel Core 2 Quad processor, Intel Core 2 Quad + // mobile processor, Intel Core 2 Extreme processor, Intel + // Pentium Dual-Core processor, Intel Xeon processor, model + // 0Fh. All processors are manufactured using the 65 nm process. + case 0x16: // Intel Celeron processor model 16h. All processors are + // manufactured using the 65 nm process + *Type = INTEL_CORE2; // "core2" + *Subtype = INTEL_CORE2_65; + break; + case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model + // 17h. All processors are manufactured using the 45 nm process. + // + // 45nm: Penryn , Wolfdale, Yorkfield (XE) + case 0x1d: // Intel Xeon processor MP. All processors are manufactured using + // the 45 nm process. + *Type = INTEL_CORE2; // "penryn" + *Subtype = INTEL_CORE2_45; + break; + case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All + // processors are manufactured using the 45 nm process. + case 0x1e: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz. + // As found in a Summer 2010 model iMac. + case 0x1f: + case 0x2e: // Nehalem EX + *Type = INTEL_COREI7; // "nehalem" + *Subtype = INTEL_COREI7_NEHALEM; + break; + case 0x25: // Intel Core i7, laptop version. + case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All + // processors are manufactured using the 32 nm process. + case 0x2f: // Westmere EX + *Type = INTEL_COREI7; // "westmere" + *Subtype = INTEL_COREI7_WESTMERE; + break; + case 0x2a: // Intel Core i7 processor. All processors are manufactured + // using the 32 nm process. + case 0x2d: + *Type = INTEL_COREI7; //"sandybridge" + *Subtype = INTEL_COREI7_SANDYBRIDGE; + break; + case 0x3a: + case 0x3e: // Ivy Bridge EP + *Type = INTEL_COREI7; // "ivybridge" + *Subtype = INTEL_COREI7_IVYBRIDGE; + break; + + // Haswell: + case 0x3c: + case 0x3f: + case 0x45: + case 0x46: + *Type = INTEL_COREI7; // "haswell" + *Subtype = INTEL_COREI7_HASWELL; + break; + + // Broadwell: + case 0x3d: + case 0x47: + case 0x4f: + case 0x56: + *Type = INTEL_COREI7; // "broadwell" + *Subtype = INTEL_COREI7_BROADWELL; + break; + + // Skylake: + case 0x4e: + *Type = INTEL_COREI7; // "skylake-avx512" + *Subtype = INTEL_COREI7_SKYLAKE_AVX512; + break; + case 0x5e: + *Type = INTEL_COREI7; // "skylake" + *Subtype = INTEL_COREI7_SKYLAKE; + break; + + case 0x1c: // Most 45 nm Intel Atom processors + case 0x26: // 45 nm Atom Lincroft + case 0x27: // 32 nm Atom Medfield + case 0x35: // 32 nm Atom Midview + case 0x36: // 32 nm Atom Midview + *Type = INTEL_ATOM; + *Subtype = INTEL_ATOM_BONNELL; + break; // "bonnell" + + // Atom Silvermont codes from the Intel software optimization guide. + case 0x37: + case 0x4a: + case 0x4d: + case 0x5a: + case 0x5d: + case 0x4c: // really airmont + *Type = INTEL_ATOM; + *Subtype = INTEL_ATOM_SILVERMONT; + break; // "silvermont" + + case 0x57: + *Type = INTEL_XEONPHI; // knl + *Subtype = INTEL_KNIGHTS_LANDING; + break; + + default: // Unknown family 6 CPU, try to guess. + if (Features & (1 << FEATURE_AVX512)) { + *Type = INTEL_XEONPHI; // knl + *Subtype = INTEL_KNIGHTS_LANDING; + break; + } + if (Features & (1 << FEATURE_ADX)) { + *Type = INTEL_COREI7; + *Subtype = INTEL_COREI7_BROADWELL; + break; + } + if (Features & (1 << FEATURE_AVX2)) { + *Type = INTEL_COREI7; + *Subtype = INTEL_COREI7_HASWELL; + break; + } + if (Features & (1 << FEATURE_AVX)) { + *Type = INTEL_COREI7; + *Subtype = INTEL_COREI7_SANDYBRIDGE; + break; + } + if (Features & (1 << FEATURE_SSE4_2)) { + if (Features & (1 << FEATURE_MOVBE)) { + *Type = INTEL_ATOM; + *Subtype = INTEL_ATOM_SILVERMONT; + } else { + *Type = INTEL_COREI7; + *Subtype = INTEL_COREI7_NEHALEM; + } + break; + } + if (Features & (1 << FEATURE_SSE4_1)) { + *Type = INTEL_CORE2; // "penryn" + *Subtype = INTEL_CORE2_45; + break; + } + if (Features & (1 << FEATURE_SSSE3)) { + if (Features & (1 << FEATURE_MOVBE)) { + *Type = INTEL_ATOM; + *Subtype = INTEL_ATOM_BONNELL; // "bonnell" + } else { + *Type = INTEL_CORE2; // "core2" + *Subtype = INTEL_CORE2_65; + } + break; + } + if (Features & (1 << FEATURE_EM64T)) { + *Type = INTEL_X86_64; + break; // x86-64 + } + if (Features & (1 << FEATURE_SSE2)) { + *Type = INTEL_PENTIUM_M; + break; + } + if (Features & (1 << FEATURE_SSE)) { + *Type = INTEL_PENTIUM_III; + break; + } + if (Features & (1 << FEATURE_MMX)) { + *Type = INTEL_PENTIUM_II; + break; + } + *Type = INTEL_PENTIUM_PRO; + break; + } + case 15: { + switch (Model) { + case 0: // Pentium 4 processor, Intel Xeon processor. All processors are + // model 00h and manufactured using the 0.18 micron process. + case 1: // Pentium 4 processor, Intel Xeon processor, Intel Xeon + // processor MP, and Intel Celeron processor. All processors are + // model 01h and manufactured using the 0.18 micron process. + case 2: // Pentium 4 processor, Mobile Intel Pentium 4 processor - M, + // Intel Xeon processor, Intel Xeon processor MP, Intel Celeron + // processor, and Mobile Intel Celeron processor. All processors + // are model 02h and manufactured using the 0.13 micron process. + *Type = + ((Features & (1 << FEATURE_EM64T)) ? INTEL_X86_64 : INTEL_PENTIUM_IV); + break; + + case 3: // Pentium 4 processor, Intel Xeon processor, Intel Celeron D + // processor. All processors are model 03h and manufactured using + // the 90 nm process. + case 4: // Pentium 4 processor, Pentium 4 processor Extreme Edition, + // Pentium D processor, Intel Xeon processor, Intel Xeon + // processor MP, Intel Celeron D processor. All processors are + // model 04h and manufactured using the 90 nm process. + case 6: // Pentium 4 processor, Pentium D processor, Pentium processor + // Extreme Edition, Intel Xeon processor, Intel Xeon processor + // MP, Intel Celeron D processor. All processors are model 06h + // and manufactured using the 65 nm process. + *Type = + ((Features & (1 << FEATURE_EM64T)) ? INTEL_NOCONA : INTEL_PRESCOTT); + break; + + default: + *Type = + ((Features & (1 << FEATURE_EM64T)) ? INTEL_X86_64 : INTEL_PENTIUM_IV); + break; + } + } + default: + break; /*"generic"*/ + } +} + +static void getAMDProcessorTypeAndSubtype(unsigned int Family, + unsigned int Model, + unsigned int Features, unsigned *Type, + unsigned *Subtype) { + // FIXME: this poorly matches the generated SubtargetFeatureKV table. There + // appears to be no way to generate the wide variety of AMD-specific targets + // from the information returned from CPUID. + switch (Family) { + case 4: + *Type = AMD_i486; + case 5: + *Type = AMDPENTIUM; + switch (Model) { + case 6: + case 7: + *Subtype = AMDPENTIUM_K6; + break; // "k6" + case 8: + *Subtype = AMDPENTIUM_K62; + break; // "k6-2" + case 9: + case 13: + *Subtype = AMDPENTIUM_K63; + break; // "k6-3" + case 10: + *Subtype = AMDPENTIUM_GEODE; + break; // "geode" + default: + break; + } + case 6: + *Type = AMDATHLON; + switch (Model) { + case 4: + *Subtype = AMDATHLON_TBIRD; + break; // "athlon-tbird" + case 6: + case 7: + case 8: + *Subtype = AMDATHLON_MP; + break; // "athlon-mp" + case 10: + *Subtype = AMDATHLON_XP; + break; // "athlon-xp" + default: + break; + } + case 15: + *Type = AMDATHLON; + if (Features & (1 << FEATURE_SSE3)) { + *Subtype = AMDATHLON_K8SSE3; + break; // "k8-sse3" + } + switch (Model) { + case 1: + *Subtype = AMDATHLON_OPTERON; + break; // "opteron" + case 5: + *Subtype = AMDATHLON_FX; + break; // "athlon-fx"; also opteron + default: + *Subtype = AMDATHLON_64; + break; // "athlon64" + } + case 16: + *Type = AMDFAM10H; // "amdfam10" + switch (Model) { + case 2: + *Subtype = AMDFAM10H_BARCELONA; + break; + case 4: + *Subtype = AMDFAM10H_SHANGHAI; + break; + case 8: + *Subtype = AMDFAM10H_ISTANBUL; + break; + default: + break; + } + case 20: + *Type = AMDFAM14H; + *Subtype = AMD_BTVER1; + break; // "btver1"; + case 21: + *Type = AMDFAM15H; + if (!(Features & + (1 << FEATURE_AVX))) { // If no AVX support, provide a sane fallback. + *Subtype = AMD_BTVER1; + break; // "btver1" + } + if (Model >= 0x50 && Model <= 0x6f) { + *Subtype = AMDFAM15H_BDVER4; + break; // "bdver4"; 50h-6Fh: Excavator + } + if (Model >= 0x30 && Model <= 0x3f) { + *Subtype = AMDFAM15H_BDVER3; + break; // "bdver3"; 30h-3Fh: Steamroller + } + if (Model >= 0x10 && Model <= 0x1f) { + *Subtype = AMDFAM15H_BDVER2; + break; // "bdver2"; 10h-1Fh: Piledriver + } + if (Model <= 0x0f) { + *Subtype = AMDFAM15H_BDVER1; + break; // "bdver1"; 00h-0Fh: Bulldozer + } + break; + case 22: + *Type = AMDFAM16H; + if (!(Features & + (1 << FEATURE_AVX))) { // If no AVX support provide a sane fallback. + *Subtype = AMD_BTVER1; + break; // "btver1"; + } + *Subtype = AMD_BTVER2; + break; // "btver2" + default: + break; // "generic" + } +} + +static unsigned getAvailableFeatures(unsigned int ECX, unsigned int EDX, + unsigned MaxLeaf) { + unsigned Features = 0; + unsigned int EAX, EBX; + Features |= (((EDX >> 23) & 1) << FEATURE_MMX); + Features |= (((EDX >> 25) & 1) << FEATURE_SSE); + Features |= (((EDX >> 26) & 1) << FEATURE_SSE2); + Features |= (((ECX >> 0) & 1) << FEATURE_SSE3); + Features |= (((ECX >> 9) & 1) << FEATURE_SSSE3); + Features |= (((ECX >> 19) & 1) << FEATURE_SSE4_1); + Features |= (((ECX >> 20) & 1) << FEATURE_SSE4_2); + Features |= (((ECX >> 22) & 1) << FEATURE_MOVBE); + + // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV + // indicates that the AVX registers will be saved and restored on context + // switch, then we have full AVX support. + const unsigned AVXBits = (1 << 27) | (1 << 28); + bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) && + ((EAX & 0x6) == 0x6); + bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0); + bool HasLeaf7 = MaxLeaf >= 0x7; + getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX); + bool HasADX = HasLeaf7 && ((EBX >> 19) & 1); + bool HasAVX2 = HasAVX && HasLeaf7 && (EBX & 0x20); + bool HasAVX512 = HasLeaf7 && HasAVX512Save && ((EBX >> 16) & 1); + Features |= (HasAVX << FEATURE_AVX); + Features |= (HasAVX2 << FEATURE_AVX2); + Features |= (HasAVX512 << FEATURE_AVX512); + Features |= (HasAVX512Save << FEATURE_AVX512SAVE); + Features |= (HasADX << FEATURE_ADX); + + getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); + Features |= (((EDX >> 29) & 0x1) << FEATURE_EM64T); + return Features; +} + +#ifdef HAVE_INIT_PRIORITY +#define CONSTRUCTOR_PRIORITY (101) +#else +#define CONSTRUCTOR_PRIORITY +#endif + +int __cpu_indicator_init(void) + __attribute__((constructor CONSTRUCTOR_PRIORITY)); + +struct __processor_model { + unsigned int __cpu_vendor; + unsigned int __cpu_type; + unsigned int __cpu_subtype; + unsigned int __cpu_features[1]; +} __cpu_model = {0, 0, 0, {0}}; + +/* A constructor function that is sets __cpu_model and __cpu_features with + the right values. This needs to run only once. This constructor is + given the highest priority and it should run before constructors without + the priority set. However, it still runs after ifunc initializers and + needs to be called explicitly there. */ + +int __attribute__((constructor CONSTRUCTOR_PRIORITY)) +__cpu_indicator_init(void) { + unsigned int EAX, EBX, ECX, EDX; + unsigned int MaxLeaf = 5; + unsigned int Vendor; + unsigned int Model, Family, Brand_id; + unsigned int Features = 0; + + /* This function needs to run just once. */ + if (__cpu_model.__cpu_vendor) + return 0; + + if (!isCpuIdSupported()) + return -1; + + /* Assume cpuid insn present. Run in level 0 to get vendor id. */ + getX86CpuIDAndInfo(0, &MaxLeaf, &Vendor, &ECX, &EDX); + + if (MaxLeaf < 1) { + __cpu_model.__cpu_vendor = VENDOR_OTHER; + return -1; + } + getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX); + detectX86FamilyModel(EAX, &Family, &Model); + Brand_id = EBX & 0xff; + + /* Find available features. */ + Features = getAvailableFeatures(ECX, EDX, MaxLeaf); + __cpu_model.__cpu_features[0] = Features; + + if (Vendor == SIG_INTEL) { + /* Get CPU type. */ + getIntelProcessorTypeAndSubtype(Family, Model, Brand_id, Features, + &(__cpu_model.__cpu_type), + &(__cpu_model.__cpu_subtype)); + __cpu_model.__cpu_vendor = VENDOR_INTEL; + } else if (Vendor == SIG_AMD) { + /* Get CPU type. */ + getAMDProcessorTypeAndSubtype(Family, Model, Features, + &(__cpu_model.__cpu_type), + &(__cpu_model.__cpu_subtype)); + __cpu_model.__cpu_vendor = VENDOR_AMD; + } else + __cpu_model.__cpu_vendor = VENDOR_OTHER; + + assert(__cpu_model.__cpu_vendor < VENDOR_MAX); + assert(__cpu_model.__cpu_type < CPU_TYPE_MAX); + assert(__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX); + + return 0; +} + +#endif Property changes on: projects/clang390-import/contrib/compiler-rt/lib/builtins/cpu_model.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/emutls.c =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/emutls.c (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/emutls.c (revision 305364) @@ -1,183 +1,189 @@ /* ===---------- emutls.c - Implements __emutls_get_address ---------------=== * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== */ #include #include #include #include #include "int_lib.h" #include "int_util.h" /* Default is not to use posix_memalign, so systems like Android * can use thread local data without heavier POSIX memory allocators. */ #ifndef EMUTLS_USE_POSIX_MEMALIGN #define EMUTLS_USE_POSIX_MEMALIGN 0 #endif /* For every TLS variable xyz, * there is one __emutls_control variable named __emutls_v.xyz. * If xyz has non-zero initial value, __emutls_v.xyz's "value" * will point to __emutls_t.xyz, which has the initial value. */ +typedef unsigned int gcc_word __attribute__((mode(word))); typedef struct __emutls_control { - size_t size; /* size of the object in bytes */ - size_t align; /* alignment of the object in bytes */ + /* Must use gcc_word here, instead of size_t, to match GCC. When + gcc_word is larger than size_t, the upper extra bits are all + zeros. We can use variables of size_t to operate on size and + align. */ + gcc_word size; /* size of the object in bytes */ + gcc_word align; /* alignment of the object in bytes */ union { uintptr_t index; /* data[index-1] is the object address */ void* address; /* object address, when in single thread env */ } object; void* value; /* null or non-zero initial value for the object */ } __emutls_control; static __inline void *emutls_memalign_alloc(size_t align, size_t size) { void *base; #if EMUTLS_USE_POSIX_MEMALIGN if (posix_memalign(&base, align, size) != 0) abort(); #else #define EXTRA_ALIGN_PTR_BYTES (align - 1 + sizeof(void*)) char* object; if ((object = malloc(EXTRA_ALIGN_PTR_BYTES + size)) == NULL) abort(); base = (void*)(((uintptr_t)(object + EXTRA_ALIGN_PTR_BYTES)) & ~(uintptr_t)(align - 1)); ((void**)base)[-1] = object; #endif return base; } static __inline void emutls_memalign_free(void *base) { #if EMUTLS_USE_POSIX_MEMALIGN free(base); #else /* The mallocated address is in ((void**)base)[-1] */ free(((void**)base)[-1]); #endif } /* Emulated TLS objects are always allocated at run-time. */ static __inline void *emutls_allocate_object(__emutls_control *control) { /* Use standard C types, check with gcc's emutls.o. */ - typedef unsigned int gcc_word __attribute__((mode(word))); typedef unsigned int gcc_pointer __attribute__((mode(pointer))); - COMPILE_TIME_ASSERT(sizeof(size_t) == sizeof(gcc_word)); COMPILE_TIME_ASSERT(sizeof(uintptr_t) == sizeof(gcc_pointer)); COMPILE_TIME_ASSERT(sizeof(uintptr_t) == sizeof(void*)); size_t size = control->size; size_t align = control->align; + void* base; if (align < sizeof(void*)) align = sizeof(void*); /* Make sure that align is power of 2. */ if ((align & (align - 1)) != 0) abort(); - void* base = emutls_memalign_alloc(align, size); + base = emutls_memalign_alloc(align, size); if (control->value) memcpy(base, control->value, size); else memset(base, 0, size); return base; } static pthread_mutex_t emutls_mutex = PTHREAD_MUTEX_INITIALIZER; static size_t emutls_num_object = 0; /* number of allocated TLS objects */ typedef struct emutls_address_array { uintptr_t size; /* number of elements in the 'data' array */ void* data[]; } emutls_address_array; static pthread_key_t emutls_pthread_key; static void emutls_key_destructor(void* ptr) { emutls_address_array* array = (emutls_address_array*)ptr; uintptr_t i; for (i = 0; i < array->size; ++i) { if (array->data[i]) emutls_memalign_free(array->data[i]); } free(ptr); } static void emutls_init(void) { if (pthread_key_create(&emutls_pthread_key, emutls_key_destructor) != 0) abort(); } /* Returns control->object.index; set index if not allocated yet. */ static __inline uintptr_t emutls_get_index(__emutls_control *control) { uintptr_t index = __atomic_load_n(&control->object.index, __ATOMIC_ACQUIRE); if (!index) { static pthread_once_t once = PTHREAD_ONCE_INIT; pthread_once(&once, emutls_init); pthread_mutex_lock(&emutls_mutex); index = control->object.index; if (!index) { index = ++emutls_num_object; __atomic_store_n(&control->object.index, index, __ATOMIC_RELEASE); } pthread_mutex_unlock(&emutls_mutex); } return index; } /* Updates newly allocated thread local emutls_address_array. */ static __inline void emutls_check_array_set_size(emutls_address_array *array, uintptr_t size) { if (array == NULL) abort(); array->size = size; pthread_setspecific(emutls_pthread_key, (void*)array); } /* Returns the new 'data' array size, number of elements, * which must be no smaller than the given index. */ static __inline uintptr_t emutls_new_data_array_size(uintptr_t index) { /* Need to allocate emutls_address_array with one extra slot * to store the data array size. * Round up the emutls_address_array size to multiple of 16. */ return ((index + 1 + 15) & ~((uintptr_t)15)) - 1; } /* Returns the thread local emutls_address_array. * Extends its size if necessary to hold address at index. */ static __inline emutls_address_array * emutls_get_address_array(uintptr_t index) { emutls_address_array* array = pthread_getspecific(emutls_pthread_key); if (array == NULL) { uintptr_t new_size = emutls_new_data_array_size(index); - array = calloc(new_size + 1, sizeof(void*)); + array = malloc(new_size * sizeof(void *) + sizeof(emutls_address_array)); + if (array) + memset(array->data, 0, new_size * sizeof(void*)); emutls_check_array_set_size(array, new_size); } else if (index > array->size) { uintptr_t orig_size = array->size; uintptr_t new_size = emutls_new_data_array_size(index); - array = realloc(array, (new_size + 1) * sizeof(void*)); + array = realloc(array, new_size * sizeof(void *) + sizeof(emutls_address_array)); if (array) memset(array->data + orig_size, 0, (new_size - orig_size) * sizeof(void*)); emutls_check_array_set_size(array, new_size); } return array; } void* __emutls_get_address(__emutls_control* control) { uintptr_t index = emutls_get_index(control); emutls_address_array* array = emutls_get_address_array(index); if (array->data[index - 1] == NULL) array->data[index - 1] = emutls_allocate_object(control); return array->data[index - 1]; } Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/floatdidf.c =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/floatdidf.c (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/floatdidf.c (revision 305364) @@ -1,107 +1,107 @@ /*===-- floatdidf.c - Implement __floatdidf -------------------------------=== * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * *===----------------------------------------------------------------------=== * * This file implements __floatdidf for the compiler_rt library. * *===----------------------------------------------------------------------=== */ #include "int_lib.h" /* Returns: convert a to a double, rounding toward even. */ -/* Assumption: double is a IEEE 64 bit floating point type +/* Assumption: double is a IEEE 64 bit floating point type * di_int is a 64 bit integral type */ /* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */ ARM_EABI_FNALIAS(l2d, floatdidf) #ifndef __SOFT_FP__ /* Support for systems that have hardware floating-point; we'll set the inexact flag * as a side-effect of this computation. */ COMPILER_RT_ABI double __floatdidf(di_int a) { - static const double twop52 = 4503599627370496.0; // 0x1.0p52 - static const double twop32 = 4294967296.0; // 0x1.0p32 - - union { int64_t x; double d; } low = { .d = twop52 }; - - const double high = (int32_t)(a >> 32) * twop32; - low.x |= a & INT64_C(0x00000000ffffffff); - - const double result = (high - twop52) + low.d; - return result; + static const double twop52 = 4503599627370496.0; // 0x1.0p52 + static const double twop32 = 4294967296.0; // 0x1.0p32 + + union { int64_t x; double d; } low = { .d = twop52 }; + + const double high = (int32_t)(a >> 32) * twop32; + low.x |= a & INT64_C(0x00000000ffffffff); + + const double result = (high - twop52) + low.d; + return result; } #else /* Support for systems that don't have hardware floating-point; there are no flags to * set, and we don't want to code-gen to an unknown soft-float implementation. */ COMPILER_RT_ABI double __floatdidf(di_int a) { if (a == 0) return 0.0; const unsigned N = sizeof(di_int) * CHAR_BIT; const di_int s = a >> (N-1); a = (a ^ s) - s; int sd = N - __builtin_clzll(a); /* number of significant digits */ int e = sd - 1; /* exponent */ if (sd > DBL_MANT_DIG) { /* start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx * finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR * 12345678901234567890123456 * 1 = msb 1 bit * P = bit DBL_MANT_DIG-1 bits to the right of 1 * Q = bit DBL_MANT_DIG bits to the right of 1 * R = "or" of all bits to the right of Q */ switch (sd) { case DBL_MANT_DIG + 1: a <<= 1; break; case DBL_MANT_DIG + 2: break; default: a = ((du_int)a >> (sd - (DBL_MANT_DIG+2))) | ((a & ((du_int)(-1) >> ((N + DBL_MANT_DIG+2) - sd))) != 0); }; /* finish: */ a |= (a & 4) != 0; /* Or P into R */ ++a; /* round - this step may add a significant bit */ a >>= 2; /* dump Q and R */ /* a is now rounded to DBL_MANT_DIG or DBL_MANT_DIG+1 bits */ if (a & ((du_int)1 << DBL_MANT_DIG)) { a >>= 1; ++e; } /* a is now rounded to DBL_MANT_DIG bits */ } else { a <<= (DBL_MANT_DIG - sd); /* a is now rounded to DBL_MANT_DIG bits */ } double_bits fb; - fb.u.high = ((su_int)s & 0x80000000) | /* sign */ - ((e + 1023) << 20) | /* exponent */ - ((su_int)(a >> 32) & 0x000FFFFF); /* mantissa-high */ - fb.u.low = (su_int)a; /* mantissa-low */ + fb.u.s.high = ((su_int)s & 0x80000000) | /* sign */ + ((e + 1023) << 20) | /* exponent */ + ((su_int)(a >> 32) & 0x000FFFFF); /* mantissa-high */ + fb.u.s.low = (su_int)a; /* mantissa-low */ return fb.f; } #endif Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/floattidf.c =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/floattidf.c (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/floattidf.c (revision 305364) @@ -1,83 +1,83 @@ /* ===-- floattidf.c - Implement __floattidf -------------------------------=== * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== * * This file implements __floattidf for the compiler_rt library. * * ===----------------------------------------------------------------------=== - */ + */ #include "int_lib.h" #ifdef CRT_HAS_128BIT /* Returns: convert a to a double, rounding toward even.*/ -/* Assumption: double is a IEEE 64 bit floating point type +/* Assumption: double is a IEEE 64 bit floating point type * ti_int is a 128 bit integral type */ -/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */ +/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */ COMPILER_RT_ABI double __floattidf(ti_int a) { if (a == 0) return 0.0; const unsigned N = sizeof(ti_int) * CHAR_BIT; const ti_int s = a >> (N-1); a = (a ^ s) - s; int sd = N - __clzti2(a); /* number of significant digits */ int e = sd - 1; /* exponent */ if (sd > DBL_MANT_DIG) { /* start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx * finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR * 12345678901234567890123456 * 1 = msb 1 bit * P = bit DBL_MANT_DIG-1 bits to the right of 1 * Q = bit DBL_MANT_DIG bits to the right of 1 * R = "or" of all bits to the right of Q */ switch (sd) { case DBL_MANT_DIG + 1: a <<= 1; break; case DBL_MANT_DIG + 2: break; default: a = ((tu_int)a >> (sd - (DBL_MANT_DIG+2))) | ((a & ((tu_int)(-1) >> ((N + DBL_MANT_DIG+2) - sd))) != 0); }; /* finish: */ a |= (a & 4) != 0; /* Or P into R */ ++a; /* round - this step may add a significant bit */ a >>= 2; /* dump Q and R */ /* a is now rounded to DBL_MANT_DIG or DBL_MANT_DIG+1 bits */ if (a & ((tu_int)1 << DBL_MANT_DIG)) { a >>= 1; ++e; } /* a is now rounded to DBL_MANT_DIG bits */ } else { a <<= (DBL_MANT_DIG - sd); /* a is now rounded to DBL_MANT_DIG bits */ } double_bits fb; fb.u.s.high = ((su_int)s & 0x80000000) | /* sign */ ((e + 1023) << 20) | /* exponent */ ((su_int)(a >> 32) & 0x000FFFFF); /* mantissa-high */ fb.u.s.low = (su_int)a; /* mantissa-low */ return fb.f; } #endif /* CRT_HAS_128BIT */ Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/floatundidf.c =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/floatundidf.c (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/floatundidf.c (revision 305364) @@ -1,106 +1,106 @@ /* ===-- floatundidf.c - Implement __floatundidf ---------------------------=== * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== * * This file implements __floatundidf for the compiler_rt library. * * ===----------------------------------------------------------------------=== */ /* Returns: convert a to a double, rounding toward even. */ -/* Assumption: double is a IEEE 64 bit floating point type +/* Assumption: double is a IEEE 64 bit floating point type * du_int is a 64 bit integral type */ /* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */ #include "int_lib.h" ARM_EABI_FNALIAS(ul2d, floatundidf) #ifndef __SOFT_FP__ /* Support for systems that have hardware floating-point; we'll set the inexact flag * as a side-effect of this computation. */ COMPILER_RT_ABI double __floatundidf(du_int a) { - static const double twop52 = 4503599627370496.0; // 0x1.0p52 - static const double twop84 = 19342813113834066795298816.0; // 0x1.0p84 - static const double twop84_plus_twop52 = 19342813118337666422669312.0; // 0x1.00000001p84 - - union { uint64_t x; double d; } high = { .d = twop84 }; - union { uint64_t x; double d; } low = { .d = twop52 }; - - high.x |= a >> 32; - low.x |= a & UINT64_C(0x00000000ffffffff); - - const double result = (high.d - twop84_plus_twop52) + low.d; - return result; + static const double twop52 = 4503599627370496.0; // 0x1.0p52 + static const double twop84 = 19342813113834066795298816.0; // 0x1.0p84 + static const double twop84_plus_twop52 = 19342813118337666422669312.0; // 0x1.00000001p84 + + union { uint64_t x; double d; } high = { .d = twop84 }; + union { uint64_t x; double d; } low = { .d = twop52 }; + + high.x |= a >> 32; + low.x |= a & UINT64_C(0x00000000ffffffff); + + const double result = (high.d - twop84_plus_twop52) + low.d; + return result; } #else /* Support for systems that don't have hardware floating-point; there are no flags to * set, and we don't want to code-gen to an unknown soft-float implementation. - */ + */ COMPILER_RT_ABI double __floatundidf(du_int a) { if (a == 0) return 0.0; const unsigned N = sizeof(du_int) * CHAR_BIT; int sd = N - __builtin_clzll(a); /* number of significant digits */ int e = sd - 1; /* exponent */ if (sd > DBL_MANT_DIG) { /* start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx * finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR * 12345678901234567890123456 * 1 = msb 1 bit * P = bit DBL_MANT_DIG-1 bits to the right of 1 * Q = bit DBL_MANT_DIG bits to the right of 1 * R = "or" of all bits to the right of Q */ switch (sd) { case DBL_MANT_DIG + 1: a <<= 1; break; case DBL_MANT_DIG + 2: break; default: a = (a >> (sd - (DBL_MANT_DIG+2))) | ((a & ((du_int)(-1) >> ((N + DBL_MANT_DIG+2) - sd))) != 0); }; /* finish: */ a |= (a & 4) != 0; /* Or P into R */ ++a; /* round - this step may add a significant bit */ a >>= 2; /* dump Q and R */ /* a is now rounded to DBL_MANT_DIG or DBL_MANT_DIG+1 bits */ if (a & ((du_int)1 << DBL_MANT_DIG)) { a >>= 1; ++e; } /* a is now rounded to DBL_MANT_DIG bits */ } else { a <<= (DBL_MANT_DIG - sd); /* a is now rounded to DBL_MANT_DIG bits */ } double_bits fb; - fb.u.high = ((e + 1023) << 20) | /* exponent */ - ((su_int)(a >> 32) & 0x000FFFFF); /* mantissa-high */ - fb.u.low = (su_int)a; /* mantissa-low */ + fb.u.s.high = ((e + 1023) << 20) | /* exponent */ + ((su_int)(a >> 32) & 0x000FFFFF); /* mantissa-high */ + fb.u.s.low = (su_int)a; /* mantissa-low */ return fb.f; } #endif Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/floatuntidf.c =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/floatuntidf.c (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/floatuntidf.c (revision 305364) @@ -1,80 +1,80 @@ /* ===-- floatuntidf.c - Implement __floatuntidf ---------------------------=== * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== * * This file implements __floatuntidf for the compiler_rt library. * * ===----------------------------------------------------------------------=== */ #include "int_lib.h" #ifdef CRT_HAS_128BIT /* Returns: convert a to a double, rounding toward even. */ -/* Assumption: double is a IEEE 64 bit floating point type +/* Assumption: double is a IEEE 64 bit floating point type * tu_int is a 128 bit integral type */ /* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */ COMPILER_RT_ABI double __floatuntidf(tu_int a) { if (a == 0) return 0.0; const unsigned N = sizeof(tu_int) * CHAR_BIT; int sd = N - __clzti2(a); /* number of significant digits */ int e = sd - 1; /* exponent */ if (sd > DBL_MANT_DIG) { /* start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx * finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR * 12345678901234567890123456 * 1 = msb 1 bit * P = bit DBL_MANT_DIG-1 bits to the right of 1 * Q = bit DBL_MANT_DIG bits to the right of 1 * R = "or" of all bits to the right of Q */ switch (sd) { case DBL_MANT_DIG + 1: a <<= 1; break; case DBL_MANT_DIG + 2: break; default: a = (a >> (sd - (DBL_MANT_DIG+2))) | ((a & ((tu_int)(-1) >> ((N + DBL_MANT_DIG+2) - sd))) != 0); }; /* finish: */ a |= (a & 4) != 0; /* Or P into R */ ++a; /* round - this step may add a significant bit */ a >>= 2; /* dump Q and R */ /* a is now rounded to DBL_MANT_DIG or DBL_MANT_DIG+1 bits */ if (a & ((tu_int)1 << DBL_MANT_DIG)) { a >>= 1; ++e; } /* a is now rounded to DBL_MANT_DIG bits */ } else { a <<= (DBL_MANT_DIG - sd); /* a is now rounded to DBL_MANT_DIG bits */ } double_bits fb; fb.u.s.high = ((e + 1023) << 20) | /* exponent */ ((su_int)(a >> 32) & 0x000FFFFF); /* mantissa-high */ fb.u.s.low = (su_int)a; /* mantissa-low */ return fb.f; } #endif /* CRT_HAS_128BIT */ Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/gcc_personality_v0.c =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/gcc_personality_v0.c (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/gcc_personality_v0.c (revision 305364) @@ -1,210 +1,241 @@ /* ===-- gcc_personality_v0.c - Implement __gcc_personality_v0 -------------=== * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== * */ #include "int_lib.h" #include /* * Pointer encodings documented at: * http://refspecs.freestandards.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html */ #define DW_EH_PE_omit 0xff /* no data follows */ #define DW_EH_PE_absptr 0x00 #define DW_EH_PE_uleb128 0x01 #define DW_EH_PE_udata2 0x02 #define DW_EH_PE_udata4 0x03 #define DW_EH_PE_udata8 0x04 #define DW_EH_PE_sleb128 0x09 #define DW_EH_PE_sdata2 0x0A #define DW_EH_PE_sdata4 0x0B #define DW_EH_PE_sdata8 0x0C #define DW_EH_PE_pcrel 0x10 #define DW_EH_PE_textrel 0x20 #define DW_EH_PE_datarel 0x30 #define DW_EH_PE_funcrel 0x40 #define DW_EH_PE_aligned 0x50 #define DW_EH_PE_indirect 0x80 /* gcc extension */ /* read a uleb128 encoded value and advance pointer */ static uintptr_t readULEB128(const uint8_t** data) { uintptr_t result = 0; uintptr_t shift = 0; unsigned char byte; const uint8_t* p = *data; do { byte = *p++; result |= (byte & 0x7f) << shift; shift += 7; } while (byte & 0x80); *data = p; return result; } /* read a pointer encoded value and advance pointer */ static uintptr_t readEncodedPointer(const uint8_t** data, uint8_t encoding) { const uint8_t* p = *data; uintptr_t result = 0; if ( encoding == DW_EH_PE_omit ) return 0; /* first get value */ switch (encoding & 0x0F) { case DW_EH_PE_absptr: result = *((const uintptr_t*)p); p += sizeof(uintptr_t); break; case DW_EH_PE_uleb128: result = readULEB128(&p); break; case DW_EH_PE_udata2: result = *((const uint16_t*)p); p += sizeof(uint16_t); break; case DW_EH_PE_udata4: result = *((const uint32_t*)p); p += sizeof(uint32_t); break; case DW_EH_PE_udata8: result = *((const uint64_t*)p); p += sizeof(uint64_t); break; case DW_EH_PE_sdata2: result = *((const int16_t*)p); p += sizeof(int16_t); break; case DW_EH_PE_sdata4: result = *((const int32_t*)p); p += sizeof(int32_t); break; case DW_EH_PE_sdata8: result = *((const int64_t*)p); p += sizeof(int64_t); break; case DW_EH_PE_sleb128: default: /* not supported */ compilerrt_abort(); break; } /* then add relative offset */ switch ( encoding & 0x70 ) { case DW_EH_PE_absptr: /* do nothing */ break; case DW_EH_PE_pcrel: result += (uintptr_t)(*data); break; case DW_EH_PE_textrel: case DW_EH_PE_datarel: case DW_EH_PE_funcrel: case DW_EH_PE_aligned: default: /* not supported */ compilerrt_abort(); break; } /* then apply indirection */ if (encoding & DW_EH_PE_indirect) { result = *((const uintptr_t*)result); } *data = p; return result; } +#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ + !defined(__ARM_DWARF_EH__) +#define USING_ARM_EHABI 1 +_Unwind_Reason_Code __gnu_unwind_frame(struct _Unwind_Exception *, + struct _Unwind_Context *); +#endif +static inline _Unwind_Reason_Code +continueUnwind(struct _Unwind_Exception *exceptionObject, + struct _Unwind_Context *context) { +#if USING_ARM_EHABI + /* + * On ARM EHABI the personality routine is responsible for actually + * unwinding a single stack frame before returning (ARM EHABI Sec. 6.1). + */ + if (__gnu_unwind_frame(exceptionObject, context) != _URC_OK) + return _URC_FAILURE; +#endif + return _URC_CONTINUE_UNWIND; +} + /* * The C compiler makes references to __gcc_personality_v0 in * the dwarf unwind information for translation units that use * __attribute__((cleanup(xx))) on local variables. * This personality routine is called by the system unwinder * on each frame as the stack is unwound during a C++ exception * throw through a C function compiled with -fexceptions. */ #if __USING_SJLJ_EXCEPTIONS__ /* the setjump-longjump based exceptions personality routine has a * different name */ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_sj0(int version, _Unwind_Action actions, uint64_t exceptionClass, struct _Unwind_Exception* exceptionObject, struct _Unwind_Context *context) +#elif USING_ARM_EHABI +/* The ARM EHABI personality routine has a different signature. */ +COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( + _Unwind_State state, struct _Unwind_Exception *exceptionObject, + struct _Unwind_Context *context) #else COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0(int version, _Unwind_Action actions, uint64_t exceptionClass, struct _Unwind_Exception* exceptionObject, struct _Unwind_Context *context) #endif { /* Since C does not have catch clauses, there is nothing to do during */ /* phase 1 (the search phase). */ - if ( actions & _UA_SEARCH_PHASE ) - return _URC_CONTINUE_UNWIND; - +#if USING_ARM_EHABI + /* After resuming from a cleanup we should also continue on to the next + * frame straight away. */ + if ((state & _US_ACTION_MASK) != _US_UNWIND_FRAME_STARTING) +#else + if ( actions & _UA_SEARCH_PHASE ) +#endif + return continueUnwind(exceptionObject, context); + /* There is nothing to do if there is no LSDA for this frame. */ const uint8_t* lsda = (uint8_t*)_Unwind_GetLanguageSpecificData(context); if ( lsda == (uint8_t*) 0 ) - return _URC_CONTINUE_UNWIND; + return continueUnwind(exceptionObject, context); uintptr_t pc = _Unwind_GetIP(context)-1; uintptr_t funcStart = _Unwind_GetRegionStart(context); uintptr_t pcOffset = pc - funcStart; /* Parse LSDA header. */ uint8_t lpStartEncoding = *lsda++; if (lpStartEncoding != DW_EH_PE_omit) { readEncodedPointer(&lsda, lpStartEncoding); } uint8_t ttypeEncoding = *lsda++; if (ttypeEncoding != DW_EH_PE_omit) { readULEB128(&lsda); } /* Walk call-site table looking for range that includes current PC. */ uint8_t callSiteEncoding = *lsda++; uint32_t callSiteTableLength = readULEB128(&lsda); const uint8_t* callSiteTableStart = lsda; const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength; const uint8_t* p=callSiteTableStart; while (p < callSiteTableEnd) { uintptr_t start = readEncodedPointer(&p, callSiteEncoding); uintptr_t length = readEncodedPointer(&p, callSiteEncoding); uintptr_t landingPad = readEncodedPointer(&p, callSiteEncoding); readULEB128(&p); /* action value not used for C code */ if ( landingPad == 0 ) continue; /* no landing pad for this entry */ if ( (start <= pcOffset) && (pcOffset < (start+length)) ) { /* Found landing pad for the PC. * Set Instruction Pointer to so we re-enter function * at landing pad. The landing pad is created by the compiler * to take two parameters in registers. */ _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), (uintptr_t)exceptionObject); _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0); _Unwind_SetIP(context, (funcStart + landingPad)); return _URC_INSTALL_CONTEXT; } } /* No landing pad found, continue unwinding. */ - return _URC_CONTINUE_UNWIND; + return continueUnwind(exceptionObject, context); } Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/ashldi3.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/ashldi3.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/ashldi3.S (revision 305364) @@ -1,58 +1,61 @@ // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. #include "../assembly.h" // di_int __ashldi3(di_int input, int count); // This routine has some extra memory traffic, loading the 64-bit input via two // 32-bit loads, then immediately storing it back to the stack via a single 64-bit // store. This is to avoid a write-small, read-large stall. // However, if callers of this routine can be safely assumed to store the argument // via a 64-bt store, this is unnecessary memory traffic, and should be avoided. // It can be turned off by defining the TRUST_CALLERS_USE_64_BIT_STORES macro. #ifdef __i386__ #ifdef __SSE2__ .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__ashldi3) movd 12(%esp), %xmm2 // Load count #ifndef TRUST_CALLERS_USE_64_BIT_STORES movd 4(%esp), %xmm0 movd 8(%esp), %xmm1 punpckldq %xmm1, %xmm0 // Load input #else movq 4(%esp), %xmm0 // Load input #endif psllq %xmm2, %xmm0 // shift input by count movd %xmm0, %eax psrlq $32, %xmm0 movd %xmm0, %edx ret END_COMPILERRT_FUNCTION(__ashldi3) #else // Use GPRs instead of SSE2 instructions, if they aren't available. .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__ashldi3) movl 12(%esp), %ecx // Load count movl 8(%esp), %edx // Load high movl 4(%esp), %eax // Load low testl $0x20, %ecx // If count >= 32 jnz 1f // goto 1 shldl %cl, %eax, %edx // left shift high by count shll %cl, %eax // left shift low by count ret 1: movl %eax, %edx // Move low to high xorl %eax, %eax // clear low shll %cl, %edx // shift high by count - 32 ret END_COMPILERRT_FUNCTION(__ashldi3) #endif // __SSE2__ #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/ashrdi3.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/ashrdi3.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/ashrdi3.S (revision 305364) @@ -1,69 +1,72 @@ // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. #include "../assembly.h" // di_int __ashrdi3(di_int input, int count); #ifdef __i386__ #ifdef __SSE2__ .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__ashrdi3) movd 12(%esp), %xmm2 // Load count movl 8(%esp), %eax #ifndef TRUST_CALLERS_USE_64_BIT_STORES movd 4(%esp), %xmm0 movd 8(%esp), %xmm1 punpckldq %xmm1, %xmm0 // Load input #else movq 4(%esp), %xmm0 // Load input #endif psrlq %xmm2, %xmm0 // unsigned shift input by count testl %eax, %eax // check the sign-bit of the input jns 1f // early out for positive inputs // If the input is negative, we need to construct the shifted sign bit // to or into the result, as xmm does not have a signed right shift. pcmpeqb %xmm1, %xmm1 // -1ULL psrlq $58, %xmm1 // 0x3f pandn %xmm1, %xmm2 // 63 - count pcmpeqb %xmm1, %xmm1 // -1ULL psubq %xmm1, %xmm2 // 64 - count psllq %xmm2, %xmm1 // -1 << (64 - count) = leading sign bits por %xmm1, %xmm0 // Move the result back to the general purpose registers and return 1: movd %xmm0, %eax psrlq $32, %xmm0 movd %xmm0, %edx ret END_COMPILERRT_FUNCTION(__ashrdi3) #else // Use GPRs instead of SSE2 instructions, if they aren't available. .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__ashrdi3) movl 12(%esp), %ecx // Load count movl 8(%esp), %edx // Load high movl 4(%esp), %eax // Load low testl $0x20, %ecx // If count >= 32 jnz 1f // goto 1 shrdl %cl, %edx, %eax // right shift low by count sarl %cl, %edx // right shift high by count ret 1: movl %edx, %eax // Move high to low sarl $31, %edx // clear high sarl %cl, %eax // shift low by count - 32 ret END_COMPILERRT_FUNCTION(__ashrdi3) #endif // __SSE2__ #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/divdi3.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/divdi3.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/divdi3.S (revision 305364) @@ -1,162 +1,165 @@ // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. #include "../assembly.h" // di_int __divdi3(di_int a, di_int b); // result = a / b. // both inputs and the output are 64-bit signed integers. // This will do whatever the underlying hardware is set to do on division by zero. // No other exceptions are generated, as the divide cannot overflow. // // This is targeted at 32-bit x86 *only*, as this can be done directly in hardware // on x86_64. The performance goal is ~40 cycles per divide, which is faster than // currently possible via simulation of integer divides on the x87 unit. // // Stephen Canon, December 2008 #ifdef __i386__ .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__divdi3) /* This is currently implemented by wrapping the unsigned divide up in an absolute value, then restoring the correct sign at the end of the computation. This could certainly be improved upon. */ pushl %esi movl 20(%esp), %edx // high word of b movl 16(%esp), %eax // low word of b movl %edx, %ecx sarl $31, %ecx // (b < 0) ? -1 : 0 xorl %ecx, %eax xorl %ecx, %edx // EDX:EAX = (b < 0) ? not(b) : b subl %ecx, %eax sbbl %ecx, %edx // EDX:EAX = abs(b) movl %edx, 20(%esp) movl %eax, 16(%esp) // store abs(b) back to stack movl %ecx, %esi // set aside sign of b movl 12(%esp), %edx // high word of b movl 8(%esp), %eax // low word of b movl %edx, %ecx sarl $31, %ecx // (a < 0) ? -1 : 0 xorl %ecx, %eax xorl %ecx, %edx // EDX:EAX = (a < 0) ? not(a) : a subl %ecx, %eax sbbl %ecx, %edx // EDX:EAX = abs(a) movl %edx, 12(%esp) movl %eax, 8(%esp) // store abs(a) back to stack xorl %ecx, %esi // sign of result = (sign of a) ^ (sign of b) pushl %ebx movl 24(%esp), %ebx // Find the index i of the leading bit in b. bsrl %ebx, %ecx // If the high word of b is zero, jump to jz 9f // the code to handle that special case [9]. /* High word of b is known to be non-zero on this branch */ movl 20(%esp), %eax // Construct bhi, containing bits [1+i:32+i] of b shrl %cl, %eax // Practically, this means that bhi is given by: shrl %eax // notl %ecx // bhi = (high word of b) << (31 - i) | shll %cl, %ebx // (low word of b) >> (1 + i) orl %eax, %ebx // movl 16(%esp), %edx // Load the high and low words of a, and jump movl 12(%esp), %eax // to [1] if the high word is larger than bhi cmpl %ebx, %edx // to avoid overflowing the upcoming divide. jae 1f /* High word of a is greater than or equal to (b >> (1 + i)) on this branch */ divl %ebx // eax <-- qs, edx <-- r such that ahi:alo = bs*qs + r pushl %edi notl %ecx shrl %eax shrl %cl, %eax // q = qs >> (1 + i) movl %eax, %edi mull 24(%esp) // q*blo movl 16(%esp), %ebx movl 20(%esp), %ecx // ECX:EBX = a subl %eax, %ebx sbbl %edx, %ecx // ECX:EBX = a - q*blo movl 28(%esp), %eax imull %edi, %eax // q*bhi subl %eax, %ecx // ECX:EBX = a - q*b sbbl $0, %edi // decrement q if remainder is negative xorl %edx, %edx movl %edi, %eax addl %esi, %eax // Restore correct sign to result adcl %esi, %edx xorl %esi, %eax xorl %esi, %edx popl %edi // Restore callee-save registers popl %ebx popl %esi retl // Return 1: /* High word of a is greater than or equal to (b >> (1 + i)) on this branch */ subl %ebx, %edx // subtract bhi from ahi so that divide will not divl %ebx // overflow, and find q and r such that // // ahi:alo = (1:q)*bhi + r // // Note that q is a number in (31-i).(1+i) // fix point. pushl %edi notl %ecx shrl %eax orl $0x80000000, %eax shrl %cl, %eax // q = (1:qs) >> (1 + i) movl %eax, %edi mull 24(%esp) // q*blo movl 16(%esp), %ebx movl 20(%esp), %ecx // ECX:EBX = a subl %eax, %ebx sbbl %edx, %ecx // ECX:EBX = a - q*blo movl 28(%esp), %eax imull %edi, %eax // q*bhi subl %eax, %ecx // ECX:EBX = a - q*b sbbl $0, %edi // decrement q if remainder is negative xorl %edx, %edx movl %edi, %eax addl %esi, %eax // Restore correct sign to result adcl %esi, %edx xorl %esi, %eax xorl %esi, %edx popl %edi // Restore callee-save registers popl %ebx popl %esi retl // Return 9: /* High word of b is zero on this branch */ movl 16(%esp), %eax // Find qhi and rhi such that movl 20(%esp), %ecx // xorl %edx, %edx // ahi = qhi*b + rhi with 0 ≤ rhi < b divl %ecx // movl %eax, %ebx // movl 12(%esp), %eax // Find qlo such that divl %ecx // movl %ebx, %edx // rhi:alo = qlo*b + rlo with 0 ≤ rlo < b addl %esi, %eax // Restore correct sign to result adcl %esi, %edx xorl %esi, %eax xorl %esi, %edx popl %ebx // Restore callee-save registers popl %esi retl // Return END_COMPILERRT_FUNCTION(__divdi3) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatdidf.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatdidf.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatdidf.S (revision 305364) @@ -1,39 +1,42 @@ // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. #include "../assembly.h" // double __floatundidf(du_int a); #ifdef __i386__ CONST_SECTION .balign 16 twop52: .quad 0x4330000000000000 .balign 16 twop32: .quad 0x41f0000000000000 #define REL_ADDR(_a) (_a)-0b(%eax) .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__floatdidf) cvtsi2sd 8(%esp), %xmm1 movss 4(%esp), %xmm0 // low 32 bits of a calll 0f 0: popl %eax mulsd REL_ADDR(twop32), %xmm1 // a_hi as a double (without rounding) movsd REL_ADDR(twop52), %xmm2 // 0x1.0p52 subsd %xmm2, %xmm1 // a_hi - 0x1p52 (no rounding occurs) orpd %xmm2, %xmm0 // 0x1p52 + a_lo (no rounding occurs) addsd %xmm1, %xmm0 // a_hi + a_lo (round happens here) movsd %xmm0, 4(%esp) fldl 4(%esp) ret END_COMPILERRT_FUNCTION(__floatdidf) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatdisf.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatdisf.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatdisf.S (revision 305364) @@ -1,32 +1,35 @@ // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. #include "../assembly.h" // float __floatdisf(di_int a); // This routine has some extra memory traffic, loading the 64-bit input via two // 32-bit loads, then immediately storing it back to the stack via a single 64-bit // store. This is to avoid a write-small, read-large stall. // However, if callers of this routine can be safely assumed to store the argument // via a 64-bt store, this is unnecessary memory traffic, and should be avoided. // It can be turned off by defining the TRUST_CALLERS_USE_64_BIT_STORES macro. #ifdef __i386__ .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__floatdisf) #ifndef TRUST_CALLERS_USE_64_BIT_STORES movd 4(%esp), %xmm0 movd 8(%esp), %xmm1 punpckldq %xmm1, %xmm0 movq %xmm0, 4(%esp) #endif fildll 4(%esp) fstps 4(%esp) flds 4(%esp) ret END_COMPILERRT_FUNCTION(__floatdisf) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatdixf.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatdixf.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatdixf.S (revision 305364) @@ -1,30 +1,33 @@ // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. #include "../assembly.h" // float __floatdixf(di_int a); #ifdef __i386__ // This routine has some extra memory traffic, loading the 64-bit input via two // 32-bit loads, then immediately storing it back to the stack via a single 64-bit // store. This is to avoid a write-small, read-large stall. // However, if callers of this routine can be safely assumed to store the argument // via a 64-bt store, this is unnecessary memory traffic, and should be avoided. // It can be turned off by defining the TRUST_CALLERS_USE_64_BIT_STORES macro. .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__floatdixf) #ifndef TRUST_CALLERS_USE_64_BIT_STORES movd 4(%esp), %xmm0 movd 8(%esp), %xmm1 punpckldq %xmm1, %xmm0 movq %xmm0, 4(%esp) #endif fildll 4(%esp) ret END_COMPILERRT_FUNCTION(__floatdixf) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatundidf.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatundidf.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatundidf.S (revision 305364) @@ -1,52 +1,55 @@ //===-- floatundidf.S - Implement __floatundidf for i386 ------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements __floatundidf for the compiler_rt library. // //===----------------------------------------------------------------------===// #include "../assembly.h" // double __floatundidf(du_int a); #ifdef __i386__ CONST_SECTION .balign 16 twop52: .quad 0x4330000000000000 .balign 16 twop84_plus_twop52: .quad 0x4530000000100000 .balign 16 twop84: .quad 0x4530000000000000 #define REL_ADDR(_a) (_a)-0b(%eax) .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__floatundidf) movss 8(%esp), %xmm1 // high 32 bits of a movss 4(%esp), %xmm0 // low 32 bits of a calll 0f 0: popl %eax orpd REL_ADDR(twop84), %xmm1 // 0x1p84 + a_hi (no rounding occurs) subsd REL_ADDR(twop84_plus_twop52), %xmm1 // a_hi - 0x1p52 (no rounding occurs) orpd REL_ADDR(twop52), %xmm0 // 0x1p52 + a_lo (no rounding occurs) addsd %xmm1, %xmm0 // a_hi + a_lo (round happens here) movsd %xmm0, 4(%esp) fldl 4(%esp) ret END_COMPILERRT_FUNCTION(__floatundidf) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatundisf.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatundisf.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatundisf.S (revision 305364) @@ -1,105 +1,108 @@ // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. #include "../assembly.h" // float __floatundisf(du_int a); // Note that there is a hardware instruction, fildll, that does most of what // this function needs to do. However, because of our ia32 ABI, it will take // a write-small read-large stall, so the software implementation here is // actually several cycles faster. // This is a branch-free implementation. A branchy implementation might be // faster for the common case if you know something a priori about the input // distribution. /* branch-free x87 implementation - one cycle slower than without x87. #ifdef __i386__ CONST_SECTION .balign 3 .quad 0x43f0000000000000 twop64: .quad 0x0000000000000000 #define TWOp64 twop64-0b(%ecx,%eax,8) .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__floatundisf) movl 8(%esp), %eax movd 8(%esp), %xmm1 movd 4(%esp), %xmm0 punpckldq %xmm1, %xmm0 calll 0f 0: popl %ecx sarl $31, %eax movq %xmm0, 4(%esp) fildll 4(%esp) faddl TWOp64 fstps 4(%esp) flds 4(%esp) ret END_COMPILERRT_FUNCTION(__floatundisf) #endif // __i386__ */ /* branch-free, x87-free implementation - faster at the expense of code size */ #ifdef __i386__ CONST_SECTION .balign 16 twop52: .quad 0x4330000000000000 .quad 0x0000000000000fff .balign 16 sticky: .quad 0x0000000000000000 .long 0x00000012 .balign 16 twelve: .long 0x00000000 #define TWOp52 twop52-0b(%ecx) #define STICKY sticky-0b(%ecx,%eax,8) .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__floatundisf) movl 8(%esp), %eax movd 8(%esp), %xmm1 movd 4(%esp), %xmm0 punpckldq %xmm1, %xmm0 calll 0f 0: popl %ecx shrl %eax // high 31 bits of input as sint32 addl $0x7ff80000, %eax sarl $31, %eax // (big input) ? -1 : 0 movsd STICKY, %xmm1 // (big input) ? 0xfff : 0 movl $12, %edx andl %eax, %edx // (big input) ? 12 : 0 movd %edx, %xmm3 andpd %xmm0, %xmm1 // (big input) ? input & 0xfff : 0 movsd TWOp52, %xmm2 // 0x1.0p52 psrlq %xmm3, %xmm0 // (big input) ? input >> 12 : input orpd %xmm2, %xmm1 // 0x1.0p52 + ((big input) ? input & 0xfff : input) orpd %xmm1, %xmm0 // 0x1.0p52 + ((big input) ? (input >> 12 | input & 0xfff) : input) subsd %xmm2, %xmm0 // (double)((big input) ? (input >> 12 | input & 0xfff) : input) cvtsd2ss %xmm0, %xmm0 // (float)((big input) ? (input >> 12 | input & 0xfff) : input) pslld $23, %xmm3 paddd %xmm3, %xmm0 // (float)input movd %xmm0, 4(%esp) flds 4(%esp) ret END_COMPILERRT_FUNCTION(__floatundisf) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatundixf.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatundixf.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/floatundixf.S (revision 305364) @@ -1,43 +1,46 @@ // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. #include "../assembly.h" // long double __floatundixf(du_int a);16 #ifdef __i386__ CONST_SECTION .balign 16 twop52: .quad 0x4330000000000000 .balign 16 twop84_plus_twop52_neg: .quad 0xc530000000100000 .balign 16 twop84: .quad 0x4530000000000000 #define REL_ADDR(_a) (_a)-0b(%eax) .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__floatundixf) calll 0f 0: popl %eax movss 8(%esp), %xmm0 // hi 32 bits of input movss 4(%esp), %xmm1 // lo 32 bits of input orpd REL_ADDR(twop84), %xmm0 // 2^84 + hi (as a double) orpd REL_ADDR(twop52), %xmm1 // 2^52 + lo (as a double) addsd REL_ADDR(twop84_plus_twop52_neg), %xmm0 // hi - 2^52 (no rounding occurs) movsd %xmm1, 4(%esp) fldl 4(%esp) movsd %xmm0, 4(%esp) faddl 4(%esp) ret END_COMPILERRT_FUNCTION(__floatundixf) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/lshrdi3.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/lshrdi3.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/lshrdi3.S (revision 305364) @@ -1,59 +1,62 @@ // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. #include "../assembly.h" // di_int __lshrdi3(di_int input, int count); // This routine has some extra memory traffic, loading the 64-bit input via two // 32-bit loads, then immediately storing it back to the stack via a single 64-bit // store. This is to avoid a write-small, read-large stall. // However, if callers of this routine can be safely assumed to store the argument // via a 64-bt store, this is unnecessary memory traffic, and should be avoided. // It can be turned off by defining the TRUST_CALLERS_USE_64_BIT_STORES macro. #ifdef __i386__ #ifdef __SSE2__ .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__lshrdi3) movd 12(%esp), %xmm2 // Load count #ifndef TRUST_CALLERS_USE_64_BIT_STORES movd 4(%esp), %xmm0 movd 8(%esp), %xmm1 punpckldq %xmm1, %xmm0 // Load input #else movq 4(%esp), %xmm0 // Load input #endif psrlq %xmm2, %xmm0 // shift input by count movd %xmm0, %eax psrlq $32, %xmm0 movd %xmm0, %edx ret END_COMPILERRT_FUNCTION(__lshrdi3) #else // Use GPRs instead of SSE2 instructions, if they aren't available. .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__lshrdi3) movl 12(%esp), %ecx // Load count movl 8(%esp), %edx // Load high movl 4(%esp), %eax // Load low testl $0x20, %ecx // If count >= 32 jnz 1f // goto 1 shrdl %cl, %edx, %eax // right shift low by count shrl %cl, %edx // right shift high by count ret 1: movl %edx, %eax // Move high to low xorl %edx, %edx // clear high shrl %cl, %eax // shift low by count - 32 ret END_COMPILERRT_FUNCTION(__lshrdi3) #endif // __SSE2__ #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/moddi3.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/moddi3.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/moddi3.S (revision 305364) @@ -1,166 +1,169 @@ // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. #include "../assembly.h" // di_int __moddi3(di_int a, di_int b); // result = remainder of a / b. // both inputs and the output are 64-bit signed integers. // This will do whatever the underlying hardware is set to do on division by zero. // No other exceptions are generated, as the divide cannot overflow. // // This is targeted at 32-bit x86 *only*, as this can be done directly in hardware // on x86_64. The performance goal is ~40 cycles per divide, which is faster than // currently possible via simulation of integer divides on the x87 unit. // // Stephen Canon, December 2008 #ifdef __i386__ .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__moddi3) /* This is currently implemented by wrapping the unsigned modulus up in an absolute value. This could certainly be improved upon. */ pushl %esi movl 20(%esp), %edx // high word of b movl 16(%esp), %eax // low word of b movl %edx, %ecx sarl $31, %ecx // (b < 0) ? -1 : 0 xorl %ecx, %eax xorl %ecx, %edx // EDX:EAX = (b < 0) ? not(b) : b subl %ecx, %eax sbbl %ecx, %edx // EDX:EAX = abs(b) movl %edx, 20(%esp) movl %eax, 16(%esp) // store abs(b) back to stack movl 12(%esp), %edx // high word of b movl 8(%esp), %eax // low word of b movl %edx, %ecx sarl $31, %ecx // (a < 0) ? -1 : 0 xorl %ecx, %eax xorl %ecx, %edx // EDX:EAX = (a < 0) ? not(a) : a subl %ecx, %eax sbbl %ecx, %edx // EDX:EAX = abs(a) movl %edx, 12(%esp) movl %eax, 8(%esp) // store abs(a) back to stack movl %ecx, %esi // set aside sign of a pushl %ebx movl 24(%esp), %ebx // Find the index i of the leading bit in b. bsrl %ebx, %ecx // If the high word of b is zero, jump to jz 9f // the code to handle that special case [9]. /* High word of b is known to be non-zero on this branch */ movl 20(%esp), %eax // Construct bhi, containing bits [1+i:32+i] of b shrl %cl, %eax // Practically, this means that bhi is given by: shrl %eax // notl %ecx // bhi = (high word of b) << (31 - i) | shll %cl, %ebx // (low word of b) >> (1 + i) orl %eax, %ebx // movl 16(%esp), %edx // Load the high and low words of a, and jump movl 12(%esp), %eax // to [2] if the high word is larger than bhi cmpl %ebx, %edx // to avoid overflowing the upcoming divide. jae 2f /* High word of a is greater than or equal to (b >> (1 + i)) on this branch */ divl %ebx // eax <-- qs, edx <-- r such that ahi:alo = bs*qs + r pushl %edi notl %ecx shrl %eax shrl %cl, %eax // q = qs >> (1 + i) movl %eax, %edi mull 24(%esp) // q*blo movl 16(%esp), %ebx movl 20(%esp), %ecx // ECX:EBX = a subl %eax, %ebx sbbl %edx, %ecx // ECX:EBX = a - q*blo movl 28(%esp), %eax imull %edi, %eax // q*bhi subl %eax, %ecx // ECX:EBX = a - q*b jnc 1f // if positive, this is the result. addl 24(%esp), %ebx // otherwise adcl 28(%esp), %ecx // ECX:EBX = a - (q-1)*b = result 1: movl %ebx, %eax movl %ecx, %edx addl %esi, %eax // Restore correct sign to result adcl %esi, %edx xorl %esi, %eax xorl %esi, %edx popl %edi // Restore callee-save registers popl %ebx popl %esi retl // Return 2: /* High word of a is greater than or equal to (b >> (1 + i)) on this branch */ subl %ebx, %edx // subtract bhi from ahi so that divide will not divl %ebx // overflow, and find q and r such that // // ahi:alo = (1:q)*bhi + r // // Note that q is a number in (31-i).(1+i) // fix point. pushl %edi notl %ecx shrl %eax orl $0x80000000, %eax shrl %cl, %eax // q = (1:qs) >> (1 + i) movl %eax, %edi mull 24(%esp) // q*blo movl 16(%esp), %ebx movl 20(%esp), %ecx // ECX:EBX = a subl %eax, %ebx sbbl %edx, %ecx // ECX:EBX = a - q*blo movl 28(%esp), %eax imull %edi, %eax // q*bhi subl %eax, %ecx // ECX:EBX = a - q*b jnc 3f // if positive, this is the result. addl 24(%esp), %ebx // otherwise adcl 28(%esp), %ecx // ECX:EBX = a - (q-1)*b = result 3: movl %ebx, %eax movl %ecx, %edx addl %esi, %eax // Restore correct sign to result adcl %esi, %edx xorl %esi, %eax xorl %esi, %edx popl %edi // Restore callee-save registers popl %ebx popl %esi retl // Return 9: /* High word of b is zero on this branch */ movl 16(%esp), %eax // Find qhi and rhi such that movl 20(%esp), %ecx // xorl %edx, %edx // ahi = qhi*b + rhi with 0 ≤ rhi < b divl %ecx // movl %eax, %ebx // movl 12(%esp), %eax // Find rlo such that divl %ecx // movl %edx, %eax // rhi:alo = qlo*b + rlo with 0 ≤ rlo < b popl %ebx // xorl %edx, %edx // and return 0:rlo addl %esi, %eax // Restore correct sign to result adcl %esi, %edx xorl %esi, %eax xorl %esi, %edx popl %esi retl // Return END_COMPILERRT_FUNCTION(__moddi3) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/muldi3.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/muldi3.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/muldi3.S (revision 305364) @@ -1,30 +1,33 @@ // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. #include "../assembly.h" // di_int __muldi3(di_int a, di_int b); #ifdef __i386__ .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__muldi3) pushl %ebx movl 16(%esp), %eax // b.lo movl 12(%esp), %ecx // a.hi imull %eax, %ecx // b.lo * a.hi movl 8(%esp), %edx // a.lo movl 20(%esp), %ebx // b.hi imull %edx, %ebx // a.lo * b.hi mull %edx // EDX:EAX = a.lo * b.lo addl %ecx, %ebx // EBX = (a.lo*b.hi + a.hi*b.lo) addl %ebx, %edx popl %ebx retl END_COMPILERRT_FUNCTION(__muldi3) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/udivdi3.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/udivdi3.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/udivdi3.S (revision 305364) @@ -1,115 +1,118 @@ // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. #include "../assembly.h" // du_int __udivdi3(du_int a, du_int b); // result = a / b. // both inputs and the output are 64-bit unsigned integers. // This will do whatever the underlying hardware is set to do on division by zero. // No other exceptions are generated, as the divide cannot overflow. // // This is targeted at 32-bit x86 *only*, as this can be done directly in hardware // on x86_64. The performance goal is ~40 cycles per divide, which is faster than // currently possible via simulation of integer divides on the x87 unit. // // Stephen Canon, December 2008 #ifdef __i386__ .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__udivdi3) pushl %ebx movl 20(%esp), %ebx // Find the index i of the leading bit in b. bsrl %ebx, %ecx // If the high word of b is zero, jump to jz 9f // the code to handle that special case [9]. /* High word of b is known to be non-zero on this branch */ movl 16(%esp), %eax // Construct bhi, containing bits [1+i:32+i] of b shrl %cl, %eax // Practically, this means that bhi is given by: shrl %eax // notl %ecx // bhi = (high word of b) << (31 - i) | shll %cl, %ebx // (low word of b) >> (1 + i) orl %eax, %ebx // movl 12(%esp), %edx // Load the high and low words of a, and jump movl 8(%esp), %eax // to [1] if the high word is larger than bhi cmpl %ebx, %edx // to avoid overflowing the upcoming divide. jae 1f /* High word of a is greater than or equal to (b >> (1 + i)) on this branch */ divl %ebx // eax <-- qs, edx <-- r such that ahi:alo = bs*qs + r pushl %edi notl %ecx shrl %eax shrl %cl, %eax // q = qs >> (1 + i) movl %eax, %edi mull 20(%esp) // q*blo movl 12(%esp), %ebx movl 16(%esp), %ecx // ECX:EBX = a subl %eax, %ebx sbbl %edx, %ecx // ECX:EBX = a - q*blo movl 24(%esp), %eax imull %edi, %eax // q*bhi subl %eax, %ecx // ECX:EBX = a - q*b sbbl $0, %edi // decrement q if remainder is negative xorl %edx, %edx movl %edi, %eax popl %edi popl %ebx retl 1: /* High word of a is greater than or equal to (b >> (1 + i)) on this branch */ subl %ebx, %edx // subtract bhi from ahi so that divide will not divl %ebx // overflow, and find q and r such that // // ahi:alo = (1:q)*bhi + r // // Note that q is a number in (31-i).(1+i) // fix point. pushl %edi notl %ecx shrl %eax orl $0x80000000, %eax shrl %cl, %eax // q = (1:qs) >> (1 + i) movl %eax, %edi mull 20(%esp) // q*blo movl 12(%esp), %ebx movl 16(%esp), %ecx // ECX:EBX = a subl %eax, %ebx sbbl %edx, %ecx // ECX:EBX = a - q*blo movl 24(%esp), %eax imull %edi, %eax // q*bhi subl %eax, %ecx // ECX:EBX = a - q*b sbbl $0, %edi // decrement q if remainder is negative xorl %edx, %edx movl %edi, %eax popl %edi popl %ebx retl 9: /* High word of b is zero on this branch */ movl 12(%esp), %eax // Find qhi and rhi such that movl 16(%esp), %ecx // xorl %edx, %edx // ahi = qhi*b + rhi with 0 ≤ rhi < b divl %ecx // movl %eax, %ebx // movl 8(%esp), %eax // Find qlo such that divl %ecx // movl %ebx, %edx // rhi:alo = qlo*b + rlo with 0 ≤ rlo < b popl %ebx // retl // and return qhi:qlo END_COMPILERRT_FUNCTION(__udivdi3) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/umoddi3.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/umoddi3.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/i386/umoddi3.S (revision 305364) @@ -1,126 +1,129 @@ // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. #include "../assembly.h" // du_int __umoddi3(du_int a, du_int b); // result = remainder of a / b. // both inputs and the output are 64-bit unsigned integers. // This will do whatever the underlying hardware is set to do on division by zero. // No other exceptions are generated, as the divide cannot overflow. // // This is targeted at 32-bit x86 *only*, as this can be done directly in hardware // on x86_64. The performance goal is ~40 cycles per divide, which is faster than // currently possible via simulation of integer divides on the x87 unit. // // Stephen Canon, December 2008 #ifdef __i386__ .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__umoddi3) pushl %ebx movl 20(%esp), %ebx // Find the index i of the leading bit in b. bsrl %ebx, %ecx // If the high word of b is zero, jump to jz 9f // the code to handle that special case [9]. /* High word of b is known to be non-zero on this branch */ movl 16(%esp), %eax // Construct bhi, containing bits [1+i:32+i] of b shrl %cl, %eax // Practically, this means that bhi is given by: shrl %eax // notl %ecx // bhi = (high word of b) << (31 - i) | shll %cl, %ebx // (low word of b) >> (1 + i) orl %eax, %ebx // movl 12(%esp), %edx // Load the high and low words of a, and jump movl 8(%esp), %eax // to [2] if the high word is larger than bhi cmpl %ebx, %edx // to avoid overflowing the upcoming divide. jae 2f /* High word of a is greater than or equal to (b >> (1 + i)) on this branch */ divl %ebx // eax <-- qs, edx <-- r such that ahi:alo = bs*qs + r pushl %edi notl %ecx shrl %eax shrl %cl, %eax // q = qs >> (1 + i) movl %eax, %edi mull 20(%esp) // q*blo movl 12(%esp), %ebx movl 16(%esp), %ecx // ECX:EBX = a subl %eax, %ebx sbbl %edx, %ecx // ECX:EBX = a - q*blo movl 24(%esp), %eax imull %edi, %eax // q*bhi subl %eax, %ecx // ECX:EBX = a - q*b jnc 1f // if positive, this is the result. addl 20(%esp), %ebx // otherwise adcl 24(%esp), %ecx // ECX:EBX = a - (q-1)*b = result 1: movl %ebx, %eax movl %ecx, %edx popl %edi popl %ebx retl 2: /* High word of a is greater than or equal to (b >> (1 + i)) on this branch */ subl %ebx, %edx // subtract bhi from ahi so that divide will not divl %ebx // overflow, and find q and r such that // // ahi:alo = (1:q)*bhi + r // // Note that q is a number in (31-i).(1+i) // fix point. pushl %edi notl %ecx shrl %eax orl $0x80000000, %eax shrl %cl, %eax // q = (1:qs) >> (1 + i) movl %eax, %edi mull 20(%esp) // q*blo movl 12(%esp), %ebx movl 16(%esp), %ecx // ECX:EBX = a subl %eax, %ebx sbbl %edx, %ecx // ECX:EBX = a - q*blo movl 24(%esp), %eax imull %edi, %eax // q*bhi subl %eax, %ecx // ECX:EBX = a - q*b jnc 3f // if positive, this is the result. addl 20(%esp), %ebx // otherwise adcl 24(%esp), %ecx // ECX:EBX = a - (q-1)*b = result 3: movl %ebx, %eax movl %ecx, %edx popl %edi popl %ebx retl 9: /* High word of b is zero on this branch */ movl 12(%esp), %eax // Find qhi and rhi such that movl 16(%esp), %ecx // xorl %edx, %edx // ahi = qhi*b + rhi with 0 ≤ rhi < b divl %ecx // movl %eax, %ebx // movl 8(%esp), %eax // Find rlo such that divl %ecx // movl %edx, %eax // rhi:alo = qlo*b + rlo with 0 ≤ rlo < b popl %ebx // xorl %edx, %edx // and return 0:rlo retl // END_COMPILERRT_FUNCTION(__umoddi3) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/int_lib.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/int_lib.h (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/int_lib.h (revision 305364) @@ -1,163 +1,159 @@ /* ===-- int_lib.h - configuration header for compiler-rt -----------------=== * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== * * This file is a configuration header for compiler-rt. * This file is not part of the interface of this library. * * ===----------------------------------------------------------------------=== */ #ifndef INT_LIB_H #define INT_LIB_H /* Assumption: Signed integral is 2's complement. */ /* Assumption: Right shift of signed negative is arithmetic shift. */ /* Assumption: Endianness is little or big (not mixed). */ #if defined(__ELF__) #define FNALIAS(alias_name, original_name) \ void alias_name() __attribute__((alias(#original_name))) #else #define FNALIAS(alias, name) _Pragma("GCC error(\"alias unsupported on this file format\")") #endif /* ABI macro definitions */ #if __ARM_EABI__ # define ARM_EABI_FNALIAS(aeabi_name, name) \ void __aeabi_##aeabi_name() __attribute__((alias("__" #name))); # if !defined(__clang__) && defined(__GNUC__) && \ (__GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ < 5) /* The pcs attribute was introduced in GCC 4.5.0 */ # define COMPILER_RT_ABI # else # define COMPILER_RT_ABI __attribute__((pcs("aapcs"))) # endif #else # define ARM_EABI_FNALIAS(aeabi_name, name) -# if defined(__arm__) && defined(_WIN32) && (!defined(_MSC_VER) || defined(__clang__)) -# define COMPILER_RT_ABI __attribute__((pcs("aapcs"))) -# else -# define COMPILER_RT_ABI -# endif +# define COMPILER_RT_ABI #endif #ifdef _MSC_VER #define ALWAYS_INLINE __forceinline #define NOINLINE __declspec(noinline) #define NORETURN __declspec(noreturn) #define UNUSED #else #define ALWAYS_INLINE __attribute__((always_inline)) #define NOINLINE __attribute__((noinline)) #define NORETURN __attribute__((noreturn)) #define UNUSED __attribute__((unused)) #endif #if defined(__NetBSD__) && (defined(_KERNEL) || defined(_STANDALONE)) /* * Kernel and boot environment can't use normal headers, * so use the equivalent system headers. */ # include # include # include #else /* Include the standard compiler builtin headers we use functionality from. */ # include # include # include # include #endif /* Include the commonly used internal type definitions. */ #include "int_types.h" /* Include internal utility function declarations. */ #include "int_util.h" /* * Workaround for LLVM bug 11663. Prevent endless recursion in * __c?zdi2(), where calls to __builtin_c?z() are expanded to * __c?zdi2() instead of __c?zsi2(). * * Instead of placing this workaround in c?zdi2.c, put it in this * global header to prevent other C files from making the detour * through __c?zdi2() as well. * * This problem has been observed on FreeBSD for sparc64 and * mips64 with GCC 4.2.1, and for riscv with GCC 5.2.0. * Presumably it's any version of GCC, and targeting an arch that * does not have dedicated bit counting instructions. */ #if defined(__FreeBSD__) && (defined(__sparc64__) || \ defined(__mips_n64) || defined(__mips_o64) || defined(__riscv__)) si_int __clzsi2(si_int); si_int __ctzsi2(si_int); #define __builtin_clz __clzsi2 #define __builtin_ctz __ctzsi2 #endif /* FreeBSD && (sparc64 || mips_n64 || mips_o64) */ COMPILER_RT_ABI si_int __paritysi2(si_int a); COMPILER_RT_ABI si_int __paritydi2(di_int a); COMPILER_RT_ABI di_int __divdi3(di_int a, di_int b); COMPILER_RT_ABI si_int __divsi3(si_int a, si_int b); COMPILER_RT_ABI su_int __udivsi3(su_int n, su_int d); COMPILER_RT_ABI su_int __udivmodsi4(su_int a, su_int b, su_int* rem); COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int* rem); #ifdef CRT_HAS_128BIT COMPILER_RT_ABI si_int __clzti2(ti_int a); COMPILER_RT_ABI tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem); #endif /* Definitions for builtins unavailable on MSVC */ #if defined(_MSC_VER) && !defined(__clang__) #include uint32_t __inline __builtin_ctz(uint32_t value) { uint32_t trailing_zero = 0; if (_BitScanForward(&trailing_zero, value)) return trailing_zero; return 32; } uint32_t __inline __builtin_clz(uint32_t value) { uint32_t leading_zero = 0; if (_BitScanReverse(&leading_zero, value)) return 31 - leading_zero; return 32; } #if defined(_M_ARM) || defined(_M_X64) uint32_t __inline __builtin_clzll(uint64_t value) { uint32_t leading_zero = 0; if (_BitScanReverse64(&leading_zero, value)) return 63 - leading_zero; return 64; } #else uint32_t __inline __builtin_clzll(uint64_t value) { if (value == 0) return 64; uint32_t msh = (uint32_t)(value >> 32); uint32_t lsh = (uint32_t)(value & 0xFFFFFFFF); if (msh != 0) return __builtin_clz(msh); return 32 + __builtin_clz(lsh); } #endif #define __builtin_clzl __builtin_clzll #endif /* defined(_MSC_VER) && !defined(__clang__) */ #endif /* INT_LIB_H */ Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/ppc/restFP.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/ppc/restFP.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/ppc/restFP.S (revision 305364) @@ -1,43 +1,46 @@ //===-- restFP.S - Implement restFP ---------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // Helper function used by compiler to restore ppc floating point registers at // the end of the function epilog. This function returns to the address // in the LR slot. So a function epilog must branch (b) not branch and link // (bl) to this function. // If the compiler wants to restore f27..f31, it does a "b restFP+52" // // This function should never be exported by a shared library. Each linkage // unit carries its own copy of this function. // DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(restFP) lfd f14,-144(r1) lfd f15,-136(r1) lfd f16,-128(r1) lfd f17,-120(r1) lfd f18,-112(r1) lfd f19,-104(r1) lfd f20,-96(r1) lfd f21,-88(r1) lfd f22,-80(r1) lfd f23,-72(r1) lfd f24,-64(r1) lfd f25,-56(r1) lfd f26,-48(r1) lfd f27,-40(r1) lfd f28,-32(r1) lfd f29,-24(r1) lfd f30,-16(r1) lfd f31,-8(r1) lwz r0,8(r1) mtlr r0 blr + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/ppc/saveFP.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/ppc/saveFP.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/ppc/saveFP.S (revision 305364) @@ -1,40 +1,43 @@ //===-- saveFP.S - Implement saveFP ---------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // // Helper function used by compiler to save ppc floating point registers in // function prologs. This routines also saves r0 in the LR slot. // If the compiler wants to save f27..f31, it does a "bl saveFP+52" // // This function should never be exported by a shared library. Each linkage // unit carries its own copy of this function. // DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(saveFP) stfd f14,-144(r1) stfd f15,-136(r1) stfd f16,-128(r1) stfd f17,-120(r1) stfd f18,-112(r1) stfd f19,-104(r1) stfd f20,-96(r1) stfd f21,-88(r1) stfd f22,-80(r1) stfd f23,-72(r1) stfd f24,-64(r1) stfd f25,-56(r1) stfd f26,-48(r1) stfd f27,-40(r1) stfd f28,-32(r1) stfd f29,-24(r1) stfd f30,-16(r1) stfd f31,-8(r1) stw r0,8(r1) blr + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/x86_64/floatundidf.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/x86_64/floatundidf.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/x86_64/floatundidf.S (revision 305364) @@ -1,49 +1,52 @@ //===-- floatundidf.S - Implement __floatundidf for x86_64 ----------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements __floatundidf for the compiler_rt library. // //===----------------------------------------------------------------------===// #include "../assembly.h" // double __floatundidf(du_int a); #ifdef __x86_64__ CONST_SECTION .balign 16 twop52: .quad 0x4330000000000000 .balign 16 twop84_plus_twop52: .quad 0x4530000000100000 .balign 16 twop84: .quad 0x4530000000000000 #define REL_ADDR(_a) (_a)(%rip) .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__floatundidf) movd %edi, %xmm0 // low 32 bits of a shrq $32, %rdi // high 32 bits of a orq REL_ADDR(twop84), %rdi // 0x1p84 + a_hi (no rounding occurs) orpd REL_ADDR(twop52), %xmm0 // 0x1p52 + a_lo (no rounding occurs) movd %rdi, %xmm1 subsd REL_ADDR(twop84_plus_twop52), %xmm1 // a_hi - 0x1p52 (no rounding occurs) addsd %xmm1, %xmm0 // a_hi + a_lo (round happens here) ret END_COMPILERRT_FUNCTION(__floatundidf) #endif // __x86_64__ + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/x86_64/floatundisf.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/x86_64/floatundisf.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/x86_64/floatundisf.S (revision 305364) @@ -1,35 +1,38 @@ // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. #include "../assembly.h" // float __floatundisf(du_int a); #ifdef __x86_64__ CONST_SECTION .balign 16 two: .single 2.0 #define REL_ADDR(_a) (_a)(%rip) .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__floatundisf) movq $1, %rsi testq %rdi, %rdi js 1f cvtsi2ssq %rdi, %xmm0 ret 1: andq %rdi, %rsi shrq %rdi orq %rsi, %rdi cvtsi2ssq %rdi, %xmm0 mulss REL_ADDR(two), %xmm0 ret END_COMPILERRT_FUNCTION(__floatundisf) #endif // __x86_64__ + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/builtins/x86_64/floatundixf.S =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/builtins/x86_64/floatundixf.S (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/builtins/x86_64/floatundixf.S (revision 305364) @@ -1,68 +1,71 @@ // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. #include "../assembly.h" // long double __floatundixf(du_int a); #ifdef __x86_64__ CONST_SECTION .balign 16 twop64: .quad 0x43f0000000000000 #define REL_ADDR(_a) (_a)(%rip) .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__floatundixf) movq %rdi, -8(%rsp) fildq -8(%rsp) test %rdi, %rdi js 1f ret 1: faddl REL_ADDR(twop64) ret END_COMPILERRT_FUNCTION(__floatundixf) #endif // __x86_64__ /* Branch-free implementation is ever so slightly slower, but more beautiful. It is likely superior for inlining, so I kept it around for future reference. #ifdef __x86_64__ CONST_SECTION .balign 4 twop52: .quad 0x4330000000000000 twop84_plus_twop52_neg: .quad 0xc530000000100000 twop84: .quad 0x4530000000000000 #define REL_ADDR(_a) (_a)(%rip) .text .balign 4 DEFINE_COMPILERRT_FUNCTION(__floatundixf) movl %edi, %esi // low 32 bits of input shrq $32, %rdi // hi 32 bits of input orq REL_ADDR(twop84), %rdi // 2^84 + hi (as a double) orq REL_ADDR(twop52), %rsi // 2^52 + lo (as a double) movq %rdi, -8(%rsp) movq %rsi, -16(%rsp) fldl REL_ADDR(twop84_plus_twop52_neg) faddl -8(%rsp) // hi - 2^52 (as double extended, no rounding occurs) faddl -16(%rsp) // hi + lo (as double extended) ret END_COMPILERRT_FUNCTION(__floatundixf) #endif // __x86_64__ */ + +NO_EXEC_STACK_DIRECTIVE + Index: projects/clang390-import/contrib/compiler-rt/lib/cfi/cfi.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/cfi/cfi.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/cfi/cfi.cc (revision 305364) @@ -1,271 +1,420 @@ //===-------- cfi.cc ------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the runtime support for the cross-DSO CFI. // //===----------------------------------------------------------------------===// -// FIXME: Intercept dlopen/dlclose. -// FIXME: Support diagnostic mode. -// FIXME: Harden: -// * mprotect shadow, use mremap for updates -// * something else equally important - #include #include #include #include +#include typedef ElfW(Phdr) Elf_Phdr; typedef ElfW(Ehdr) Elf_Ehdr; #include "interception/interception.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_flag_parser.h" #include "ubsan/ubsan_init.h" #include "ubsan/ubsan_flags.h" -static uptr __cfi_shadow; +#ifdef CFI_ENABLE_DIAG +#include "ubsan/ubsan_handlers.h" +#endif + +namespace __cfi { + +#define kCfiShadowLimitsStorageSize 4096 // 1 page +// Lets hope that the data segment is mapped with 4K pages. +// The pointer to the cfi shadow region is stored at the start of this page. +// The rest of the page is unused and re-mapped read-only. +static union { + char space[kCfiShadowLimitsStorageSize]; + struct { + uptr start; + uptr size; + } limits; +} cfi_shadow_limits_storage + __attribute__((aligned(kCfiShadowLimitsStorageSize))); static constexpr uptr kShadowGranularity = 12; static constexpr uptr kShadowAlign = 1UL << kShadowGranularity; // 4096 static constexpr uint16_t kInvalidShadow = 0; static constexpr uint16_t kUncheckedShadow = 0xFFFFU; -static uint16_t *mem_to_shadow(uptr x) { - return (uint16_t *)(__cfi_shadow + ((x >> kShadowGranularity) << 1)); +// Get the start address of the CFI shadow region. +uptr GetShadow() { + return cfi_shadow_limits_storage.limits.start; } -typedef int (*CFICheckFn)(u64, void *); +uptr GetShadowSize() { + return cfi_shadow_limits_storage.limits.size; +} +// This will only work while the shadow is not allocated. +void SetShadowSize(uptr size) { + cfi_shadow_limits_storage.limits.size = size; +} + +uptr MemToShadowOffset(uptr x) { + return (x >> kShadowGranularity) << 1; +} + +uint16_t *MemToShadow(uptr x, uptr shadow_base) { + return (uint16_t *)(shadow_base + MemToShadowOffset(x)); +} + +typedef int (*CFICheckFn)(u64, void *, void *); + +// This class reads and decodes the shadow contents. class ShadowValue { uptr addr; uint16_t v; explicit ShadowValue(uptr addr, uint16_t v) : addr(addr), v(v) {} public: bool is_invalid() const { return v == kInvalidShadow; } bool is_unchecked() const { return v == kUncheckedShadow; } CFICheckFn get_cfi_check() const { assert(!is_invalid() && !is_unchecked()); uptr aligned_addr = addr & ~(kShadowAlign - 1); uptr p = aligned_addr - (((uptr)v - 1) << kShadowGranularity); return reinterpret_cast(p); } - // Load a shadow valud for the given application memory address. + // Load a shadow value for the given application memory address. static const ShadowValue load(uptr addr) { - return ShadowValue(addr, *mem_to_shadow(addr)); + uptr shadow_base = GetShadow(); + uptr shadow_offset = MemToShadowOffset(addr); + if (shadow_offset > GetShadowSize()) + return ShadowValue(addr, kInvalidShadow); + else + return ShadowValue( + addr, *reinterpret_cast(shadow_base + shadow_offset)); } }; -static void fill_shadow_constant(uptr begin, uptr end, uint16_t v) { - assert(v == kInvalidShadow || v == kUncheckedShadow); - uint16_t *shadow_begin = mem_to_shadow(begin); - uint16_t *shadow_end = mem_to_shadow(end - 1) + 1; - memset(shadow_begin, v, (shadow_end - shadow_begin) * sizeof(*shadow_begin)); +class ShadowBuilder { + uptr shadow_; + +public: + // Allocate a new empty shadow (for the entire address space) on the side. + void Start(); + // Mark the given address range as unchecked. + // This is used for uninstrumented libraries like libc. + // Any CFI check with a target in that range will pass. + void AddUnchecked(uptr begin, uptr end); + // Mark the given address range as belonging to a library with the given + // cfi_check function. + void Add(uptr begin, uptr end, uptr cfi_check); + // Finish shadow construction. Atomically switch the current active shadow + // region with the newly constructed one and deallocate the former. + void Install(); +}; + +void ShadowBuilder::Start() { + shadow_ = (uptr)MmapNoReserveOrDie(GetShadowSize(), "CFI shadow"); + VReport(1, "CFI: shadow at %zx .. %zx\n", shadow_, shadow_ + GetShadowSize()); } -static void fill_shadow(uptr begin, uptr end, uptr cfi_check) { +void ShadowBuilder::AddUnchecked(uptr begin, uptr end) { + uint16_t *shadow_begin = MemToShadow(begin, shadow_); + uint16_t *shadow_end = MemToShadow(end - 1, shadow_) + 1; + memset(shadow_begin, kUncheckedShadow, + (shadow_end - shadow_begin) * sizeof(*shadow_begin)); +} + +void ShadowBuilder::Add(uptr begin, uptr end, uptr cfi_check) { assert((cfi_check & (kShadowAlign - 1)) == 0); // Don't fill anything below cfi_check. We can not represent those addresses // in the shadow, and must make sure at codegen to place all valid call // targets above cfi_check. - uptr p = Max(begin, cfi_check); - uint16_t *s = mem_to_shadow(p); - uint16_t *s_end = mem_to_shadow(end - 1) + 1; - uint16_t sv = ((p - cfi_check) >> kShadowGranularity) + 1; + begin = Max(begin, cfi_check); + uint16_t *s = MemToShadow(begin, shadow_); + uint16_t *s_end = MemToShadow(end - 1, shadow_) + 1; + uint16_t sv = ((begin - cfi_check) >> kShadowGranularity) + 1; for (; s < s_end; s++, sv++) *s = sv; +} - // Sanity checks. - uptr q = p & ~(kShadowAlign - 1); - for (; q < end; q += kShadowAlign) { - assert((uptr)ShadowValue::load(q).get_cfi_check() == cfi_check); - assert((uptr)ShadowValue::load(q + kShadowAlign / 2).get_cfi_check() == - cfi_check); - assert((uptr)ShadowValue::load(q + kShadowAlign - 1).get_cfi_check() == - cfi_check); +#if SANITIZER_LINUX +void ShadowBuilder::Install() { + MprotectReadOnly(shadow_, GetShadowSize()); + uptr main_shadow = GetShadow(); + if (main_shadow) { + // Update. + void *res = mremap((void *)shadow_, GetShadowSize(), GetShadowSize(), + MREMAP_MAYMOVE | MREMAP_FIXED, (void *)main_shadow); + CHECK(res != MAP_FAILED); + } else { + // Initial setup. + CHECK_EQ(kCfiShadowLimitsStorageSize, GetPageSizeCached()); + CHECK_EQ(0, GetShadow()); + cfi_shadow_limits_storage.limits.start = shadow_; + MprotectReadOnly((uptr)&cfi_shadow_limits_storage, + sizeof(cfi_shadow_limits_storage)); + CHECK_EQ(shadow_, GetShadow()); } } +#else +#error not implemented +#endif // This is a workaround for a glibc bug: // https://sourceware.org/bugzilla/show_bug.cgi?id=15199 // Other platforms can, hopefully, just do // dlopen(RTLD_NOLOAD | RTLD_LAZY) // dlsym("__cfi_check"). -static uptr find_cfi_check_in_dso(dl_phdr_info *info) { +uptr find_cfi_check_in_dso(dl_phdr_info *info) { const ElfW(Dyn) *dynamic = nullptr; for (int i = 0; i < info->dlpi_phnum; ++i) { if (info->dlpi_phdr[i].p_type == PT_DYNAMIC) { dynamic = (const ElfW(Dyn) *)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr); break; } } if (!dynamic) return 0; uptr strtab = 0, symtab = 0; for (const ElfW(Dyn) *p = dynamic; p->d_tag != PT_NULL; ++p) { if (p->d_tag == DT_SYMTAB) symtab = p->d_un.d_ptr; else if (p->d_tag == DT_STRTAB) strtab = p->d_un.d_ptr; } if (symtab > strtab) { VReport(1, "Can not handle: symtab > strtab (%p > %zx)\n", symtab, strtab); return 0; } // Verify that strtab and symtab are inside of the same LOAD segment. // This excludes VDSO, which has (very high) bogus strtab and symtab pointers. int phdr_idx; for (phdr_idx = 0; phdr_idx < info->dlpi_phnum; phdr_idx++) { const Elf_Phdr *phdr = &info->dlpi_phdr[phdr_idx]; if (phdr->p_type == PT_LOAD) { uptr beg = info->dlpi_addr + phdr->p_vaddr; uptr end = beg + phdr->p_memsz; if (strtab >= beg && strtab < end && symtab >= beg && symtab < end) break; } } if (phdr_idx == info->dlpi_phnum) { // Nope, either different segments or just bogus pointers. // Can not handle this. VReport(1, "Can not handle: symtab %p, strtab %zx\n", symtab, strtab); return 0; } for (const ElfW(Sym) *p = (const ElfW(Sym) *)symtab; (ElfW(Addr))p < strtab; ++p) { char *name = (char*)(strtab + p->st_name); if (strcmp(name, "__cfi_check") == 0) { assert(p->st_info == ELF32_ST_INFO(STB_GLOBAL, STT_FUNC)); uptr addr = info->dlpi_addr + p->st_value; return addr; } } return 0; } -static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *data) { +int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *data) { uptr cfi_check = find_cfi_check_in_dso(info); if (cfi_check) VReport(1, "Module '%s' __cfi_check %zx\n", info->dlpi_name, cfi_check); + ShadowBuilder *b = reinterpret_cast(data); + for (int i = 0; i < info->dlpi_phnum; i++) { const Elf_Phdr *phdr = &info->dlpi_phdr[i]; if (phdr->p_type == PT_LOAD) { // Jump tables are in the executable segment. // VTables are in the non-executable one. // Need to fill shadow for both. // FIXME: reject writable if vtables are in the r/o segment. Depend on // PT_RELRO? uptr cur_beg = info->dlpi_addr + phdr->p_vaddr; uptr cur_end = cur_beg + phdr->p_memsz; if (cfi_check) { VReport(1, " %zx .. %zx\n", cur_beg, cur_end); - fill_shadow(cur_beg, cur_end, cfi_check ? cfi_check : (uptr)(-1)); + b->Add(cur_beg, cur_end, cfi_check); } else { - fill_shadow_constant(cur_beg, cur_end, kUncheckedShadow); + b->AddUnchecked(cur_beg, cur_end); } } } return 0; } -// Fill shadow for the initial libraries. -static void init_shadow() { - dl_iterate_phdr(dl_iterate_phdr_cb, nullptr); +// Init or update shadow for the current set of loaded libraries. +void UpdateShadow() { + ShadowBuilder b; + b.Start(); + dl_iterate_phdr(dl_iterate_phdr_cb, &b); + b.Install(); } -extern "C" SANITIZER_INTERFACE_ATTRIBUTE -void __cfi_slowpath(u64 CallSiteTypeId, void *Ptr) { +void InitShadow() { + CHECK_EQ(0, GetShadow()); + CHECK_EQ(0, GetShadowSize()); + + uptr vma = GetMaxVirtualAddress(); + // Shadow is 2 -> 2**kShadowGranularity. + SetShadowSize((vma >> (kShadowGranularity - 1)) + 1); + VReport(1, "CFI: VMA size %zx, shadow size %zx\n", vma, GetShadowSize()); + + UpdateShadow(); +} + +THREADLOCAL int in_loader; +BlockingMutex shadow_update_lock(LINKER_INITIALIZED); + +void EnterLoader() { + if (in_loader == 0) { + shadow_update_lock.Lock(); + } + ++in_loader; +} + +void ExitLoader() { + CHECK(in_loader > 0); + --in_loader; + UpdateShadow(); + if (in_loader == 0) { + shadow_update_lock.Unlock(); + } +} + +ALWAYS_INLINE void CfiSlowPathCommon(u64 CallSiteTypeId, void *Ptr, + void *DiagData) { uptr Addr = (uptr)Ptr; VReport(3, "__cfi_slowpath: %llx, %p\n", CallSiteTypeId, Ptr); ShadowValue sv = ShadowValue::load(Addr); if (sv.is_invalid()) { - VReport(2, "CFI: invalid memory region for a function pointer (shadow==0): %p\n", Ptr); - Die(); + VReport(1, "CFI: invalid memory region for a check target: %p\n", Ptr); +#ifdef CFI_ENABLE_DIAG + if (DiagData) { + __ubsan_handle_cfi_check_fail( + reinterpret_cast<__ubsan::CFICheckFailData *>(DiagData), Addr, false); + return; + } +#endif + Trap(); } if (sv.is_unchecked()) { VReport(2, "CFI: unchecked call (shadow=FFFF): %p\n", Ptr); return; } CFICheckFn cfi_check = sv.get_cfi_check(); VReport(2, "__cfi_check at %p\n", cfi_check); - cfi_check(CallSiteTypeId, Ptr); + cfi_check(CallSiteTypeId, Ptr, DiagData); } -static void InitializeFlags() { +void InitializeFlags() { SetCommonFlagsDefaults(); #ifdef CFI_ENABLE_DIAG __ubsan::Flags *uf = __ubsan::flags(); uf->SetDefaults(); #endif FlagParser cfi_parser; RegisterCommonFlags(&cfi_parser); cfi_parser.ParseString(GetEnv("CFI_OPTIONS")); #ifdef CFI_ENABLE_DIAG FlagParser ubsan_parser; __ubsan::RegisterUbsanFlags(&ubsan_parser, uf); RegisterCommonFlags(&ubsan_parser); const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions(); ubsan_parser.ParseString(ubsan_default_options); ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS")); #endif - SetVerbosity(common_flags()->verbosity); + InitializeCommonFlags(); - if (Verbosity()) ReportUnrecognizedFlags(); + if (Verbosity()) + ReportUnrecognizedFlags(); if (common_flags()->help) { cfi_parser.PrintFlagDescriptions(); } } +} // namespace __cfi + +using namespace __cfi; + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void +__cfi_slowpath(u64 CallSiteTypeId, void *Ptr) { + CfiSlowPathCommon(CallSiteTypeId, Ptr, nullptr); +} + +#ifdef CFI_ENABLE_DIAG +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void +__cfi_slowpath_diag(u64 CallSiteTypeId, void *Ptr, void *DiagData) { + CfiSlowPathCommon(CallSiteTypeId, Ptr, DiagData); +} +#endif + +// Setup shadow for dlopen()ed libraries. +// The actual shadow setup happens after dlopen() returns, which means that +// a library can not be a target of any CFI checks while its constructors are +// running. It's unclear how to fix this without some extra help from libc. +// In glibc, mmap inside dlopen is not interceptable. +// Maybe a seccomp-bpf filter? +// We could insert a high-priority constructor into the library, but that would +// not help with the uninstrumented libraries. +INTERCEPTOR(void*, dlopen, const char *filename, int flag) { + EnterLoader(); + void *handle = REAL(dlopen)(filename, flag); + ExitLoader(); + return handle; +} + +INTERCEPTOR(int, dlclose, void *handle) { + EnterLoader(); + int res = REAL(dlclose)(handle); + ExitLoader(); + return res; +} + extern "C" SANITIZER_INTERFACE_ATTRIBUTE #if !SANITIZER_CAN_USE_PREINIT_ARRAY // On ELF platforms, the constructor is invoked using .preinit_array (see below) __attribute__((constructor(0))) #endif void __cfi_init() { SanitizerToolName = "CFI"; InitializeFlags(); + InitShadow(); - uptr vma = GetMaxVirtualAddress(); - // Shadow is 2 -> 2**kShadowGranularity. - uptr shadow_size = (vma >> (kShadowGranularity - 1)) + 1; - VReport(1, "CFI: VMA size %zx, shadow size %zx\n", vma, shadow_size); - void *shadow = MmapNoReserveOrDie(shadow_size, "CFI shadow"); - VReport(1, "CFI: shadow at %zx .. %zx\n", shadow, - reinterpret_cast(shadow) + shadow_size); - __cfi_shadow = (uptr)shadow; - init_shadow(); + INTERCEPT_FUNCTION(dlopen); + INTERCEPT_FUNCTION(dlclose); #ifdef CFI_ENABLE_DIAG __ubsan::InitAsPlugin(); #endif } #if SANITIZER_CAN_USE_PREINIT_ARRAY // On ELF platforms, run cfi initialization before any other constructors. // On other platforms we use the constructor attribute to arrange to run our // initialization early. extern "C" { __attribute__((section(".preinit_array"), used)) void (*__cfi_preinit)(void) = __cfi_init; } #endif Index: projects/clang390-import/contrib/compiler-rt/lib/dfsan/dfsan.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/dfsan/dfsan.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/dfsan/dfsan.cc (revision 305364) @@ -1,429 +1,430 @@ //===-- dfsan.cc ----------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of DataFlowSanitizer. // // DataFlowSanitizer runtime. This file defines the public interface to // DataFlowSanitizer as well as the definition of certain runtime functions // called automatically by the compiler (specifically the instrumentation pass // in llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp). // // The public interface is defined in include/sanitizer/dfsan_interface.h whose // functions are prefixed dfsan_ while the compiler interface functions are // prefixed __dfsan_. //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_flag_parser.h" #include "sanitizer_common/sanitizer_libc.h" #include "dfsan/dfsan.h" using namespace __dfsan; typedef atomic_uint16_t atomic_dfsan_label; static const dfsan_label kInitializingLabel = -1; static const uptr kNumLabels = 1 << (sizeof(dfsan_label) * 8); static atomic_dfsan_label __dfsan_last_label; static dfsan_label_info __dfsan_label_info[kNumLabels]; Flags __dfsan::flags_data; SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL dfsan_label __dfsan_retval_tls; SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL dfsan_label __dfsan_arg_tls[64]; SANITIZER_INTERFACE_ATTRIBUTE uptr __dfsan_shadow_ptr_mask; // On Linux/x86_64, memory is laid out as follows: // // +--------------------+ 0x800000000000 (top of memory) // | application memory | // +--------------------+ 0x700000008000 (kAppAddr) // | | // | unused | // | | // +--------------------+ 0x200200000000 (kUnusedAddr) // | union table | // +--------------------+ 0x200000000000 (kUnionTableAddr) // | shadow memory | // +--------------------+ 0x000000010000 (kShadowAddr) // | reserved by kernel | // +--------------------+ 0x000000000000 // // To derive a shadow memory address from an application memory address, // bits 44-46 are cleared to bring the address into the range // [0x000000008000,0x100000000000). Then the address is shifted left by 1 to // account for the double byte representation of shadow labels and move the // address into the shadow memory range. See the function shadow_for below. // On Linux/MIPS64, memory is laid out as follows: // // +--------------------+ 0x10000000000 (top of memory) // | application memory | // +--------------------+ 0xF000008000 (kAppAddr) // | | // | unused | // | | // +--------------------+ 0x2200000000 (kUnusedAddr) // | union table | // +--------------------+ 0x2000000000 (kUnionTableAddr) // | shadow memory | // +--------------------+ 0x0000010000 (kShadowAddr) // | reserved by kernel | // +--------------------+ 0x0000000000 // On Linux/AArch64 (39-bit VMA), memory is laid out as follow: // // +--------------------+ 0x8000000000 (top of memory) // | application memory | // +--------------------+ 0x7000008000 (kAppAddr) // | | // | unused | // | | // +--------------------+ 0x1200000000 (kUnusedAddr) // | union table | // +--------------------+ 0x1000000000 (kUnionTableAddr) // | shadow memory | // +--------------------+ 0x0000010000 (kShadowAddr) // | reserved by kernel | // +--------------------+ 0x0000000000 // On Linux/AArch64 (42-bit VMA), memory is laid out as follow: // // +--------------------+ 0x40000000000 (top of memory) // | application memory | // +--------------------+ 0x3ff00008000 (kAppAddr) // | | // | unused | // | | // +--------------------+ 0x1200000000 (kUnusedAddr) // | union table | // +--------------------+ 0x8000000000 (kUnionTableAddr) // | shadow memory | // +--------------------+ 0x0000010000 (kShadowAddr) // | reserved by kernel | // +--------------------+ 0x0000000000 typedef atomic_dfsan_label dfsan_union_table_t[kNumLabels][kNumLabels]; #ifdef DFSAN_RUNTIME_VMA // Runtime detected VMA size. int __dfsan::vmaSize; #endif static uptr UnusedAddr() { return MappingArchImpl() + sizeof(dfsan_union_table_t); } static atomic_dfsan_label *union_table(dfsan_label l1, dfsan_label l2) { return &(*(dfsan_union_table_t *) UnionTableAddr())[l1][l2]; } // Checks we do not run out of labels. static void dfsan_check_label(dfsan_label label) { if (label == kInitializingLabel) { Report("FATAL: DataFlowSanitizer: out of labels\n"); Die(); } } // Resolves the union of two unequal labels. Nonequality is a precondition for // this function (the instrumentation pass inlines the equality test). extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label __dfsan_union(dfsan_label l1, dfsan_label l2) { DCHECK_NE(l1, l2); if (l1 == 0) return l2; if (l2 == 0) return l1; if (l1 > l2) Swap(l1, l2); atomic_dfsan_label *table_ent = union_table(l1, l2); // We need to deal with the case where two threads concurrently request // a union of the same pair of labels. If the table entry is uninitialized, // (i.e. 0) use a compare-exchange to set the entry to kInitializingLabel // (i.e. -1) to mark that we are initializing it. dfsan_label label = 0; if (atomic_compare_exchange_strong(table_ent, &label, kInitializingLabel, memory_order_acquire)) { // Check whether l2 subsumes l1. We don't need to check whether l1 // subsumes l2 because we are guaranteed here that l1 < l2, and (at least // in the cases we are interested in) a label may only subsume labels // created earlier (i.e. with a lower numerical value). if (__dfsan_label_info[l2].l1 == l1 || __dfsan_label_info[l2].l2 == l1) { label = l2; } else { label = atomic_fetch_add(&__dfsan_last_label, 1, memory_order_relaxed) + 1; dfsan_check_label(label); __dfsan_label_info[label].l1 = l1; __dfsan_label_info[label].l2 = l2; } atomic_store(table_ent, label, memory_order_release); } else if (label == kInitializingLabel) { // Another thread is initializing the entry. Wait until it is finished. do { internal_sched_yield(); label = atomic_load(table_ent, memory_order_acquire); } while (label == kInitializingLabel); } return label; } extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label __dfsan_union_load(const dfsan_label *ls, uptr n) { dfsan_label label = ls[0]; for (uptr i = 1; i != n; ++i) { dfsan_label next_label = ls[i]; if (label != next_label) label = __dfsan_union(label, next_label); } return label; } extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_unimplemented(char *fname) { if (flags().warn_unimplemented) Report("WARNING: DataFlowSanitizer: call to uninstrumented function %s\n", fname); } // Use '-mllvm -dfsan-debug-nonzero-labels' and break on this function // to try to figure out where labels are being introduced in a nominally // label-free program. extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_nonzero_label() { if (flags().warn_nonzero_labels) Report("WARNING: DataFlowSanitizer: saw nonzero label\n"); } // Indirect call to an uninstrumented vararg function. We don't have a way of // handling these at the moment. extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_vararg_wrapper(const char *fname) { Report("FATAL: DataFlowSanitizer: unsupported indirect call to vararg " "function %s\n", fname); Die(); } // Like __dfsan_union, but for use from the client or custom functions. Hence // the equality comparison is done here before calling __dfsan_union. SANITIZER_INTERFACE_ATTRIBUTE dfsan_label dfsan_union(dfsan_label l1, dfsan_label l2) { if (l1 == l2) return l1; return __dfsan_union(l1, l2); } extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label dfsan_create_label(const char *desc, void *userdata) { dfsan_label label = atomic_fetch_add(&__dfsan_last_label, 1, memory_order_relaxed) + 1; dfsan_check_label(label); __dfsan_label_info[label].l1 = __dfsan_label_info[label].l2 = 0; __dfsan_label_info[label].desc = desc; __dfsan_label_info[label].userdata = userdata; return label; } extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_set_label(dfsan_label label, void *addr, uptr size) { for (dfsan_label *labelp = shadow_for(addr); size != 0; --size, ++labelp) { // Don't write the label if it is already the value we need it to be. // In a program where most addresses are not labeled, it is common that // a page of shadow memory is entirely zeroed. The Linux copy-on-write // implementation will share all of the zeroed pages, making a copy of a // page when any value is written. The un-sharing will happen even if // the value written does not change the value in memory. Avoiding the // write when both |label| and |*labelp| are zero dramatically reduces // the amount of real memory used by large programs. if (label == *labelp) continue; *labelp = label; } } SANITIZER_INTERFACE_ATTRIBUTE void dfsan_set_label(dfsan_label label, void *addr, uptr size) { __dfsan_set_label(label, addr, size); } SANITIZER_INTERFACE_ATTRIBUTE void dfsan_add_label(dfsan_label label, void *addr, uptr size) { for (dfsan_label *labelp = shadow_for(addr); size != 0; --size, ++labelp) if (*labelp != label) *labelp = __dfsan_union(*labelp, label); } // Unlike the other dfsan interface functions the behavior of this function // depends on the label of one of its arguments. Hence it is implemented as a // custom function. extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label __dfsw_dfsan_get_label(long data, dfsan_label data_label, dfsan_label *ret_label) { *ret_label = 0; return data_label; } SANITIZER_INTERFACE_ATTRIBUTE dfsan_label dfsan_read_label(const void *addr, uptr size) { if (size == 0) return 0; return __dfsan_union_load(shadow_for(addr), size); } extern "C" SANITIZER_INTERFACE_ATTRIBUTE const struct dfsan_label_info *dfsan_get_label_info(dfsan_label label) { return &__dfsan_label_info[label]; } extern "C" SANITIZER_INTERFACE_ATTRIBUTE int dfsan_has_label(dfsan_label label, dfsan_label elem) { if (label == elem) return true; const dfsan_label_info *info = dfsan_get_label_info(label); if (info->l1 != 0) { return dfsan_has_label(info->l1, elem) || dfsan_has_label(info->l2, elem); } else { return false; } } extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label dfsan_has_label_with_desc(dfsan_label label, const char *desc) { const dfsan_label_info *info = dfsan_get_label_info(label); if (info->l1 != 0) { return dfsan_has_label_with_desc(info->l1, desc) || dfsan_has_label_with_desc(info->l2, desc); } else { return internal_strcmp(desc, info->desc) == 0; } } extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr dfsan_get_label_count(void) { dfsan_label max_label_allocated = atomic_load(&__dfsan_last_label, memory_order_relaxed); return static_cast(max_label_allocated); } extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_dump_labels(int fd) { dfsan_label last_label = atomic_load(&__dfsan_last_label, memory_order_relaxed); for (uptr l = 1; l <= last_label; ++l) { char buf[64]; internal_snprintf(buf, sizeof(buf), "%u %u %u ", l, __dfsan_label_info[l].l1, __dfsan_label_info[l].l2); WriteToFile(fd, buf, internal_strlen(buf)); if (__dfsan_label_info[l].l1 == 0 && __dfsan_label_info[l].desc) { WriteToFile(fd, __dfsan_label_info[l].desc, internal_strlen(__dfsan_label_info[l].desc)); } WriteToFile(fd, "\n", 1); } } void Flags::SetDefaults() { #define DFSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; #include "dfsan_flags.inc" #undef DFSAN_FLAG } static void RegisterDfsanFlags(FlagParser *parser, Flags *f) { #define DFSAN_FLAG(Type, Name, DefaultValue, Description) \ RegisterFlag(parser, #Name, Description, &f->Name); #include "dfsan_flags.inc" #undef DFSAN_FLAG } static void InitializeFlags() { SetCommonFlagsDefaults(); flags().SetDefaults(); FlagParser parser; RegisterCommonFlags(&parser); RegisterDfsanFlags(&parser, &flags()); parser.ParseString(GetEnv("DFSAN_OPTIONS")); - SetVerbosity(common_flags()->verbosity); + InitializeCommonFlags(); if (Verbosity()) ReportUnrecognizedFlags(); if (common_flags()->help) parser.PrintFlagDescriptions(); } static void InitializePlatformEarly() { + AvoidCVE_2016_2143(); #ifdef DFSAN_RUNTIME_VMA __dfsan::vmaSize = (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1); if (__dfsan::vmaSize == 39 || __dfsan::vmaSize == 42) { __dfsan_shadow_ptr_mask = ShadowMask(); } else { Printf("FATAL: DataFlowSanitizer: unsupported VMA range\n"); Printf("FATAL: Found %d - Supported 39 and 42\n", __dfsan::vmaSize); Die(); } #endif } static void dfsan_fini() { if (internal_strcmp(flags().dump_labels_at_exit, "") != 0) { fd_t fd = OpenFile(flags().dump_labels_at_exit, WrOnly); if (fd == kInvalidFd) { Report("WARNING: DataFlowSanitizer: unable to open output file %s\n", flags().dump_labels_at_exit); return; } Report("INFO: DataFlowSanitizer: dumping labels to %s\n", flags().dump_labels_at_exit); dfsan_dump_labels(fd); CloseFile(fd); } } static void dfsan_init(int argc, char **argv, char **envp) { InitializeFlags(); InitializePlatformEarly(); MmapFixedNoReserve(ShadowAddr(), UnusedAddr() - ShadowAddr()); // Protect the region of memory we don't use, to preserve the one-to-one // mapping from application to shadow memory. But if ASLR is disabled, Linux // will load our executable in the middle of our unused region. This mostly // works so long as the program doesn't use too much memory. We support this // case by disabling memory protection when ASLR is disabled. uptr init_addr = (uptr)&dfsan_init; if (!(init_addr >= UnusedAddr() && init_addr < AppAddr())) - MmapNoAccess(UnusedAddr(), AppAddr() - UnusedAddr()); + MmapFixedNoAccess(UnusedAddr(), AppAddr() - UnusedAddr()); InitializeInterceptors(); // Register the fini callback to run when the program terminates successfully // or it is killed by the runtime. Atexit(dfsan_fini); AddDieCallback(dfsan_fini); __dfsan_label_info[kInitializingLabel].desc = ""; } #if SANITIZER_CAN_USE_PREINIT_ARRAY __attribute__((section(".preinit_array"), used)) static void (*dfsan_init_ptr)(int, char **, char **) = dfsan_init; #endif Index: projects/clang390-import/contrib/compiler-rt/lib/esan/cache_frag.cpp =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/cache_frag.cpp (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/cache_frag.cpp (revision 305364) @@ -0,0 +1,208 @@ +//===-- cache_frag.cpp ----------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +// This file contains cache fragmentation-specific code. +//===----------------------------------------------------------------------===// + +#include "esan.h" +#include "esan_flags.h" +#include "sanitizer_common/sanitizer_addrhashmap.h" +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_placement_new.h" +#include + +namespace __esan { + +//===-- Struct field access counter runtime -------------------------------===// + +// This should be kept consistent with LLVM's EfficiencySanitizer StructInfo. +struct StructInfo { + const char *StructName; + u32 Size; + u32 NumFields; + u32 *FieldOffset; // auxiliary struct field info. + u32 *FieldSize; // auxiliary struct field info. + const char **FieldTypeName; // auxiliary struct field info. + u64 *FieldCounters; + u64 *ArrayCounter; + bool hasAuxFieldInfo() { return FieldOffset != nullptr; } +}; + +// This should be kept consistent with LLVM's EfficiencySanitizer CacheFragInfo. +// The tool-specific information per compilation unit (module). +struct CacheFragInfo { + const char *UnitName; + u32 NumStructs; + StructInfo *Structs; +}; + +struct StructCounter { + StructInfo *Struct; + u64 Count; // The total access count of the struct. + u64 Ratio; // Difference ratio for the struct layout access. +}; + +// We use StructHashMap to keep track of an unique copy of StructCounter. +typedef AddrHashMap StructHashMap; +struct Context { + StructHashMap StructMap; + u32 NumStructs; + u64 TotalCount; // The total access count of all structs. +}; +static Context *Ctx; + +static void reportStructSummary() { + // FIXME: provide a better struct field access summary report. + Report("%s: total struct field access count = %llu\n", SanitizerToolName, + Ctx->TotalCount); +} + +// FIXME: we are still exploring proper ways to evaluate the difference between +// struct field counts. Currently, we use a simple formula to calculate the +// difference ratio: V1/V2. +static inline u64 computeDifferenceRatio(u64 Val1, u64 Val2) { + if (Val2 > Val1) { + Swap(Val1, Val2); + } + if (Val2 == 0) + Val2 = 1; + return (Val1 / Val2); +} + +static void reportStructCounter(StructHashMap::Handle &Handle) { + const u32 TypePrintLimit = 512; + const char *type, *start, *end; + StructInfo *Struct = Handle->Struct; + // Union field address calculation is done via bitcast instead of GEP, + // so the count for union is always 0. + // We skip the union report to avoid confusion. + if (strncmp(Struct->StructName, "union.", 6) == 0) + return; + // Remove the '.' after class/struct during print. + if (strncmp(Struct->StructName, "class.", 6) == 0) { + type = "class"; + start = &Struct->StructName[6]; + } else { + type = "struct"; + start = &Struct->StructName[7]; + } + // Remove the suffixes with '#' during print. + end = strchr(start, '#'); + CHECK(end != nullptr); + Report(" %s %.*s\n", type, end - start, start); + Report(" size = %u, count = %llu, ratio = %llu, array access = %llu\n", + Struct->Size, Handle->Count, Handle->Ratio, *Struct->ArrayCounter); + if (Struct->hasAuxFieldInfo()) { + for (u32 i = 0; i < Struct->NumFields; ++i) { + Report(" #%2u: offset = %u,\t size = %u," + "\t count = %llu,\t type = %.*s\n", + i, Struct->FieldOffset[i], Struct->FieldSize[i], + Struct->FieldCounters[i], TypePrintLimit, Struct->FieldTypeName[i]); + } + } else { + for (u32 i = 0; i < Struct->NumFields; ++i) { + Report(" #%2u: count = %llu\n", i, Struct->FieldCounters[i]); + } + } +} + +static void computeStructRatio(StructHashMap::Handle &Handle) { + Handle->Ratio = 0; + Handle->Count = Handle->Struct->FieldCounters[0]; + for (u32 i = 1; i < Handle->Struct->NumFields; ++i) { + Handle->Count += Handle->Struct->FieldCounters[i]; + Handle->Ratio += computeDifferenceRatio( + Handle->Struct->FieldCounters[i - 1], Handle->Struct->FieldCounters[i]); + } + Ctx->TotalCount += Handle->Count; + if (Handle->Ratio >= (u64)getFlags()->report_threshold || + (Verbosity() >= 1 && Handle->Count > 0)) + reportStructCounter(Handle); +} + +static void registerStructInfo(CacheFragInfo *CacheFrag) { + for (u32 i = 0; i < CacheFrag->NumStructs; ++i) { + StructInfo *Struct = &CacheFrag->Structs[i]; + StructHashMap::Handle H(&Ctx->StructMap, (uptr)Struct->FieldCounters); + if (H.created()) { + VPrintf(2, " Register %s: %u fields\n", Struct->StructName, + Struct->NumFields); + H->Struct = Struct; + ++Ctx->NumStructs; + } else { + VPrintf(2, " Duplicated %s: %u fields\n", Struct->StructName, + Struct->NumFields); + } + } +} + +static void unregisterStructInfo(CacheFragInfo *CacheFrag) { + // FIXME: if the library is unloaded before finalizeCacheFrag, we should + // collect the result for later report. + for (u32 i = 0; i < CacheFrag->NumStructs; ++i) { + StructInfo *Struct = &CacheFrag->Structs[i]; + StructHashMap::Handle H(&Ctx->StructMap, (uptr)Struct->FieldCounters, true); + if (H.exists()) { + VPrintf(2, " Unregister %s: %u fields\n", Struct->StructName, + Struct->NumFields); + // FIXME: we should move this call to finalizeCacheFrag once we can + // iterate over the hash map there. + computeStructRatio(H); + --Ctx->NumStructs; + } else { + VPrintf(2, " Duplicated %s: %u fields\n", Struct->StructName, + Struct->NumFields); + } + } + static bool Reported = false; + if (Ctx->NumStructs == 0 && !Reported) { + Reported = true; + reportStructSummary(); + } +} + +//===-- Init/exit functions -----------------------------------------------===// + +void processCacheFragCompilationUnitInit(void *Ptr) { + CacheFragInfo *CacheFrag = (CacheFragInfo *)Ptr; + VPrintf(2, "in esan::%s: %s with %u class(es)/struct(s)\n", __FUNCTION__, + CacheFrag->UnitName, CacheFrag->NumStructs); + registerStructInfo(CacheFrag); +} + +void processCacheFragCompilationUnitExit(void *Ptr) { + CacheFragInfo *CacheFrag = (CacheFragInfo *)Ptr; + VPrintf(2, "in esan::%s: %s with %u class(es)/struct(s)\n", __FUNCTION__, + CacheFrag->UnitName, CacheFrag->NumStructs); + unregisterStructInfo(CacheFrag); +} + +void initializeCacheFrag() { + VPrintf(2, "in esan::%s\n", __FUNCTION__); + // We use placement new to initialize Ctx before C++ static initializaion. + // We make CtxMem 8-byte aligned for atomic operations in AddrHashMap. + static u64 CtxMem[sizeof(Context) / sizeof(u64) + 1]; + Ctx = new (CtxMem) Context(); + Ctx->NumStructs = 0; +} + +int finalizeCacheFrag() { + VPrintf(2, "in esan::%s\n", __FUNCTION__); + return 0; +} + +void reportCacheFrag() { + VPrintf(2, "in esan::%s\n", __FUNCTION__); + // FIXME: Not yet implemented. We need to iterate over all of the + // compilation unit data. +} + +} // namespace __esan Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/cache_frag.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/esan/cache_frag.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/cache_frag.h (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/cache_frag.h (revision 305364) @@ -0,0 +1,29 @@ +//===-- cache_frag.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +// Header for cache-fragmentation-specific code. +//===----------------------------------------------------------------------===// + +#ifndef CACHE_FRAG_H +#define CACHE_FRAG_H + +namespace __esan { + +void processCacheFragCompilationUnitInit(void *Ptr); +void processCacheFragCompilationUnitExit(void *Ptr); + +void initializeCacheFrag(); +int finalizeCacheFrag(); +void reportCacheFrag(); + +} // namespace __esan + +#endif // CACHE_FRAG_H Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/cache_frag.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/esan/esan.cpp =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/esan.cpp (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/esan.cpp (revision 305364) @@ -0,0 +1,270 @@ +//===-- esan.cpp ----------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +// Main file (entry points) for the Esan run-time. +//===----------------------------------------------------------------------===// + +#include "esan.h" +#include "esan_flags.h" +#include "esan_interface_internal.h" +#include "esan_shadow.h" +#include "cache_frag.h" +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_flag_parser.h" +#include "sanitizer_common/sanitizer_flags.h" +#include "working_set.h" + +// See comment below. +extern "C" { +extern void __cxa_atexit(void (*function)(void)); +} + +namespace __esan { + +bool EsanIsInitialized; +bool EsanDuringInit; +ShadowMapping Mapping; + +// Different tools use different scales within the same shadow mapping scheme. +// The scale used here must match that used by the compiler instrumentation. +// This array is indexed by the ToolType enum. +static const uptr ShadowScale[] = { + 0, // ESAN_None. + 2, // ESAN_CacheFrag: 4B:1B, so 4 to 1 == >>2. + 6, // ESAN_WorkingSet: 64B:1B, so 64 to 1 == >>6. +}; + +// We are combining multiple performance tuning tools under the umbrella of +// one EfficiencySanitizer super-tool. Most of our tools have very similar +// memory access instrumentation, shadow memory mapping, libc interception, +// etc., and there is typically more shared code than distinct code. +// +// We are not willing to dispatch on tool dynamically in our fastpath +// instrumentation: thus, which tool to use is a static option selected +// at compile time and passed to __esan_init(). +// +// We are willing to pay the overhead of tool dispatch in the slowpath to more +// easily share code. We expect to only come here rarely. +// If this becomes a performance hit, we can add separate interface +// routines for each subtool (e.g., __esan_cache_frag_aligned_load_4). +// But for libc interceptors, we'll have to do one of the following: +// A) Add multiple-include support to sanitizer_common_interceptors.inc, +// instantiate it separately for each tool, and call the selected +// tool's intercept setup code. +// B) Build separate static runtime libraries, one for each tool. +// C) Completely split the tools into separate sanitizers. + +void processRangeAccess(uptr PC, uptr Addr, int Size, bool IsWrite) { + VPrintf(3, "in esan::%s %p: %c %p %d\n", __FUNCTION__, PC, + IsWrite ? 'w' : 'r', Addr, Size); + if (__esan_which_tool == ESAN_CacheFrag) { + // TODO(bruening): add shadow mapping and update shadow bits here. + // We'll move this to cache_frag.cpp once we have something. + } else if (__esan_which_tool == ESAN_WorkingSet) { + processRangeAccessWorkingSet(PC, Addr, Size, IsWrite); + } +} + +bool processSignal(int SigNum, void (*Handler)(int), void (**Result)(int)) { + if (__esan_which_tool == ESAN_WorkingSet) + return processWorkingSetSignal(SigNum, Handler, Result); + return true; +} + +bool processSigaction(int SigNum, const void *Act, void *OldAct) { + if (__esan_which_tool == ESAN_WorkingSet) + return processWorkingSetSigaction(SigNum, Act, OldAct); + return true; +} + +bool processSigprocmask(int How, void *Set, void *OldSet) { + if (__esan_which_tool == ESAN_WorkingSet) + return processWorkingSetSigprocmask(How, Set, OldSet); + return true; +} + +#if SANITIZER_DEBUG +static bool verifyShadowScheme() { + // Sanity checks for our shadow mapping scheme. + uptr AppStart, AppEnd; + if (Verbosity() >= 3) { + for (int i = 0; getAppRegion(i, &AppStart, &AppEnd); ++i) { + VPrintf(3, "App #%d: [%zx-%zx) (%zuGB)\n", i, AppStart, AppEnd, + (AppEnd - AppStart) >> 30); + } + } + for (int Scale = 0; Scale < 8; ++Scale) { + Mapping.initialize(Scale); + if (Verbosity() >= 3) { + VPrintf(3, "\nChecking scale %d\n", Scale); + uptr ShadowStart, ShadowEnd; + for (int i = 0; getShadowRegion(i, &ShadowStart, &ShadowEnd); ++i) { + VPrintf(3, "Shadow #%d: [%zx-%zx) (%zuGB)\n", i, ShadowStart, + ShadowEnd, (ShadowEnd - ShadowStart) >> 30); + } + for (int i = 0; getShadowRegion(i, &ShadowStart, &ShadowEnd); ++i) { + VPrintf(3, "Shadow(Shadow) #%d: [%zx-%zx)\n", i, + appToShadow(ShadowStart), appToShadow(ShadowEnd - 1)+1); + } + } + for (int i = 0; getAppRegion(i, &AppStart, &AppEnd); ++i) { + DCHECK(isAppMem(AppStart)); + DCHECK(!isAppMem(AppStart - 1)); + DCHECK(isAppMem(AppEnd - 1)); + DCHECK(!isAppMem(AppEnd)); + DCHECK(!isShadowMem(AppStart)); + DCHECK(!isShadowMem(AppEnd - 1)); + DCHECK(isShadowMem(appToShadow(AppStart))); + DCHECK(isShadowMem(appToShadow(AppEnd - 1))); + // Double-shadow checks. + DCHECK(!isShadowMem(appToShadow(appToShadow(AppStart)))); + DCHECK(!isShadowMem(appToShadow(appToShadow(AppEnd - 1)))); + } + // Ensure no shadow regions overlap each other. + uptr ShadowAStart, ShadowBStart, ShadowAEnd, ShadowBEnd; + for (int i = 0; getShadowRegion(i, &ShadowAStart, &ShadowAEnd); ++i) { + for (int j = 0; getShadowRegion(j, &ShadowBStart, &ShadowBEnd); ++j) { + DCHECK(i == j || ShadowAStart >= ShadowBEnd || + ShadowAEnd <= ShadowBStart); + } + } + } + return true; +} +#endif + +static void initializeShadow() { + verifyAddressSpace(); + + DCHECK(verifyShadowScheme()); + + Mapping.initialize(ShadowScale[__esan_which_tool]); + + VPrintf(1, "Shadow scale=%d offset=%p\n", Mapping.Scale, Mapping.Offset); + + uptr ShadowStart, ShadowEnd; + for (int i = 0; getShadowRegion(i, &ShadowStart, &ShadowEnd); ++i) { + VPrintf(1, "Shadow #%d: [%zx-%zx) (%zuGB)\n", i, ShadowStart, ShadowEnd, + (ShadowEnd - ShadowStart) >> 30); + + uptr Map; + if (__esan_which_tool == ESAN_WorkingSet) { + // We want to identify all shadow pages that are touched so we start + // out inaccessible. + Map = (uptr)MmapFixedNoAccess(ShadowStart, ShadowEnd- ShadowStart, + "shadow"); + } else { + Map = (uptr)MmapFixedNoReserve(ShadowStart, ShadowEnd - ShadowStart, + "shadow"); + } + if (Map != ShadowStart) { + Printf("FATAL: EfficiencySanitizer failed to map its shadow memory.\n"); + Die(); + } + + if (common_flags()->no_huge_pages_for_shadow) + NoHugePagesInRegion(ShadowStart, ShadowEnd - ShadowStart); + if (common_flags()->use_madv_dontdump) + DontDumpShadowMemory(ShadowStart, ShadowEnd - ShadowStart); + + // TODO: Call MmapNoAccess() on in-between regions. + } +} + +void initializeLibrary(ToolType Tool) { + // We assume there is only one thread during init, but we need to + // guard against double-init when we're (re-)called from an + // early interceptor. + if (EsanIsInitialized || EsanDuringInit) + return; + EsanDuringInit = true; + CHECK(Tool == __esan_which_tool); + SanitizerToolName = "EfficiencySanitizer"; + CacheBinaryName(); + initializeFlags(); + + // Intercepting libc _exit or exit via COMMON_INTERCEPTOR_ON_EXIT only + // finalizes on an explicit exit call by the app. To handle a normal + // exit we register an atexit handler. + ::__cxa_atexit((void (*)())finalizeLibrary); + + VPrintf(1, "in esan::%s\n", __FUNCTION__); + if (__esan_which_tool <= ESAN_None || __esan_which_tool >= ESAN_Max) { + Printf("ERROR: unknown tool %d requested\n", __esan_which_tool); + Die(); + } + + initializeShadow(); + if (__esan_which_tool == ESAN_WorkingSet) + initializeShadowWorkingSet(); + + initializeInterceptors(); + + if (__esan_which_tool == ESAN_CacheFrag) { + initializeCacheFrag(); + } else if (__esan_which_tool == ESAN_WorkingSet) { + initializeWorkingSet(); + } + + EsanIsInitialized = true; + EsanDuringInit = false; +} + +int finalizeLibrary() { + VPrintf(1, "in esan::%s\n", __FUNCTION__); + if (__esan_which_tool == ESAN_CacheFrag) { + return finalizeCacheFrag(); + } else if (__esan_which_tool == ESAN_WorkingSet) { + return finalizeWorkingSet(); + } + return 0; +} + +void reportResults() { + VPrintf(1, "in esan::%s\n", __FUNCTION__); + if (__esan_which_tool == ESAN_CacheFrag) { + return reportCacheFrag(); + } else if (__esan_which_tool == ESAN_WorkingSet) { + return reportWorkingSet(); + } +} + +void processCompilationUnitInit(void *Ptr) { + VPrintf(2, "in esan::%s\n", __FUNCTION__); + if (__esan_which_tool == ESAN_CacheFrag) { + DCHECK(Ptr != nullptr); + processCacheFragCompilationUnitInit(Ptr); + } else { + DCHECK(Ptr == nullptr); + } +} + +// This is called when the containing module is unloaded. +// For the main executable module, this is called after finalizeLibrary. +void processCompilationUnitExit(void *Ptr) { + VPrintf(2, "in esan::%s\n", __FUNCTION__); + if (__esan_which_tool == ESAN_CacheFrag) { + DCHECK(Ptr != nullptr); + processCacheFragCompilationUnitExit(Ptr); + } else { + DCHECK(Ptr == nullptr); + } +} + +unsigned int getSampleCount() { + VPrintf(1, "in esan::%s\n", __FUNCTION__); + if (__esan_which_tool == ESAN_WorkingSet) { + return getSampleCountWorkingSet(); + } + return 0; +} + +} // namespace __esan Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/esan.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/esan/esan.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/esan.h (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/esan.h (revision 305364) @@ -0,0 +1,60 @@ +//===-- esan.h --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +// Main internal esan header file. +// +// Ground rules: +// - C++ run-time should not be used (static CTORs, RTTI, exceptions, static +// function-scope locals) +// - All functions/classes/etc reside in namespace __esan, except for those +// declared in esan_interface_internal.h. +// - Platform-specific files should be used instead of ifdefs (*). +// - No system headers included in header files (*). +// - Platform specific headers included only into platform-specific files (*). +// +// (*) Except when inlining is critical for performance. +//===----------------------------------------------------------------------===// + +#ifndef ESAN_H +#define ESAN_H + +#include "interception/interception.h" +#include "sanitizer_common/sanitizer_common.h" +#include "esan_interface_internal.h" + +namespace __esan { + +extern bool EsanIsInitialized; +extern bool EsanDuringInit; + +void initializeLibrary(ToolType Tool); +int finalizeLibrary(); +void reportResults(); +unsigned int getSampleCount(); +// Esan creates the variable per tool per compilation unit at compile time +// and passes its pointer Ptr to the runtime library. +void processCompilationUnitInit(void *Ptr); +void processCompilationUnitExit(void *Ptr); +void processRangeAccess(uptr PC, uptr Addr, int Size, bool IsWrite); +void initializeInterceptors(); + +// Platform-dependent routines. +void verifyAddressSpace(); +bool fixMmapAddr(void **Addr, SIZE_T Size, int Flags); +uptr checkMmapResult(uptr Addr, SIZE_T Size); +// The return value indicates whether to call the real version or not. +bool processSignal(int SigNum, void (*Handler)(int), void (**Result)(int)); +bool processSigaction(int SigNum, const void *Act, void *OldAct); +bool processSigprocmask(int How, void *Set, void *OldSet); + +} // namespace __esan + +#endif // ESAN_H Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/esan.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/esan/esan.syms.extra =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/esan.syms.extra (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/esan.syms.extra (revision 305364) @@ -0,0 +1,4 @@ +__esan_init +__esan_exit +__esan_aligned* +__esan_unaligned* Index: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_circular_buffer.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/esan_circular_buffer.h (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/esan_circular_buffer.h (revision 305364) @@ -0,0 +1,96 @@ +//===-- esan_circular_buffer.h ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +// Circular buffer data structure. +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_common.h" + +namespace __esan { + +// A circular buffer for POD data whose memory is allocated using mmap. +// There are two usage models: one is to use initialize/free (for global +// instances) and the other is to use placement new with the +// constructor and to call the destructor or free (they are equivalent). +template +class CircularBuffer { + public: + // To support global instances we cannot initialize any field in the + // default constructor. + explicit CircularBuffer() {} + CircularBuffer(uptr BufferCapacity) { + initialize(BufferCapacity); + WasConstructed = true; + } + ~CircularBuffer() { + if (WasConstructed) // Else caller will call free() explicitly. + free(); + } + void initialize(uptr BufferCapacity) { + Capacity = BufferCapacity; + // MmapOrDie rounds up to the page size for us. + Data = (T *)MmapOrDie(Capacity * sizeof(T), "CircularBuffer"); + StartIdx = 0; + Count = 0; + WasConstructed = false; + } + void free() { + UnmapOrDie(Data, Capacity * sizeof(T)); + } + T &operator[](uptr Idx) { + CHECK_LT(Idx, Count); + uptr ArrayIdx = (StartIdx + Idx) % Capacity; + return Data[ArrayIdx]; + } + const T &operator[](uptr Idx) const { + CHECK_LT(Idx, Count); + uptr ArrayIdx = (StartIdx + Idx) % Capacity; + return Data[ArrayIdx]; + } + void push_back(const T &Item) { + CHECK_GT(Capacity, 0); + uptr ArrayIdx = (StartIdx + Count) % Capacity; + Data[ArrayIdx] = Item; + if (Count < Capacity) + ++Count; + else + StartIdx = (StartIdx + 1) % Capacity; + } + T &back() { + CHECK_GT(Count, 0); + uptr ArrayIdx = (StartIdx + Count - 1) % Capacity; + return Data[ArrayIdx]; + } + void pop_back() { + CHECK_GT(Count, 0); + --Count; + } + uptr size() const { + return Count; + } + void clear() { + StartIdx = 0; + Count = 0; + } + bool empty() const { return size() == 0; } + + private: + CircularBuffer(const CircularBuffer&); + void operator=(const CircularBuffer&); + + bool WasConstructed; + T *Data; + uptr Capacity; + uptr StartIdx; + uptr Count; +}; + +} // namespace __esan Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_circular_buffer.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_flags.cpp =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/esan_flags.cpp (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/esan_flags.cpp (revision 305364) @@ -0,0 +1,58 @@ +//===-- esan_flags.cc -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +// Esan flag parsing logic. +//===----------------------------------------------------------------------===// + +#include "esan_flags.h" +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_flag_parser.h" +#include "sanitizer_common/sanitizer_flags.h" + +namespace __esan { + +static const char EsanOptsEnv[] = "ESAN_OPTIONS"; + +Flags EsanFlagsDontUseDirectly; + +void Flags::setDefaults() { +#define ESAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; +#include "esan_flags.inc" +#undef ESAN_FLAG +} + +static void registerEsanFlags(FlagParser *Parser, Flags *F) { +#define ESAN_FLAG(Type, Name, DefaultValue, Description) \ + RegisterFlag(Parser, #Name, Description, &F->Name); +#include "esan_flags.inc" +#undef ESAN_FLAG +} + +void initializeFlags() { + SetCommonFlagsDefaults(); + Flags *F = getFlags(); + F->setDefaults(); + + FlagParser Parser; + registerEsanFlags(&Parser, F); + RegisterCommonFlags(&Parser); + Parser.ParseString(GetEnv(EsanOptsEnv)); + + InitializeCommonFlags(); + if (Verbosity()) + ReportUnrecognizedFlags(); + if (common_flags()->help) + Parser.PrintFlagDescriptions(); + + __sanitizer_set_report_path(common_flags()->log_path); +} + +} // namespace __esan Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_flags.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_flags.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/esan_flags.h (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/esan_flags.h (revision 305364) @@ -0,0 +1,41 @@ +//===-- esan_flags.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +// Esan runtime flags. +//===----------------------------------------------------------------------===// + +#ifndef ESAN_FLAGS_H +#define ESAN_FLAGS_H + +#include "sanitizer_common/sanitizer_internal_defs.h" +#include "sanitizer_common/sanitizer_flag_parser.h" + +namespace __esan { + +class Flags { +public: +#define ESAN_FLAG(Type, Name, DefaultValue, Description) Type Name; +#include "esan_flags.inc" +#undef ESAN_FLAG + + void setDefaults(); +}; + +extern Flags EsanFlagsDontUseDirectly; +inline Flags *getFlags() { + return &EsanFlagsDontUseDirectly; +} + +void initializeFlags(); + +} // namespace __esan + +#endif // ESAN_FLAGS_H Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_flags.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_flags.inc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/esan_flags.inc (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/esan_flags.inc (revision 305364) @@ -0,0 +1,56 @@ +//===-- esan_flags.inc ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Esan runtime flags. +// +//===----------------------------------------------------------------------===// + +#ifndef ESAN_FLAG +# error "Define ESAN_FLAG prior to including this file!" +#endif + +// ESAN_FLAG(Type, Name, DefaultValue, Description) +// See COMMON_FLAG in sanitizer_flags.inc for more details. + +//===----------------------------------------------------------------------===// +// Cross-tool options +//===----------------------------------------------------------------------===// + +ESAN_FLAG(int, cache_line_size, 64, + "The number of bytes in a cache line. For the working-set tool, this " + "cannot be changed without also changing the compiler " + "instrumentation.") + +//===----------------------------------------------------------------------===// +// Working set tool options +//===----------------------------------------------------------------------===// + +ESAN_FLAG(bool, record_snapshots, true, + "Working set tool: whether to sample snapshots during a run.") + +// Typical profiling uses a 10ms timer. Our snapshots take some work +// to scan memory so we reduce to 20ms. +// To disable samples, turn off record_snapshots. +ESAN_FLAG(int, sample_freq, 20, + "Working set tool: sampling frequency in milliseconds.") + +// This controls the difference in frequency between each successive series +// of snapshots. There are 8 in total, with number 0 using sample_freq. +// Number N samples number N-1 every (1 << snapshot_step) instance of N-1. +ESAN_FLAG(int, snapshot_step, 2, "Working set tool: the log of the sampling " + "performed for the next-higher-frequency snapshot series.") + +//===----------------------------------------------------------------------===// +// Cache Fragmentation tool options +//===----------------------------------------------------------------------===// + +// The difference information of a struct is reported if the struct's difference +// score is greater than the report_threshold. +ESAN_FLAG(int, report_threshold, 1<<10, "Cache-frag tool: the struct difference" + " score threshold for reporting.") Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_flags.inc ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_interceptors.cpp =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/esan_interceptors.cpp (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/esan_interceptors.cpp (revision 305364) @@ -0,0 +1,547 @@ +//===-- esan_interceptors.cpp ---------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +// Interception routines for the esan run-time. +//===----------------------------------------------------------------------===// + +#include "esan.h" +#include "esan_shadow.h" +#include "interception/interception.h" +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_libc.h" +#include "sanitizer_common/sanitizer_linux.h" +#include "sanitizer_common/sanitizer_stacktrace.h" + +using namespace __esan; // NOLINT + +#define CUR_PC() (StackTrace::GetCurrentPc()) + +//===----------------------------------------------------------------------===// +// Interception via sanitizer common interceptors +//===----------------------------------------------------------------------===// + +// Get the per-platform defines for what is possible to intercept +#include "sanitizer_common/sanitizer_platform_interceptors.h" + +// TODO(bruening): tsan disables several interceptors (getpwent, etc.) claiming +// that interception is a perf hit: should we do the same? + +// We have no need to intercept: +#undef SANITIZER_INTERCEPT_TLS_GET_ADDR + +// TODO(bruening): the common realpath interceptor assumes malloc is +// intercepted! We should try to parametrize that, though we'll +// intercept malloc soon ourselves and can then remove this undef. +#undef SANITIZER_INTERCEPT_REALPATH + +// We provide our own version: +#undef SANITIZER_INTERCEPT_SIGPROCMASK + +#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!EsanIsInitialized) + +#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name) +#define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \ + INTERCEPT_FUNCTION_VER(name, ver) + +// We must initialize during early interceptors, to support tcmalloc. +// This means that for some apps we fully initialize prior to +// __esan_init() being called. +// We currently do not use ctx. +#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ + do { \ + if (UNLIKELY(COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)) { \ + if (!UNLIKELY(EsanDuringInit)) \ + initializeLibrary(__esan_which_tool); \ + return REAL(func)(__VA_ARGS__); \ + } \ + ctx = nullptr; \ + (void)ctx; \ + } while (false) + +#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, func, ...) \ + COMMON_INTERCEPTOR_ENTER(ctx, func, __VA_ARGS__) + +#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ + processRangeAccess(CUR_PC(), (uptr)ptr, size, true) + +#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \ + processRangeAccess(CUR_PC(), (uptr)ptr, size, false) + +// This is only called if the app explicitly calls exit(), not on +// a normal exit. +#define COMMON_INTERCEPTOR_ON_EXIT(ctx) finalizeLibrary() + +#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) \ + do { \ + (void)(ctx); \ + (void)(file); \ + (void)(path); \ + } while (false) +#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) \ + do { \ + (void)(ctx); \ + (void)(file); \ + } while (false) +#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \ + do { \ + (void)(filename); \ + (void)(handle); \ + } while (false) +#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() \ + do { \ + } while (false) +#define COMMON_INTERCEPTOR_ACQUIRE(ctx, u) \ + do { \ + (void)(ctx); \ + (void)(u); \ + } while (false) +#define COMMON_INTERCEPTOR_RELEASE(ctx, u) \ + do { \ + (void)(ctx); \ + (void)(u); \ + } while (false) +#define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \ + do { \ + (void)(ctx); \ + (void)(path); \ + } while (false) +#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \ + do { \ + (void)(ctx); \ + (void)(fd); \ + } while (false) +#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \ + do { \ + (void)(ctx); \ + (void)(fd); \ + } while (false) +#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) \ + do { \ + (void)(ctx); \ + (void)(fd); \ + } while (false) +#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \ + do { \ + (void)(ctx); \ + (void)(fd); \ + (void)(newfd); \ + } while (false) +#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \ + do { \ + (void)(ctx); \ + (void)(name); \ + } while (false) +#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \ + do { \ + (void)(ctx); \ + (void)(thread); \ + (void)(name); \ + } while (false) +#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) +#define COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m) \ + do { \ + (void)(ctx); \ + (void)(m); \ + } while (false) +#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) \ + do { \ + (void)(ctx); \ + (void)(m); \ + } while (false) +#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) \ + do { \ + (void)(ctx); \ + (void)(m); \ + } while (false) +#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) \ + do { \ + (void)(ctx); \ + (void)(msg); \ + } while (false) +#define COMMON_INTERCEPTOR_USER_CALLBACK_START() \ + do { \ + } while (false) +#define COMMON_INTERCEPTOR_USER_CALLBACK_END() \ + do { \ + } while (false) + +#include "sanitizer_common/sanitizer_common_interceptors.inc" + +//===----------------------------------------------------------------------===// +// Syscall interception +//===----------------------------------------------------------------------===// + +// We want the caller's PC b/c unlike the other function interceptors these +// are separate pre and post functions called around the app's syscall(). + +#define COMMON_SYSCALL_PRE_READ_RANGE(ptr, size) \ + processRangeAccess(GET_CALLER_PC(), (uptr)ptr, size, false) + +#define COMMON_SYSCALL_PRE_WRITE_RANGE(ptr, size) \ + do { \ + (void)(ptr); \ + (void)(size); \ + } while (false) + +#define COMMON_SYSCALL_POST_READ_RANGE(ptr, size) \ + do { \ + (void)(ptr); \ + (void)(size); \ + } while (false) + +// The actual amount written is in post, not pre. +#define COMMON_SYSCALL_POST_WRITE_RANGE(ptr, size) \ + processRangeAccess(GET_CALLER_PC(), (uptr)ptr, size, true) + +#define COMMON_SYSCALL_ACQUIRE(addr) \ + do { \ + (void)(addr); \ + } while (false) +#define COMMON_SYSCALL_RELEASE(addr) \ + do { \ + (void)(addr); \ + } while (false) +#define COMMON_SYSCALL_FD_CLOSE(fd) \ + do { \ + (void)(fd); \ + } while (false) +#define COMMON_SYSCALL_FD_ACQUIRE(fd) \ + do { \ + (void)(fd); \ + } while (false) +#define COMMON_SYSCALL_FD_RELEASE(fd) \ + do { \ + (void)(fd); \ + } while (false) +#define COMMON_SYSCALL_PRE_FORK() \ + do { \ + } while (false) +#define COMMON_SYSCALL_POST_FORK(res) \ + do { \ + (void)(res); \ + } while (false) + +#include "sanitizer_common/sanitizer_common_syscalls.inc" + +//===----------------------------------------------------------------------===// +// Custom interceptors +//===----------------------------------------------------------------------===// + +// TODO(bruening): move more of these to the common interception pool as they +// are shared with tsan and asan. +// While our other files match LLVM style, here we match sanitizer style as we +// expect to move these to the common pool. + +INTERCEPTOR(char *, strcpy, char *dst, const char *src) { // NOLINT + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, strcpy, dst, src); + uptr srclen = internal_strlen(src); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, srclen + 1); + COMMON_INTERCEPTOR_READ_RANGE(ctx, src, srclen + 1); + return REAL(strcpy)(dst, src); // NOLINT +} + +INTERCEPTOR(char *, strncpy, char *dst, char *src, uptr n) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, strncpy, dst, src, n); + uptr srclen = internal_strnlen(src, n); + uptr copied_size = srclen + 1 > n ? n : srclen + 1; + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, copied_size); + COMMON_INTERCEPTOR_READ_RANGE(ctx, src, copied_size); + return REAL(strncpy)(dst, src, n); +} + +INTERCEPTOR(int, open, const char *name, int flags, int mode) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, open, name, flags, mode); + COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0); + return REAL(open)(name, flags, mode); +} + +#if SANITIZER_LINUX +INTERCEPTOR(int, open64, const char *name, int flags, int mode) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, open64, name, flags, mode); + COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0); + return REAL(open64)(name, flags, mode); +} +#define ESAN_MAYBE_INTERCEPT_OPEN64 INTERCEPT_FUNCTION(open64) +#else +#define ESAN_MAYBE_INTERCEPT_OPEN64 +#endif + +INTERCEPTOR(int, creat, const char *name, int mode) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, creat, name, mode); + COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0); + return REAL(creat)(name, mode); +} + +#if SANITIZER_LINUX +INTERCEPTOR(int, creat64, const char *name, int mode) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, creat64, name, mode); + COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0); + return REAL(creat64)(name, mode); +} +#define ESAN_MAYBE_INTERCEPT_CREAT64 INTERCEPT_FUNCTION(creat64) +#else +#define ESAN_MAYBE_INTERCEPT_CREAT64 +#endif + +INTERCEPTOR(int, unlink, char *path) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, unlink, path); + COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0); + return REAL(unlink)(path); +} + +INTERCEPTOR(uptr, fread, void *ptr, uptr size, uptr nmemb, void *f) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, fread, ptr, size, nmemb, f); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size * nmemb); + return REAL(fread)(ptr, size, nmemb, f); +} + +INTERCEPTOR(uptr, fwrite, const void *p, uptr size, uptr nmemb, void *f) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, fwrite, p, size, nmemb, f); + COMMON_INTERCEPTOR_READ_RANGE(ctx, p, size * nmemb); + return REAL(fwrite)(p, size, nmemb, f); +} + +INTERCEPTOR(int, puts, const char *s) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, puts, s); + COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s)); + return REAL(puts)(s); +} + +INTERCEPTOR(int, rmdir, char *path) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, rmdir, path); + COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0); + return REAL(rmdir)(path); +} + +//===----------------------------------------------------------------------===// +// Shadow-related interceptors +//===----------------------------------------------------------------------===// + +// These are candidates for sharing with all sanitizers if shadow memory +// support is also standardized. + +INTERCEPTOR(void *, mmap, void *addr, SIZE_T sz, int prot, int flags, + int fd, OFF_T off) { + if (UNLIKELY(REAL(mmap) == nullptr)) { + // With esan init during interceptor init and a static libc preventing + // our early-calloc from triggering, we can end up here before our + // REAL pointer is set up. + return (void *)internal_mmap(addr, sz, prot, flags, fd, off); + } + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, mmap, addr, sz, prot, flags, fd, off); + if (!fixMmapAddr(&addr, sz, flags)) + return (void *)-1; + void *result = REAL(mmap)(addr, sz, prot, flags, fd, off); + return (void *)checkMmapResult((uptr)result, sz); +} + +#if SANITIZER_LINUX +INTERCEPTOR(void *, mmap64, void *addr, SIZE_T sz, int prot, int flags, + int fd, OFF64_T off) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, mmap64, addr, sz, prot, flags, fd, off); + if (!fixMmapAddr(&addr, sz, flags)) + return (void *)-1; + void *result = REAL(mmap64)(addr, sz, prot, flags, fd, off); + return (void *)checkMmapResult((uptr)result, sz); +} +#define ESAN_MAYBE_INTERCEPT_MMAP64 INTERCEPT_FUNCTION(mmap64) +#else +#define ESAN_MAYBE_INTERCEPT_MMAP64 +#endif + +//===----------------------------------------------------------------------===// +// Signal-related interceptors +//===----------------------------------------------------------------------===// + +#if SANITIZER_LINUX +typedef void (*signal_handler_t)(int); +INTERCEPTOR(signal_handler_t, signal, int signum, signal_handler_t handler) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, signal, signum, handler); + signal_handler_t result; + if (!processSignal(signum, handler, &result)) + return result; + else + return REAL(signal)(signum, handler); +} +#define ESAN_MAYBE_INTERCEPT_SIGNAL INTERCEPT_FUNCTION(signal) +#else +#error Platform not supported +#define ESAN_MAYBE_INTERCEPT_SIGNAL +#endif + +#if SANITIZER_LINUX +DECLARE_REAL(int, sigaction, int signum, const struct sigaction *act, + struct sigaction *oldact) +INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, + struct sigaction *oldact) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, sigaction, signum, act, oldact); + if (!processSigaction(signum, act, oldact)) + return 0; + else + return REAL(sigaction)(signum, act, oldact); +} + +// This is required to properly use internal_sigaction. +namespace __sanitizer { +int real_sigaction(int signum, const void *act, void *oldact) { + if (REAL(sigaction) == nullptr) { + // With an instrumented allocator, this is called during interceptor init + // and we need a raw syscall solution. + return internal_sigaction_syscall(signum, act, oldact); + } + return REAL(sigaction)(signum, (const struct sigaction *)act, + (struct sigaction *)oldact); +} +} // namespace __sanitizer + +#define ESAN_MAYBE_INTERCEPT_SIGACTION INTERCEPT_FUNCTION(sigaction) +#else +#error Platform not supported +#define ESAN_MAYBE_INTERCEPT_SIGACTION +#endif + +#if SANITIZER_LINUX +INTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set, + __sanitizer_sigset_t *oldset) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, sigprocmask, how, set, oldset); + int res = 0; + if (processSigprocmask(how, set, oldset)) + res = REAL(sigprocmask)(how, set, oldset); + if (!res && oldset) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset)); + return res; +} +#define ESAN_MAYBE_INTERCEPT_SIGPROCMASK INTERCEPT_FUNCTION(sigprocmask) +#else +#define ESAN_MAYBE_INTERCEPT_SIGPROCMASK +#endif + +#if !SANITIZER_WINDOWS +INTERCEPTOR(int, pthread_sigmask, int how, __sanitizer_sigset_t *set, + __sanitizer_sigset_t *oldset) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, pthread_sigmask, how, set, oldset); + int res = 0; + if (processSigprocmask(how, set, oldset)) + res = REAL(sigprocmask)(how, set, oldset); + if (!res && oldset) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset)); + return res; +} +#define ESAN_MAYBE_INTERCEPT_PTHREAD_SIGMASK INTERCEPT_FUNCTION(pthread_sigmask) +#else +#define ESAN_MAYBE_INTERCEPT_PTHREAD_SIGMASK +#endif + +//===----------------------------------------------------------------------===// +// Malloc interceptors +//===----------------------------------------------------------------------===// + +static char early_alloc_buf[128]; +static bool used_early_alloc_buf; + +static void *handleEarlyAlloc(uptr size) { + // If esan is initialized during an interceptor (which happens with some + // tcmalloc implementations that call pthread_mutex_lock), the call from + // dlsym to calloc will deadlock. There is only one such calloc (dlsym + // allocates a single pthread key), so we work around it by using a + // static buffer for the calloc request. The loader currently needs + // 32 bytes but we size at 128 to allow for future changes. + // This solution will also allow us to deliberately intercept malloc & family + // in the future (to perform tool actions on each allocation, without + // replacing the allocator), as it also solves the problem of intercepting + // calloc when it will itself be called before its REAL pointer is + // initialized. + CHECK(!used_early_alloc_buf && size < sizeof(early_alloc_buf)); + // We do not handle multiple threads here. This only happens at process init + // time, and while it's possible for a shared library to create early threads + // that race here, we consider that to be a corner case extreme enough that + // it's not worth the effort to handle. + used_early_alloc_buf = true; + return (void *)early_alloc_buf; +} + +INTERCEPTOR(void*, calloc, uptr size, uptr n) { + if (EsanDuringInit && REAL(calloc) == nullptr) + return handleEarlyAlloc(size * n); + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, calloc, size, n); + void *res = REAL(calloc)(size, n); + // The memory is zeroed and thus is all written. + COMMON_INTERCEPTOR_WRITE_RANGE(nullptr, (uptr)res, size * n); + return res; +} + +INTERCEPTOR(void, free, void *p) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, free, p); + if (p == (void *)early_alloc_buf) { + // We expect just a singleton use but we clear this for cleanliness. + used_early_alloc_buf = false; + return; + } + REAL(free)(p); +} + +namespace __esan { + +void initializeInterceptors() { + InitializeCommonInterceptors(); + + INTERCEPT_FUNCTION(strcpy); // NOLINT + INTERCEPT_FUNCTION(strncpy); + + INTERCEPT_FUNCTION(open); + ESAN_MAYBE_INTERCEPT_OPEN64; + INTERCEPT_FUNCTION(creat); + ESAN_MAYBE_INTERCEPT_CREAT64; + INTERCEPT_FUNCTION(unlink); + INTERCEPT_FUNCTION(fread); + INTERCEPT_FUNCTION(fwrite); + INTERCEPT_FUNCTION(puts); + INTERCEPT_FUNCTION(rmdir); + + INTERCEPT_FUNCTION(mmap); + ESAN_MAYBE_INTERCEPT_MMAP64; + + ESAN_MAYBE_INTERCEPT_SIGNAL; + ESAN_MAYBE_INTERCEPT_SIGACTION; + ESAN_MAYBE_INTERCEPT_SIGPROCMASK; + ESAN_MAYBE_INTERCEPT_PTHREAD_SIGMASK; + + INTERCEPT_FUNCTION(calloc); + INTERCEPT_FUNCTION(free); + + // TODO(bruening): intercept routines that other sanitizers intercept that + // are not in the common pool or here yet, ideally by adding to the common + // pool. Examples include wcslen and bcopy. + + // TODO(bruening): there are many more libc routines that read or write data + // structures that no sanitizer is intercepting: sigaction, strtol, etc. +} + +} // namespace __esan Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_interceptors.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_interface.cpp =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/esan_interface.cpp (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/esan_interface.cpp (revision 305364) @@ -0,0 +1,122 @@ +//===-- esan_interface.cpp ------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +//===----------------------------------------------------------------------===// + +#include "esan_interface_internal.h" +#include "esan.h" +#include "sanitizer_common/sanitizer_internal_defs.h" + +using namespace __esan; // NOLINT + +void __esan_init(ToolType Tool, void *Ptr) { + if (Tool != __esan_which_tool) { + Printf("ERROR: tool mismatch: %d vs %d\n", Tool, __esan_which_tool); + Die(); + } + initializeLibrary(Tool); + processCompilationUnitInit(Ptr); +} + +void __esan_exit(void *Ptr) { + processCompilationUnitExit(Ptr); +} + +void __esan_aligned_load1(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 1, false); +} + +void __esan_aligned_load2(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 2, false); +} + +void __esan_aligned_load4(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 4, false); +} + +void __esan_aligned_load8(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 8, false); +} + +void __esan_aligned_load16(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 16, false); +} + +void __esan_aligned_store1(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 1, true); +} + +void __esan_aligned_store2(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 2, true); +} + +void __esan_aligned_store4(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 4, true); +} + +void __esan_aligned_store8(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 8, true); +} + +void __esan_aligned_store16(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 16, true); +} + +void __esan_unaligned_load2(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 2, false); +} + +void __esan_unaligned_load4(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 4, false); +} + +void __esan_unaligned_load8(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 8, false); +} + +void __esan_unaligned_load16(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 16, false); +} + +void __esan_unaligned_store2(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 2, true); +} + +void __esan_unaligned_store4(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 4, true); +} + +void __esan_unaligned_store8(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 8, true); +} + +void __esan_unaligned_store16(void *Addr) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, 16, true); +} + +void __esan_unaligned_loadN(void *Addr, uptr Size) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, Size, false); +} + +void __esan_unaligned_storeN(void *Addr, uptr Size) { + processRangeAccess(GET_CALLER_PC(), (uptr)Addr, Size, true); +} + +// Public interface: +extern "C" { +SANITIZER_INTERFACE_ATTRIBUTE void __esan_report() { + reportResults(); +} + +SANITIZER_INTERFACE_ATTRIBUTE unsigned int __esan_get_sample_count() { + return getSampleCount(); +} +} // extern "C" Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_interface.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_interface_internal.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/esan_interface_internal.h (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/esan_interface_internal.h (revision 305364) @@ -0,0 +1,80 @@ +//===-- esan_interface_internal.h -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +// Calls to the functions declared in this header will be inserted by +// the instrumentation module. +//===----------------------------------------------------------------------===// + +#ifndef ESAN_INTERFACE_INTERNAL_H +#define ESAN_INTERFACE_INTERNAL_H + +#include + +// This header should NOT include any other headers. +// All functions in this header are extern "C" and start with __esan_. + +extern "C" { + +// This should be kept consistent with LLVM's EfficiencySanitizerOptions. +// The value is passed as a 32-bit integer by the compiler. +typedef enum Type : u32 { + ESAN_None = 0, + ESAN_CacheFrag, + ESAN_WorkingSet, + ESAN_Max, +} ToolType; + +// To handle interceptors that invoke instrumented code prior to +// __esan_init() being called, the instrumentation module creates this +// global variable specifying the tool. +extern ToolType __esan_which_tool; + +// This function should be called at the very beginning of the process, +// before any instrumented code is executed and before any call to malloc. +SANITIZER_INTERFACE_ATTRIBUTE void __esan_init(ToolType Tool, void *Ptr); +SANITIZER_INTERFACE_ATTRIBUTE void __esan_exit(void *Ptr); + +// The instrumentation module will insert a call to one of these routines prior +// to each load and store instruction for which we do not have "fastpath" +// inlined instrumentation. These calls constitute the "slowpath" for our +// tools. We have separate routines for each type of memory access to enable +// targeted optimization. +SANITIZER_INTERFACE_ATTRIBUTE void __esan_aligned_load1(void *Addr); +SANITIZER_INTERFACE_ATTRIBUTE void __esan_aligned_load2(void *Addr); +SANITIZER_INTERFACE_ATTRIBUTE void __esan_aligned_load4(void *Addr); +SANITIZER_INTERFACE_ATTRIBUTE void __esan_aligned_load8(void *Addr); +SANITIZER_INTERFACE_ATTRIBUTE void __esan_aligned_load16(void *Addr); + +SANITIZER_INTERFACE_ATTRIBUTE void __esan_aligned_store1(void *Addr); +SANITIZER_INTERFACE_ATTRIBUTE void __esan_aligned_store2(void *Addr); +SANITIZER_INTERFACE_ATTRIBUTE void __esan_aligned_store4(void *Addr); +SANITIZER_INTERFACE_ATTRIBUTE void __esan_aligned_store8(void *Addr); +SANITIZER_INTERFACE_ATTRIBUTE void __esan_aligned_store16(void *Addr); + +SANITIZER_INTERFACE_ATTRIBUTE void __esan_unaligned_load2(void *Addr); +SANITIZER_INTERFACE_ATTRIBUTE void __esan_unaligned_load4(void *Addr); +SANITIZER_INTERFACE_ATTRIBUTE void __esan_unaligned_load8(void *Addr); +SANITIZER_INTERFACE_ATTRIBUTE void __esan_unaligned_load16(void *Addr); + +SANITIZER_INTERFACE_ATTRIBUTE void __esan_unaligned_store2(void *Addr); +SANITIZER_INTERFACE_ATTRIBUTE void __esan_unaligned_store4(void *Addr); +SANITIZER_INTERFACE_ATTRIBUTE void __esan_unaligned_store8(void *Addr); +SANITIZER_INTERFACE_ATTRIBUTE void __esan_unaligned_store16(void *Addr); + +// These cover unusually-sized accesses. +SANITIZER_INTERFACE_ATTRIBUTE +void __esan_unaligned_loadN(void *Addr, uptr Size); +SANITIZER_INTERFACE_ATTRIBUTE +void __esan_unaligned_storeN(void *Addr, uptr Size); + +} // extern "C" + +#endif // ESAN_INTERFACE_INTERNAL_H Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_interface_internal.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_linux.cpp =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/esan_linux.cpp (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/esan_linux.cpp (revision 305364) @@ -0,0 +1,83 @@ +//===-- esan.cpp ----------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +// Linux-specific code for the Esan run-time. +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" +#if SANITIZER_FREEBSD || SANITIZER_LINUX + +#include "esan.h" +#include "esan_shadow.h" +#include "interception/interception.h" +#include "sanitizer_common/sanitizer_common.h" +#include +#include + +namespace __esan { + +void verifyAddressSpace() { +#if SANITIZER_LINUX && defined(__x86_64__) + // The kernel determines its mmap base from the stack size limit. + // Our Linux 64-bit shadow mapping assumes the stack limit is less than a + // terabyte, which keeps the mmap region above 0x7e00'. + uptr StackLimit = GetStackSizeLimitInBytes(); + if (StackSizeIsUnlimited() || StackLimit > MaxStackSize) { + VReport(1, "The stack size limit is beyond the maximum supported.\n" + "Re-execing with a stack size below 1TB.\n"); + SetStackSizeLimitInBytes(MaxStackSize); + ReExec(); + } +#endif +} + +static bool liesWithinSingleAppRegion(uptr Start, SIZE_T Size) { + uptr AppStart, AppEnd; + for (int i = 0; getAppRegion(i, &AppStart, &AppEnd); ++i) { + if (Start >= AppStart && Start + Size - 1 <= AppEnd) { + return true; + } + } + return false; +} + +bool fixMmapAddr(void **Addr, SIZE_T Size, int Flags) { + if (*Addr) { + if (!liesWithinSingleAppRegion((uptr)*Addr, Size)) { + VPrintf(1, "mmap conflict: [%p-%p) is not in an app region\n", + *Addr, (uptr)*Addr + Size); + if (Flags & MAP_FIXED) { + errno = EINVAL; + return false; + } else { + *Addr = 0; + } + } + } + return true; +} + +uptr checkMmapResult(uptr Addr, SIZE_T Size) { + if ((void *)Addr == MAP_FAILED) + return Addr; + if (!liesWithinSingleAppRegion(Addr, Size)) { + // FIXME: attempt to dynamically add this as an app region if it + // fits our shadow criteria. + // We could also try to remap somewhere else. + Printf("ERROR: unsupported mapping at [%p-%p)\n", Addr, Addr+Size); + Die(); + } + return Addr; +} + +} // namespace __esan + +#endif // SANITIZER_FREEBSD || SANITIZER_LINUX Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_linux.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_shadow.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/esan_shadow.h (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/esan_shadow.h (revision 305364) @@ -0,0 +1,203 @@ +//===-- esan_shadow.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +// Shadow memory mappings for the esan run-time. +//===----------------------------------------------------------------------===// + +#ifndef ESAN_SHADOW_H +#define ESAN_SHADOW_H + +#include + +#if SANITIZER_WORDSIZE != 64 +#error Only 64-bit is supported +#endif + +namespace __esan { + +#if SANITIZER_LINUX && defined(__x86_64__) +// Linux x86_64 +// +// Application memory falls into these 5 regions (ignoring the corner case +// of PIE with a non-zero PT_LOAD base): +// +// [0x00000000'00000000, 0x00000100'00000000) non-PIE + heap +// [0x00005500'00000000, 0x00005700'00000000) PIE +// [0x00007e00'00000000, 0x00007fff'ff600000) libraries + stack, part 1 +// [0x00007fff'ff601000, 0x00008000'00000000) libraries + stack, part 2 +// [0xffffffff'ff600000, 0xffffffff'ff601000) vsyscall +// +// Although we can ignore the vsyscall for the most part as there are few data +// references there (other sanitizers ignore it), we enforce a gap inside the +// library region to distinguish the vsyscall's shadow, considering this gap to +// be an invalid app region. +// We disallow application memory outside of those 5 regions. +// Our regions assume that the stack rlimit is less than a terabyte (otherwise +// the Linux kernel's default mmap region drops below 0x7e00'), which we enforce +// at init time (we can support larger and unlimited sizes for shadow +// scaledowns, but it is difficult for 1:1 mappings). +// +// Our shadow memory is scaled from a 1:1 mapping and supports a scale +// specified at library initialization time that can be any power-of-2 +// scaledown (1x, 2x, 4x, 8x, 16x, etc.). +// +// We model our shadow memory after Umbra, a library used by the Dr. Memory +// tool: https://github.com/DynamoRIO/drmemory/blob/master/umbra/umbra_x64.c. +// We use Umbra's scheme as it was designed to support different +// offsets, it supports two different shadow mappings (which we may want to +// use for future tools), and it ensures that the shadow of a shadow will +// not overlap either shadow memory or application memory. +// +// This formula translates from application memory to shadow memory: +// +// shadow(app) = ((app & 0x00000fff'ffffffff) + offset) >> scale +// +// Where the offset for 1:1 is 0x00001300'00000000. For other scales, the +// offset is shifted left by the scale, except for scales of 1 and 2 where +// it must be tweaked in order to pass the double-shadow test +// (see the "shadow(shadow)" comments below): +// scale == 0: 0x00001300'000000000 +// scale == 1: 0x00002200'000000000 +// scale == 2: 0x00004400'000000000 +// scale >= 3: (0x00001300'000000000 << scale) +// +// Do not pass in the open-ended end value to the formula as it will fail. +// +// The resulting shadow memory regions for a 0 scaling are: +// +// [0x00001300'00000000, 0x00001400'00000000) +// [0x00001800'00000000, 0x00001a00'00000000) +// [0x00002100'00000000, 0x000022ff'ff600000) +// [0x000022ff'ff601000, 0x00002300'00000000) +// [0x000022ff'ff600000, 0x000022ff'ff601000] +// +// We also want to ensure that a wild access by the application into the shadow +// regions will not corrupt our own shadow memory. shadow(shadow) ends up +// disjoint from shadow(app): +// +// [0x00001600'00000000, 0x00001700'00000000) +// [0x00001b00'00000000, 0x00001d00'00000000) +// [0x00001400'00000000, 0x000015ff'ff600000] +// [0x000015ff'ff601000, 0x00001600'00000000] +// [0x000015ff'ff600000, 0x000015ff'ff601000] + +struct ApplicationRegion { + uptr Start; + uptr End; + bool ShadowMergedWithPrev; +}; + +static const struct ApplicationRegion AppRegions[] = { + {0x0000000000000000ull, 0x0000010000000000u, false}, + {0x0000550000000000u, 0x0000570000000000u, false}, + // We make one shadow mapping to hold the shadow regions for all 3 of these + // app regions, as the mappings interleave, and the gap between the 3rd and + // 4th scales down below a page. + {0x00007e0000000000u, 0x00007fffff600000u, false}, + {0x00007fffff601000u, 0x0000800000000000u, true}, + {0xffffffffff600000u, 0xffffffffff601000u, true}, +}; +static const u32 NumAppRegions = sizeof(AppRegions)/sizeof(AppRegions[0]); + +// See the comment above: we do not currently support a stack size rlimit +// equal to or larger than 1TB. +static const uptr MaxStackSize = (1ULL << 40) - 4096; + +class ShadowMapping { +public: + static const uptr Mask = 0x00000fffffffffffu; + // The scale and offset vary by tool. + uptr Scale; + uptr Offset; + void initialize(uptr ShadowScale) { + static const uptr OffsetArray[3] = { + 0x0000130000000000u, + 0x0000220000000000u, + 0x0000440000000000u, + }; + Scale = ShadowScale; + if (Scale <= 2) + Offset = OffsetArray[Scale]; + else + Offset = OffsetArray[0] << Scale; + } +}; +extern ShadowMapping Mapping; +#else +// We'll want to use templatized functions over the ShadowMapping once +// we support more platforms. +#error Platform not supported +#endif + +static inline bool getAppRegion(u32 i, uptr *Start, uptr *End) { + if (i >= NumAppRegions) + return false; + *Start = AppRegions[i].Start; + *End = AppRegions[i].End; + return true; +} + +ALWAYS_INLINE +bool isAppMem(uptr Mem) { + for (u32 i = 0; i < NumAppRegions; ++i) { + if (Mem >= AppRegions[i].Start && Mem < AppRegions[i].End) + return true; + } + return false; +} + +ALWAYS_INLINE +uptr appToShadow(uptr App) { + return (((App & ShadowMapping::Mask) + Mapping.Offset) >> Mapping.Scale); +} + +static inline bool getShadowRegion(u32 i, uptr *Start, uptr *End) { + if (i >= NumAppRegions) + return false; + u32 UnmergedShadowCount = 0; + u32 AppIdx; + for (AppIdx = 0; AppIdx < NumAppRegions; ++AppIdx) { + if (!AppRegions[AppIdx].ShadowMergedWithPrev) { + if (UnmergedShadowCount == i) + break; + UnmergedShadowCount++; + } + } + if (AppIdx >= NumAppRegions || UnmergedShadowCount != i) + return false; + *Start = appToShadow(AppRegions[AppIdx].Start); + // The formula fails for the end itself. + *End = appToShadow(AppRegions[AppIdx].End - 1) + 1; + // Merge with adjacent shadow regions: + for (++AppIdx; AppIdx < NumAppRegions; ++AppIdx) { + if (!AppRegions[AppIdx].ShadowMergedWithPrev) + break; + *Start = Min(*Start, appToShadow(AppRegions[AppIdx].Start)); + *End = Max(*End, appToShadow(AppRegions[AppIdx].End - 1) + 1); + } + return true; +} + +ALWAYS_INLINE +bool isShadowMem(uptr Mem) { + // We assume this is not used on any critical performance path and so there's + // no need to hardcode the mapping results. + for (uptr i = 0; i < NumAppRegions; ++i) { + if (Mem >= appToShadow(AppRegions[i].Start) && + Mem < appToShadow(AppRegions[i].End - 1) + 1) + return true; + } + return false; +} + +} // namespace __esan + +#endif /* ESAN_SHADOW_H */ Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_shadow.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_sideline.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/esan_sideline.h (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/esan_sideline.h (revision 305364) @@ -0,0 +1,61 @@ +//===-- esan_sideline.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +// Esan sideline thread support. +//===----------------------------------------------------------------------===// + +#ifndef ESAN_SIDELINE_H +#define ESAN_SIDELINE_H + +#include "sanitizer_common/sanitizer_atomic.h" +#include "sanitizer_common/sanitizer_internal_defs.h" + +namespace __esan { + +typedef void (*SidelineFunc)(void *Arg); + +// Currently only one sideline thread is supported. +// It calls the SidelineFunc passed to launchThread once on each sample at the +// given frequency in real time (i.e., wall clock time). +class SidelineThread { +public: + // We cannot initialize any fields in the constructor as it will be called + // *after* launchThread for a static instance, as esan.module_ctor is called + // before static initializers. + SidelineThread() {} + ~SidelineThread() {} + + // To simplify declaration in sanitizer code where we want to avoid + // heap allocations, the constructor and destructor do nothing and + // launchThread and joinThread do the real work. + // They should each be called just once. + bool launchThread(SidelineFunc takeSample, void *Arg, u32 FreqMilliSec); + bool joinThread(); + + // Must be called from the sideline thread itself. + bool adjustTimer(u32 FreqMilliSec); + +private: + static int runSideline(void *Arg); + static void registerSignal(int SigNum); + static void handleSidelineSignal(int SigNum, void *SigInfo, void *Ctx); + + char *Stack; + SidelineFunc sampleFunc; + void *FuncArg; + u32 Freq; + uptr SidelineId; + atomic_uintptr_t SidelineExit; +}; + +} // namespace __esan + +#endif // ESAN_SIDELINE_H Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_sideline.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_sideline_linux.cpp =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/esan_sideline_linux.cpp (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/esan_sideline_linux.cpp (revision 305364) @@ -0,0 +1,177 @@ +//===-- esan_sideline_linux.cpp ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +// Support for a separate or "sideline" tool thread on Linux. +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" +#if SANITIZER_LINUX + +#include "esan_sideline.h" +#include "sanitizer_common/sanitizer_atomic.h" +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_linux.h" +#include +#include +#include +#include +#include +#include +#include + +namespace __esan { + +static const int SigAltStackSize = 4*1024; +static const int SidelineStackSize = 4*1024; +static const uptr SidelineIdUninitialized = 1; + +// FIXME: we'll need some kind of TLS (can we trust that a pthread key will +// work in our non-POSIX thread?) to access our data in our signal handler +// with multiple sideline threads. For now we assume there is only one +// sideline thread and we use a dirty solution of a global var. +static SidelineThread *TheThread; + +// We aren't passing SA_NODEFER so the same signal is blocked while here. +void SidelineThread::handleSidelineSignal(int SigNum, void *SigInfo, + void *Ctx) { + VPrintf(3, "Sideline signal %d\n", SigNum); + CHECK_EQ(SigNum, SIGALRM); + // See above about needing TLS to avoid this global var. + SidelineThread *Thread = TheThread; + if (atomic_load(&Thread->SidelineExit, memory_order_relaxed) != 0) + return; + Thread->sampleFunc(Thread->FuncArg); +} + +void SidelineThread::registerSignal(int SigNum) { + __sanitizer_sigaction SigAct; + internal_memset(&SigAct, 0, sizeof(SigAct)); + SigAct.sigaction = handleSidelineSignal; + // We do not pass SA_NODEFER as we want to block the same signal. + SigAct.sa_flags = SA_ONSTACK | SA_SIGINFO; + int Res = internal_sigaction(SigNum, &SigAct, nullptr); + CHECK_EQ(Res, 0); +} + +int SidelineThread::runSideline(void *Arg) { + VPrintf(1, "Sideline thread starting\n"); + SidelineThread *Thread = static_cast(Arg); + + // If the parent dies, we want to exit also. + internal_prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); + + // Set up a signal handler on an alternate stack for safety. + InternalScopedBuffer StackMap(SigAltStackSize); + struct sigaltstack SigAltStack; + SigAltStack.ss_sp = StackMap.data(); + SigAltStack.ss_size = SigAltStackSize; + SigAltStack.ss_flags = 0; + internal_sigaltstack(&SigAltStack, nullptr); + + // We inherit the signal mask from the app thread. In case + // we weren't created at init time, we ensure the mask is empty. + __sanitizer_sigset_t SigSet; + internal_sigfillset(&SigSet); + int Res = internal_sigprocmask(SIG_UNBLOCK, &SigSet, nullptr); + CHECK_EQ(Res, 0); + + registerSignal(SIGALRM); + + bool TimerSuccess = Thread->adjustTimer(Thread->Freq); + CHECK(TimerSuccess); + + // We loop, doing nothing but handling itimer signals. + while (atomic_load(&TheThread->SidelineExit, memory_order_relaxed) == 0) + sched_yield(); + + if (!Thread->adjustTimer(0)) + VPrintf(1, "Failed to disable timer\n"); + + VPrintf(1, "Sideline thread exiting\n"); + return 0; +} + +bool SidelineThread::launchThread(SidelineFunc takeSample, void *Arg, + u32 FreqMilliSec) { + // This can only be called once. However, we can't clear a field in + // the constructor and check for that here as the constructor for + // a static instance is called *after* our module_ctor and thus after + // this routine! Thus we rely on the TheThread check below. + CHECK(TheThread == nullptr); // Only one sideline thread is supported. + TheThread = this; + sampleFunc = takeSample; + FuncArg = Arg; + Freq = FreqMilliSec; + atomic_store(&SidelineExit, 0, memory_order_relaxed); + + // We do without a guard page. + Stack = static_cast(MmapOrDie(SidelineStackSize, "SidelineStack")); + // We need to handle the return value from internal_clone() not having been + // assigned yet (for our CHECK in adjustTimer()) so we ensure this has a + // sentinel value. + SidelineId = SidelineIdUninitialized; + // By omitting CLONE_THREAD, the child is in its own thread group and will not + // receive any of the application's signals. + SidelineId = internal_clone( + runSideline, Stack + SidelineStackSize, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_UNTRACED, + this, nullptr /* parent_tidptr */, + nullptr /* newtls */, nullptr /* child_tidptr */); + int ErrCode; + if (internal_iserror(SidelineId, &ErrCode)) { + Printf("FATAL: EfficiencySanitizer failed to spawn a thread (code %d).\n", + ErrCode); + Die(); + return false; // Not reached. + } + return true; +} + +bool SidelineThread::joinThread() { + VPrintf(1, "Joining sideline thread\n"); + bool Res = true; + atomic_store(&SidelineExit, 1, memory_order_relaxed); + while (true) { + uptr Status = internal_waitpid(SidelineId, nullptr, __WALL); + int ErrCode; + if (!internal_iserror(Status, &ErrCode)) + break; + if (ErrCode == EINTR) + continue; + VPrintf(1, "Failed to join sideline thread (errno %d)\n", ErrCode); + Res = false; + break; + } + UnmapOrDie(Stack, SidelineStackSize); + return Res; +} + +// Must be called from the sideline thread itself. +bool SidelineThread::adjustTimer(u32 FreqMilliSec) { + // The return value of internal_clone() may not have been assigned yet: + CHECK(internal_getpid() == SidelineId || + SidelineId == SidelineIdUninitialized); + Freq = FreqMilliSec; + struct itimerval TimerVal; + TimerVal.it_interval.tv_sec = (time_t) Freq / 1000; + TimerVal.it_interval.tv_usec = (time_t) (Freq % 1000) * 1000; + TimerVal.it_value.tv_sec = (time_t) Freq / 1000; + TimerVal.it_value.tv_usec = (time_t) (Freq % 1000) * 1000; + // As we're in a different thread group, we cannot use either + // ITIMER_PROF or ITIMER_VIRTUAL without taking up scheduled + // time ourselves: thus we must use real time. + int Res = setitimer(ITIMER_REAL, &TimerVal, nullptr); + return (Res == 0); +} + +} // namespace __esan + +#endif // SANITIZER_LINUX Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/esan_sideline_linux.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/esan/working_set.cpp =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/working_set.cpp (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/working_set.cpp (revision 305364) @@ -0,0 +1,279 @@ +//===-- working_set.cpp ---------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +// This file contains working-set-specific code. +//===----------------------------------------------------------------------===// + +#include "working_set.h" +#include "esan.h" +#include "esan_circular_buffer.h" +#include "esan_flags.h" +#include "esan_shadow.h" +#include "esan_sideline.h" +#include "sanitizer_common/sanitizer_procmaps.h" + +// We shadow every cache line of app memory with one shadow byte. +// - The highest bit of each shadow byte indicates whether the corresponding +// cache line has ever been accessed. +// - The lowest bit of each shadow byte indicates whether the corresponding +// cache line was accessed since the last sample. +// - The other bits are used for working set snapshots at successively +// lower frequencies, each bit to the left from the lowest bit stepping +// down the frequency by 2 to the power of getFlags()->snapshot_step. +// Thus we have something like this: +// Bit 0: Since last sample +// Bit 1: Since last 2^2 samples +// Bit 2: Since last 2^4 samples +// Bit 3: ... +// Bit 7: Ever accessed. +// We live with races in accessing each shadow byte. +typedef unsigned char byte; + +namespace __esan { + +// Our shadow memory assumes that the line size is 64. +static const u32 CacheLineSize = 64; + +// See the shadow byte layout description above. +static const u32 TotalWorkingSetBitIdx = 7; +// We accumulate to the left until we hit this bit. +// We don't need to accumulate to the final bit as it's set on each ref +// by the compiler instrumentation. +static const u32 MaxAccumBitIdx = 6; +static const u32 CurWorkingSetBitIdx = 0; +static const byte ShadowAccessedVal = + (1 << TotalWorkingSetBitIdx) | (1 << CurWorkingSetBitIdx); + +static SidelineThread Thread; +// If we use real-time-based timer samples this won't overflow in any realistic +// scenario, but if we switch to some other unit (such as memory accesses) we +// may want to consider a 64-bit int. +static u32 SnapshotNum; + +// We store the wset size for each of 8 different sampling frequencies. +static const u32 NumFreq = 8; // One for each bit of our shadow bytes. +// We cannot use static objects as the global destructor is called +// prior to our finalize routine. +// These are each circular buffers, sized up front. +CircularBuffer SizePerFreq[NumFreq]; +// We cannot rely on static initializers (they may run too late) but +// we record the size here for clarity: +u32 CircularBufferSizes[NumFreq] = { + // These are each mmap-ed so our minimum is one page. + 32*1024, + 16*1024, + 8*1024, + 4*1024, + 4*1024, + 4*1024, + 4*1024, + 4*1024, +}; + +void processRangeAccessWorkingSet(uptr PC, uptr Addr, SIZE_T Size, + bool IsWrite) { + if (Size == 0) + return; + SIZE_T I = 0; + uptr LineSize = getFlags()->cache_line_size; + // As Addr+Size could overflow at the top of a 32-bit address space, + // we avoid the simpler formula that rounds the start and end. + SIZE_T NumLines = Size / LineSize + + // Add any extra at the start or end adding on an extra line: + (LineSize - 1 + Addr % LineSize + Size % LineSize) / LineSize; + byte *Shadow = (byte *)appToShadow(Addr); + // Write shadow bytes until we're word-aligned. + while (I < NumLines && (uptr)Shadow % 4 != 0) { + if ((*Shadow & ShadowAccessedVal) != ShadowAccessedVal) + *Shadow |= ShadowAccessedVal; + ++Shadow; + ++I; + } + // Write whole shadow words at a time. + // Using a word-stride loop improves the runtime of a microbenchmark of + // memset calls by 10%. + u32 WordValue = ShadowAccessedVal | ShadowAccessedVal << 8 | + ShadowAccessedVal << 16 | ShadowAccessedVal << 24; + while (I + 4 <= NumLines) { + if ((*(u32*)Shadow & WordValue) != WordValue) + *(u32*)Shadow |= WordValue; + Shadow += 4; + I += 4; + } + // Write any trailing shadow bytes. + while (I < NumLines) { + if ((*Shadow & ShadowAccessedVal) != ShadowAccessedVal) + *Shadow |= ShadowAccessedVal; + ++Shadow; + ++I; + } +} + +// This routine will word-align ShadowStart and ShadowEnd prior to scanning. +// It does *not* clear for BitIdx==TotalWorkingSetBitIdx, as that top bit +// measures the access during the entire execution and should never be cleared. +static u32 countAndClearShadowValues(u32 BitIdx, uptr ShadowStart, + uptr ShadowEnd) { + u32 WorkingSetSize = 0; + u32 ByteValue = 0x1 << BitIdx; + u32 WordValue = ByteValue | ByteValue << 8 | ByteValue << 16 | + ByteValue << 24; + // Get word aligned start. + ShadowStart = RoundDownTo(ShadowStart, sizeof(u32)); + bool Accum = getFlags()->record_snapshots && BitIdx < MaxAccumBitIdx; + // Do not clear the bit that measures access during the entire execution. + bool Clear = BitIdx < TotalWorkingSetBitIdx; + for (u32 *Ptr = (u32 *)ShadowStart; Ptr < (u32 *)ShadowEnd; ++Ptr) { + if ((*Ptr & WordValue) != 0) { + byte *BytePtr = (byte *)Ptr; + for (u32 j = 0; j < sizeof(u32); ++j) { + if (BytePtr[j] & ByteValue) { + ++WorkingSetSize; + if (Accum) { + // Accumulate to the lower-frequency bit to the left. + BytePtr[j] |= (ByteValue << 1); + } + } + } + if (Clear) { + // Clear this bit from every shadow byte. + *Ptr &= ~WordValue; + } + } + } + return WorkingSetSize; +} + +// Scan shadow memory to calculate the number of cache lines being accessed, +// i.e., the number of non-zero bits indexed by BitIdx in each shadow byte. +// We also clear the lowest bits (most recent working set snapshot). +// We do *not* clear for BitIdx==TotalWorkingSetBitIdx, as that top bit +// measures the access during the entire execution and should never be cleared. +static u32 computeWorkingSizeAndReset(u32 BitIdx) { + u32 WorkingSetSize = 0; + MemoryMappingLayout MemIter(true/*cache*/); + uptr Start, End, Prot; + while (MemIter.Next(&Start, &End, nullptr/*offs*/, nullptr/*file*/, + 0/*file size*/, &Prot)) { + VPrintf(4, "%s: considering %p-%p app=%d shadow=%d prot=%u\n", + __FUNCTION__, Start, End, Prot, isAppMem(Start), + isShadowMem(Start)); + if (isShadowMem(Start) && (Prot & MemoryMappingLayout::kProtectionWrite)) { + VPrintf(3, "%s: walking %p-%p\n", __FUNCTION__, Start, End); + WorkingSetSize += countAndClearShadowValues(BitIdx, Start, End); + } + } + return WorkingSetSize; +} + +// This is invoked from a signal handler but in a sideline thread doing nothing +// else so it is a little less fragile than a typical signal handler. +static void takeSample(void *Arg) { + u32 BitIdx = CurWorkingSetBitIdx; + u32 Freq = 1; + ++SnapshotNum; // Simpler to skip 0 whose mod matches everything. + while (BitIdx <= MaxAccumBitIdx && (SnapshotNum % Freq) == 0) { + u32 NumLines = computeWorkingSizeAndReset(BitIdx); + VReport(1, "%s: snapshot #%5d bit %d freq %4d: %8u\n", SanitizerToolName, + SnapshotNum, BitIdx, Freq, NumLines); + SizePerFreq[BitIdx].push_back(NumLines); + Freq = Freq << getFlags()->snapshot_step; + BitIdx++; + } +} + +unsigned int getSampleCountWorkingSet() +{ + return SnapshotNum; +} + +// Initialization that must be done before any instrumented code is executed. +void initializeShadowWorkingSet() { + CHECK(getFlags()->cache_line_size == CacheLineSize); + registerMemoryFaultHandler(); +} + +void initializeWorkingSet() { + if (getFlags()->record_snapshots) { + for (u32 i = 0; i < NumFreq; ++i) + SizePerFreq[i].initialize(CircularBufferSizes[i]); + Thread.launchThread(takeSample, nullptr, getFlags()->sample_freq); + } +} + +static u32 getPeriodForPrinting(u32 MilliSec, const char *&Unit) { + if (MilliSec > 600000) { + Unit = "min"; + return MilliSec / 60000; + } else if (MilliSec > 10000) { + Unit = "sec"; + return MilliSec / 1000; + } else { + Unit = "ms"; + return MilliSec; + } +} + +static u32 getSizeForPrinting(u32 NumOfCachelines, const char *&Unit) { + // We need a constant to avoid software divide support: + static const u32 KilobyteCachelines = (0x1 << 10) / CacheLineSize; + static const u32 MegabyteCachelines = KilobyteCachelines << 10; + + if (NumOfCachelines > 10 * MegabyteCachelines) { + Unit = "MB"; + return NumOfCachelines / MegabyteCachelines; + } else if (NumOfCachelines > 10 * KilobyteCachelines) { + Unit = "KB"; + return NumOfCachelines / KilobyteCachelines; + } else { + Unit = "Bytes"; + return NumOfCachelines * CacheLineSize; + } +} + +void reportWorkingSet() { + const char *Unit; + if (getFlags()->record_snapshots) { + u32 Freq = 1; + Report(" Total number of samples: %u\n", SnapshotNum); + for (u32 i = 0; i < NumFreq; ++i) { + u32 Time = getPeriodForPrinting(getFlags()->sample_freq*Freq, Unit); + Report(" Samples array #%d at period %u %s\n", i, Time, Unit); + // FIXME: report whether we wrapped around and thus whether we + // have data on the whole run or just the last N samples. + for (u32 j = 0; j < SizePerFreq[i].size(); ++j) { + u32 Size = getSizeForPrinting(SizePerFreq[i][j], Unit); + Report("#%4d: %8u %s (%9u cache lines)\n", j, Size, Unit, + SizePerFreq[i][j]); + } + Freq = Freq << getFlags()->snapshot_step; + } + } + + // Get the working set size for the entire execution. + u32 NumOfCachelines = computeWorkingSizeAndReset(TotalWorkingSetBitIdx); + u32 Size = getSizeForPrinting(NumOfCachelines, Unit); + Report(" %s: the total working set size: %u %s (%u cache lines)\n", + SanitizerToolName, Size, Unit, NumOfCachelines); +} + +int finalizeWorkingSet() { + if (getFlags()->record_snapshots) + Thread.joinThread(); + reportWorkingSet(); + if (getFlags()->record_snapshots) { + for (u32 i = 0; i < NumFreq; ++i) + SizePerFreq[i].free(); + } + return 0; +} + +} // namespace __esan Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/working_set.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/esan/working_set.h =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/working_set.h (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/working_set.h (revision 305364) @@ -0,0 +1,40 @@ +//===-- working_set.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +// Header for working-set-specific code. +//===----------------------------------------------------------------------===// + +#ifndef WORKING_SET_H +#define WORKING_SET_H + +#include "interception/interception.h" +#include "sanitizer_common/sanitizer_internal_defs.h" + +namespace __esan { + +void initializeWorkingSet(); +void initializeShadowWorkingSet(); +int finalizeWorkingSet(); +void reportWorkingSet(); +unsigned int getSampleCountWorkingSet(); +void processRangeAccessWorkingSet(uptr PC, uptr Addr, SIZE_T Size, + bool IsWrite); + +// Platform-dependent. +void registerMemoryFaultHandler(); +bool processWorkingSetSignal(int SigNum, void (*Handler)(int), + void (**Result)(int)); +bool processWorkingSetSigaction(int SigNum, const void *Act, void *OldAct); +bool processWorkingSetSigprocmask(int How, void *Set, void *OldSet); + +} // namespace __esan + +#endif // WORKING_SET_H Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/working_set.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/esan/working_set_posix.cpp =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/esan/working_set_posix.cpp (nonexistent) +++ projects/clang390-import/contrib/compiler-rt/lib/esan/working_set_posix.cpp (revision 305364) @@ -0,0 +1,133 @@ +//===-- working_set_posix.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of EfficiencySanitizer, a family of performance tuners. +// +// POSIX-specific working set tool code. +//===----------------------------------------------------------------------===// + +#include "working_set.h" +#include "esan_flags.h" +#include "esan_shadow.h" +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_linux.h" +#include +#include + +namespace __esan { + +// We only support regular POSIX threads with a single signal handler +// for the whole process == thread group. +// Thus we only need to store one app signal handler. +// FIXME: Store and use any alternate stack and signal flags set by +// the app. For now we just call the app handler from our handler. +static __sanitizer_sigaction AppSigAct; + +bool processWorkingSetSignal(int SigNum, void (*Handler)(int), + void (**Result)(int)) { + VPrintf(2, "%s: %d\n", __FUNCTION__, SigNum); + if (SigNum == SIGSEGV) { + *Result = AppSigAct.handler; + AppSigAct.sigaction = (void (*)(int, void*, void*))Handler; + return false; // Skip real call. + } + return true; +} + +bool processWorkingSetSigaction(int SigNum, const void *ActVoid, + void *OldActVoid) { + VPrintf(2, "%s: %d\n", __FUNCTION__, SigNum); + if (SigNum == SIGSEGV) { + const struct sigaction *Act = (const struct sigaction *) ActVoid; + struct sigaction *OldAct = (struct sigaction *) OldActVoid; + if (OldAct) + internal_memcpy(OldAct, &AppSigAct, sizeof(OldAct)); + if (Act) + internal_memcpy(&AppSigAct, Act, sizeof(AppSigAct)); + return false; // Skip real call. + } + return true; +} + +bool processWorkingSetSigprocmask(int How, void *Set, void *OldSet) { + VPrintf(2, "%s\n", __FUNCTION__); + // All we need to do is ensure that SIGSEGV is not blocked. + // FIXME: we are not fully transparent as we do not pretend that + // SIGSEGV is still blocked on app queries: that would require + // per-thread mask tracking. + if (Set && (How == SIG_BLOCK || How == SIG_SETMASK)) { + if (internal_sigismember((__sanitizer_sigset_t *)Set, SIGSEGV)) { + VPrintf(1, "%s: removing SIGSEGV from the blocked set\n", __FUNCTION__); + internal_sigdelset((__sanitizer_sigset_t *)Set, SIGSEGV); + } + } + return true; +} + +static void reinstateDefaultHandler(int SigNum) { + __sanitizer_sigaction SigAct; + internal_memset(&SigAct, 0, sizeof(SigAct)); + SigAct.sigaction = (void (*)(int, void*, void*)) SIG_DFL; + int Res = internal_sigaction(SigNum, &SigAct, nullptr); + CHECK(Res == 0); + VPrintf(1, "Unregistered for %d handler\n", SigNum); +} + +// If this is a shadow fault, we handle it here; otherwise, we pass it to the +// app to handle it just as the app would do without our tool in place. +static void handleMemoryFault(int SigNum, void *Info, void *Ctx) { + if (SigNum == SIGSEGV) { + // We rely on si_addr being filled in (thus we do not support old kernels). + siginfo_t *SigInfo = (siginfo_t *)Info; + uptr Addr = (uptr)SigInfo->si_addr; + if (isShadowMem(Addr)) { + VPrintf(3, "Shadow fault @%p\n", Addr); + uptr PageSize = GetPageSizeCached(); + int Res = internal_mprotect((void *)RoundDownTo(Addr, PageSize), + PageSize, PROT_READ|PROT_WRITE); + CHECK(Res == 0); + } else if (AppSigAct.sigaction) { + // FIXME: For simplicity we ignore app options including its signal stack + // (we just use ours) and all the delivery flags. + AppSigAct.sigaction(SigNum, Info, Ctx); + } else { + // Crash instead of spinning with infinite faults. + reinstateDefaultHandler(SigNum); + } + } else + UNREACHABLE("signal not registered"); +} + +void registerMemoryFaultHandler() { + // We do not use an alternate signal stack, as doing so would require + // setting it up for each app thread. + // FIXME: This could result in problems with emulating the app's signal + // handling if the app relies on an alternate stack for SIGSEGV. + + // We require that SIGSEGV is not blocked. We use a sigprocmask + // interceptor to ensure that in the future. Here we ensure it for + // the current thread. We assume there are no other threads at this + // point during initialization, or that at least they do not block + // SIGSEGV. + __sanitizer_sigset_t SigSet; + internal_sigemptyset(&SigSet); + internal_sigprocmask(SIG_BLOCK, &SigSet, nullptr); + + __sanitizer_sigaction SigAct; + internal_memset(&SigAct, 0, sizeof(SigAct)); + SigAct.sigaction = handleMemoryFault; + // We want to handle nested signals b/c we need to handle a + // shadow fault in an app signal handler. + SigAct.sa_flags = SA_SIGINFO | SA_NODEFER; + int Res = internal_sigaction(SIGSEGV, &SigAct, &AppSigAct); + CHECK(Res == 0); + VPrintf(1, "Registered for SIGSEGV handler\n"); +} + +} // namespace __esan Property changes on: projects/clang390-import/contrib/compiler-rt/lib/esan/working_set_posix.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/compiler-rt/lib/interception/interception_win.cc =================================================================== --- projects/clang390-import/contrib/compiler-rt/lib/interception/interception_win.cc (revision 305363) +++ projects/clang390-import/contrib/compiler-rt/lib/interception/interception_win.cc (revision 305364) @@ -1,273 +1,912 @@ //===-- interception_linux.cc -----------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // Windows-specific interception methods. +// +// This file is implementing several hooking techniques to intercept calls +// to functions. The hooks are dynamically installed by modifying the assembly +// code. +// +// The hooking techniques are making assumptions on the way the code is +// generated and are safe under these assumptions. +// +// On 64-bit architecture, there is no direct 64-bit jump instruction. To allow +// arbitrary branching on the whole memory space, the notion of trampoline +// region is used. A trampoline region is a memory space withing 2G boundary +// where it is safe to add custom assembly code to build 64-bit jumps. +// +// Hooking techniques +// ================== +// +// 1) Detour +// +// The Detour hooking technique is assuming the presence of an header with +// padding and an overridable 2-bytes nop instruction (mov edi, edi). The +// nop instruction can safely be replaced by a 2-bytes jump without any need +// to save the instruction. A jump to the target is encoded in the function +// header and the nop instruction is replaced by a short jump to the header. +// +// head: 5 x nop head: jmp +// func: mov edi, edi --> func: jmp short +// [...] real: [...] +// +// This technique is only implemented on 32-bit architecture. +// Most of the time, Windows API are hookable with the detour technique. +// +// 2) Redirect Jump +// +// The redirect jump is applicable when the first instruction is a direct +// jump. The instruction is replaced by jump to the hook. +// +// func: jmp