2012-06-04 22:27:50 +08:00
|
|
|
//===-- sanitizer_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 shared between AddressSanitizer and ThreadSanitizer
|
|
|
|
// run-time libraries and implements linux-specific functions from
|
|
|
|
// sanitizer_libc.h.
|
|
|
|
//===----------------------------------------------------------------------===//
|
2013-03-19 22:33:38 +08:00
|
|
|
|
|
|
|
#include "sanitizer_platform.h"
|
2015-10-01 07:52:54 +08:00
|
|
|
|
2018-03-20 07:12:14 +08:00
|
|
|
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
|
|
|
|
SANITIZER_OPENBSD || SANITIZER_SOLARIS
|
2012-06-04 22:27:50 +08:00
|
|
|
|
2012-06-07 14:15:12 +08:00
|
|
|
#include "sanitizer_common.h"
|
2014-01-31 21:10:07 +08:00
|
|
|
#include "sanitizer_flags.h"
|
2017-11-07 05:27:06 +08:00
|
|
|
#include "sanitizer_getauxval.h"
|
2012-06-05 22:25:27 +08:00
|
|
|
#include "sanitizer_internal_defs.h"
|
2012-06-04 22:27:50 +08:00
|
|
|
#include "sanitizer_libc.h"
|
2013-02-27 19:22:40 +08:00
|
|
|
#include "sanitizer_linux.h"
|
2012-12-01 10:39:45 +08:00
|
|
|
#include "sanitizer_mutex.h"
|
2012-07-03 16:24:14 +08:00
|
|
|
#include "sanitizer_placement_new.h"
|
2012-06-07 14:15:12 +08:00
|
|
|
#include "sanitizer_procmaps.h"
|
2012-12-13 17:34:23 +08:00
|
|
|
#include "sanitizer_stacktrace.h"
|
2013-05-23 19:53:36 +08:00
|
|
|
#include "sanitizer_symbolizer.h"
|
2012-06-04 22:27:50 +08:00
|
|
|
|
2017-08-09 04:36:10 +08:00
|
|
|
#if SANITIZER_LINUX
|
2013-05-20 23:57:44 +08:00
|
|
|
#include <asm/param.h>
|
2014-03-07 18:03:54 +08:00
|
|
|
#endif
|
|
|
|
|
2017-08-09 04:36:10 +08:00
|
|
|
#if SANITIZER_NETBSD
|
|
|
|
#include <lwp.h>
|
|
|
|
#endif
|
|
|
|
|
2014-12-16 15:11:08 +08:00
|
|
|
// For mips64, syscall(__NR_stat) fills the buffer in the 'struct kernel_stat'
|
|
|
|
// format. Struct kernel_stat is defined as 'struct stat' in asm/stat.h. To
|
|
|
|
// access stat from asm/stat.h, without conflicting with definition in
|
|
|
|
// sys/stat.h, we use this trick.
|
|
|
|
#if defined(__mips64)
|
2015-05-06 13:38:21 +08:00
|
|
|
#include <asm/unistd.h>
|
2014-12-16 15:11:08 +08:00
|
|
|
#include <sys/types.h>
|
|
|
|
#define stat kernel_stat
|
|
|
|
#include <asm/stat.h>
|
|
|
|
#undef stat
|
|
|
|
#endif
|
|
|
|
|
2013-03-13 16:19:53 +08:00
|
|
|
#include <dlfcn.h>
|
2013-02-27 21:03:35 +08:00
|
|
|
#include <errno.h>
|
2012-06-05 15:05:10 +08:00
|
|
|
#include <fcntl.h>
|
2013-07-30 03:09:49 +08:00
|
|
|
#include <link.h>
|
2012-06-07 15:13:46 +08:00
|
|
|
#include <pthread.h>
|
2012-06-18 16:44:30 +08:00
|
|
|
#include <sched.h>
|
2012-06-04 22:27:50 +08:00
|
|
|
#include <sys/mman.h>
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#if !SANITIZER_SOLARIS
|
2013-02-27 19:22:40 +08:00
|
|
|
#include <sys/ptrace.h>
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#endif
|
2012-06-07 15:13:46 +08:00
|
|
|
#include <sys/resource.h>
|
2012-06-05 15:05:10 +08:00
|
|
|
#include <sys/stat.h>
|
2012-06-04 22:27:50 +08:00
|
|
|
#include <sys/syscall.h>
|
2012-06-07 15:13:46 +08:00
|
|
|
#include <sys/time.h>
|
2012-06-04 22:27:50 +08:00
|
|
|
#include <sys/types.h>
|
2018-03-20 07:12:14 +08:00
|
|
|
#if !SANITIZER_OPENBSD
|
2015-03-13 02:10:06 +08:00
|
|
|
#include <ucontext.h>
|
2018-03-20 07:12:14 +08:00
|
|
|
#endif
|
|
|
|
#if SANITIZER_OPENBSD
|
2018-03-23 04:42:28 +08:00
|
|
|
#include <signal.h>
|
2018-03-20 07:12:14 +08:00
|
|
|
#include <sys/futex.h>
|
|
|
|
#endif
|
2012-06-04 22:27:50 +08:00
|
|
|
#include <unistd.h>
|
2013-02-27 21:03:35 +08:00
|
|
|
|
2017-07-07 01:45:01 +08:00
|
|
|
#if SANITIZER_LINUX
|
|
|
|
#include <sys/utsname.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
|
|
|
#include <sys/personality.h>
|
|
|
|
#endif
|
|
|
|
|
2014-03-07 18:03:54 +08:00
|
|
|
#if SANITIZER_FREEBSD
|
Retrieve command line arguments and environment correctly on FreeBSD
Summary:
Recently I saw the test `TestCases/Posix/print_cmdline.cc` failing on
FreeBSD, with "expected string not found in input". This is because
asan could not retrieve the command line arguments properly.
In `lib/sanitizer_common/sanitizer_linux.cc`, this is taken care of by
the `GetArgsAndEnv()` function, but it uses `__libc_stack_end` to get at
the required data. This variable does not exist on BSDs; the regular
way to retrieve the arguments and environment information is via the
`kern.ps_strings` sysctl.
I added this functionality in sanitizer_linux.cc, as a separate #ifdef
block in `GetArgsAndEnv()`. Also, `ReadNullSepFileToArray()` becomes
unused due to this change. (It won't work on FreeBSD anyway, since
`/proc` is not mounted by default.)
Reviewers: kcc, emaste, joerg, davide
Subscribers: llvm-commits, emaste
Differential Revision: http://reviews.llvm.org/D17832
llvm-svn: 263157
2016-03-11 04:22:02 +08:00
|
|
|
#include <sys/exec.h>
|
2014-05-29 20:12:42 +08:00
|
|
|
#include <sys/sysctl.h>
|
2014-03-07 18:03:54 +08:00
|
|
|
#include <machine/atomic.h>
|
|
|
|
extern "C" {
|
|
|
|
// <sys/umtx.h> must be included after <errno.h> and <sys/types.h> on
|
|
|
|
// FreeBSD 9.2 and 10.0.
|
|
|
|
#include <sys/umtx.h>
|
|
|
|
}
|
2018-03-03 19:50:58 +08:00
|
|
|
#include <sys/thr.h>
|
2014-03-07 18:03:54 +08:00
|
|
|
#endif // SANITIZER_FREEBSD
|
|
|
|
|
2017-08-09 04:36:10 +08:00
|
|
|
#if SANITIZER_NETBSD
|
|
|
|
#include <limits.h> // For NAME_MAX
|
|
|
|
#include <sys/sysctl.h>
|
2017-10-26 01:09:05 +08:00
|
|
|
#include <sys/exec.h>
|
|
|
|
extern struct ps_strings *__ps_strings;
|
|
|
|
#endif // SANITIZER_NETBSD
|
2017-08-09 04:36:10 +08:00
|
|
|
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#if SANITIZER_SOLARIS
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <thread.h>
|
2018-03-21 15:50:02 +08:00
|
|
|
#define environ _environ
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#endif
|
|
|
|
|
2013-03-19 22:33:38 +08:00
|
|
|
#if !SANITIZER_ANDROID
|
2013-02-27 21:03:35 +08:00
|
|
|
#include <sys/signal.h>
|
|
|
|
#endif
|
2013-01-30 22:39:27 +08:00
|
|
|
|
2018-03-21 15:50:02 +08:00
|
|
|
extern char **environ;
|
2018-03-20 04:44:06 +08:00
|
|
|
|
2014-03-07 18:03:54 +08:00
|
|
|
#if SANITIZER_LINUX
|
2013-03-21 14:24:31 +08:00
|
|
|
// <linux/time.h>
|
|
|
|
struct kernel_timeval {
|
|
|
|
long tv_sec;
|
|
|
|
long tv_usec;
|
|
|
|
};
|
|
|
|
|
2013-01-30 22:39:27 +08:00
|
|
|
// <linux/futex.h> is broken on some linux distributions.
|
|
|
|
const int FUTEX_WAIT = 0;
|
|
|
|
const int FUTEX_WAKE = 1;
|
2014-03-07 18:03:54 +08:00
|
|
|
#endif // SANITIZER_LINUX
|
2012-06-04 22:27:50 +08:00
|
|
|
|
2014-03-07 18:03:54 +08:00
|
|
|
// Are we using 32-bit or 64-bit Linux syscalls?
|
2012-11-21 20:38:58 +08:00
|
|
|
// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
|
2012-11-20 16:57:26 +08:00
|
|
|
// but it still needs to use 64-bit syscalls.
|
2018-03-20 07:12:14 +08:00
|
|
|
#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__powerpc64__) || \
|
|
|
|
SANITIZER_WORDSIZE == 64)
|
2012-11-19 15:53:36 +08:00
|
|
|
# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
|
|
|
|
#else
|
|
|
|
# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
|
|
|
|
#endif
|
|
|
|
|
2016-10-06 17:58:11 +08:00
|
|
|
#if defined(__x86_64__) || SANITIZER_MIPS64
|
[sanitizer][esan] Add internal_sigaction_syscall
Summary:
Adds a version of sigaction that uses a raw system call, to avoid circular
dependencies and support calling sigaction prior to setting up
interceptors. The new sigaction relies on an assembly sigreturn routine
for its restorer, which is Linux x86_64-only for now.
Uses the new sigaction to initialize the working set tool's shadow fault
handler prior to libc interceptor being set up. This is required to
support instrumentation invoked during interceptor setup, which happens
with an instrumented tcmalloc or other allocator compiled with esan.
Adds a test that emulates an instrumented allocator.
Reviewers: aizatsky
Subscribers: vitalybuka, tberghammer, zhaoqin, danalbert, kcc, srhines, eugenis, llvm-commits, kubabrecka
Differential Revision: http://reviews.llvm.org/D21083
llvm-svn: 272676
2016-06-14 23:15:38 +08:00
|
|
|
extern "C" {
|
|
|
|
extern void internal_sigreturn();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-08-14 22:53:47 +08:00
|
|
|
#if SANITIZER_LINUX && defined(__NR_getrandom)
|
|
|
|
# if !defined(GRND_NONBLOCK)
|
|
|
|
# define GRND_NONBLOCK 1
|
|
|
|
# endif
|
|
|
|
# define SANITIZER_USE_GETRANDOM 1
|
|
|
|
#else
|
|
|
|
# define SANITIZER_USE_GETRANDOM 0
|
|
|
|
#endif // SANITIZER_LINUX && defined(__NR_getrandom)
|
|
|
|
|
2012-06-04 22:27:50 +08:00
|
|
|
namespace __sanitizer {
|
|
|
|
|
2014-03-07 18:03:54 +08:00
|
|
|
#if SANITIZER_LINUX && defined(__x86_64__)
|
2013-05-08 22:43:49 +08:00
|
|
|
#include "sanitizer_syscall_linux_x86_64.inc"
|
2015-08-21 22:50:36 +08:00
|
|
|
#elif SANITIZER_LINUX && defined(__aarch64__)
|
|
|
|
#include "sanitizer_syscall_linux_aarch64.inc"
|
2017-11-08 08:15:12 +08:00
|
|
|
#elif SANITIZER_LINUX && defined(__arm__)
|
|
|
|
#include "sanitizer_syscall_linux_arm.inc"
|
2013-05-08 22:43:49 +08:00
|
|
|
#else
|
|
|
|
#include "sanitizer_syscall_generic.inc"
|
|
|
|
#endif
|
|
|
|
|
2012-06-07 15:13:46 +08:00
|
|
|
// --------------- sanitizer_libc.h
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#if !SANITIZER_SOLARIS
|
2018-03-20 07:12:14 +08:00
|
|
|
#if !SANITIZER_S390 && !SANITIZER_OPENBSD
|
2014-12-24 20:58:09 +08:00
|
|
|
uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
|
2015-07-31 19:29:25 +08:00
|
|
|
OFF_T offset) {
|
2017-08-09 04:36:10 +08:00
|
|
|
#if SANITIZER_NETBSD
|
|
|
|
return internal_syscall_ptr(SYSCALL(mmap), addr, length, prot, flags, fd,
|
|
|
|
(long)0, offset);
|
|
|
|
#elif SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
|
2014-03-07 18:03:54 +08:00
|
|
|
return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd,
|
2013-11-07 01:47:39 +08:00
|
|
|
offset);
|
2012-06-04 22:27:50 +08:00
|
|
|
#else
|
2014-12-24 20:58:09 +08:00
|
|
|
// mmap2 specifies file offset in 4096-byte units.
|
|
|
|
CHECK(IsAligned(offset, 4096));
|
2014-03-07 18:03:54 +08:00
|
|
|
return internal_syscall(SYSCALL(mmap2), addr, length, prot, flags, fd,
|
2014-12-24 20:58:09 +08:00
|
|
|
offset / 4096);
|
2012-06-04 22:27:50 +08:00
|
|
|
#endif
|
|
|
|
}
|
2018-03-20 07:12:14 +08:00
|
|
|
#endif // !SANITIZER_S390 && !SANITIZER_OPENBSD
|
2012-06-04 22:27:50 +08:00
|
|
|
|
2018-03-20 07:12:14 +08:00
|
|
|
#if !SANITIZER_OPENBSD
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_munmap(void *addr, uptr length) {
|
2017-10-26 01:09:05 +08:00
|
|
|
return internal_syscall_ptr(SYSCALL(munmap), (uptr)addr, length);
|
2012-06-05 17:49:25 +08:00
|
|
|
}
|
|
|
|
|
2015-04-10 23:02:19 +08:00
|
|
|
int internal_mprotect(void *addr, uptr length, int prot) {
|
2017-10-26 01:09:05 +08:00
|
|
|
return internal_syscall_ptr(SYSCALL(mprotect), (uptr)addr, length, prot);
|
2015-04-10 23:02:19 +08:00
|
|
|
}
|
2018-03-20 07:12:14 +08:00
|
|
|
#endif
|
2015-04-10 23:02:19 +08:00
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_close(fd_t fd) {
|
2014-03-07 18:03:54 +08:00
|
|
|
return internal_syscall(SYSCALL(close), fd);
|
2012-06-05 16:32:53 +08:00
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_open(const char *filename, int flags) {
|
2014-02-13 15:50:20 +08:00
|
|
|
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
|
2014-03-07 18:03:54 +08:00
|
|
|
return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags);
|
2014-02-13 15:50:20 +08:00
|
|
|
#else
|
2017-10-26 01:09:05 +08:00
|
|
|
return internal_syscall_ptr(SYSCALL(open), (uptr)filename, flags);
|
2014-02-13 15:50:20 +08:00
|
|
|
#endif
|
2013-02-01 23:58:46 +08:00
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_open(const char *filename, int flags, u32 mode) {
|
2014-02-13 15:50:20 +08:00
|
|
|
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
|
2014-03-07 18:03:54 +08:00
|
|
|
return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags,
|
|
|
|
mode);
|
2014-02-13 15:50:20 +08:00
|
|
|
#else
|
2017-10-26 01:09:05 +08:00
|
|
|
return internal_syscall_ptr(SYSCALL(open), (uptr)filename, flags, mode);
|
2014-02-13 15:50:20 +08:00
|
|
|
#endif
|
2013-02-01 23:58:46 +08:00
|
|
|
}
|
|
|
|
|
2012-06-05 16:32:53 +08:00
|
|
|
uptr internal_read(fd_t fd, void *buf, uptr count) {
|
2012-10-02 21:41:40 +08:00
|
|
|
sptr res;
|
2017-10-26 01:09:05 +08:00
|
|
|
HANDLE_EINTR(res, (sptr)internal_syscall_ptr(SYSCALL(read), fd, (uptr)buf,
|
2014-03-07 18:03:54 +08:00
|
|
|
count));
|
2012-10-02 21:41:40 +08:00
|
|
|
return res;
|
2012-06-05 16:32:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
uptr internal_write(fd_t fd, const void *buf, uptr count) {
|
2012-10-02 21:41:40 +08:00
|
|
|
sptr res;
|
2017-10-26 01:09:05 +08:00
|
|
|
HANDLE_EINTR(res, (sptr)internal_syscall_ptr(SYSCALL(write), fd, (uptr)buf,
|
2014-03-07 18:03:54 +08:00
|
|
|
count));
|
2012-10-02 21:41:40 +08:00
|
|
|
return res;
|
2012-06-05 16:32:53 +08:00
|
|
|
}
|
|
|
|
|
2014-05-27 20:37:52 +08:00
|
|
|
uptr internal_ftruncate(fd_t fd, uptr size) {
|
|
|
|
sptr res;
|
2017-08-09 04:36:10 +08:00
|
|
|
#if SANITIZER_NETBSD
|
2017-10-26 01:09:05 +08:00
|
|
|
HANDLE_EINTR(res, internal_syscall64(SYSCALL(ftruncate), fd, 0, (s64)size));
|
2017-08-09 04:36:10 +08:00
|
|
|
#else
|
2015-03-24 03:44:35 +08:00
|
|
|
HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd,
|
|
|
|
(OFF_T)size));
|
2017-08-09 04:36:10 +08:00
|
|
|
#endif
|
2014-05-27 20:37:52 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2017-08-09 04:36:10 +08:00
|
|
|
#if !SANITIZER_LINUX_USES_64BIT_SYSCALLS && SANITIZER_LINUX
|
2013-05-07 20:47:04 +08:00
|
|
|
static void stat64_to_stat(struct stat64 *in, struct stat *out) {
|
|
|
|
internal_memset(out, 0, sizeof(*out));
|
|
|
|
out->st_dev = in->st_dev;
|
|
|
|
out->st_ino = in->st_ino;
|
|
|
|
out->st_mode = in->st_mode;
|
|
|
|
out->st_nlink = in->st_nlink;
|
|
|
|
out->st_uid = in->st_uid;
|
|
|
|
out->st_gid = in->st_gid;
|
|
|
|
out->st_rdev = in->st_rdev;
|
|
|
|
out->st_size = in->st_size;
|
|
|
|
out->st_blksize = in->st_blksize;
|
|
|
|
out->st_blocks = in->st_blocks;
|
|
|
|
out->st_atime = in->st_atime;
|
|
|
|
out->st_mtime = in->st_mtime;
|
|
|
|
out->st_ctime = in->st_ctime;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-12-16 15:11:08 +08:00
|
|
|
#if defined(__mips64)
|
2017-09-15 23:18:51 +08:00
|
|
|
// Undefine compatibility macros from <sys/stat.h>
|
|
|
|
// so that they would not clash with the kernel_stat
|
|
|
|
// st_[a|m|c]time fields
|
|
|
|
#undef st_atime
|
|
|
|
#undef st_mtime
|
|
|
|
#undef st_ctime
|
|
|
|
#if defined(SANITIZER_ANDROID)
|
|
|
|
// Bionic sys/stat.h defines additional macros
|
|
|
|
// for compatibility with the old NDKs and
|
|
|
|
// they clash with the kernel_stat structure
|
|
|
|
// st_[a|m|c]time_nsec fields.
|
|
|
|
#undef st_atime_nsec
|
|
|
|
#undef st_mtime_nsec
|
|
|
|
#undef st_ctime_nsec
|
|
|
|
#endif
|
2014-12-16 15:11:08 +08:00
|
|
|
static void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) {
|
|
|
|
internal_memset(out, 0, sizeof(*out));
|
|
|
|
out->st_dev = in->st_dev;
|
|
|
|
out->st_ino = in->st_ino;
|
|
|
|
out->st_mode = in->st_mode;
|
|
|
|
out->st_nlink = in->st_nlink;
|
|
|
|
out->st_uid = in->st_uid;
|
|
|
|
out->st_gid = in->st_gid;
|
|
|
|
out->st_rdev = in->st_rdev;
|
|
|
|
out->st_size = in->st_size;
|
|
|
|
out->st_blksize = in->st_blksize;
|
|
|
|
out->st_blocks = in->st_blocks;
|
2017-09-15 23:18:51 +08:00
|
|
|
#if defined(__USE_MISC) || \
|
|
|
|
defined(__USE_XOPEN2K8) || \
|
|
|
|
defined(SANITIZER_ANDROID)
|
|
|
|
out->st_atim.tv_sec = in->st_atime;
|
|
|
|
out->st_atim.tv_nsec = in->st_atime_nsec;
|
|
|
|
out->st_mtim.tv_sec = in->st_mtime;
|
|
|
|
out->st_mtim.tv_nsec = in->st_mtime_nsec;
|
|
|
|
out->st_ctim.tv_sec = in->st_ctime;
|
|
|
|
out->st_ctim.tv_nsec = in->st_ctime_nsec;
|
|
|
|
#else
|
|
|
|
out->st_atime = in->st_atime;
|
|
|
|
out->st_atimensec = in->st_atime_nsec;
|
|
|
|
out->st_mtime = in->st_mtime;
|
|
|
|
out->st_mtimensec = in->st_mtime_nsec;
|
|
|
|
out->st_ctime = in->st_ctime;
|
|
|
|
out->st_atimensec = in->st_ctime_nsec;
|
|
|
|
#endif
|
2014-12-16 15:11:08 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_stat(const char *path, void *buf) {
|
2018-03-20 07:12:14 +08:00
|
|
|
#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD
|
|
|
|
return internal_syscall_ptr(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf,
|
|
|
|
0);
|
2014-03-07 18:03:54 +08:00
|
|
|
#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
|
2018-03-20 07:12:14 +08:00
|
|
|
return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
|
|
|
|
0);
|
2014-02-13 15:50:20 +08:00
|
|
|
#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
|
2014-12-16 15:11:08 +08:00
|
|
|
# if defined(__mips64)
|
|
|
|
// For mips64, stat syscall fills buffer in the format of kernel_stat
|
|
|
|
struct kernel_stat kbuf;
|
|
|
|
int res = internal_syscall(SYSCALL(stat), path, &kbuf);
|
|
|
|
kernel_stat_to_stat(&kbuf, (struct stat *)buf);
|
|
|
|
return res;
|
|
|
|
# else
|
2014-03-07 18:03:54 +08:00
|
|
|
return internal_syscall(SYSCALL(stat), (uptr)path, (uptr)buf);
|
2014-12-16 15:11:08 +08:00
|
|
|
# endif
|
2013-02-04 18:16:50 +08:00
|
|
|
#else
|
2013-05-07 20:47:04 +08:00
|
|
|
struct stat64 buf64;
|
2014-03-07 18:03:54 +08:00
|
|
|
int res = internal_syscall(SYSCALL(stat64), path, &buf64);
|
2013-05-07 20:47:04 +08:00
|
|
|
stat64_to_stat(&buf64, (struct stat *)buf);
|
|
|
|
return res;
|
2013-02-04 18:16:50 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_lstat(const char *path, void *buf) {
|
2017-08-09 04:36:10 +08:00
|
|
|
#if SANITIZER_NETBSD
|
2017-10-26 01:09:05 +08:00
|
|
|
return internal_syscall_ptr(SYSCALL(lstat), path, buf);
|
2018-03-20 07:12:14 +08:00
|
|
|
#elif SANITIZER_FREEBSD || SANITIZER_OPENBSD
|
|
|
|
return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf,
|
|
|
|
AT_SYMLINK_NOFOLLOW);
|
2014-03-07 18:03:54 +08:00
|
|
|
#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
|
2018-03-20 07:12:14 +08:00
|
|
|
return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
|
|
|
|
AT_SYMLINK_NOFOLLOW);
|
2014-02-13 15:50:20 +08:00
|
|
|
#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
|
2016-03-11 18:51:03 +08:00
|
|
|
# if SANITIZER_MIPS64
|
|
|
|
// For mips64, lstat syscall fills buffer in the format of kernel_stat
|
|
|
|
struct kernel_stat kbuf;
|
|
|
|
int res = internal_syscall(SYSCALL(lstat), path, &kbuf);
|
|
|
|
kernel_stat_to_stat(&kbuf, (struct stat *)buf);
|
|
|
|
return res;
|
|
|
|
# else
|
2014-03-07 18:03:54 +08:00
|
|
|
return internal_syscall(SYSCALL(lstat), (uptr)path, (uptr)buf);
|
2016-03-11 18:51:03 +08:00
|
|
|
# endif
|
2013-02-04 18:16:50 +08:00
|
|
|
#else
|
2013-05-07 20:47:04 +08:00
|
|
|
struct stat64 buf64;
|
2014-03-07 18:03:54 +08:00
|
|
|
int res = internal_syscall(SYSCALL(lstat64), path, &buf64);
|
2013-05-07 20:47:04 +08:00
|
|
|
stat64_to_stat(&buf64, (struct stat *)buf);
|
|
|
|
return res;
|
2013-02-04 18:16:50 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_fstat(fd_t fd, void *buf) {
|
2018-03-20 07:12:14 +08:00
|
|
|
#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD || \
|
|
|
|
SANITIZER_LINUX_USES_64BIT_SYSCALLS
|
|
|
|
#if SANITIZER_MIPS64 && !SANITIZER_NETBSD && !SANITIZER_OPENBSD
|
2016-03-11 18:51:03 +08:00
|
|
|
// For mips64, fstat syscall fills buffer in the format of kernel_stat
|
|
|
|
struct kernel_stat kbuf;
|
|
|
|
int res = internal_syscall(SYSCALL(fstat), fd, &kbuf);
|
|
|
|
kernel_stat_to_stat(&kbuf, (struct stat *)buf);
|
|
|
|
return res;
|
|
|
|
# else
|
2017-10-26 01:09:05 +08:00
|
|
|
return internal_syscall_ptr(SYSCALL(fstat), fd, (uptr)buf);
|
2016-03-11 18:51:03 +08:00
|
|
|
# endif
|
2013-02-04 18:16:50 +08:00
|
|
|
#else
|
2013-05-07 20:47:04 +08:00
|
|
|
struct stat64 buf64;
|
2014-03-07 18:03:54 +08:00
|
|
|
int res = internal_syscall(SYSCALL(fstat64), fd, &buf64);
|
2013-05-07 20:47:04 +08:00
|
|
|
stat64_to_stat(&buf64, (struct stat *)buf);
|
|
|
|
return res;
|
2013-02-04 18:16:50 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-06-06 15:30:33 +08:00
|
|
|
uptr internal_filesize(fd_t fd) {
|
2012-07-03 16:24:14 +08:00
|
|
|
struct stat st;
|
2013-02-04 18:16:50 +08:00
|
|
|
if (internal_fstat(fd, &st))
|
|
|
|
return -1;
|
2012-06-06 15:30:33 +08:00
|
|
|
return (uptr)st.st_size;
|
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_dup2(int oldfd, int newfd) {
|
2014-02-13 15:50:20 +08:00
|
|
|
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
|
2014-03-07 18:03:54 +08:00
|
|
|
return internal_syscall(SYSCALL(dup3), oldfd, newfd, 0);
|
2014-02-13 15:50:20 +08:00
|
|
|
#else
|
2014-03-07 18:03:54 +08:00
|
|
|
return internal_syscall(SYSCALL(dup2), oldfd, newfd);
|
2014-02-13 15:50:20 +08:00
|
|
|
#endif
|
2012-06-06 15:30:33 +08:00
|
|
|
}
|
|
|
|
|
2012-09-05 22:48:24 +08:00
|
|
|
uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
|
2018-03-23 04:42:28 +08:00
|
|
|
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
|
2018-03-20 07:12:14 +08:00
|
|
|
return internal_syscall(SYSCALL(readlinkat), AT_FDCWD, (uptr)path, (uptr)buf,
|
|
|
|
bufsize);
|
2018-03-23 04:42:28 +08:00
|
|
|
#elif SANITIZER_OPENBSD
|
|
|
|
return internal_syscall_ptr(SYSCALL(readlinkat), AT_FDCWD, (uptr)path,
|
|
|
|
(uptr)buf, bufsize);
|
2014-02-13 15:50:20 +08:00
|
|
|
#else
|
2017-10-26 01:09:05 +08:00
|
|
|
return internal_syscall_ptr(SYSCALL(readlink), path, buf, bufsize);
|
2014-02-13 15:50:20 +08:00
|
|
|
#endif
|
2012-09-05 22:48:24 +08:00
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_unlink(const char *path) {
|
2018-03-20 07:12:14 +08:00
|
|
|
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS || SANITIZER_OPENBSD
|
2014-03-07 18:03:54 +08:00
|
|
|
return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0);
|
2014-02-13 15:50:20 +08:00
|
|
|
#else
|
2017-10-26 01:09:05 +08:00
|
|
|
return internal_syscall_ptr(SYSCALL(unlink), (uptr)path);
|
2014-02-13 15:50:20 +08:00
|
|
|
#endif
|
2013-03-20 18:28:36 +08:00
|
|
|
}
|
|
|
|
|
2014-05-27 20:37:52 +08:00
|
|
|
uptr internal_rename(const char *oldpath, const char *newpath) {
|
2018-03-20 07:12:14 +08:00
|
|
|
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS || SANITIZER_OPENBSD
|
2014-05-27 20:37:52 +08:00
|
|
|
return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
|
|
|
|
(uptr)newpath);
|
|
|
|
#else
|
2017-10-26 01:09:05 +08:00
|
|
|
return internal_syscall_ptr(SYSCALL(rename), (uptr)oldpath, (uptr)newpath);
|
2014-05-27 20:37:52 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_sched_yield() {
|
2014-03-07 18:03:54 +08:00
|
|
|
return internal_syscall(SYSCALL(sched_yield));
|
2012-06-18 16:44:30 +08:00
|
|
|
}
|
|
|
|
|
2013-02-20 21:54:32 +08:00
|
|
|
void internal__exit(int exitcode) {
|
2018-03-20 07:12:14 +08:00
|
|
|
#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD
|
2014-03-07 18:03:54 +08:00
|
|
|
internal_syscall(SYSCALL(exit), exitcode);
|
|
|
|
#else
|
|
|
|
internal_syscall(SYSCALL(exit_group), exitcode);
|
|
|
|
#endif
|
2013-02-20 21:54:32 +08:00
|
|
|
Die(); // Unreachable.
|
|
|
|
}
|
|
|
|
|
2016-05-12 22:08:56 +08:00
|
|
|
unsigned int internal_sleep(unsigned int seconds) {
|
|
|
|
struct timespec ts;
|
|
|
|
ts.tv_sec = 1;
|
|
|
|
ts.tv_nsec = 0;
|
2017-10-26 01:09:05 +08:00
|
|
|
int res = internal_syscall_ptr(SYSCALL(nanosleep), &ts, &ts);
|
2016-05-12 22:08:56 +08:00
|
|
|
if (res) return ts.tv_sec;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_execve(const char *filename, char *const argv[],
|
|
|
|
char *const envp[]) {
|
2017-10-26 01:09:05 +08:00
|
|
|
return internal_syscall_ptr(SYSCALL(execve), (uptr)filename, (uptr)argv,
|
2018-03-20 07:12:14 +08:00
|
|
|
(uptr)envp);
|
2013-05-08 22:43:49 +08:00
|
|
|
}
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#endif // !SANITIZER_SOLARIS
|
2013-05-08 22:43:49 +08:00
|
|
|
|
2012-06-07 15:13:46 +08:00
|
|
|
// ----------------- sanitizer_common.h
|
2012-11-09 22:45:30 +08:00
|
|
|
bool FileExists(const char *filename) {
|
2014-02-13 15:50:20 +08:00
|
|
|
struct stat st;
|
2014-11-21 21:55:19 +08:00
|
|
|
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
|
2014-03-07 18:03:54 +08:00
|
|
|
if (internal_syscall(SYSCALL(newfstatat), AT_FDCWD, filename, &st, 0))
|
2014-02-13 15:50:20 +08:00
|
|
|
#else
|
2013-05-07 20:47:04 +08:00
|
|
|
if (internal_stat(filename, &st))
|
2014-11-21 21:55:19 +08:00
|
|
|
#endif
|
2012-11-09 22:45:30 +08:00
|
|
|
return false;
|
|
|
|
// Sanity check: filename is a regular file.
|
|
|
|
return S_ISREG(st.st_mode);
|
|
|
|
}
|
|
|
|
|
2017-04-18 02:17:38 +08:00
|
|
|
tid_t GetTid() {
|
2014-03-07 18:03:54 +08:00
|
|
|
#if SANITIZER_FREEBSD
|
2018-03-03 19:50:58 +08:00
|
|
|
long Tid;
|
|
|
|
thr_self(&Tid);
|
|
|
|
return Tid;
|
2018-03-20 07:12:14 +08:00
|
|
|
#elif SANITIZER_OPENBSD
|
|
|
|
return internal_syscall(SYSCALL(getthrid));
|
2017-08-09 04:36:10 +08:00
|
|
|
#elif SANITIZER_NETBSD
|
|
|
|
return _lwp_self();
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#elif SANITIZER_SOLARIS
|
2018-03-03 19:50:58 +08:00
|
|
|
return thr_self();
|
2014-03-07 18:03:54 +08:00
|
|
|
#else
|
|
|
|
return internal_syscall(SYSCALL(gettid));
|
|
|
|
#endif
|
2012-10-02 20:58:14 +08:00
|
|
|
}
|
|
|
|
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#if !SANITIZER_SOLARIS
|
2013-03-21 14:24:31 +08:00
|
|
|
u64 NanoTime() {
|
2018-03-20 07:12:14 +08:00
|
|
|
#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD
|
2014-03-07 18:03:54 +08:00
|
|
|
timeval tv;
|
|
|
|
#else
|
2013-10-22 02:11:57 +08:00
|
|
|
kernel_timeval tv;
|
2014-03-07 18:03:54 +08:00
|
|
|
#endif
|
2013-10-22 02:11:57 +08:00
|
|
|
internal_memset(&tv, 0, sizeof(tv));
|
2017-10-26 01:09:05 +08:00
|
|
|
internal_syscall_ptr(SYSCALL(gettimeofday), &tv, 0);
|
2013-03-21 14:24:31 +08:00
|
|
|
return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000;
|
|
|
|
}
|
|
|
|
|
2017-12-14 00:23:54 +08:00
|
|
|
uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) {
|
|
|
|
return internal_syscall_ptr(SYSCALL(clock_gettime), clk_id, tp);
|
|
|
|
}
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#endif // !SANITIZER_SOLARIS
|
2017-12-14 00:23:54 +08:00
|
|
|
|
2014-07-10 16:53:29 +08:00
|
|
|
// Like getenv, but reads env directly from /proc (on Linux) or parses the
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
// 'environ' array (on some others) and does not use libc. This function
|
|
|
|
// should be called first inside __asan_init.
|
2012-06-14 22:07:21 +08:00
|
|
|
const char *GetEnv(const char *name) {
|
2018-03-20 07:12:14 +08:00
|
|
|
#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD || \
|
|
|
|
SANITIZER_SOLARIS
|
2014-07-10 16:53:29 +08:00
|
|
|
if (::environ != 0) {
|
|
|
|
uptr NameLen = internal_strlen(name);
|
|
|
|
for (char **Env = ::environ; *Env != 0; Env++) {
|
|
|
|
if (internal_strncmp(*Env, name, NameLen) == 0 && (*Env)[NameLen] == '=')
|
|
|
|
return (*Env) + NameLen + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0; // Not found.
|
|
|
|
#elif SANITIZER_LINUX
|
2012-06-14 22:07:21 +08:00
|
|
|
static char *environ;
|
|
|
|
static uptr len;
|
|
|
|
static bool inited;
|
|
|
|
if (!inited) {
|
|
|
|
inited = true;
|
|
|
|
uptr environ_size;
|
2015-07-18 07:50:08 +08:00
|
|
|
if (!ReadFileToBuffer("/proc/self/environ", &environ, &environ_size, &len))
|
|
|
|
environ = nullptr;
|
2012-06-14 22:07:21 +08:00
|
|
|
}
|
2015-10-01 07:52:54 +08:00
|
|
|
if (!environ || len == 0) return nullptr;
|
2012-06-14 22:07:21 +08:00
|
|
|
uptr namelen = internal_strlen(name);
|
|
|
|
const char *p = environ;
|
|
|
|
while (*p != '\0') { // will happen at the \0\0 that terminates the buffer
|
|
|
|
// proc file has the format NAME=value\0NAME=value\0NAME=value\0...
|
|
|
|
const char* endp =
|
|
|
|
(char*)internal_memchr(p, '\0', len - (p - environ));
|
2015-10-01 07:52:54 +08:00
|
|
|
if (!endp) // this entry isn't NUL terminated
|
|
|
|
return nullptr;
|
2012-06-14 22:07:21 +08:00
|
|
|
else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=') // Match.
|
|
|
|
return p + namelen + 1; // point after =
|
|
|
|
p = endp + 1;
|
|
|
|
}
|
2015-10-01 07:52:54 +08:00
|
|
|
return nullptr; // Not found.
|
2014-06-21 06:49:41 +08:00
|
|
|
#else
|
2014-07-10 16:53:29 +08:00
|
|
|
#error "Unsupported platform"
|
2014-06-21 06:49:41 +08:00
|
|
|
#endif
|
2014-07-10 16:53:29 +08:00
|
|
|
}
|
2012-06-14 22:07:21 +08:00
|
|
|
|
2018-03-20 07:12:14 +08:00
|
|
|
#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD && !SANITIZER_OPENBSD
|
2013-02-14 22:40:03 +08:00
|
|
|
extern "C" {
|
2018-03-20 07:12:14 +08:00
|
|
|
SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end;
|
2013-02-14 22:40:03 +08:00
|
|
|
}
|
Retrieve command line arguments and environment correctly on FreeBSD
Summary:
Recently I saw the test `TestCases/Posix/print_cmdline.cc` failing on
FreeBSD, with "expected string not found in input". This is because
asan could not retrieve the command line arguments properly.
In `lib/sanitizer_common/sanitizer_linux.cc`, this is taken care of by
the `GetArgsAndEnv()` function, but it uses `__libc_stack_end` to get at
the required data. This variable does not exist on BSDs; the regular
way to retrieve the arguments and environment information is via the
`kern.ps_strings` sysctl.
I added this functionality in sanitizer_linux.cc, as a separate #ifdef
block in `GetArgsAndEnv()`. Also, `ReadNullSepFileToArray()` becomes
unused due to this change. (It won't work on FreeBSD anyway, since
`/proc` is not mounted by default.)
Reviewers: kcc, emaste, joerg, davide
Subscribers: llvm-commits, emaste
Differential Revision: http://reviews.llvm.org/D17832
llvm-svn: 263157
2016-03-11 04:22:02 +08:00
|
|
|
#endif
|
2013-02-14 22:40:03 +08:00
|
|
|
|
2018-03-20 07:12:14 +08:00
|
|
|
#if !SANITIZER_GO && !SANITIZER_FREEBSD && !SANITIZER_NETBSD && \
|
|
|
|
!SANITIZER_OPENBSD
|
2013-01-18 03:50:42 +08:00
|
|
|
static void ReadNullSepFileToArray(const char *path, char ***arr,
|
|
|
|
int arr_size) {
|
|
|
|
char *buff;
|
2015-07-18 07:50:08 +08:00
|
|
|
uptr buff_size;
|
|
|
|
uptr buff_len;
|
2013-01-18 03:50:42 +08:00
|
|
|
*arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray");
|
2015-07-18 07:50:08 +08:00
|
|
|
if (!ReadFileToBuffer(path, &buff, &buff_size, &buff_len, 1024 * 1024)) {
|
|
|
|
(*arr)[0] = nullptr;
|
|
|
|
return;
|
|
|
|
}
|
2013-01-18 03:50:42 +08:00
|
|
|
(*arr)[0] = buff;
|
|
|
|
int count, i;
|
|
|
|
for (count = 1, i = 1; ; i++) {
|
2012-09-17 17:12:39 +08:00
|
|
|
if (buff[i] == 0) {
|
|
|
|
if (buff[i+1] == 0) break;
|
2013-01-18 03:50:42 +08:00
|
|
|
(*arr)[count] = &buff[i+1];
|
|
|
|
CHECK_LE(count, arr_size - 1); // FIXME: make this more flexible.
|
|
|
|
count++;
|
2012-09-17 17:12:39 +08:00
|
|
|
}
|
|
|
|
}
|
2015-07-18 07:50:08 +08:00
|
|
|
(*arr)[count] = nullptr;
|
2013-01-18 03:50:42 +08:00
|
|
|
}
|
2014-12-12 00:12:45 +08:00
|
|
|
#endif
|
2014-12-09 09:22:59 +08:00
|
|
|
|
2018-03-20 07:12:14 +08:00
|
|
|
#if !SANITIZER_OPENBSD
|
2016-01-18 15:55:12 +08:00
|
|
|
static void GetArgsAndEnv(char ***argv, char ***envp) {
|
2017-10-26 01:09:05 +08:00
|
|
|
#if SANITIZER_FREEBSD
|
|
|
|
// On FreeBSD, retrieving the argument and environment arrays is done via the
|
|
|
|
// kern.ps_strings sysctl, which returns a pointer to a structure containing
|
|
|
|
// this information. See also <sys/exec.h>.
|
|
|
|
ps_strings *pss;
|
|
|
|
size_t sz = sizeof(pss);
|
|
|
|
if (sysctlbyname("kern.ps_strings", &pss, &sz, NULL, 0) == -1) {
|
|
|
|
Printf("sysctl kern.ps_strings failed\n");
|
|
|
|
Die();
|
|
|
|
}
|
|
|
|
*argv = pss->ps_argvstr;
|
|
|
|
*envp = pss->ps_envstr;
|
|
|
|
#elif SANITIZER_NETBSD
|
|
|
|
*argv = __ps_strings->ps_argvstr;
|
2018-02-07 22:05:57 +08:00
|
|
|
*envp = __ps_strings->ps_envstr;
|
2018-03-20 07:12:14 +08:00
|
|
|
#else // SANITIZER_FREEBSD
|
2013-05-20 22:25:32 +08:00
|
|
|
#if !SANITIZER_GO
|
|
|
|
if (&__libc_stack_end) {
|
2018-03-20 07:12:14 +08:00
|
|
|
#endif // !SANITIZER_GO
|
2013-05-20 22:25:32 +08:00
|
|
|
uptr* stack_end = (uptr*)__libc_stack_end;
|
|
|
|
int argc = *stack_end;
|
|
|
|
*argv = (char**)(stack_end + 1);
|
|
|
|
*envp = (char**)(stack_end + argc + 2);
|
|
|
|
#if !SANITIZER_GO
|
|
|
|
} else {
|
|
|
|
static const int kMaxArgv = 2000, kMaxEnvp = 2000;
|
|
|
|
ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv);
|
|
|
|
ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp);
|
|
|
|
}
|
2018-03-20 07:12:14 +08:00
|
|
|
#endif // !SANITIZER_GO
|
|
|
|
#endif // SANITIZER_FREEBSD
|
2013-02-14 22:40:03 +08:00
|
|
|
}
|
|
|
|
|
2016-01-18 15:55:12 +08:00
|
|
|
char **GetArgv() {
|
|
|
|
char **argv, **envp;
|
|
|
|
GetArgsAndEnv(&argv, &envp);
|
|
|
|
return argv;
|
|
|
|
}
|
|
|
|
|
2013-02-14 22:40:03 +08:00
|
|
|
void ReExec() {
|
2013-01-18 03:50:42 +08:00
|
|
|
char **argv, **envp;
|
2017-10-26 01:09:05 +08:00
|
|
|
const char *pathname = "/proc/self/exe";
|
|
|
|
|
|
|
|
#if SANITIZER_NETBSD
|
|
|
|
static const int name[] = {
|
|
|
|
CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME,
|
|
|
|
};
|
|
|
|
char path[400];
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
len = sizeof(path);
|
|
|
|
if (sysctl(name, ARRAY_SIZE(name), path, &len, NULL, 0) != -1)
|
|
|
|
pathname = path;
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#elif SANITIZER_SOLARIS
|
|
|
|
pathname = getexecname();
|
|
|
|
CHECK_NE(pathname, NULL);
|
2017-10-26 01:09:05 +08:00
|
|
|
#endif
|
|
|
|
|
2013-02-14 22:40:03 +08:00
|
|
|
GetArgsAndEnv(&argv, &envp);
|
2017-10-26 01:09:05 +08:00
|
|
|
uptr rv = internal_execve(pathname, argv, envp);
|
2013-05-08 22:43:49 +08:00
|
|
|
int rverrno;
|
|
|
|
CHECK_EQ(internal_iserror(rv, &rverrno), true);
|
|
|
|
Printf("execve failed, errno %d\n", rverrno);
|
2013-02-19 19:09:29 +08:00
|
|
|
Die();
|
2012-09-17 17:12:39 +08:00
|
|
|
}
|
2018-03-20 07:12:14 +08:00
|
|
|
#endif
|
2012-09-17 17:12:39 +08:00
|
|
|
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#if !SANITIZER_SOLARIS
|
2013-01-14 15:51:39 +08:00
|
|
|
enum MutexState {
|
|
|
|
MtxUnlocked = 0,
|
|
|
|
MtxLocked = 1,
|
|
|
|
MtxSleeping = 2
|
|
|
|
};
|
|
|
|
|
2013-03-14 21:30:56 +08:00
|
|
|
BlockingMutex::BlockingMutex() {
|
|
|
|
internal_memset(this, 0, sizeof(*this));
|
|
|
|
}
|
|
|
|
|
2013-01-14 15:51:39 +08:00
|
|
|
void BlockingMutex::Lock() {
|
2015-01-30 14:20:43 +08:00
|
|
|
CHECK_EQ(owner_, 0);
|
2013-01-14 15:51:39 +08:00
|
|
|
atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
|
|
|
|
if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
|
|
|
|
return;
|
2014-03-07 18:03:54 +08:00
|
|
|
while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) {
|
|
|
|
#if SANITIZER_FREEBSD
|
|
|
|
_umtx_op(m, UMTX_OP_WAIT_UINT, MtxSleeping, 0, 0);
|
2017-08-09 04:36:10 +08:00
|
|
|
#elif SANITIZER_NETBSD
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
sched_yield(); /* No userspace futex-like synchronization */
|
2014-03-07 18:03:54 +08:00
|
|
|
#else
|
|
|
|
internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAIT, MtxSleeping, 0, 0, 0);
|
|
|
|
#endif
|
|
|
|
}
|
2013-01-14 15:51:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void BlockingMutex::Unlock() {
|
|
|
|
atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
|
2017-05-25 23:07:07 +08:00
|
|
|
u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release);
|
2013-01-14 16:01:58 +08:00
|
|
|
CHECK_NE(v, MtxUnlocked);
|
2014-03-07 18:03:54 +08:00
|
|
|
if (v == MtxSleeping) {
|
|
|
|
#if SANITIZER_FREEBSD
|
|
|
|
_umtx_op(m, UMTX_OP_WAKE, 1, 0, 0);
|
2017-08-09 04:36:10 +08:00
|
|
|
#elif SANITIZER_NETBSD
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
/* No userspace futex-like synchronization */
|
2014-03-07 18:03:54 +08:00
|
|
|
#else
|
|
|
|
internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAKE, 1, 0, 0, 0);
|
|
|
|
#endif
|
|
|
|
}
|
2013-01-14 15:51:39 +08:00
|
|
|
}
|
|
|
|
|
2013-03-11 23:45:20 +08:00
|
|
|
void BlockingMutex::CheckLocked() {
|
|
|
|
atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
|
|
|
|
CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
|
|
|
|
}
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#endif // !SANITIZER_SOLARIS
|
2013-03-11 23:45:20 +08:00
|
|
|
|
2013-02-27 19:22:40 +08:00
|
|
|
// ----------------- sanitizer_linux.h
|
|
|
|
// The actual size of this structure is specified by d_reclen.
|
|
|
|
// Note that getdents64 uses a different structure format. We only provide the
|
|
|
|
// 32-bit syscall here.
|
2018-03-20 07:12:14 +08:00
|
|
|
#if SANITIZER_NETBSD || SANITIZER_OPENBSD
|
2017-08-09 04:36:10 +08:00
|
|
|
// struct dirent is different for Linux and us. At this moment, we use only
|
|
|
|
// d_fileno (Linux call this d_ino), d_reclen, and d_name.
|
|
|
|
struct linux_dirent {
|
|
|
|
u64 d_ino; // d_fileno
|
|
|
|
u16 d_reclen;
|
|
|
|
u16 d_namlen; // not used
|
|
|
|
u8 d_type; // not used
|
|
|
|
char d_name[NAME_MAX + 1];
|
|
|
|
};
|
|
|
|
#else
|
2013-02-27 19:22:40 +08:00
|
|
|
struct linux_dirent {
|
2015-10-21 21:08:06 +08:00
|
|
|
#if SANITIZER_X32 || defined(__aarch64__)
|
2014-05-21 16:21:13 +08:00
|
|
|
u64 d_ino;
|
|
|
|
u64 d_off;
|
|
|
|
#else
|
2013-02-27 19:22:40 +08:00
|
|
|
unsigned long d_ino;
|
|
|
|
unsigned long d_off;
|
2014-05-21 16:21:13 +08:00
|
|
|
#endif
|
2013-02-27 19:22:40 +08:00
|
|
|
unsigned short d_reclen;
|
2015-10-21 21:08:06 +08:00
|
|
|
#ifdef __aarch64__
|
|
|
|
unsigned char d_type;
|
|
|
|
#endif
|
2013-02-27 19:22:40 +08:00
|
|
|
char d_name[256];
|
|
|
|
};
|
2017-08-09 04:36:10 +08:00
|
|
|
#endif
|
2013-02-27 19:22:40 +08:00
|
|
|
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#if !SANITIZER_SOLARIS
|
2013-02-27 19:22:40 +08:00
|
|
|
// Syscall wrappers.
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_ptrace(int request, int pid, void *addr, void *data) {
|
2017-08-09 04:36:10 +08:00
|
|
|
#if SANITIZER_NETBSD
|
|
|
|
// XXX We need additional work for ptrace:
|
|
|
|
// - for request, we use PT_FOO whereas Linux uses PTRACE_FOO
|
|
|
|
// - data is int for us, but void * for Linux
|
|
|
|
// - Linux sometimes uses data in the case where we use addr instead
|
|
|
|
// At this moment, this function is used only within
|
|
|
|
// "#if SANITIZER_LINUX && defined(__x86_64__)" block in
|
|
|
|
// sanitizer_stoptheworld_linux_libcdep.cc.
|
|
|
|
return internal_syscall_ptr(SYSCALL(ptrace), request, pid, (uptr)addr,
|
|
|
|
(uptr)data);
|
|
|
|
#else
|
2014-03-07 18:03:54 +08:00
|
|
|
return internal_syscall(SYSCALL(ptrace), request, pid, (uptr)addr,
|
|
|
|
(uptr)data);
|
2017-08-09 04:36:10 +08:00
|
|
|
#endif
|
2013-05-08 22:43:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
uptr internal_waitpid(int pid, int *status, int options) {
|
2017-10-26 01:09:05 +08:00
|
|
|
return internal_syscall_ptr(SYSCALL(wait4), pid, (uptr)status, options,
|
2013-11-07 01:47:39 +08:00
|
|
|
0 /* rusage */);
|
2013-02-27 19:22:40 +08:00
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_getpid() {
|
2014-03-07 18:03:54 +08:00
|
|
|
return internal_syscall(SYSCALL(getpid));
|
2013-02-27 19:22:40 +08:00
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_getppid() {
|
2014-03-07 18:03:54 +08:00
|
|
|
return internal_syscall(SYSCALL(getppid));
|
2013-02-27 19:22:40 +08:00
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
|
2017-10-26 01:09:05 +08:00
|
|
|
#if SANITIZER_FREEBSD
|
Adjust sanitizers for FreeBSD 64-bit inode update
Summary:
Very recently, FreeBSD 12 has been updated to use 64-bit inode numbers:
<https://svnweb.freebsd.org/changeset/base/318737>. This entails many
user-visible changes, but for the sanitizers the modifications are
limited in scope:
* The `stat` and `lstat` syscalls were removed, and should be replaced
with calls to `fstatat`.
* The `getdents` syscall was removed, and should be replaced with calls
to `getdirentries`.
* The layout of `struct dirent` was changed to accomodate 64-bit inode
numbers, and a new `d_off` field was added.
* The system header <sys/_types.h> now contains a macro `__INO64` to
determine whether the system uses 64-bit inode numbers.
I tested these changes on both FreeBSD 12.0-CURRENT (after r318959,
which adds the `__INO64` macro), and FreeBSD 11.0-STABLE (which still
uses 32-bit inode numbers).
Reviewers: emaste, kcc, vitalybuka, kubamracek
Reviewed By: vitalybuka
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D33600
llvm-svn: 304658
2017-06-03 19:11:36 +08:00
|
|
|
return internal_syscall(SYSCALL(getdirentries), fd, (uptr)dirp, count, NULL);
|
|
|
|
#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
|
2014-03-07 18:03:54 +08:00
|
|
|
return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count);
|
2014-02-13 15:50:20 +08:00
|
|
|
#else
|
2017-10-26 01:09:05 +08:00
|
|
|
return internal_syscall_ptr(SYSCALL(getdents), fd, (uptr)dirp, count);
|
2014-02-13 15:50:20 +08:00
|
|
|
#endif
|
2013-02-27 19:22:40 +08:00
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
|
2017-08-09 04:36:10 +08:00
|
|
|
#if SANITIZER_NETBSD
|
|
|
|
return internal_syscall64(SYSCALL(lseek), fd, 0, offset, whence);
|
|
|
|
#else
|
2014-03-07 18:03:54 +08:00
|
|
|
return internal_syscall(SYSCALL(lseek), fd, offset, whence);
|
2017-08-09 04:36:10 +08:00
|
|
|
#endif
|
2013-02-27 19:22:40 +08:00
|
|
|
}
|
|
|
|
|
2014-03-07 18:03:54 +08:00
|
|
|
#if SANITIZER_LINUX
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
|
2014-03-07 18:03:54 +08:00
|
|
|
return internal_syscall(SYSCALL(prctl), option, arg2, arg3, arg4, arg5);
|
2013-02-27 19:22:40 +08:00
|
|
|
}
|
2014-03-07 18:03:54 +08:00
|
|
|
#endif
|
2013-02-27 19:22:40 +08:00
|
|
|
|
2017-07-14 05:59:01 +08:00
|
|
|
uptr internal_sigaltstack(const void *ss, void *oss) {
|
2017-10-26 01:09:05 +08:00
|
|
|
return internal_syscall_ptr(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss);
|
2013-02-27 19:22:40 +08:00
|
|
|
}
|
|
|
|
|
2014-05-14 01:31:09 +08:00
|
|
|
int internal_fork() {
|
2014-05-27 07:44:55 +08:00
|
|
|
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
|
|
|
|
return internal_syscall(SYSCALL(clone), SIGCHLD, 0);
|
|
|
|
#else
|
2014-05-14 00:17:54 +08:00
|
|
|
return internal_syscall(SYSCALL(fork));
|
2014-05-27 07:44:55 +08:00
|
|
|
#endif
|
2014-05-14 00:17:54 +08:00
|
|
|
}
|
|
|
|
|
2014-03-07 18:03:54 +08:00
|
|
|
#if SANITIZER_LINUX
|
2015-03-03 01:36:02 +08:00
|
|
|
#define SA_RESTORER 0x04000000
|
[sanitizer][esan] Add internal_sigaction_syscall
Summary:
Adds a version of sigaction that uses a raw system call, to avoid circular
dependencies and support calling sigaction prior to setting up
interceptors. The new sigaction relies on an assembly sigreturn routine
for its restorer, which is Linux x86_64-only for now.
Uses the new sigaction to initialize the working set tool's shadow fault
handler prior to libc interceptor being set up. This is required to
support instrumentation invoked during interceptor setup, which happens
with an instrumented tcmalloc or other allocator compiled with esan.
Adds a test that emulates an instrumented allocator.
Reviewers: aizatsky
Subscribers: vitalybuka, tberghammer, zhaoqin, danalbert, kcc, srhines, eugenis, llvm-commits, kubabrecka
Differential Revision: http://reviews.llvm.org/D21083
llvm-svn: 272676
2016-06-14 23:15:38 +08:00
|
|
|
// Doesn't set sa_restorer if the caller did not set it, so use with caution
|
|
|
|
//(see below).
|
2014-01-31 19:29:51 +08:00
|
|
|
int internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
|
|
|
|
__sanitizer_kernel_sigaction_t k_act, k_oldact;
|
|
|
|
internal_memset(&k_act, 0, sizeof(__sanitizer_kernel_sigaction_t));
|
|
|
|
internal_memset(&k_oldact, 0, sizeof(__sanitizer_kernel_sigaction_t));
|
2014-11-14 06:40:59 +08:00
|
|
|
const __sanitizer_sigaction *u_act = (const __sanitizer_sigaction *)act;
|
2014-01-31 19:29:51 +08:00
|
|
|
__sanitizer_sigaction *u_oldact = (__sanitizer_sigaction *)oldact;
|
|
|
|
if (u_act) {
|
|
|
|
k_act.handler = u_act->handler;
|
|
|
|
k_act.sigaction = u_act->sigaction;
|
|
|
|
internal_memcpy(&k_act.sa_mask, &u_act->sa_mask,
|
|
|
|
sizeof(__sanitizer_kernel_sigset_t));
|
2015-03-03 01:36:02 +08:00
|
|
|
// Without SA_RESTORER kernel ignores the calls (probably returns EINVAL).
|
|
|
|
k_act.sa_flags = u_act->sa_flags | SA_RESTORER;
|
2014-01-31 19:29:51 +08:00
|
|
|
// FIXME: most often sa_restorer is unset, however the kernel requires it
|
|
|
|
// to point to a valid signal restorer that calls the rt_sigreturn syscall.
|
|
|
|
// If sa_restorer passed to the kernel is NULL, the program may crash upon
|
|
|
|
// signal delivery or fail to unwind the stack in the signal handler.
|
|
|
|
// libc implementation of sigaction() passes its own restorer to
|
|
|
|
// rt_sigaction, so we need to do the same (we'll need to reimplement the
|
|
|
|
// restorers; for x86_64 the restorer address can be obtained from
|
|
|
|
// oldact->sa_restorer upon a call to sigaction(xxx, NULL, oldact).
|
2016-03-16 16:23:10 +08:00
|
|
|
#if !SANITIZER_ANDROID || !SANITIZER_MIPS32
|
2014-01-31 19:29:51 +08:00
|
|
|
k_act.sa_restorer = u_act->sa_restorer;
|
2016-03-16 16:23:10 +08:00
|
|
|
#endif
|
2014-01-31 19:29:51 +08:00
|
|
|
}
|
|
|
|
|
2014-03-07 18:03:54 +08:00
|
|
|
uptr result = internal_syscall(SYSCALL(rt_sigaction), (uptr)signum,
|
2015-10-01 07:52:54 +08:00
|
|
|
(uptr)(u_act ? &k_act : nullptr),
|
|
|
|
(uptr)(u_oldact ? &k_oldact : nullptr),
|
2014-01-31 19:29:51 +08:00
|
|
|
(uptr)sizeof(__sanitizer_kernel_sigset_t));
|
|
|
|
|
|
|
|
if ((result == 0) && u_oldact) {
|
|
|
|
u_oldact->handler = k_oldact.handler;
|
|
|
|
u_oldact->sigaction = k_oldact.sigaction;
|
|
|
|
internal_memcpy(&u_oldact->sa_mask, &k_oldact.sa_mask,
|
|
|
|
sizeof(__sanitizer_kernel_sigset_t));
|
|
|
|
u_oldact->sa_flags = k_oldact.sa_flags;
|
2016-03-16 16:23:10 +08:00
|
|
|
#if !SANITIZER_ANDROID || !SANITIZER_MIPS32
|
2014-01-31 19:29:51 +08:00
|
|
|
u_oldact->sa_restorer = k_oldact.sa_restorer;
|
2016-03-16 16:23:10 +08:00
|
|
|
#endif
|
2014-01-31 19:29:51 +08:00
|
|
|
}
|
|
|
|
return result;
|
2013-10-15 19:31:51 +08:00
|
|
|
}
|
[sanitizer][esan] Add internal_sigaction_syscall
Summary:
Adds a version of sigaction that uses a raw system call, to avoid circular
dependencies and support calling sigaction prior to setting up
interceptors. The new sigaction relies on an assembly sigreturn routine
for its restorer, which is Linux x86_64-only for now.
Uses the new sigaction to initialize the working set tool's shadow fault
handler prior to libc interceptor being set up. This is required to
support instrumentation invoked during interceptor setup, which happens
with an instrumented tcmalloc or other allocator compiled with esan.
Adds a test that emulates an instrumented allocator.
Reviewers: aizatsky
Subscribers: vitalybuka, tberghammer, zhaoqin, danalbert, kcc, srhines, eugenis, llvm-commits, kubabrecka
Differential Revision: http://reviews.llvm.org/D21083
llvm-svn: 272676
2016-06-14 23:15:38 +08:00
|
|
|
|
|
|
|
// Invokes sigaction via a raw syscall with a restorer, but does not support
|
|
|
|
// all platforms yet.
|
|
|
|
// We disable for Go simply because we have not yet added to buildgo.sh.
|
2016-10-06 17:58:11 +08:00
|
|
|
#if (defined(__x86_64__) || SANITIZER_MIPS64) && !SANITIZER_GO
|
[sanitizer][esan] Add internal_sigaction_syscall
Summary:
Adds a version of sigaction that uses a raw system call, to avoid circular
dependencies and support calling sigaction prior to setting up
interceptors. The new sigaction relies on an assembly sigreturn routine
for its restorer, which is Linux x86_64-only for now.
Uses the new sigaction to initialize the working set tool's shadow fault
handler prior to libc interceptor being set up. This is required to
support instrumentation invoked during interceptor setup, which happens
with an instrumented tcmalloc or other allocator compiled with esan.
Adds a test that emulates an instrumented allocator.
Reviewers: aizatsky
Subscribers: vitalybuka, tberghammer, zhaoqin, danalbert, kcc, srhines, eugenis, llvm-commits, kubabrecka
Differential Revision: http://reviews.llvm.org/D21083
llvm-svn: 272676
2016-06-14 23:15:38 +08:00
|
|
|
int internal_sigaction_syscall(int signum, const void *act, void *oldact) {
|
2016-07-07 04:13:40 +08:00
|
|
|
if (act == nullptr)
|
|
|
|
return internal_sigaction_norestorer(signum, act, oldact);
|
[sanitizer][esan] Add internal_sigaction_syscall
Summary:
Adds a version of sigaction that uses a raw system call, to avoid circular
dependencies and support calling sigaction prior to setting up
interceptors. The new sigaction relies on an assembly sigreturn routine
for its restorer, which is Linux x86_64-only for now.
Uses the new sigaction to initialize the working set tool's shadow fault
handler prior to libc interceptor being set up. This is required to
support instrumentation invoked during interceptor setup, which happens
with an instrumented tcmalloc or other allocator compiled with esan.
Adds a test that emulates an instrumented allocator.
Reviewers: aizatsky
Subscribers: vitalybuka, tberghammer, zhaoqin, danalbert, kcc, srhines, eugenis, llvm-commits, kubabrecka
Differential Revision: http://reviews.llvm.org/D21083
llvm-svn: 272676
2016-06-14 23:15:38 +08:00
|
|
|
__sanitizer_sigaction u_adjust;
|
|
|
|
internal_memcpy(&u_adjust, act, sizeof(u_adjust));
|
|
|
|
#if !SANITIZER_ANDROID || !SANITIZER_MIPS32
|
2018-03-20 07:12:14 +08:00
|
|
|
if (u_adjust.sa_restorer == nullptr) {
|
|
|
|
u_adjust.sa_restorer = internal_sigreturn;
|
|
|
|
}
|
[sanitizer][esan] Add internal_sigaction_syscall
Summary:
Adds a version of sigaction that uses a raw system call, to avoid circular
dependencies and support calling sigaction prior to setting up
interceptors. The new sigaction relies on an assembly sigreturn routine
for its restorer, which is Linux x86_64-only for now.
Uses the new sigaction to initialize the working set tool's shadow fault
handler prior to libc interceptor being set up. This is required to
support instrumentation invoked during interceptor setup, which happens
with an instrumented tcmalloc or other allocator compiled with esan.
Adds a test that emulates an instrumented allocator.
Reviewers: aizatsky
Subscribers: vitalybuka, tberghammer, zhaoqin, danalbert, kcc, srhines, eugenis, llvm-commits, kubabrecka
Differential Revision: http://reviews.llvm.org/D21083
llvm-svn: 272676
2016-06-14 23:15:38 +08:00
|
|
|
#endif
|
2018-03-20 07:12:14 +08:00
|
|
|
return internal_sigaction_norestorer(signum, (const void *)&u_adjust, oldact);
|
[sanitizer][esan] Add internal_sigaction_syscall
Summary:
Adds a version of sigaction that uses a raw system call, to avoid circular
dependencies and support calling sigaction prior to setting up
interceptors. The new sigaction relies on an assembly sigreturn routine
for its restorer, which is Linux x86_64-only for now.
Uses the new sigaction to initialize the working set tool's shadow fault
handler prior to libc interceptor being set up. This is required to
support instrumentation invoked during interceptor setup, which happens
with an instrumented tcmalloc or other allocator compiled with esan.
Adds a test that emulates an instrumented allocator.
Reviewers: aizatsky
Subscribers: vitalybuka, tberghammer, zhaoqin, danalbert, kcc, srhines, eugenis, llvm-commits, kubabrecka
Differential Revision: http://reviews.llvm.org/D21083
llvm-svn: 272676
2016-06-14 23:15:38 +08:00
|
|
|
}
|
2018-03-20 07:12:14 +08:00
|
|
|
#endif // defined(__x86_64__) && !SANITIZER_GO
|
2014-03-07 18:03:54 +08:00
|
|
|
#endif // SANITIZER_LINUX
|
2013-10-15 19:31:51 +08:00
|
|
|
|
2014-01-31 19:29:51 +08:00
|
|
|
uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
|
2018-03-20 07:12:14 +08:00
|
|
|
__sanitizer_sigset_t *oldset) {
|
|
|
|
#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD
|
2017-10-26 01:09:05 +08:00
|
|
|
return internal_syscall_ptr(SYSCALL(sigprocmask), how, set, oldset);
|
2014-03-07 18:03:54 +08:00
|
|
|
#else
|
2014-01-31 19:29:51 +08:00
|
|
|
__sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
|
|
|
|
__sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset;
|
2014-05-21 15:49:03 +08:00
|
|
|
return internal_syscall(SYSCALL(rt_sigprocmask), (uptr)how,
|
|
|
|
(uptr)&k_set->sig[0], (uptr)&k_oldset->sig[0],
|
|
|
|
sizeof(__sanitizer_kernel_sigset_t));
|
2014-03-07 18:03:54 +08:00
|
|
|
#endif
|
2013-10-15 19:31:51 +08:00
|
|
|
}
|
|
|
|
|
2014-01-31 19:29:51 +08:00
|
|
|
void internal_sigfillset(__sanitizer_sigset_t *set) {
|
2013-10-15 19:31:51 +08:00
|
|
|
internal_memset(set, 0xff, sizeof(*set));
|
|
|
|
}
|
|
|
|
|
2016-07-07 05:04:48 +08:00
|
|
|
void internal_sigemptyset(__sanitizer_sigset_t *set) {
|
|
|
|
internal_memset(set, 0, sizeof(*set));
|
|
|
|
}
|
|
|
|
|
2014-03-07 18:03:54 +08:00
|
|
|
#if SANITIZER_LINUX
|
2014-01-31 19:29:51 +08:00
|
|
|
void internal_sigdelset(__sanitizer_sigset_t *set, int signum) {
|
2013-10-15 19:31:51 +08:00
|
|
|
signum -= 1;
|
|
|
|
CHECK_GE(signum, 0);
|
|
|
|
CHECK_LT(signum, sizeof(*set) * 8);
|
2014-01-31 19:29:51 +08:00
|
|
|
__sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
|
|
|
|
const uptr idx = signum / (sizeof(k_set->sig[0]) * 8);
|
|
|
|
const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);
|
|
|
|
k_set->sig[idx] &= ~(1 << bit);
|
2013-10-15 19:31:51 +08:00
|
|
|
}
|
2016-07-07 05:04:48 +08:00
|
|
|
|
|
|
|
bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {
|
|
|
|
signum -= 1;
|
|
|
|
CHECK_GE(signum, 0);
|
|
|
|
CHECK_LT(signum, sizeof(*set) * 8);
|
|
|
|
__sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
|
|
|
|
const uptr idx = signum / (sizeof(k_set->sig[0]) * 8);
|
|
|
|
const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);
|
|
|
|
return k_set->sig[idx] & (1 << bit);
|
|
|
|
}
|
2014-03-07 18:03:54 +08:00
|
|
|
#endif // SANITIZER_LINUX
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#endif // !SANITIZER_SOLARIS
|
2013-10-15 19:31:51 +08:00
|
|
|
|
2013-02-27 19:22:40 +08:00
|
|
|
// ThreadLister implementation.
|
|
|
|
ThreadLister::ThreadLister(int pid)
|
|
|
|
: pid_(pid),
|
|
|
|
descriptor_(-1),
|
2013-04-05 15:41:21 +08:00
|
|
|
buffer_(4096),
|
2013-02-27 19:22:40 +08:00
|
|
|
error_(true),
|
2013-04-05 15:41:21 +08:00
|
|
|
entry_((struct linux_dirent *)buffer_.data()),
|
2013-02-27 19:22:40 +08:00
|
|
|
bytes_read_(0) {
|
|
|
|
char task_directory_path[80];
|
|
|
|
internal_snprintf(task_directory_path, sizeof(task_directory_path),
|
|
|
|
"/proc/%d/task/", pid);
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr openrv = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY);
|
|
|
|
if (internal_iserror(openrv)) {
|
2013-02-27 19:22:40 +08:00
|
|
|
error_ = true;
|
|
|
|
Report("Can't open /proc/%d/task for reading.\n", pid);
|
|
|
|
} else {
|
|
|
|
error_ = false;
|
2013-05-08 22:43:49 +08:00
|
|
|
descriptor_ = openrv;
|
2013-02-27 19:22:40 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int ThreadLister::GetNextTID() {
|
|
|
|
int tid = -1;
|
|
|
|
do {
|
|
|
|
if (error_)
|
|
|
|
return -1;
|
|
|
|
if ((char *)entry_ >= &buffer_[bytes_read_] && !GetDirectoryEntries())
|
|
|
|
return -1;
|
|
|
|
if (entry_->d_ino != 0 && entry_->d_name[0] >= '0' &&
|
|
|
|
entry_->d_name[0] <= '9') {
|
|
|
|
// Found a valid tid.
|
|
|
|
tid = (int)internal_atoll(entry_->d_name);
|
|
|
|
}
|
|
|
|
entry_ = (struct linux_dirent *)(((char *)entry_) + entry_->d_reclen);
|
|
|
|
} while (tid < 0);
|
|
|
|
return tid;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ThreadLister::Reset() {
|
|
|
|
if (error_ || descriptor_ < 0)
|
|
|
|
return;
|
|
|
|
internal_lseek(descriptor_, 0, SEEK_SET);
|
|
|
|
}
|
|
|
|
|
|
|
|
ThreadLister::~ThreadLister() {
|
|
|
|
if (descriptor_ >= 0)
|
|
|
|
internal_close(descriptor_);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ThreadLister::error() { return error_; }
|
|
|
|
|
|
|
|
bool ThreadLister::GetDirectoryEntries() {
|
|
|
|
CHECK_GE(descriptor_, 0);
|
|
|
|
CHECK_NE(error_, true);
|
|
|
|
bytes_read_ = internal_getdents(descriptor_,
|
2013-04-05 15:41:21 +08:00
|
|
|
(struct linux_dirent *)buffer_.data(),
|
|
|
|
buffer_.size());
|
2013-05-08 22:43:49 +08:00
|
|
|
if (internal_iserror(bytes_read_)) {
|
2013-02-27 19:22:40 +08:00
|
|
|
Report("Can't read directory entries from /proc/%d/task.\n", pid_);
|
|
|
|
error_ = true;
|
|
|
|
return false;
|
|
|
|
} else if (bytes_read_ == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
2013-04-05 15:41:21 +08:00
|
|
|
entry_ = (struct linux_dirent *)buffer_.data();
|
2013-02-27 19:22:40 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-07-07 01:17:50 +08:00
|
|
|
#if SANITIZER_WORDSIZE == 32
|
|
|
|
// Take care of unusable kernel area in top gigabyte.
|
|
|
|
static uptr GetKernelAreaSize() {
|
|
|
|
#if SANITIZER_LINUX && !SANITIZER_X32
|
|
|
|
const uptr gbyte = 1UL << 30;
|
|
|
|
|
|
|
|
// Firstly check if there are writable segments
|
|
|
|
// mapped to top gigabyte (e.g. stack).
|
|
|
|
MemoryMappingLayout proc_maps(/*cache_enabled*/true);
|
2017-07-12 02:54:00 +08:00
|
|
|
MemoryMappedSegment segment;
|
|
|
|
while (proc_maps.Next(&segment)) {
|
|
|
|
if ((segment.end >= 3 * gbyte) && segment.IsWritable()) return 0;
|
2017-07-07 01:17:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#if !SANITIZER_ANDROID
|
|
|
|
// Even if nothing is mapped, top Gb may still be accessible
|
|
|
|
// if we are running on 64-bit kernel.
|
|
|
|
// Uname may report misleading results if personality type
|
|
|
|
// is modified (e.g. under schroot) so check this as well.
|
|
|
|
struct utsname uname_info;
|
|
|
|
int pers = personality(0xffffffffUL);
|
|
|
|
if (!(pers & PER_MASK)
|
|
|
|
&& uname(&uname_info) == 0
|
|
|
|
&& internal_strstr(uname_info.machine, "64"))
|
|
|
|
return 0;
|
|
|
|
#endif // SANITIZER_ANDROID
|
|
|
|
|
|
|
|
// Top gigabyte is reserved for kernel.
|
|
|
|
return gbyte;
|
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif // SANITIZER_LINUX && !SANITIZER_X32
|
|
|
|
}
|
|
|
|
#endif // SANITIZER_WORDSIZE == 32
|
|
|
|
|
2017-11-21 01:41:57 +08:00
|
|
|
uptr GetMaxVirtualAddress() {
|
2018-03-20 07:12:14 +08:00
|
|
|
#if (SANITIZER_NETBSD || SANITIZER_OPENBSD) && defined(__x86_64__)
|
2017-08-09 04:36:10 +08:00
|
|
|
return 0x7f7ffffff000ULL; // (0x00007f8000000000 - PAGE_SIZE)
|
|
|
|
#elif SANITIZER_WORDSIZE == 64
|
2017-07-07 01:13:40 +08:00
|
|
|
# if defined(__powerpc64__) || defined(__aarch64__)
|
|
|
|
// On PowerPC64 we have two different address space layouts: 44- and 46-bit.
|
|
|
|
// We somehow need to figure out which one we are using now and choose
|
|
|
|
// one of 0x00000fffffffffffUL and 0x00003fffffffffffUL.
|
|
|
|
// Note that with 'ulimit -s unlimited' the stack is moved away from the top
|
|
|
|
// of the address space, so simply checking the stack address is not enough.
|
|
|
|
// This should (does) work for both PowerPC64 Endian modes.
|
|
|
|
// Similarly, aarch64 has multiple address space layouts: 39, 42 and 47-bit.
|
|
|
|
return (1ULL << (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1)) - 1;
|
|
|
|
# elif defined(__mips64)
|
|
|
|
return (1ULL << 40) - 1; // 0x000000ffffffffffUL;
|
|
|
|
# elif defined(__s390x__)
|
|
|
|
return (1ULL << 53) - 1; // 0x001fffffffffffffUL;
|
|
|
|
# else
|
|
|
|
return (1ULL << 47) - 1; // 0x00007fffffffffffUL;
|
|
|
|
# endif
|
|
|
|
#else // SANITIZER_WORDSIZE == 32
|
|
|
|
# if defined(__s390__)
|
|
|
|
return (1ULL << 31) - 1; // 0x7fffffff;
|
|
|
|
# else
|
2017-11-21 01:41:57 +08:00
|
|
|
return (1ULL << 32) - 1; // 0xffffffff;
|
2017-07-07 01:13:40 +08:00
|
|
|
# endif
|
|
|
|
#endif // SANITIZER_WORDSIZE
|
|
|
|
}
|
|
|
|
|
2017-11-21 01:41:57 +08:00
|
|
|
uptr GetMaxUserVirtualAddress() {
|
|
|
|
uptr addr = GetMaxVirtualAddress();
|
|
|
|
#if SANITIZER_WORDSIZE == 32 && !defined(__s390__)
|
|
|
|
if (!common_flags()->full_address_space)
|
|
|
|
addr -= GetKernelAreaSize();
|
|
|
|
CHECK_LT(reinterpret_cast<uptr>(&addr), addr);
|
|
|
|
#endif
|
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
|
2013-05-21 01:05:29 +08:00
|
|
|
uptr GetPageSize() {
|
2016-01-26 03:25:20 +08:00
|
|
|
// Android post-M sysconf(_SC_PAGESIZE) crashes if called from .preinit_array.
|
2016-07-27 05:02:44 +08:00
|
|
|
#if SANITIZER_ANDROID
|
|
|
|
return 4096;
|
|
|
|
#elif SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__))
|
2013-05-21 01:05:29 +08:00
|
|
|
return EXEC_PAGESIZE;
|
2017-03-23 23:57:58 +08:00
|
|
|
#elif SANITIZER_USE_GETAUXVAL
|
|
|
|
return getauxval(AT_PAGESZ);
|
2013-05-21 14:15:50 +08:00
|
|
|
#else
|
|
|
|
return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy.
|
|
|
|
#endif
|
2013-05-21 01:05:29 +08:00
|
|
|
}
|
|
|
|
|
2018-03-20 07:12:14 +08:00
|
|
|
#if !SANITIZER_OPENBSD
|
2013-09-10 22:36:16 +08:00
|
|
|
uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#if SANITIZER_SOLARIS
|
|
|
|
const char *default_module_name = getexecname();
|
|
|
|
CHECK_NE(default_module_name, NULL);
|
|
|
|
return internal_snprintf(buf, buf_len, "%s", default_module_name);
|
|
|
|
#else
|
2017-08-09 04:36:10 +08:00
|
|
|
#if SANITIZER_FREEBSD || SANITIZER_NETBSD
|
2014-05-29 20:12:42 +08:00
|
|
|
#if SANITIZER_FREEBSD
|
2017-08-09 04:36:10 +08:00
|
|
|
const int Mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
|
|
|
|
#else
|
|
|
|
const int Mib[4] = {CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME};
|
|
|
|
#endif
|
2015-06-04 15:29:43 +08:00
|
|
|
const char *default_module_name = "kern.proc.pathname";
|
2014-05-29 20:12:42 +08:00
|
|
|
size_t Size = buf_len;
|
2015-06-04 15:29:43 +08:00
|
|
|
bool IsErr = (sysctl(Mib, ARRAY_SIZE(Mib), buf, &Size, NULL, 0) != 0);
|
2014-05-29 20:12:42 +08:00
|
|
|
int readlink_error = IsErr ? errno : 0;
|
|
|
|
uptr module_name_len = Size;
|
|
|
|
#else
|
2015-06-04 15:29:43 +08:00
|
|
|
const char *default_module_name = "/proc/self/exe";
|
2013-09-10 22:36:16 +08:00
|
|
|
uptr module_name_len = internal_readlink(
|
2015-06-04 15:29:43 +08:00
|
|
|
default_module_name, buf, buf_len);
|
2013-09-10 22:36:16 +08:00
|
|
|
int readlink_error;
|
2014-05-29 20:12:42 +08:00
|
|
|
bool IsErr = internal_iserror(module_name_len, &readlink_error);
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#endif // SANITIZER_SOLARIS
|
2014-05-29 20:12:42 +08:00
|
|
|
if (IsErr) {
|
2015-06-04 15:29:43 +08:00
|
|
|
// We can't read binary name for some reason, assume it's unknown.
|
|
|
|
Report("WARNING: reading executable name failed with errno %d, "
|
2014-05-29 05:23:53 +08:00
|
|
|
"some stack frames may not be symbolized\n", readlink_error);
|
2015-06-04 15:29:43 +08:00
|
|
|
module_name_len = internal_snprintf(buf, buf_len, "%s",
|
|
|
|
default_module_name);
|
2013-09-10 22:36:16 +08:00
|
|
|
CHECK_LT(module_name_len, buf_len);
|
|
|
|
}
|
|
|
|
return module_name_len;
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#endif
|
2013-09-10 22:36:16 +08:00
|
|
|
}
|
2018-03-20 07:12:14 +08:00
|
|
|
#endif // !SANITIZER_OPENBSD
|
2013-09-10 22:36:16 +08:00
|
|
|
|
2015-07-29 05:01:42 +08:00
|
|
|
uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
|
2015-07-29 04:27:51 +08:00
|
|
|
#if SANITIZER_LINUX
|
|
|
|
char *tmpbuf;
|
|
|
|
uptr tmpsize;
|
|
|
|
uptr tmplen;
|
|
|
|
if (ReadFileToBuffer("/proc/self/cmdline", &tmpbuf, &tmpsize, &tmplen,
|
|
|
|
1024 * 1024)) {
|
|
|
|
internal_strncpy(buf, tmpbuf, buf_len);
|
|
|
|
UnmapOrDie(tmpbuf, tmpsize);
|
|
|
|
return internal_strlen(buf);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return ReadBinaryName(buf, buf_len);
|
|
|
|
}
|
|
|
|
|
2013-05-14 21:24:46 +08:00
|
|
|
// Match full names of the form /path/to/base_name{-,.}*
|
|
|
|
bool LibraryNameIs(const char *full_name, const char *base_name) {
|
|
|
|
const char *name = full_name;
|
|
|
|
// Strip path.
|
|
|
|
while (*name != '\0') name++;
|
|
|
|
while (name > full_name && *name != '/') name--;
|
|
|
|
if (*name == '/') name++;
|
|
|
|
uptr base_name_length = internal_strlen(base_name);
|
|
|
|
if (internal_strncmp(name, base_name, base_name_length)) return false;
|
|
|
|
return (name[base_name_length] == '-' || name[base_name_length] == '.');
|
|
|
|
}
|
|
|
|
|
2013-07-30 16:39:16 +08:00
|
|
|
#if !SANITIZER_ANDROID
|
2013-07-30 03:09:49 +08:00
|
|
|
// Call cb for each region mapped by map.
|
|
|
|
void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
|
2015-01-30 20:43:52 +08:00
|
|
|
CHECK_NE(map, nullptr);
|
2018-03-20 07:12:14 +08:00
|
|
|
#if !SANITIZER_FREEBSD && !SANITIZER_OPENBSD
|
2013-07-30 03:09:49 +08:00
|
|
|
typedef ElfW(Phdr) Elf_Phdr;
|
|
|
|
typedef ElfW(Ehdr) Elf_Ehdr;
|
2018-03-20 07:12:14 +08:00
|
|
|
#endif // !SANITIZER_FREEBSD && !SANITIZER_OPENBSD
|
2013-07-30 03:09:49 +08:00
|
|
|
char *base = (char *)map->l_addr;
|
|
|
|
Elf_Ehdr *ehdr = (Elf_Ehdr *)base;
|
|
|
|
char *phdrs = base + ehdr->e_phoff;
|
|
|
|
char *phdrs_end = phdrs + ehdr->e_phnum * ehdr->e_phentsize;
|
|
|
|
|
|
|
|
// Find the segment with the minimum base so we can "relocate" the p_vaddr
|
|
|
|
// fields. Typically ET_DYN objects (DSOs) have base of zero and ET_EXEC
|
|
|
|
// objects have a non-zero base.
|
2013-07-30 04:13:41 +08:00
|
|
|
uptr preferred_base = (uptr)-1;
|
2013-07-30 03:09:49 +08:00
|
|
|
for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
|
|
|
|
Elf_Phdr *phdr = (Elf_Phdr *)iter;
|
|
|
|
if (phdr->p_type == PT_LOAD && preferred_base > (uptr)phdr->p_vaddr)
|
|
|
|
preferred_base = (uptr)phdr->p_vaddr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute the delta from the real base to get a relocation delta.
|
|
|
|
sptr delta = (uptr)base - preferred_base;
|
|
|
|
// Now we can figure out what the loader really mapped.
|
|
|
|
for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
|
|
|
|
Elf_Phdr *phdr = (Elf_Phdr *)iter;
|
|
|
|
if (phdr->p_type == PT_LOAD) {
|
|
|
|
uptr seg_start = phdr->p_vaddr + delta;
|
|
|
|
uptr seg_end = seg_start + phdr->p_memsz;
|
|
|
|
// None of these values are aligned. We consider the ragged edges of the
|
|
|
|
// load command as defined, since they are mapped from the file.
|
|
|
|
seg_start = RoundDownTo(seg_start, GetPageSizeCached());
|
|
|
|
seg_end = RoundUpTo(seg_end, GetPageSizeCached());
|
|
|
|
cb((void *)seg_start, seg_end - seg_start);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-07-30 16:39:16 +08:00
|
|
|
#endif
|
2013-07-30 03:09:49 +08:00
|
|
|
|
2014-03-07 18:03:54 +08:00
|
|
|
#if defined(__x86_64__) && SANITIZER_LINUX
|
2013-09-02 19:36:19 +08:00
|
|
|
// We cannot use glibc's clone wrapper, because it messes with the child
|
|
|
|
// task's TLS. It writes the PID and TID of the child task to its thread
|
|
|
|
// descriptor, but in our case the child task shares the thread descriptor with
|
|
|
|
// the parent (because we don't know how to allocate a new thread
|
|
|
|
// descriptor to keep glibc happy). So the stock version of clone(), when
|
|
|
|
// used with CLONE_VM, would end up corrupting the parent's thread descriptor.
|
|
|
|
uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
|
|
|
|
int *parent_tidptr, void *newtls, int *child_tidptr) {
|
|
|
|
long long res;
|
|
|
|
if (!fn || !child_stack)
|
|
|
|
return -EINVAL;
|
|
|
|
CHECK_EQ(0, (uptr)child_stack % 16);
|
2013-11-07 01:47:39 +08:00
|
|
|
child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
|
|
|
|
((unsigned long long *)child_stack)[0] = (uptr)fn;
|
|
|
|
((unsigned long long *)child_stack)[1] = (uptr)arg;
|
|
|
|
register void *r8 __asm__("r8") = newtls;
|
|
|
|
register int *r10 __asm__("r10") = child_tidptr;
|
2013-09-02 19:36:19 +08:00
|
|
|
__asm__ __volatile__(
|
2014-03-07 18:03:54 +08:00
|
|
|
/* %rax = syscall(%rax = SYSCALL(clone),
|
2013-09-02 19:36:19 +08:00
|
|
|
* %rdi = flags,
|
|
|
|
* %rsi = child_stack,
|
|
|
|
* %rdx = parent_tidptr,
|
|
|
|
* %r8 = new_tls,
|
|
|
|
* %r10 = child_tidptr)
|
|
|
|
*/
|
|
|
|
"syscall\n"
|
|
|
|
|
|
|
|
/* if (%rax != 0)
|
|
|
|
* return;
|
|
|
|
*/
|
|
|
|
"testq %%rax,%%rax\n"
|
|
|
|
"jnz 1f\n"
|
|
|
|
|
|
|
|
/* In the child. Terminate unwind chain. */
|
2013-10-09 00:38:39 +08:00
|
|
|
// XXX: We should also terminate the CFI unwind chain
|
|
|
|
// here. Unfortunately clang 3.2 doesn't support the
|
|
|
|
// necessary CFI directives, so we skip that part.
|
2013-09-02 19:36:19 +08:00
|
|
|
"xorq %%rbp,%%rbp\n"
|
|
|
|
|
|
|
|
/* Call "fn(arg)". */
|
|
|
|
"popq %%rax\n"
|
|
|
|
"popq %%rdi\n"
|
|
|
|
"call *%%rax\n"
|
|
|
|
|
|
|
|
/* Call _exit(%rax). */
|
|
|
|
"movq %%rax,%%rdi\n"
|
|
|
|
"movq %2,%%rax\n"
|
|
|
|
"syscall\n"
|
|
|
|
|
|
|
|
/* Return to parent. */
|
|
|
|
"1:\n"
|
|
|
|
: "=a" (res)
|
2014-03-07 18:03:54 +08:00
|
|
|
: "a"(SYSCALL(clone)), "i"(SYSCALL(exit)),
|
2013-09-02 19:36:19 +08:00
|
|
|
"S"(child_stack),
|
|
|
|
"D"(flags),
|
|
|
|
"d"(parent_tidptr),
|
2013-11-07 01:47:39 +08:00
|
|
|
"r"(r8),
|
|
|
|
"r"(r10)
|
|
|
|
: "rsp", "memory", "r11", "rcx");
|
2013-09-02 19:36:19 +08:00
|
|
|
return res;
|
|
|
|
}
|
2015-02-19 15:30:39 +08:00
|
|
|
#elif defined(__mips__)
|
|
|
|
uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
|
|
|
|
int *parent_tidptr, void *newtls, int *child_tidptr) {
|
2015-05-06 13:38:21 +08:00
|
|
|
long long res;
|
|
|
|
if (!fn || !child_stack)
|
|
|
|
return -EINVAL;
|
|
|
|
CHECK_EQ(0, (uptr)child_stack % 16);
|
|
|
|
child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
|
|
|
|
((unsigned long long *)child_stack)[0] = (uptr)fn;
|
|
|
|
((unsigned long long *)child_stack)[1] = (uptr)arg;
|
|
|
|
register void *a3 __asm__("$7") = newtls;
|
|
|
|
register int *a4 __asm__("$8") = child_tidptr;
|
|
|
|
// We don't have proper CFI directives here because it requires alot of code
|
|
|
|
// for very marginal benefits.
|
|
|
|
__asm__ __volatile__(
|
|
|
|
/* $v0 = syscall($v0 = __NR_clone,
|
|
|
|
* $a0 = flags,
|
|
|
|
* $a1 = child_stack,
|
|
|
|
* $a2 = parent_tidptr,
|
|
|
|
* $a3 = new_tls,
|
|
|
|
* $a4 = child_tidptr)
|
|
|
|
*/
|
|
|
|
".cprestore 16;\n"
|
|
|
|
"move $4,%1;\n"
|
|
|
|
"move $5,%2;\n"
|
|
|
|
"move $6,%3;\n"
|
|
|
|
"move $7,%4;\n"
|
|
|
|
/* Store the fifth argument on stack
|
|
|
|
* if we are using 32-bit abi.
|
|
|
|
*/
|
|
|
|
#if SANITIZER_WORDSIZE == 32
|
|
|
|
"lw %5,16($29);\n"
|
|
|
|
#else
|
|
|
|
"move $8,%5;\n"
|
|
|
|
#endif
|
|
|
|
"li $2,%6;\n"
|
|
|
|
"syscall;\n"
|
|
|
|
|
|
|
|
/* if ($v0 != 0)
|
|
|
|
* return;
|
|
|
|
*/
|
|
|
|
"bnez $2,1f;\n"
|
|
|
|
|
|
|
|
/* Call "fn(arg)". */
|
2016-05-12 22:21:33 +08:00
|
|
|
#if SANITIZER_WORDSIZE == 32
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
"lw $25,4($29);\n"
|
|
|
|
"lw $4,12($29);\n"
|
|
|
|
#else
|
|
|
|
"lw $25,0($29);\n"
|
|
|
|
"lw $4,8($29);\n"
|
|
|
|
#endif
|
|
|
|
#else
|
2015-05-06 13:38:21 +08:00
|
|
|
"ld $25,0($29);\n"
|
|
|
|
"ld $4,8($29);\n"
|
2016-05-12 22:21:33 +08:00
|
|
|
#endif
|
2015-05-06 13:38:21 +08:00
|
|
|
"jal $25;\n"
|
|
|
|
|
|
|
|
/* Call _exit($v0). */
|
|
|
|
"move $4,$2;\n"
|
|
|
|
"li $2,%7;\n"
|
|
|
|
"syscall;\n"
|
|
|
|
|
|
|
|
/* Return to parent. */
|
|
|
|
"1:\n"
|
|
|
|
: "=r" (res)
|
|
|
|
: "r"(flags),
|
|
|
|
"r"(child_stack),
|
|
|
|
"r"(parent_tidptr),
|
|
|
|
"r"(a3),
|
|
|
|
"r"(a4),
|
|
|
|
"i"(__NR_clone),
|
|
|
|
"i"(__NR_exit)
|
|
|
|
: "memory", "$29" );
|
|
|
|
return res;
|
2015-02-19 15:30:39 +08:00
|
|
|
}
|
2015-08-05 23:17:59 +08:00
|
|
|
#elif defined(__aarch64__)
|
|
|
|
uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
|
|
|
|
int *parent_tidptr, void *newtls, int *child_tidptr) {
|
|
|
|
long long res;
|
|
|
|
if (!fn || !child_stack)
|
|
|
|
return -EINVAL;
|
|
|
|
CHECK_EQ(0, (uptr)child_stack % 16);
|
|
|
|
child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
|
|
|
|
((unsigned long long *)child_stack)[0] = (uptr)fn;
|
|
|
|
((unsigned long long *)child_stack)[1] = (uptr)arg;
|
|
|
|
|
|
|
|
register int (*__fn)(void *) __asm__("x0") = fn;
|
|
|
|
register void *__stack __asm__("x1") = child_stack;
|
|
|
|
register int __flags __asm__("x2") = flags;
|
|
|
|
register void *__arg __asm__("x3") = arg;
|
|
|
|
register int *__ptid __asm__("x4") = parent_tidptr;
|
|
|
|
register void *__tls __asm__("x5") = newtls;
|
|
|
|
register int *__ctid __asm__("x6") = child_tidptr;
|
|
|
|
|
|
|
|
__asm__ __volatile__(
|
|
|
|
"mov x0,x2\n" /* flags */
|
|
|
|
"mov x2,x4\n" /* ptid */
|
|
|
|
"mov x3,x5\n" /* tls */
|
|
|
|
"mov x4,x6\n" /* ctid */
|
|
|
|
"mov x8,%9\n" /* clone */
|
|
|
|
|
|
|
|
"svc 0x0\n"
|
|
|
|
|
|
|
|
/* if (%r0 != 0)
|
|
|
|
* return %r0;
|
|
|
|
*/
|
|
|
|
"cmp x0, #0\n"
|
|
|
|
"bne 1f\n"
|
|
|
|
|
|
|
|
/* In the child, now. Call "fn(arg)". */
|
|
|
|
"ldp x1, x0, [sp], #16\n"
|
|
|
|
"blr x1\n"
|
|
|
|
|
|
|
|
/* Call _exit(%r0). */
|
|
|
|
"mov x8, %10\n"
|
|
|
|
"svc 0x0\n"
|
|
|
|
"1:\n"
|
|
|
|
|
|
|
|
: "=r" (res)
|
|
|
|
: "i"(-EINVAL),
|
|
|
|
"r"(__fn), "r"(__stack), "r"(__flags), "r"(__arg),
|
|
|
|
"r"(__ptid), "r"(__tls), "r"(__ctid),
|
|
|
|
"i"(__NR_clone), "i"(__NR_exit)
|
|
|
|
: "x30", "memory");
|
|
|
|
return res;
|
|
|
|
}
|
2015-12-09 05:54:39 +08:00
|
|
|
#elif defined(__powerpc64__)
|
|
|
|
uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
|
|
|
|
int *parent_tidptr, void *newtls, int *child_tidptr) {
|
|
|
|
long long res;
|
2017-04-11 07:24:50 +08:00
|
|
|
// Stack frame structure.
|
|
|
|
#if SANITIZER_PPC64V1
|
|
|
|
// Back chain == 0 (SP + 112)
|
|
|
|
// Frame (112 bytes):
|
|
|
|
// Parameter save area (SP + 48), 8 doublewords
|
|
|
|
// TOC save area (SP + 40)
|
|
|
|
// Link editor doubleword (SP + 32)
|
|
|
|
// Compiler doubleword (SP + 24)
|
|
|
|
// LR save area (SP + 16)
|
|
|
|
// CR save area (SP + 8)
|
|
|
|
// Back chain (SP + 0)
|
|
|
|
# define FRAME_SIZE 112
|
|
|
|
# define FRAME_TOC_SAVE_OFFSET 40
|
|
|
|
#elif SANITIZER_PPC64V2
|
|
|
|
// Back chain == 0 (SP + 32)
|
|
|
|
// Frame (32 bytes):
|
|
|
|
// TOC save area (SP + 24)
|
|
|
|
// LR save area (SP + 16)
|
|
|
|
// CR save area (SP + 8)
|
|
|
|
// Back chain (SP + 0)
|
|
|
|
# define FRAME_SIZE 32
|
|
|
|
# define FRAME_TOC_SAVE_OFFSET 24
|
2015-12-09 05:54:39 +08:00
|
|
|
#else
|
2017-04-11 07:24:50 +08:00
|
|
|
# error "Unsupported PPC64 ABI"
|
2015-12-09 05:54:39 +08:00
|
|
|
#endif
|
|
|
|
if (!fn || !child_stack)
|
|
|
|
return -EINVAL;
|
|
|
|
CHECK_EQ(0, (uptr)child_stack % 16);
|
|
|
|
|
|
|
|
register int (*__fn)(void *) __asm__("r3") = fn;
|
|
|
|
register void *__cstack __asm__("r4") = child_stack;
|
|
|
|
register int __flags __asm__("r5") = flags;
|
2017-04-11 07:24:50 +08:00
|
|
|
register void *__arg __asm__("r6") = arg;
|
|
|
|
register int *__ptidptr __asm__("r7") = parent_tidptr;
|
|
|
|
register void *__newtls __asm__("r8") = newtls;
|
|
|
|
register int *__ctidptr __asm__("r9") = child_tidptr;
|
2015-12-09 05:54:39 +08:00
|
|
|
|
|
|
|
__asm__ __volatile__(
|
2017-04-11 07:24:50 +08:00
|
|
|
/* fn and arg are saved across the syscall */
|
2015-12-09 05:54:39 +08:00
|
|
|
"mr 28, %5\n\t"
|
|
|
|
"mr 27, %8\n\t"
|
|
|
|
|
|
|
|
/* syscall
|
2017-04-11 07:24:50 +08:00
|
|
|
r0 == __NR_clone
|
2015-12-09 05:54:39 +08:00
|
|
|
r3 == flags
|
|
|
|
r4 == child_stack
|
|
|
|
r5 == parent_tidptr
|
|
|
|
r6 == newtls
|
|
|
|
r7 == child_tidptr */
|
|
|
|
"mr 3, %7\n\t"
|
|
|
|
"mr 5, %9\n\t"
|
|
|
|
"mr 6, %10\n\t"
|
|
|
|
"mr 7, %11\n\t"
|
|
|
|
"li 0, %3\n\t"
|
|
|
|
"sc\n\t"
|
|
|
|
|
|
|
|
/* Test if syscall was successful */
|
|
|
|
"cmpdi cr1, 3, 0\n\t"
|
|
|
|
"crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t"
|
|
|
|
"bne- cr1, 1f\n\t"
|
|
|
|
|
2017-04-11 07:24:50 +08:00
|
|
|
/* Set up stack frame */
|
|
|
|
"li 29, 0\n\t"
|
|
|
|
"stdu 29, -8(1)\n\t"
|
|
|
|
"stdu 1, -%12(1)\n\t"
|
2015-12-09 05:54:39 +08:00
|
|
|
/* Do the function call */
|
|
|
|
"std 2, %13(1)\n\t"
|
2017-04-11 07:24:50 +08:00
|
|
|
#if SANITIZER_PPC64V1
|
2015-12-09 05:54:39 +08:00
|
|
|
"ld 0, 0(28)\n\t"
|
|
|
|
"ld 2, 8(28)\n\t"
|
|
|
|
"mtctr 0\n\t"
|
2017-04-11 07:24:50 +08:00
|
|
|
#elif SANITIZER_PPC64V2
|
2015-12-09 05:54:39 +08:00
|
|
|
"mr 12, 28\n\t"
|
|
|
|
"mtctr 12\n\t"
|
2017-04-11 07:24:50 +08:00
|
|
|
#else
|
|
|
|
# error "Unsupported PPC64 ABI"
|
2015-12-09 05:54:39 +08:00
|
|
|
#endif
|
|
|
|
"mr 3, 27\n\t"
|
|
|
|
"bctrl\n\t"
|
|
|
|
"ld 2, %13(1)\n\t"
|
|
|
|
|
|
|
|
/* Call _exit(r3) */
|
|
|
|
"li 0, %4\n\t"
|
|
|
|
"sc\n\t"
|
|
|
|
|
|
|
|
/* Return to parent */
|
|
|
|
"1:\n\t"
|
|
|
|
"mr %0, 3\n\t"
|
|
|
|
: "=r" (res)
|
2017-04-11 07:24:50 +08:00
|
|
|
: "0" (-1),
|
|
|
|
"i" (EINVAL),
|
|
|
|
"i" (__NR_clone),
|
|
|
|
"i" (__NR_exit),
|
|
|
|
"r" (__fn),
|
|
|
|
"r" (__cstack),
|
|
|
|
"r" (__flags),
|
|
|
|
"r" (__arg),
|
|
|
|
"r" (__ptidptr),
|
|
|
|
"r" (__newtls),
|
|
|
|
"r" (__ctidptr),
|
|
|
|
"i" (FRAME_SIZE),
|
|
|
|
"i" (FRAME_TOC_SAVE_OFFSET)
|
|
|
|
: "cr0", "cr1", "memory", "ctr", "r0", "r27", "r28", "r29");
|
2015-12-09 05:54:39 +08:00
|
|
|
return res;
|
|
|
|
}
|
2017-01-31 15:15:37 +08:00
|
|
|
#elif defined(__i386__) && SANITIZER_LINUX
|
|
|
|
uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
|
|
|
|
int *parent_tidptr, void *newtls, int *child_tidptr) {
|
|
|
|
int res;
|
|
|
|
if (!fn || !child_stack)
|
|
|
|
return -EINVAL;
|
|
|
|
CHECK_EQ(0, (uptr)child_stack % 16);
|
|
|
|
child_stack = (char *)child_stack - 7 * sizeof(unsigned int);
|
|
|
|
((unsigned int *)child_stack)[0] = (uptr)flags;
|
|
|
|
((unsigned int *)child_stack)[1] = (uptr)0;
|
|
|
|
((unsigned int *)child_stack)[2] = (uptr)fn;
|
|
|
|
((unsigned int *)child_stack)[3] = (uptr)arg;
|
|
|
|
__asm__ __volatile__(
|
|
|
|
/* %eax = syscall(%eax = SYSCALL(clone),
|
|
|
|
* %ebx = flags,
|
|
|
|
* %ecx = child_stack,
|
|
|
|
* %edx = parent_tidptr,
|
|
|
|
* %esi = new_tls,
|
|
|
|
* %edi = child_tidptr)
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Obtain flags */
|
|
|
|
"movl (%%ecx), %%ebx\n"
|
|
|
|
/* Do the system call */
|
|
|
|
"pushl %%ebx\n"
|
|
|
|
"pushl %%esi\n"
|
|
|
|
"pushl %%edi\n"
|
|
|
|
/* Remember the flag value. */
|
|
|
|
"movl %%ebx, (%%ecx)\n"
|
|
|
|
"int $0x80\n"
|
|
|
|
"popl %%edi\n"
|
|
|
|
"popl %%esi\n"
|
|
|
|
"popl %%ebx\n"
|
|
|
|
|
|
|
|
/* if (%eax != 0)
|
|
|
|
* return;
|
|
|
|
*/
|
|
|
|
|
|
|
|
"test %%eax,%%eax\n"
|
|
|
|
"jnz 1f\n"
|
|
|
|
|
|
|
|
/* terminate the stack frame */
|
|
|
|
"xorl %%ebp,%%ebp\n"
|
|
|
|
/* Call FN. */
|
|
|
|
"call *%%ebx\n"
|
|
|
|
#ifdef PIC
|
|
|
|
"call here\n"
|
|
|
|
"here:\n"
|
|
|
|
"popl %%ebx\n"
|
|
|
|
"addl $_GLOBAL_OFFSET_TABLE_+[.-here], %%ebx\n"
|
|
|
|
#endif
|
|
|
|
/* Call exit */
|
|
|
|
"movl %%eax, %%ebx\n"
|
|
|
|
"movl %2, %%eax\n"
|
|
|
|
"int $0x80\n"
|
|
|
|
"1:\n"
|
|
|
|
: "=a" (res)
|
|
|
|
: "a"(SYSCALL(clone)), "i"(SYSCALL(exit)),
|
|
|
|
"c"(child_stack),
|
|
|
|
"d"(parent_tidptr),
|
|
|
|
"S"(newtls),
|
|
|
|
"D"(child_tidptr)
|
|
|
|
: "memory");
|
|
|
|
return res;
|
|
|
|
}
|
2017-04-11 22:58:26 +08:00
|
|
|
#elif defined(__arm__) && SANITIZER_LINUX
|
|
|
|
uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
|
|
|
|
int *parent_tidptr, void *newtls, int *child_tidptr) {
|
|
|
|
unsigned int res;
|
|
|
|
if (!fn || !child_stack)
|
|
|
|
return -EINVAL;
|
|
|
|
child_stack = (char *)child_stack - 2 * sizeof(unsigned int);
|
|
|
|
((unsigned int *)child_stack)[0] = (uptr)fn;
|
|
|
|
((unsigned int *)child_stack)[1] = (uptr)arg;
|
|
|
|
register int r0 __asm__("r0") = flags;
|
|
|
|
register void *r1 __asm__("r1") = child_stack;
|
|
|
|
register int *r2 __asm__("r2") = parent_tidptr;
|
|
|
|
register void *r3 __asm__("r3") = newtls;
|
|
|
|
register int *r4 __asm__("r4") = child_tidptr;
|
|
|
|
register int r7 __asm__("r7") = __NR_clone;
|
|
|
|
|
|
|
|
#if __ARM_ARCH > 4 || defined (__ARM_ARCH_4T__)
|
|
|
|
# define ARCH_HAS_BX
|
|
|
|
#endif
|
|
|
|
#if __ARM_ARCH > 4
|
|
|
|
# define ARCH_HAS_BLX
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef ARCH_HAS_BX
|
|
|
|
# ifdef ARCH_HAS_BLX
|
|
|
|
# define BLX(R) "blx " #R "\n"
|
|
|
|
# else
|
|
|
|
# define BLX(R) "mov lr, pc; bx " #R "\n"
|
|
|
|
# endif
|
|
|
|
#else
|
|
|
|
# define BLX(R) "mov lr, pc; mov pc," #R "\n"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
__asm__ __volatile__(
|
|
|
|
/* %r0 = syscall(%r7 = SYSCALL(clone),
|
|
|
|
* %r0 = flags,
|
|
|
|
* %r1 = child_stack,
|
|
|
|
* %r2 = parent_tidptr,
|
|
|
|
* %r3 = new_tls,
|
|
|
|
* %r4 = child_tidptr)
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Do the system call */
|
|
|
|
"swi 0x0\n"
|
|
|
|
|
|
|
|
/* if (%r0 != 0)
|
|
|
|
* return %r0;
|
|
|
|
*/
|
|
|
|
"cmp r0, #0\n"
|
|
|
|
"bne 1f\n"
|
|
|
|
|
|
|
|
/* In the child, now. Call "fn(arg)". */
|
|
|
|
"ldr r0, [sp, #4]\n"
|
|
|
|
"ldr ip, [sp], #8\n"
|
|
|
|
BLX(ip)
|
|
|
|
/* Call _exit(%r0). */
|
|
|
|
"mov r7, %7\n"
|
|
|
|
"swi 0x0\n"
|
|
|
|
"1:\n"
|
|
|
|
"mov %0, r0\n"
|
|
|
|
: "=r"(res)
|
|
|
|
: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r7),
|
|
|
|
"i"(__NR_exit)
|
|
|
|
: "memory");
|
|
|
|
return res;
|
|
|
|
}
|
2014-03-07 18:03:54 +08:00
|
|
|
#endif // defined(__x86_64__) && SANITIZER_LINUX
|
2014-01-23 19:34:41 +08:00
|
|
|
|
|
|
|
#if SANITIZER_ANDROID
|
2015-05-07 02:55:31 +08:00
|
|
|
#if __ANDROID_API__ < 21
|
|
|
|
extern "C" __attribute__((weak)) int dl_iterate_phdr(
|
|
|
|
int (*)(struct dl_phdr_info *, size_t, void *), void *);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size,
|
|
|
|
void *data) {
|
2015-06-30 04:28:55 +08:00
|
|
|
// Any name starting with "lib" indicates a bug in L where library base names
|
2015-05-07 02:55:31 +08:00
|
|
|
// are returned instead of paths.
|
|
|
|
if (info->dlpi_name && info->dlpi_name[0] == 'l' &&
|
|
|
|
info->dlpi_name[1] == 'i' && info->dlpi_name[2] == 'b') {
|
|
|
|
*(bool *)data = true;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static atomic_uint32_t android_api_level;
|
|
|
|
|
2015-06-30 04:28:55 +08:00
|
|
|
static AndroidApiLevel AndroidDetectApiLevel() {
|
2015-06-09 02:15:52 +08:00
|
|
|
if (!&dl_iterate_phdr)
|
2015-06-30 04:28:55 +08:00
|
|
|
return ANDROID_KITKAT; // K or lower
|
2015-05-07 02:55:31 +08:00
|
|
|
bool base_name_seen = false;
|
|
|
|
dl_iterate_phdr(dl_iterate_phdr_test_cb, &base_name_seen);
|
|
|
|
if (base_name_seen)
|
2015-06-30 04:28:55 +08:00
|
|
|
return ANDROID_LOLLIPOP_MR1; // L MR1
|
|
|
|
return ANDROID_POST_LOLLIPOP; // post-L
|
2015-05-07 02:55:31 +08:00
|
|
|
// Plain L (API level 21) is completely broken wrt ASan and not very
|
|
|
|
// interesting to detect.
|
|
|
|
}
|
|
|
|
|
2015-06-30 04:28:55 +08:00
|
|
|
AndroidApiLevel AndroidGetApiLevel() {
|
|
|
|
AndroidApiLevel level =
|
|
|
|
(AndroidApiLevel)atomic_load(&android_api_level, memory_order_relaxed);
|
2015-05-07 02:55:31 +08:00
|
|
|
if (level) return level;
|
|
|
|
level = AndroidDetectApiLevel();
|
|
|
|
atomic_store(&android_api_level, level, memory_order_relaxed);
|
|
|
|
return level;
|
|
|
|
}
|
|
|
|
|
2014-01-23 19:34:41 +08:00
|
|
|
#endif
|
|
|
|
|
2017-06-15 08:19:13 +08:00
|
|
|
static HandleSignalMode GetHandleSignalModeImpl(int signum) {
|
2017-05-19 07:13:22 +08:00
|
|
|
switch (signum) {
|
|
|
|
case SIGABRT:
|
|
|
|
return common_flags()->handle_abort;
|
|
|
|
case SIGILL:
|
|
|
|
return common_flags()->handle_sigill;
|
2018-02-22 03:52:23 +08:00
|
|
|
case SIGTRAP:
|
|
|
|
return common_flags()->handle_sigtrap;
|
2017-05-19 07:13:22 +08:00
|
|
|
case SIGFPE:
|
|
|
|
return common_flags()->handle_sigfpe;
|
|
|
|
case SIGSEGV:
|
|
|
|
return common_flags()->handle_segv;
|
|
|
|
case SIGBUS:
|
|
|
|
return common_flags()->handle_sigbus;
|
|
|
|
}
|
2017-05-26 07:42:33 +08:00
|
|
|
return kHandleSignalNo;
|
2014-01-31 21:10:07 +08:00
|
|
|
}
|
|
|
|
|
2017-06-15 08:19:13 +08:00
|
|
|
HandleSignalMode GetHandleSignalMode(int signum) {
|
|
|
|
HandleSignalMode result = GetHandleSignalModeImpl(signum);
|
|
|
|
if (result == kHandleSignalYes && !common_flags()->allow_user_segv_handler)
|
|
|
|
return kHandleSignalExclusive;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2016-10-29 04:14:18 +08:00
|
|
|
#if !SANITIZER_GO
|
2014-12-17 03:13:01 +08:00
|
|
|
void *internal_start_thread(void(*func)(void *arg), void *arg) {
|
|
|
|
// Start the thread with signals blocked, otherwise it can steal user signals.
|
|
|
|
__sanitizer_sigset_t set, old;
|
|
|
|
internal_sigfillset(&set);
|
2015-06-27 07:39:23 +08:00
|
|
|
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
2015-04-23 17:33:27 +08:00
|
|
|
// Glibc uses SIGSETXID signal during setuid call. If this signal is blocked
|
|
|
|
// on any thread, setuid call hangs (see test/tsan/setuid.c).
|
|
|
|
internal_sigdelset(&set, 33);
|
2015-04-24 15:48:26 +08:00
|
|
|
#endif
|
2014-12-17 03:13:01 +08:00
|
|
|
internal_sigprocmask(SIG_SETMASK, &set, &old);
|
|
|
|
void *th;
|
2015-10-01 07:52:54 +08:00
|
|
|
real_pthread_create(&th, nullptr, (void*(*)(void *arg))func, arg);
|
|
|
|
internal_sigprocmask(SIG_SETMASK, &old, nullptr);
|
2014-12-17 03:13:01 +08:00
|
|
|
return th;
|
|
|
|
}
|
|
|
|
|
|
|
|
void internal_join_thread(void *th) {
|
2015-10-01 07:52:54 +08:00
|
|
|
real_pthread_join(th, nullptr);
|
2014-12-17 03:13:01 +08:00
|
|
|
}
|
2015-01-07 10:12:41 +08:00
|
|
|
#else
|
|
|
|
void *internal_start_thread(void (*func)(void *), void *arg) { return 0; }
|
|
|
|
|
|
|
|
void internal_join_thread(void *th) {}
|
|
|
|
#endif
|
2014-12-17 03:13:01 +08:00
|
|
|
|
2016-02-09 06:50:25 +08:00
|
|
|
#if defined(__aarch64__)
|
|
|
|
// Android headers in the older NDK releases miss this definition.
|
|
|
|
struct __sanitizer_esr_context {
|
|
|
|
struct _aarch64_ctx head;
|
|
|
|
uint64_t esr;
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) {
|
|
|
|
static const u32 kEsrMagic = 0x45535201;
|
|
|
|
u8 *aux = ucontext->uc_mcontext.__reserved;
|
|
|
|
while (true) {
|
|
|
|
_aarch64_ctx *ctx = (_aarch64_ctx *)aux;
|
|
|
|
if (ctx->size == 0) break;
|
|
|
|
if (ctx->magic == kEsrMagic) {
|
|
|
|
*esr = ((__sanitizer_esr_context *)ctx)->esr;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
aux += ctx->size;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-03-23 04:42:28 +08:00
|
|
|
#if SANITIZER_OPENBSD
|
|
|
|
using Context = sigcontext;
|
|
|
|
#else
|
2018-03-23 08:15:10 +08:00
|
|
|
using Context = ucontext_t;
|
|
|
|
#endif
|
2018-03-23 04:42:28 +08:00
|
|
|
|
2017-09-14 10:48:41 +08:00
|
|
|
SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
|
2018-03-23 08:15:10 +08:00
|
|
|
Context *ucontext = (Context *)context;
|
2016-02-04 10:33:48 +08:00
|
|
|
#if defined(__x86_64__) || defined(__i386__)
|
2016-02-09 06:50:25 +08:00
|
|
|
static const uptr PF_WRITE = 1U << 1;
|
2016-02-08 01:40:45 +08:00
|
|
|
#if SANITIZER_FREEBSD
|
2016-02-09 06:50:25 +08:00
|
|
|
uptr err = ucontext->uc_mcontext.mc_err;
|
2017-08-09 04:36:10 +08:00
|
|
|
#elif SANITIZER_NETBSD
|
|
|
|
uptr err = ucontext->uc_mcontext.__gregs[_REG_ERR];
|
2018-03-23 04:42:28 +08:00
|
|
|
#elif SANITIZER_OPENBSD
|
|
|
|
uptr err = ucontext->sc_err;
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#elif SANITIZER_SOLARIS && defined(__i386__)
|
2018-03-23 04:42:28 +08:00
|
|
|
const int Err = 13;
|
|
|
|
uptr err = ucontext->uc_mcontext.gregs[Err];
|
2016-02-08 01:40:45 +08:00
|
|
|
#else
|
2016-02-09 06:50:25 +08:00
|
|
|
uptr err = ucontext->uc_mcontext.gregs[REG_ERR];
|
2018-03-23 04:42:28 +08:00
|
|
|
#endif // SANITIZER_FREEBSD
|
2016-02-09 06:50:25 +08:00
|
|
|
return err & PF_WRITE ? WRITE : READ;
|
|
|
|
#elif defined(__arm__)
|
|
|
|
static const uptr FSR_WRITE = 1U << 11;
|
|
|
|
uptr fsr = ucontext->uc_mcontext.error_code;
|
|
|
|
return fsr & FSR_WRITE ? WRITE : READ;
|
|
|
|
#elif defined(__aarch64__)
|
|
|
|
static const u64 ESR_ELx_WNR = 1U << 6;
|
|
|
|
u64 esr;
|
|
|
|
if (!Aarch64GetESR(ucontext, &esr)) return UNKNOWN;
|
|
|
|
return esr & ESR_ELx_WNR ? WRITE : READ;
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#elif SANITIZER_SOLARIS && defined(__sparc__)
|
|
|
|
// Decode the instruction to determine the access type.
|
|
|
|
// From OpenSolaris $SRC/uts/sun4/os/trap.c (get_accesstype).
|
|
|
|
uptr pc = ucontext->uc_mcontext.gregs[REG_PC];
|
|
|
|
u32 instr = *(u32 *)pc;
|
|
|
|
return (instr >> 21) & 1 ? WRITE: READ;
|
2016-02-04 10:33:48 +08:00
|
|
|
#else
|
2016-02-09 08:28:57 +08:00
|
|
|
(void)ucontext;
|
2016-02-09 06:50:25 +08:00
|
|
|
return UNKNOWN; // FIXME: Implement.
|
2016-02-04 10:33:48 +08:00
|
|
|
#endif
|
2016-02-04 10:02:09 +08:00
|
|
|
}
|
|
|
|
|
2016-11-26 08:50:08 +08:00
|
|
|
void SignalContext::DumpAllRegisters(void *context) {
|
|
|
|
// FIXME: Implement this.
|
|
|
|
}
|
|
|
|
|
2017-09-14 10:48:41 +08:00
|
|
|
static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
|
Recognize all NetBSD architectures in UBSan
Summary:
Use uniform accessors for Program Pointer,
Stack Pointer and Frame Pointer.
Remove CPU check in UBSan supported platforms
and rely only on the OS type.
This adds NetBSD support in GetPcSpBp() for:
- ARM
- ARM64
- HPPA
- PowerPC/PowerPC64
- SPARC/SPARC64
- MIPS
- DEC Alpha AXP
- DEC VAX
- M68K and M68010
- SH3
- IA64
- OR1K
- RISCV
Sponsored by <The NetBSD Foundation>
Reviewers: joerg, vitalybuka, ro
Reviewed By: vitalybuka
Subscribers: aemerson, jyknight, sdardis, kubamracek, arichardson, llvm-commits, kristof.beyls, fedor.sergeev, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D43021
llvm-svn: 325431
2018-02-17 21:35:09 +08:00
|
|
|
#if SANITIZER_NETBSD
|
|
|
|
// This covers all NetBSD architectures
|
|
|
|
ucontext_t *ucontext = (ucontext_t *)context;
|
|
|
|
*pc = _UC_MACHINE_PC(ucontext);
|
|
|
|
*bp = _UC_MACHINE_FP(ucontext);
|
|
|
|
*sp = _UC_MACHINE_SP(ucontext);
|
|
|
|
#elif defined(__arm__)
|
2015-03-03 01:36:02 +08:00
|
|
|
ucontext_t *ucontext = (ucontext_t*)context;
|
|
|
|
*pc = ucontext->uc_mcontext.arm_pc;
|
|
|
|
*bp = ucontext->uc_mcontext.arm_fp;
|
|
|
|
*sp = ucontext->uc_mcontext.arm_sp;
|
|
|
|
#elif defined(__aarch64__)
|
|
|
|
ucontext_t *ucontext = (ucontext_t*)context;
|
|
|
|
*pc = ucontext->uc_mcontext.pc;
|
|
|
|
*bp = ucontext->uc_mcontext.regs[29];
|
|
|
|
*sp = ucontext->uc_mcontext.sp;
|
|
|
|
#elif defined(__hppa__)
|
|
|
|
ucontext_t *ucontext = (ucontext_t*)context;
|
|
|
|
*pc = ucontext->uc_mcontext.sc_iaoq[0];
|
|
|
|
/* GCC uses %r3 whenever a frame pointer is needed. */
|
|
|
|
*bp = ucontext->uc_mcontext.sc_gr[3];
|
|
|
|
*sp = ucontext->uc_mcontext.sc_gr[30];
|
|
|
|
#elif defined(__x86_64__)
|
|
|
|
# if SANITIZER_FREEBSD
|
|
|
|
ucontext_t *ucontext = (ucontext_t*)context;
|
|
|
|
*pc = ucontext->uc_mcontext.mc_rip;
|
|
|
|
*bp = ucontext->uc_mcontext.mc_rbp;
|
|
|
|
*sp = ucontext->uc_mcontext.mc_rsp;
|
2018-03-23 04:42:28 +08:00
|
|
|
#elif SANITIZER_OPENBSD
|
|
|
|
sigcontext *ucontext = (sigcontext *)context;
|
|
|
|
*pc = ucontext->sc_rip;
|
|
|
|
*bp = ucontext->sc_rbp;
|
|
|
|
*sp = ucontext->sc_rsp;
|
2015-03-03 01:36:02 +08:00
|
|
|
# else
|
|
|
|
ucontext_t *ucontext = (ucontext_t*)context;
|
|
|
|
*pc = ucontext->uc_mcontext.gregs[REG_RIP];
|
|
|
|
*bp = ucontext->uc_mcontext.gregs[REG_RBP];
|
|
|
|
*sp = ucontext->uc_mcontext.gregs[REG_RSP];
|
|
|
|
# endif
|
|
|
|
#elif defined(__i386__)
|
|
|
|
# if SANITIZER_FREEBSD
|
|
|
|
ucontext_t *ucontext = (ucontext_t*)context;
|
|
|
|
*pc = ucontext->uc_mcontext.mc_eip;
|
|
|
|
*bp = ucontext->uc_mcontext.mc_ebp;
|
|
|
|
*sp = ucontext->uc_mcontext.mc_esp;
|
2018-03-23 04:42:28 +08:00
|
|
|
#elif SANITIZER_OPENBSD
|
|
|
|
sigcontext *ucontext = (sigcontext *)context;
|
|
|
|
*pc = ucontext->sc_eip;
|
|
|
|
*bp = ucontext->sc_ebp;
|
|
|
|
*sp = ucontext->sc_esp;
|
2015-03-03 01:36:02 +08:00
|
|
|
# else
|
|
|
|
ucontext_t *ucontext = (ucontext_t*)context;
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
# if SANITIZER_SOLARIS
|
|
|
|
/* Use the numeric values: the symbolic ones are undefined by llvm
|
|
|
|
include/llvm/Support/Solaris.h. */
|
|
|
|
# ifndef REG_EIP
|
|
|
|
# define REG_EIP 14 // REG_PC
|
|
|
|
# endif
|
|
|
|
# ifndef REG_EBP
|
|
|
|
# define REG_EBP 6 // REG_FP
|
|
|
|
# endif
|
|
|
|
# ifndef REG_ESP
|
|
|
|
# define REG_ESP 17 // REG_SP
|
|
|
|
# endif
|
|
|
|
# endif
|
2015-03-03 01:36:02 +08:00
|
|
|
*pc = ucontext->uc_mcontext.gregs[REG_EIP];
|
|
|
|
*bp = ucontext->uc_mcontext.gregs[REG_EBP];
|
|
|
|
*sp = ucontext->uc_mcontext.gregs[REG_ESP];
|
|
|
|
# endif
|
|
|
|
#elif defined(__powerpc__) || defined(__powerpc64__)
|
|
|
|
ucontext_t *ucontext = (ucontext_t*)context;
|
|
|
|
*pc = ucontext->uc_mcontext.regs->nip;
|
|
|
|
*sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
|
|
|
|
// The powerpc{,64}-linux ABIs do not specify r31 as the frame
|
|
|
|
// pointer, but GCC always uses r31 when we need a frame pointer.
|
|
|
|
*bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
|
|
|
|
#elif defined(__sparc__)
|
|
|
|
ucontext_t *ucontext = (ucontext_t*)context;
|
|
|
|
uptr *stk_ptr;
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
# if defined (__sparcv9)
|
|
|
|
# ifndef MC_PC
|
|
|
|
# define MC_PC REG_PC
|
|
|
|
# endif
|
|
|
|
# ifndef MC_O6
|
|
|
|
# define MC_O6 REG_O6
|
|
|
|
# endif
|
|
|
|
# ifdef SANITIZER_SOLARIS
|
|
|
|
# define mc_gregs gregs
|
|
|
|
# endif
|
2015-03-03 01:36:02 +08:00
|
|
|
*pc = ucontext->uc_mcontext.mc_gregs[MC_PC];
|
|
|
|
*sp = ucontext->uc_mcontext.mc_gregs[MC_O6];
|
|
|
|
stk_ptr = (uptr *) (*sp + 2047);
|
|
|
|
*bp = stk_ptr[15];
|
|
|
|
# else
|
|
|
|
*pc = ucontext->uc_mcontext.gregs[REG_PC];
|
|
|
|
*sp = ucontext->uc_mcontext.gregs[REG_O6];
|
|
|
|
stk_ptr = (uptr *) *sp;
|
|
|
|
*bp = stk_ptr[15];
|
|
|
|
# endif
|
|
|
|
#elif defined(__mips__)
|
|
|
|
ucontext_t *ucontext = (ucontext_t*)context;
|
2015-05-06 14:53:09 +08:00
|
|
|
*pc = ucontext->uc_mcontext.pc;
|
2015-03-03 01:36:02 +08:00
|
|
|
*bp = ucontext->uc_mcontext.gregs[30];
|
|
|
|
*sp = ucontext->uc_mcontext.gregs[29];
|
2016-04-15 05:17:19 +08:00
|
|
|
#elif defined(__s390__)
|
|
|
|
ucontext_t *ucontext = (ucontext_t*)context;
|
|
|
|
# if defined(__s390x__)
|
|
|
|
*pc = ucontext->uc_mcontext.psw.addr;
|
|
|
|
# else
|
|
|
|
*pc = ucontext->uc_mcontext.psw.addr & 0x7fffffff;
|
|
|
|
# endif
|
|
|
|
*bp = ucontext->uc_mcontext.gregs[11];
|
|
|
|
*sp = ucontext->uc_mcontext.gregs[15];
|
2015-03-03 01:36:02 +08:00
|
|
|
#else
|
|
|
|
# error "Unsupported arch"
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-09-14 10:48:41 +08:00
|
|
|
void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); }
|
|
|
|
|
2015-12-03 18:39:43 +08:00
|
|
|
void MaybeReexec() {
|
|
|
|
// No need to re-exec on Linux.
|
|
|
|
}
|
|
|
|
|
2017-01-07 04:57:47 +08:00
|
|
|
void PrintModuleMap() { }
|
|
|
|
|
2017-03-09 18:47:38 +08:00
|
|
|
void CheckNoDeepBind(const char *filename, int flag) {
|
2017-03-15 02:18:14 +08:00
|
|
|
#ifdef RTLD_DEEPBIND
|
2017-03-09 18:47:38 +08:00
|
|
|
if (flag & RTLD_DEEPBIND) {
|
|
|
|
Report(
|
|
|
|
"You are trying to dlopen a %s shared library with RTLD_DEEPBIND flag"
|
|
|
|
" which is incompatibe with sanitizer runtime "
|
|
|
|
"(see https://github.com/google/sanitizers/issues/611 for details"
|
|
|
|
"). If you want to run %s library under sanitizers please remove "
|
|
|
|
"RTLD_DEEPBIND from dlopen flags.\n",
|
|
|
|
filename, filename);
|
|
|
|
Die();
|
|
|
|
}
|
2017-03-09 22:40:15 +08:00
|
|
|
#endif
|
2017-03-09 18:47:38 +08:00
|
|
|
}
|
|
|
|
|
2017-07-13 07:29:21 +08:00
|
|
|
uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
|
2018-02-27 02:33:21 +08:00
|
|
|
uptr *largest_gap_found,
|
|
|
|
uptr *max_occupied_addr) {
|
2016-10-06 04:33:59 +08:00
|
|
|
UNREACHABLE("FindAvailableMemoryRange is not available");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-08-14 22:53:47 +08:00
|
|
|
bool GetRandom(void *buffer, uptr length, bool blocking) {
|
[sanitizer] Add a function to gather random bytes
Summary:
AFAICT compiler-rt doesn't have a function that would return 'good' random
bytes to seed a PRNG. Currently, the `SizeClassAllocator64` uses addresses
returned by `mmap` to seed its PRNG, which is not ideal, and
`SizeClassAllocator32` doesn't benefit from the entropy offered by its 64-bit
counterpart address space, so right now it has nothing. This function aims at
solving this, allowing to implement good 32-bit chunk randomization. Scudo also
has a function that does this for Cookie purposes, which would go away in a
later CL once this lands.
This function will try the `getrandom` syscall if available, and fallback to
`/dev/urandom` if not.
Unfortunately, I do not have a way to implement and test a Mac and Windows
version, so those are unimplemented as of now. Note that `kRandomShuffleChunks`
is only used on Linux for now.
Reviewers: alekseyshl
Reviewed By: alekseyshl
Subscribers: zturner, rnk, llvm-commits, kubamracek
Differential Revision: https://reviews.llvm.org/D34412
llvm-svn: 305922
2017-06-21 23:56:03 +08:00
|
|
|
if (!buffer || !length || length > 256)
|
|
|
|
return false;
|
2017-08-14 22:53:47 +08:00
|
|
|
#if SANITIZER_USE_GETRANDOM
|
[sanitizer] Add a function to gather random bytes
Summary:
AFAICT compiler-rt doesn't have a function that would return 'good' random
bytes to seed a PRNG. Currently, the `SizeClassAllocator64` uses addresses
returned by `mmap` to seed its PRNG, which is not ideal, and
`SizeClassAllocator32` doesn't benefit from the entropy offered by its 64-bit
counterpart address space, so right now it has nothing. This function aims at
solving this, allowing to implement good 32-bit chunk randomization. Scudo also
has a function that does this for Cookie purposes, which would go away in a
later CL once this lands.
This function will try the `getrandom` syscall if available, and fallback to
`/dev/urandom` if not.
Unfortunately, I do not have a way to implement and test a Mac and Windows
version, so those are unimplemented as of now. Note that `kRandomShuffleChunks`
is only used on Linux for now.
Reviewers: alekseyshl
Reviewed By: alekseyshl
Subscribers: zturner, rnk, llvm-commits, kubamracek
Differential Revision: https://reviews.llvm.org/D34412
llvm-svn: 305922
2017-06-21 23:56:03 +08:00
|
|
|
static atomic_uint8_t skip_getrandom_syscall;
|
|
|
|
if (!atomic_load_relaxed(&skip_getrandom_syscall)) {
|
|
|
|
// Up to 256 bytes, getrandom will not be interrupted.
|
2017-08-14 22:53:47 +08:00
|
|
|
uptr res = internal_syscall(SYSCALL(getrandom), buffer, length,
|
|
|
|
blocking ? 0 : GRND_NONBLOCK);
|
[sanitizer] Add a function to gather random bytes
Summary:
AFAICT compiler-rt doesn't have a function that would return 'good' random
bytes to seed a PRNG. Currently, the `SizeClassAllocator64` uses addresses
returned by `mmap` to seed its PRNG, which is not ideal, and
`SizeClassAllocator32` doesn't benefit from the entropy offered by its 64-bit
counterpart address space, so right now it has nothing. This function aims at
solving this, allowing to implement good 32-bit chunk randomization. Scudo also
has a function that does this for Cookie purposes, which would go away in a
later CL once this lands.
This function will try the `getrandom` syscall if available, and fallback to
`/dev/urandom` if not.
Unfortunately, I do not have a way to implement and test a Mac and Windows
version, so those are unimplemented as of now. Note that `kRandomShuffleChunks`
is only used on Linux for now.
Reviewers: alekseyshl
Reviewed By: alekseyshl
Subscribers: zturner, rnk, llvm-commits, kubamracek
Differential Revision: https://reviews.llvm.org/D34412
llvm-svn: 305922
2017-06-21 23:56:03 +08:00
|
|
|
int rverrno = 0;
|
|
|
|
if (internal_iserror(res, &rverrno) && rverrno == ENOSYS)
|
|
|
|
atomic_store_relaxed(&skip_getrandom_syscall, 1);
|
|
|
|
else if (res == length)
|
|
|
|
return true;
|
|
|
|
}
|
2017-08-14 22:53:47 +08:00
|
|
|
#endif // SANITIZER_USE_GETRANDOM
|
|
|
|
// Up to 256 bytes, a read off /dev/urandom will not be interrupted.
|
|
|
|
// blocking is moot here, O_NONBLOCK has no effect when opening /dev/urandom.
|
[sanitizer] Add a function to gather random bytes
Summary:
AFAICT compiler-rt doesn't have a function that would return 'good' random
bytes to seed a PRNG. Currently, the `SizeClassAllocator64` uses addresses
returned by `mmap` to seed its PRNG, which is not ideal, and
`SizeClassAllocator32` doesn't benefit from the entropy offered by its 64-bit
counterpart address space, so right now it has nothing. This function aims at
solving this, allowing to implement good 32-bit chunk randomization. Scudo also
has a function that does this for Cookie purposes, which would go away in a
later CL once this lands.
This function will try the `getrandom` syscall if available, and fallback to
`/dev/urandom` if not.
Unfortunately, I do not have a way to implement and test a Mac and Windows
version, so those are unimplemented as of now. Note that `kRandomShuffleChunks`
is only used on Linux for now.
Reviewers: alekseyshl
Reviewed By: alekseyshl
Subscribers: zturner, rnk, llvm-commits, kubamracek
Differential Revision: https://reviews.llvm.org/D34412
llvm-svn: 305922
2017-06-21 23:56:03 +08:00
|
|
|
uptr fd = internal_open("/dev/urandom", O_RDONLY);
|
|
|
|
if (internal_iserror(fd))
|
|
|
|
return false;
|
|
|
|
uptr res = internal_read(fd, buffer, length);
|
|
|
|
if (internal_iserror(res))
|
|
|
|
return false;
|
|
|
|
internal_close(fd);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-10-01 07:52:54 +08:00
|
|
|
} // namespace __sanitizer
|
2012-06-04 22:27:50 +08:00
|
|
|
|
2018-03-20 07:12:14 +08:00
|
|
|
#endif
|