]>
Commit | Line | Data |
---|---|---|
1e80ce41 | 1 | //===-- sanitizer_linux.h ---------------------------------------*- C++ -*-===// |
2 | // | |
3 | // This file is distributed under the University of Illinois Open Source | |
4 | // License. See LICENSE.TXT for details. | |
5 | // | |
6 | //===----------------------------------------------------------------------===// | |
7 | // | |
8 | // Linux-specific syscall wrappers and classes. | |
9 | // | |
10 | //===----------------------------------------------------------------------===// | |
11 | #ifndef SANITIZER_LINUX_H | |
12 | #define SANITIZER_LINUX_H | |
13 | ||
14 | #include "sanitizer_platform.h" | |
d2ef4bee | 15 | #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ |
16 | SANITIZER_OPENBSD || SANITIZER_SOLARIS | |
1e80ce41 | 17 | #include "sanitizer_common.h" |
18 | #include "sanitizer_internal_defs.h" | |
36093749 | 19 | #include "sanitizer_platform_limits_netbsd.h" |
d2ef4bee | 20 | #include "sanitizer_platform_limits_openbsd.h" |
4fc7b5ac | 21 | #include "sanitizer_platform_limits_posix.h" |
d2ef4bee | 22 | #include "sanitizer_platform_limits_solaris.h" |
36093749 | 23 | #include "sanitizer_posix.h" |
1e80ce41 | 24 | |
25 | struct link_map; // Opaque type returned by dlopen(). | |
1e80ce41 | 26 | |
27 | namespace __sanitizer { | |
28 | // Dirent structure for getdents(). Note that this structure is different from | |
29 | // the one in <dirent.h>, which is used by readdir(). | |
30 | struct linux_dirent; | |
31 | ||
36093749 | 32 | struct ProcSelfMapsBuff { |
33 | char *data; | |
34 | uptr mmaped_size; | |
35 | uptr len; | |
36 | }; | |
37 | ||
38 | struct MemoryMappingLayoutData { | |
39 | ProcSelfMapsBuff proc_self_maps; | |
40 | const char *current; | |
41 | }; | |
42 | ||
43 | void ReadProcMaps(ProcSelfMapsBuff *proc_maps); | |
44 | ||
1e80ce41 | 45 | // Syscall wrappers. |
46 | uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count); | |
67dce058 | 47 | uptr internal_sigaltstack(const void* ss, void* oss); |
7d752f28 | 48 | uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, |
49 | __sanitizer_sigset_t *oldset); | |
d2ef4bee | 50 | uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp); |
4fc7b5ac | 51 | |
7d752f28 | 52 | // Linux-only syscalls. |
53 | #if SANITIZER_LINUX | |
54 | uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5); | |
55 | // Used only by sanitizer_stoptheworld. Signal handlers that are actually used | |
56 | // (like the process-wide error reporting SEGV handler) must use | |
57 | // internal_sigaction instead. | |
58 | int internal_sigaction_norestorer(int signum, const void *act, void *oldact); | |
23e39437 | 59 | #if (defined(__x86_64__) || SANITIZER_MIPS64) && !SANITIZER_GO |
60 | // Uses a raw system call to avoid interceptors. | |
61 | int internal_sigaction_syscall(int signum, const void *act, void *oldact); | |
62 | #endif | |
7d752f28 | 63 | void internal_sigdelset(__sanitizer_sigset_t *set, int signum); |
23e39437 | 64 | #if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) \ |
36093749 | 65 | || defined(__powerpc64__) || defined(__s390__) || defined(__i386__) \ |
66 | || defined(__arm__) | |
1e80ce41 | 67 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, |
68 | int *parent_tidptr, void *newtls, int *child_tidptr); | |
69 | #endif | |
d2ef4bee | 70 | #elif SANITIZER_FREEBSD |
71 | void internal_sigdelset(__sanitizer_sigset_t *set, int signum); | |
7d752f28 | 72 | #endif // SANITIZER_LINUX |
1e80ce41 | 73 | |
74 | // This class reads thread IDs from /proc/<pid>/task using only syscalls. | |
75 | class ThreadLister { | |
76 | public: | |
d2ef4bee | 77 | explicit ThreadLister(pid_t pid); |
1e80ce41 | 78 | ~ThreadLister(); |
d2ef4bee | 79 | enum Result { |
80 | Error, | |
81 | Incomplete, | |
82 | Ok, | |
83 | }; | |
84 | Result ListThreads(InternalMmapVector<tid_t> *threads); | |
1e80ce41 | 85 | |
86 | private: | |
d2ef4bee | 87 | bool IsAlive(int tid); |
88 | ||
89 | pid_t pid_; | |
90 | int descriptor_ = -1; | |
91 | InternalMmapVector<char> buffer_; | |
1e80ce41 | 92 | }; |
93 | ||
1e80ce41 | 94 | // Exposed for testing. |
95 | uptr ThreadDescriptorSize(); | |
96 | uptr ThreadSelf(); | |
97 | uptr ThreadSelfOffset(); | |
98 | ||
99 | // Matches a library's file name against a base name (stripping path and version | |
100 | // information). | |
101 | bool LibraryNameIs(const char *full_name, const char *base_name); | |
102 | ||
1e80ce41 | 103 | // Call cb for each region mapped by map. |
104 | void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)); | |
36093749 | 105 | |
106 | #if SANITIZER_ANDROID | |
107 | ||
108 | #if defined(__aarch64__) | |
109 | # define __get_tls() \ | |
110 | ({ void** __v; __asm__("mrs %0, tpidr_el0" : "=r"(__v)); __v; }) | |
111 | #elif defined(__arm__) | |
112 | # define __get_tls() \ | |
113 | ({ void** __v; __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__v)); __v; }) | |
114 | #elif defined(__mips__) | |
115 | // On mips32r1, this goes via a kernel illegal instruction trap that's | |
116 | // optimized for v1. | |
117 | # define __get_tls() \ | |
118 | ({ register void** __v asm("v1"); \ | |
119 | __asm__(".set push\n" \ | |
120 | ".set mips32r2\n" \ | |
121 | "rdhwr %0,$29\n" \ | |
122 | ".set pop\n" : "=r"(__v)); \ | |
123 | __v; }) | |
124 | #elif defined(__i386__) | |
125 | # define __get_tls() \ | |
126 | ({ void** __v; __asm__("movl %%gs:0, %0" : "=r"(__v)); __v; }) | |
127 | #elif defined(__x86_64__) | |
128 | # define __get_tls() \ | |
129 | ({ void** __v; __asm__("mov %%fs:0, %0" : "=r"(__v)); __v; }) | |
130 | #else | |
131 | #error "Unsupported architecture." | |
132 | #endif | |
133 | ||
134 | // The Android Bionic team has allocated a TLS slot for TSan starting with N, | |
135 | // given that Android currently doesn't support ELF TLS. It is used to store | |
136 | // Sanitizers thread specific data. | |
137 | static const int TLS_SLOT_TSAN = 8; | |
138 | ||
139 | ALWAYS_INLINE uptr *get_android_tls_ptr() { | |
140 | return reinterpret_cast<uptr *>(&__get_tls()[TLS_SLOT_TSAN]); | |
141 | } | |
142 | ||
143 | #endif // SANITIZER_ANDROID | |
144 | ||
1e80ce41 | 145 | } // namespace __sanitizer |
146 | ||
d2ef4bee | 147 | #endif |
1e80ce41 | 148 | #endif // SANITIZER_LINUX_H |