blob: 6e234e5f1e1dcf16ead9b23de710bccc4bf1c8f3 [file] [log] [blame]
Alexey Samsonovae4d9ca2012-06-04 14:27:50 +00001//===-- sanitizer_linux.cc ------------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is shared between AddressSanitizer and ThreadSanitizer
11// run-time libraries and implements linux-specific functions from
12// sanitizer_libc.h.
13//===----------------------------------------------------------------------===//
Evgeniy Stepanov24e13722013-03-19 14:33:38 +000014
15#include "sanitizer_platform.h"
16#if SANITIZER_LINUX
Alexey Samsonovae4d9ca2012-06-04 14:27:50 +000017
Alexey Samsonov6895adc2012-06-07 06:15:12 +000018#include "sanitizer_common.h"
Alexey Samsonov94b50362012-06-05 14:25:27 +000019#include "sanitizer_internal_defs.h"
Alexey Samsonovae4d9ca2012-06-04 14:27:50 +000020#include "sanitizer_libc.h"
Kostya Serebryany6fb47af2013-02-27 11:22:40 +000021#include "sanitizer_linux.h"
Alexander Potapenko93da8b62012-12-01 02:39:45 +000022#include "sanitizer_mutex.h"
Alexey Samsonova68633f2012-07-03 08:24:14 +000023#include "sanitizer_placement_new.h"
Alexey Samsonov6895adc2012-06-07 06:15:12 +000024#include "sanitizer_procmaps.h"
Kostya Serebryanya30c8f92012-12-13 09:34:23 +000025#include "sanitizer_stacktrace.h"
Alexander Potapenko5ce93fc2013-05-23 11:53:36 +000026#include "sanitizer_symbolizer.h"
Alexey Samsonovae4d9ca2012-06-04 14:27:50 +000027
Peter Collingbourne088ea2b2013-05-20 15:57:44 +000028#include <asm/param.h>
Evgeniy Stepanovb114ed82013-03-13 08:19:53 +000029#include <dlfcn.h>
Alexey Samsonov35a7faf2013-02-27 13:03:35 +000030#include <errno.h>
Alexey Samsonovc5d46512012-06-05 07:05:10 +000031#include <fcntl.h>
Alexey Samsonove5931fd2012-06-07 07:13:46 +000032#include <pthread.h>
Alexey Samsonov0969bcf2012-06-18 08:44:30 +000033#include <sched.h>
Alexey Samsonovae4d9ca2012-06-04 14:27:50 +000034#include <sys/mman.h>
Kostya Serebryany6fb47af2013-02-27 11:22:40 +000035#include <sys/ptrace.h>
Alexey Samsonove5931fd2012-06-07 07:13:46 +000036#include <sys/resource.h>
Alexey Samsonovc5d46512012-06-05 07:05:10 +000037#include <sys/stat.h>
Alexey Samsonovae4d9ca2012-06-04 14:27:50 +000038#include <sys/syscall.h>
Alexey Samsonove5931fd2012-06-07 07:13:46 +000039#include <sys/time.h>
Alexey Samsonovae4d9ca2012-06-04 14:27:50 +000040#include <sys/types.h>
41#include <unistd.h>
Kostya Serebryanya30c8f92012-12-13 09:34:23 +000042#include <unwind.h>
Alexey Samsonov35a7faf2013-02-27 13:03:35 +000043
Evgeniy Stepanov24e13722013-03-19 14:33:38 +000044#if !SANITIZER_ANDROID
Alexey Samsonov35a7faf2013-02-27 13:03:35 +000045#include <sys/signal.h>
46#endif
Dmitry Vyukovfa5c41e2013-01-30 14:39:27 +000047
Dmitry Vyukov4bebe7b2013-03-21 06:24:31 +000048// <linux/time.h>
49struct kernel_timeval {
50 long tv_sec;
51 long tv_usec;
52};
53
Dmitry Vyukovfa5c41e2013-01-30 14:39:27 +000054// <linux/futex.h> is broken on some linux distributions.
55const int FUTEX_WAIT = 0;
56const int FUTEX_WAKE = 1;
Alexey Samsonovae4d9ca2012-06-04 14:27:50 +000057
Kostya Serebryany9d0dbba2012-11-19 07:53:36 +000058// Are we using 32-bit or 64-bit syscalls?
Kostya Serebryany5af39e52012-11-21 12:38:58 +000059// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
Kostya Serebryany08bfe492012-11-20 08:57:26 +000060// but it still needs to use 64-bit syscalls.
Kostya Serebryany5af39e52012-11-21 12:38:58 +000061#if defined(__x86_64__) || SANITIZER_WORDSIZE == 64
Kostya Serebryany9d0dbba2012-11-19 07:53:36 +000062# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
63#else
64# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
65#endif
66
Alexey Samsonovae4d9ca2012-06-04 14:27:50 +000067namespace __sanitizer {
68
Peter Collingbourne9578a3e2013-05-08 14:43:49 +000069#ifdef __x86_64__
70#include "sanitizer_syscall_linux_x86_64.inc"
71#else
72#include "sanitizer_syscall_generic.inc"
73#endif
74
Alexey Samsonove5931fd2012-06-07 07:13:46 +000075// --------------- sanitizer_libc.h
Peter Collingbourne9578a3e2013-05-08 14:43:49 +000076uptr internal_mmap(void *addr, uptr length, int prot, int flags,
Alexey Samsonovae4d9ca2012-06-04 14:27:50 +000077 int fd, u64 offset) {
Kostya Serebryany9d0dbba2012-11-19 07:53:36 +000078#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
Peter Collingbourne9578a3e2013-05-08 14:43:49 +000079 return internal_syscall(__NR_mmap, addr, length, prot, flags, fd, offset);
Alexey Samsonovae4d9ca2012-06-04 14:27:50 +000080#else
Peter Collingbourne9578a3e2013-05-08 14:43:49 +000081 return internal_syscall(__NR_mmap2, addr, length, prot, flags, fd, offset);
Alexey Samsonovae4d9ca2012-06-04 14:27:50 +000082#endif
83}
84
Peter Collingbourne9578a3e2013-05-08 14:43:49 +000085uptr internal_munmap(void *addr, uptr length) {
86 return internal_syscall(__NR_munmap, addr, length);
Alexey Samsonov1f11d312012-06-05 09:49:25 +000087}
88
Peter Collingbourne9578a3e2013-05-08 14:43:49 +000089uptr internal_close(fd_t fd) {
90 return internal_syscall(__NR_close, fd);
Alexey Samsonova56aefd2012-06-05 08:32:53 +000091}
92
Peter Collingbourne9578a3e2013-05-08 14:43:49 +000093uptr internal_open(const char *filename, int flags) {
94 return internal_syscall(__NR_open, filename, flags);
Alexey Samsonovee7cc442013-02-01 15:58:46 +000095}
96
Peter Collingbourne9578a3e2013-05-08 14:43:49 +000097uptr internal_open(const char *filename, int flags, u32 mode) {
98 return internal_syscall(__NR_open, filename, flags, mode);
Alexey Samsonovee7cc442013-02-01 15:58:46 +000099}
100
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000101uptr OpenFile(const char *filename, bool write) {
Alexey Samsonovee7cc442013-02-01 15:58:46 +0000102 return internal_open(filename,
Kostya Serebryany9b8a9c12012-06-06 14:11:31 +0000103 write ? O_WRONLY | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660);
Alexey Samsonovc5d46512012-06-05 07:05:10 +0000104}
105
Alexey Samsonova56aefd2012-06-05 08:32:53 +0000106uptr internal_read(fd_t fd, void *buf, uptr count) {
Evgeniy Stepanov3334e122012-10-02 13:41:40 +0000107 sptr res;
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000108 HANDLE_EINTR(res, (sptr)internal_syscall(__NR_read, fd, buf, count));
Evgeniy Stepanov3334e122012-10-02 13:41:40 +0000109 return res;
Alexey Samsonova56aefd2012-06-05 08:32:53 +0000110}
111
112uptr internal_write(fd_t fd, const void *buf, uptr count) {
Evgeniy Stepanov3334e122012-10-02 13:41:40 +0000113 sptr res;
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000114 HANDLE_EINTR(res, (sptr)internal_syscall(__NR_write, fd, buf, count));
Evgeniy Stepanov3334e122012-10-02 13:41:40 +0000115 return res;
Alexey Samsonova56aefd2012-06-05 08:32:53 +0000116}
117
Evgeniy Stepanov2be3a282013-05-07 12:47:04 +0000118#if !SANITIZER_LINUX_USES_64BIT_SYSCALLS
119static void stat64_to_stat(struct stat64 *in, struct stat *out) {
120 internal_memset(out, 0, sizeof(*out));
121 out->st_dev = in->st_dev;
122 out->st_ino = in->st_ino;
123 out->st_mode = in->st_mode;
124 out->st_nlink = in->st_nlink;
125 out->st_uid = in->st_uid;
126 out->st_gid = in->st_gid;
127 out->st_rdev = in->st_rdev;
128 out->st_size = in->st_size;
129 out->st_blksize = in->st_blksize;
130 out->st_blocks = in->st_blocks;
131 out->st_atime = in->st_atime;
132 out->st_mtime = in->st_mtime;
133 out->st_ctime = in->st_ctime;
134 out->st_ino = in->st_ino;
135}
136#endif
137
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000138uptr internal_stat(const char *path, void *buf) {
Alexey Samsonov4c9317a2013-02-04 10:16:50 +0000139#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000140 return internal_syscall(__NR_stat, path, buf);
Alexey Samsonov4c9317a2013-02-04 10:16:50 +0000141#else
Evgeniy Stepanov2be3a282013-05-07 12:47:04 +0000142 struct stat64 buf64;
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000143 int res = internal_syscall(__NR_stat64, path, &buf64);
Evgeniy Stepanov2be3a282013-05-07 12:47:04 +0000144 stat64_to_stat(&buf64, (struct stat *)buf);
145 return res;
Alexey Samsonov4c9317a2013-02-04 10:16:50 +0000146#endif
147}
148
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000149uptr internal_lstat(const char *path, void *buf) {
Alexey Samsonov4c9317a2013-02-04 10:16:50 +0000150#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000151 return internal_syscall(__NR_lstat, path, buf);
Alexey Samsonov4c9317a2013-02-04 10:16:50 +0000152#else
Evgeniy Stepanov2be3a282013-05-07 12:47:04 +0000153 struct stat64 buf64;
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000154 int res = internal_syscall(__NR_lstat64, path, &buf64);
Evgeniy Stepanov2be3a282013-05-07 12:47:04 +0000155 stat64_to_stat(&buf64, (struct stat *)buf);
156 return res;
Alexey Samsonov4c9317a2013-02-04 10:16:50 +0000157#endif
158}
159
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000160uptr internal_fstat(fd_t fd, void *buf) {
Alexey Samsonov4c9317a2013-02-04 10:16:50 +0000161#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000162 return internal_syscall(__NR_fstat, fd, buf);
Alexey Samsonov4c9317a2013-02-04 10:16:50 +0000163#else
Evgeniy Stepanov2be3a282013-05-07 12:47:04 +0000164 struct stat64 buf64;
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000165 int res = internal_syscall(__NR_fstat64, fd, &buf64);
Evgeniy Stepanov2be3a282013-05-07 12:47:04 +0000166 stat64_to_stat(&buf64, (struct stat *)buf);
167 return res;
Alexey Samsonov4c9317a2013-02-04 10:16:50 +0000168#endif
169}
170
Alexey Samsonov8e820fc2012-06-06 07:30:33 +0000171uptr internal_filesize(fd_t fd) {
Alexey Samsonova68633f2012-07-03 08:24:14 +0000172 struct stat st;
Alexey Samsonov4c9317a2013-02-04 10:16:50 +0000173 if (internal_fstat(fd, &st))
174 return -1;
Alexey Samsonov8e820fc2012-06-06 07:30:33 +0000175 return (uptr)st.st_size;
176}
177
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000178uptr internal_dup2(int oldfd, int newfd) {
179 return internal_syscall(__NR_dup2, oldfd, newfd);
Alexey Samsonov8e820fc2012-06-06 07:30:33 +0000180}
181
Alexey Samsonovd1b8f582012-09-05 14:48:24 +0000182uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000183 return internal_syscall(__NR_readlink, path, buf, bufsize);
Alexey Samsonovd1b8f582012-09-05 14:48:24 +0000184}
185
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000186uptr internal_unlink(const char *path) {
187 return internal_syscall(__NR_unlink, path);
Dmitry Vyukov6d6ab9e2013-03-20 10:28:36 +0000188}
189
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000190uptr internal_sched_yield() {
191 return internal_syscall(__NR_sched_yield);
Alexey Samsonov0969bcf2012-06-18 08:44:30 +0000192}
193
Alexey Samsonovf8822472013-02-20 13:54:32 +0000194void internal__exit(int exitcode) {
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000195 internal_syscall(__NR_exit_group, exitcode);
Alexey Samsonovf8822472013-02-20 13:54:32 +0000196 Die(); // Unreachable.
197}
198
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000199uptr internal_execve(const char *filename, char *const argv[],
200 char *const envp[]) {
201 return internal_syscall(__NR_execve, filename, argv, envp);
202}
203
Alexey Samsonove5931fd2012-06-07 07:13:46 +0000204// ----------------- sanitizer_common.h
Alexey Samsonov93b4caf2012-11-09 14:45:30 +0000205bool FileExists(const char *filename) {
Alexey Samsonov93b4caf2012-11-09 14:45:30 +0000206 struct stat st;
Evgeniy Stepanov2be3a282013-05-07 12:47:04 +0000207 if (internal_stat(filename, &st))
Alexey Samsonov93b4caf2012-11-09 14:45:30 +0000208 return false;
Alexey Samsonov93b4caf2012-11-09 14:45:30 +0000209 // Sanity check: filename is a regular file.
210 return S_ISREG(st.st_mode);
211}
212
Dmitry Vyukove0023f72012-10-02 12:58:14 +0000213uptr GetTid() {
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000214 return internal_syscall(__NR_gettid);
Dmitry Vyukove0023f72012-10-02 12:58:14 +0000215}
216
Dmitry Vyukov4bebe7b2013-03-21 06:24:31 +0000217u64 NanoTime() {
218 kernel_timeval tv;
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000219 internal_syscall(__NR_gettimeofday, &tv, 0);
Dmitry Vyukov4bebe7b2013-03-21 06:24:31 +0000220 return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000;
221}
222
Alexey Samsonov3dbeabb2012-06-14 14:07:21 +0000223// Like getenv, but reads env directly from /proc and does not use libc.
224// This function should be called first inside __asan_init.
225const char *GetEnv(const char *name) {
226 static char *environ;
227 static uptr len;
228 static bool inited;
229 if (!inited) {
230 inited = true;
231 uptr environ_size;
232 len = ReadFileToBuffer("/proc/self/environ",
233 &environ, &environ_size, 1 << 26);
234 }
235 if (!environ || len == 0) return 0;
236 uptr namelen = internal_strlen(name);
237 const char *p = environ;
238 while (*p != '\0') { // will happen at the \0\0 that terminates the buffer
239 // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
240 const char* endp =
241 (char*)internal_memchr(p, '\0', len - (p - environ));
242 if (endp == 0) // this entry isn't NUL terminated
243 return 0;
244 else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=') // Match.
245 return p + namelen + 1; // point after =
246 p = endp + 1;
247 }
248 return 0; // Not found.
249}
250
Evgeniy Stepanoveab06112013-02-14 14:40:03 +0000251extern "C" {
Peter Collingbourne26337b62013-05-20 14:25:32 +0000252 extern void *__libc_stack_end SANITIZER_WEAK_ATTRIBUTE;
Evgeniy Stepanoveab06112013-02-14 14:40:03 +0000253}
254
Peter Collingbourne26337b62013-05-20 14:25:32 +0000255#if !SANITIZER_GO
Peter Collingbourne23709c92013-01-17 19:50:42 +0000256static void ReadNullSepFileToArray(const char *path, char ***arr,
257 int arr_size) {
258 char *buff;
Alexey Samsonovd7e5bb42012-09-17 09:12:39 +0000259 uptr buff_size = 0;
Peter Collingbourne23709c92013-01-17 19:50:42 +0000260 *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray");
261 ReadFileToBuffer(path, &buff, &buff_size, 1024 * 1024);
262 (*arr)[0] = buff;
263 int count, i;
264 for (count = 1, i = 1; ; i++) {
Alexey Samsonovd7e5bb42012-09-17 09:12:39 +0000265 if (buff[i] == 0) {
266 if (buff[i+1] == 0) break;
Peter Collingbourne23709c92013-01-17 19:50:42 +0000267 (*arr)[count] = &buff[i+1];
268 CHECK_LE(count, arr_size - 1); // FIXME: make this more flexible.
269 count++;
Alexey Samsonovd7e5bb42012-09-17 09:12:39 +0000270 }
271 }
Peter Collingbourne23709c92013-01-17 19:50:42 +0000272 (*arr)[count] = 0;
273}
Peter Collingbourne26337b62013-05-20 14:25:32 +0000274#endif
Peter Collingbourne23709c92013-01-17 19:50:42 +0000275
Peter Collingbourne26337b62013-05-20 14:25:32 +0000276static void GetArgsAndEnv(char*** argv, char*** envp) {
277#if !SANITIZER_GO
278 if (&__libc_stack_end) {
279#endif
280 uptr* stack_end = (uptr*)__libc_stack_end;
281 int argc = *stack_end;
282 *argv = (char**)(stack_end + 1);
283 *envp = (char**)(stack_end + argc + 2);
284#if !SANITIZER_GO
285 } else {
286 static const int kMaxArgv = 2000, kMaxEnvp = 2000;
287 ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv);
288 ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp);
289 }
290#endif
Evgeniy Stepanoveab06112013-02-14 14:40:03 +0000291}
292
Evgeniy Stepanoveab06112013-02-14 14:40:03 +0000293void ReExec() {
Peter Collingbourne23709c92013-01-17 19:50:42 +0000294 char **argv, **envp;
Evgeniy Stepanoveab06112013-02-14 14:40:03 +0000295 GetArgsAndEnv(&argv, &envp);
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000296 uptr rv = internal_execve("/proc/self/exe", argv, envp);
297 int rverrno;
298 CHECK_EQ(internal_iserror(rv, &rverrno), true);
299 Printf("execve failed, errno %d\n", rverrno);
Evgeniy Stepanovf35eae82013-02-19 11:09:29 +0000300 Die();
Alexey Samsonovd7e5bb42012-09-17 09:12:39 +0000301}
302
Alexander Potapenko25742572012-12-10 13:10:40 +0000303void PrepareForSandboxing() {
304 // Some kinds of sandboxes may forbid filesystem access, so we won't be able
305 // to read the file mappings from /proc/self/maps. Luckily, neither the
306 // process will be able to load additional libraries, so it's fine to use the
307 // cached mappings.
308 MemoryMappingLayout::CacheMemoryMappings();
Alexander Potapenko5ce93fc2013-05-23 11:53:36 +0000309 // Same for /proc/self/exe in the symbolizer.
310 SymbolizerPrepareForSandboxing();
Alexander Potapenko25742572012-12-10 13:10:40 +0000311}
312
Alexey Samsonove5931fd2012-06-07 07:13:46 +0000313// ----------------- sanitizer_procmaps.h
Dmitry Vyukov286dd3f2012-12-05 10:16:02 +0000314// Linker initialized.
315ProcSelfMapsBuff MemoryMappingLayout::cached_proc_self_maps_;
Alexander Potapenkoad912672012-12-03 21:21:22 +0000316StaticSpinMutex MemoryMappingLayout::cache_lock_; // Linker initialized.
Alexander Potapenko93da8b62012-12-01 02:39:45 +0000317
Alexander Potapenko9ae28832013-03-26 10:34:37 +0000318MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
Alexander Potapenkoad912672012-12-03 21:21:22 +0000319 proc_self_maps_.len =
320 ReadFileToBuffer("/proc/self/maps", &proc_self_maps_.data,
321 &proc_self_maps_.mmaped_size, 1 << 26);
Alexander Potapenko9ae28832013-03-26 10:34:37 +0000322 if (cache_enabled) {
323 if (proc_self_maps_.mmaped_size == 0) {
324 LoadFromCache();
325 CHECK_GT(proc_self_maps_.len, 0);
326 }
327 } else {
328 CHECK_GT(proc_self_maps_.mmaped_size, 0);
Alexander Potapenko93da8b62012-12-01 02:39:45 +0000329 }
Alexey Samsonov6895adc2012-06-07 06:15:12 +0000330 Reset();
Alexander Potapenko93da8b62012-12-01 02:39:45 +0000331 // FIXME: in the future we may want to cache the mappings on demand only.
Alexander Potapenko9ae28832013-03-26 10:34:37 +0000332 if (cache_enabled)
333 CacheMemoryMappings();
Alexey Samsonov6895adc2012-06-07 06:15:12 +0000334}
335
Alexey Samsonove1f5dac2012-08-27 13:48:48 +0000336MemoryMappingLayout::~MemoryMappingLayout() {
Alexander Potapenko7385f8b2012-12-04 23:30:00 +0000337 // Only unmap the buffer if it is different from the cached one. Otherwise
338 // it will be unmapped when the cache is refreshed.
339 if (proc_self_maps_.data != cached_proc_self_maps_.data) {
340 UnmapOrDie(proc_self_maps_.data, proc_self_maps_.mmaped_size);
341 }
Alexey Samsonov6895adc2012-06-07 06:15:12 +0000342}
343
Alexey Samsonove1f5dac2012-08-27 13:48:48 +0000344void MemoryMappingLayout::Reset() {
Alexander Potapenkoad912672012-12-03 21:21:22 +0000345 current_ = proc_self_maps_.data;
Alexey Samsonov6895adc2012-06-07 06:15:12 +0000346}
347
Alexander Potapenko93da8b62012-12-01 02:39:45 +0000348// static
349void MemoryMappingLayout::CacheMemoryMappings() {
350 SpinMutexLock l(&cache_lock_);
351 // Don't invalidate the cache if the mappings are unavailable.
Alexander Potapenkoad912672012-12-03 21:21:22 +0000352 ProcSelfMapsBuff old_proc_self_maps;
353 old_proc_self_maps = cached_proc_self_maps_;
354 cached_proc_self_maps_.len =
355 ReadFileToBuffer("/proc/self/maps", &cached_proc_self_maps_.data,
356 &cached_proc_self_maps_.mmaped_size, 1 << 26);
357 if (cached_proc_self_maps_.mmaped_size == 0) {
358 cached_proc_self_maps_ = old_proc_self_maps;
Alexander Potapenko93da8b62012-12-01 02:39:45 +0000359 } else {
Alexander Potapenkoad912672012-12-03 21:21:22 +0000360 if (old_proc_self_maps.mmaped_size) {
361 UnmapOrDie(old_proc_self_maps.data,
362 old_proc_self_maps.mmaped_size);
Alexander Potapenko93da8b62012-12-01 02:39:45 +0000363 }
364 }
365}
366
367void MemoryMappingLayout::LoadFromCache() {
368 SpinMutexLock l(&cache_lock_);
Alexander Potapenkoad912672012-12-03 21:21:22 +0000369 if (cached_proc_self_maps_.data) {
Dmitry Vyukov286dd3f2012-12-05 10:16:02 +0000370 proc_self_maps_ = cached_proc_self_maps_;
Alexander Potapenko93da8b62012-12-01 02:39:45 +0000371 }
372}
373
Kostya Serebryanya4e47442012-06-29 13:05:36 +0000374// Parse a hex value in str and update str.
375static uptr ParseHex(char **str) {
376 uptr x = 0;
377 char *s;
378 for (s = *str; ; s++) {
379 char c = *s;
380 uptr v = 0;
381 if (c >= '0' && c <= '9')
382 v = c - '0';
383 else if (c >= 'a' && c <= 'f')
384 v = c - 'a' + 10;
385 else if (c >= 'A' && c <= 'F')
386 v = c - 'A' + 10;
387 else
388 break;
389 x = x * 16 + v;
390 }
391 *str = s;
392 return x;
393}
394
Alexey Samsonovab11e0b2013-03-13 06:55:02 +0000395static bool IsOneOf(char c, char c1, char c2) {
Kostya Serebryanya4e47442012-06-29 13:05:36 +0000396 return c == c1 || c == c2;
397}
398
399static bool IsDecimal(char c) {
400 return c >= '0' && c <= '9';
401}
402
Alexey Samsonove1f5dac2012-08-27 13:48:48 +0000403bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
Alexey Samsonov45717c92013-03-13 06:51:02 +0000404 char filename[], uptr filename_size,
405 uptr *protection) {
Alexander Potapenkoad912672012-12-03 21:21:22 +0000406 char *last = proc_self_maps_.data + proc_self_maps_.len;
Alexey Samsonov6895adc2012-06-07 06:15:12 +0000407 if (current_ >= last) return false;
Alexey Samsonov6895adc2012-06-07 06:15:12 +0000408 uptr dummy;
409 if (!start) start = &dummy;
410 if (!end) end = &dummy;
411 if (!offset) offset = &dummy;
412 char *next_line = (char*)internal_memchr(current_, '\n', last - current_);
413 if (next_line == 0)
414 next_line = last;
Kostya Serebryanya4e47442012-06-29 13:05:36 +0000415 // Example: 08048000-08056000 r-xp 00000000 03:0c 64593 /foo/bar
416 *start = ParseHex(&current_);
Kostya Serebryanybb8a9512012-06-29 14:14:32 +0000417 CHECK_EQ(*current_++, '-');
Kostya Serebryanya4e47442012-06-29 13:05:36 +0000418 *end = ParseHex(&current_);
Kostya Serebryanybb8a9512012-06-29 14:14:32 +0000419 CHECK_EQ(*current_++, ' ');
Alexey Samsonov45717c92013-03-13 06:51:02 +0000420 uptr local_protection = 0;
Alexey Samsonovab11e0b2013-03-13 06:55:02 +0000421 CHECK(IsOneOf(*current_, '-', 'r'));
Alexey Samsonov45717c92013-03-13 06:51:02 +0000422 if (*current_++ == 'r')
423 local_protection |= kProtectionRead;
Alexey Samsonovab11e0b2013-03-13 06:55:02 +0000424 CHECK(IsOneOf(*current_, '-', 'w'));
Alexey Samsonov45717c92013-03-13 06:51:02 +0000425 if (*current_++ == 'w')
426 local_protection |= kProtectionWrite;
Alexey Samsonovab11e0b2013-03-13 06:55:02 +0000427 CHECK(IsOneOf(*current_, '-', 'x'));
Alexey Samsonov45717c92013-03-13 06:51:02 +0000428 if (*current_++ == 'x')
429 local_protection |= kProtectionExecute;
Alexey Samsonovab11e0b2013-03-13 06:55:02 +0000430 CHECK(IsOneOf(*current_, 's', 'p'));
Alexey Samsonov45717c92013-03-13 06:51:02 +0000431 if (*current_++ == 's')
432 local_protection |= kProtectionShared;
433 if (protection) {
434 *protection = local_protection;
435 }
Kostya Serebryanybb8a9512012-06-29 14:14:32 +0000436 CHECK_EQ(*current_++, ' ');
Kostya Serebryanya4e47442012-06-29 13:05:36 +0000437 *offset = ParseHex(&current_);
Kostya Serebryanybb8a9512012-06-29 14:14:32 +0000438 CHECK_EQ(*current_++, ' ');
Kostya Serebryanya4e47442012-06-29 13:05:36 +0000439 ParseHex(&current_);
Kostya Serebryanybb8a9512012-06-29 14:14:32 +0000440 CHECK_EQ(*current_++, ':');
Kostya Serebryanya4e47442012-06-29 13:05:36 +0000441 ParseHex(&current_);
Kostya Serebryanybb8a9512012-06-29 14:14:32 +0000442 CHECK_EQ(*current_++, ' ');
Kostya Serebryanya4e47442012-06-29 13:05:36 +0000443 while (IsDecimal(*current_))
444 current_++;
Kostya Serebryanybb8a9512012-06-29 14:14:32 +0000445 CHECK_EQ(*current_++, ' ');
Alexey Samsonov6895adc2012-06-07 06:15:12 +0000446 // Skip spaces.
447 while (current_ < next_line && *current_ == ' ')
448 current_++;
449 // Fill in the filename.
450 uptr i = 0;
451 while (current_ < next_line) {
452 if (filename && i < filename_size - 1)
453 filename[i++] = *current_;
454 current_++;
455 }
456 if (filename && i < filename_size)
457 filename[i] = 0;
458 current_ = next_line + 1;
459 return true;
460}
461
Alexey Samsonove1f5dac2012-08-27 13:48:48 +0000462// Gets the object name and the offset by walking MemoryMappingLayout.
463bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
464 char filename[],
Alexey Samsonov45717c92013-03-13 06:51:02 +0000465 uptr filename_size,
466 uptr *protection) {
467 return IterateForObjectNameAndOffset(addr, offset, filename, filename_size,
468 protection);
Alexey Samsonov6895adc2012-06-07 06:15:12 +0000469}
470
Dmitry Vyukovf4f51f22013-01-14 07:51:39 +0000471enum MutexState {
472 MtxUnlocked = 0,
473 MtxLocked = 1,
474 MtxSleeping = 2
475};
476
477BlockingMutex::BlockingMutex(LinkerInitialized) {
Dmitry Vyukovd164ed12013-01-14 08:21:34 +0000478 CHECK_EQ(owner_, 0);
Dmitry Vyukovf4f51f22013-01-14 07:51:39 +0000479}
480
Alexey Samsonov93af5942013-03-14 13:30:56 +0000481BlockingMutex::BlockingMutex() {
482 internal_memset(this, 0, sizeof(*this));
483}
484
Dmitry Vyukovf4f51f22013-01-14 07:51:39 +0000485void BlockingMutex::Lock() {
486 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
487 if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
488 return;
489 while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked)
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000490 internal_syscall(__NR_futex, m, FUTEX_WAIT, MtxSleeping, 0, 0, 0);
Dmitry Vyukovf4f51f22013-01-14 07:51:39 +0000491}
492
493void BlockingMutex::Unlock() {
494 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
495 u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed);
Dmitry Vyukov48526012013-01-14 08:01:58 +0000496 CHECK_NE(v, MtxUnlocked);
Dmitry Vyukovf4f51f22013-01-14 07:51:39 +0000497 if (v == MtxSleeping)
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000498 internal_syscall(__NR_futex, m, FUTEX_WAKE, 1, 0, 0, 0);
Dmitry Vyukovf4f51f22013-01-14 07:51:39 +0000499}
500
Alexey Samsonovce700972013-03-11 15:45:20 +0000501void BlockingMutex::CheckLocked() {
502 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
503 CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
504}
505
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000506// ----------------- sanitizer_linux.h
507// The actual size of this structure is specified by d_reclen.
508// Note that getdents64 uses a different structure format. We only provide the
509// 32-bit syscall here.
510struct linux_dirent {
511 unsigned long d_ino;
512 unsigned long d_off;
513 unsigned short d_reclen;
514 char d_name[256];
515};
516
517// Syscall wrappers.
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000518uptr internal_ptrace(int request, int pid, void *addr, void *data) {
519 return internal_syscall(__NR_ptrace, request, pid, addr, data);
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000520}
521
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000522uptr internal_waitpid(int pid, int *status, int options) {
523 return internal_syscall(__NR_wait4, pid, status, options, 0 /* rusage */);
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000524}
525
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000526uptr internal_getpid() {
527 return internal_syscall(__NR_getpid);
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000528}
529
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000530uptr internal_getppid() {
531 return internal_syscall(__NR_getppid);
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000532}
533
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000534uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
535 return internal_syscall(__NR_getdents, fd, dirp, count);
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000536}
537
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000538uptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
539 return internal_syscall(__NR_lseek, fd, offset, whence);
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000540}
541
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000542uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
543 return internal_syscall(__NR_prctl, option, arg2, arg3, arg4, arg5);
544}
545
546uptr internal_sigaltstack(const struct sigaltstack *ss,
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000547 struct sigaltstack *oss) {
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000548 return internal_syscall(__NR_sigaltstack, ss, oss);
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000549}
550
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000551// ThreadLister implementation.
552ThreadLister::ThreadLister(int pid)
553 : pid_(pid),
554 descriptor_(-1),
Alexey Samsonov10f3ab72013-04-05 07:41:21 +0000555 buffer_(4096),
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000556 error_(true),
Alexey Samsonov10f3ab72013-04-05 07:41:21 +0000557 entry_((struct linux_dirent *)buffer_.data()),
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000558 bytes_read_(0) {
559 char task_directory_path[80];
560 internal_snprintf(task_directory_path, sizeof(task_directory_path),
561 "/proc/%d/task/", pid);
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000562 uptr openrv = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY);
563 if (internal_iserror(openrv)) {
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000564 error_ = true;
565 Report("Can't open /proc/%d/task for reading.\n", pid);
566 } else {
567 error_ = false;
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000568 descriptor_ = openrv;
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000569 }
570}
571
572int ThreadLister::GetNextTID() {
573 int tid = -1;
574 do {
575 if (error_)
576 return -1;
577 if ((char *)entry_ >= &buffer_[bytes_read_] && !GetDirectoryEntries())
578 return -1;
579 if (entry_->d_ino != 0 && entry_->d_name[0] >= '0' &&
580 entry_->d_name[0] <= '9') {
581 // Found a valid tid.
582 tid = (int)internal_atoll(entry_->d_name);
583 }
584 entry_ = (struct linux_dirent *)(((char *)entry_) + entry_->d_reclen);
585 } while (tid < 0);
586 return tid;
587}
588
589void ThreadLister::Reset() {
590 if (error_ || descriptor_ < 0)
591 return;
592 internal_lseek(descriptor_, 0, SEEK_SET);
593}
594
595ThreadLister::~ThreadLister() {
596 if (descriptor_ >= 0)
597 internal_close(descriptor_);
598}
599
600bool ThreadLister::error() { return error_; }
601
602bool ThreadLister::GetDirectoryEntries() {
603 CHECK_GE(descriptor_, 0);
604 CHECK_NE(error_, true);
605 bytes_read_ = internal_getdents(descriptor_,
Alexey Samsonov10f3ab72013-04-05 07:41:21 +0000606 (struct linux_dirent *)buffer_.data(),
607 buffer_.size());
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000608 if (internal_iserror(bytes_read_)) {
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000609 Report("Can't read directory entries from /proc/%d/task.\n", pid_);
610 error_ = true;
611 return false;
612 } else if (bytes_read_ == 0) {
613 return false;
614 }
Alexey Samsonov10f3ab72013-04-05 07:41:21 +0000615 entry_ = (struct linux_dirent *)buffer_.data();
Kostya Serebryany6fb47af2013-02-27 11:22:40 +0000616 return true;
617}
618
Peter Collingbourne4df343a2013-05-20 17:05:29 +0000619uptr GetPageSize() {
Kostya Serebryanya8bc34e2013-05-21 06:15:50 +0000620#if defined(__x86_64__) || defined(__i386__)
Peter Collingbourne4df343a2013-05-20 17:05:29 +0000621 return EXEC_PAGESIZE;
Kostya Serebryanya8bc34e2013-05-21 06:15:50 +0000622#else
623 return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy.
624#endif
Peter Collingbourne4df343a2013-05-20 17:05:29 +0000625}
626
Sergey Matveev3de00862013-05-14 13:24:46 +0000627// Match full names of the form /path/to/base_name{-,.}*
628bool LibraryNameIs(const char *full_name, const char *base_name) {
629 const char *name = full_name;
630 // Strip path.
631 while (*name != '\0') name++;
632 while (name > full_name && *name != '/') name--;
633 if (*name == '/') name++;
634 uptr base_name_length = internal_strlen(base_name);
635 if (internal_strncmp(name, base_name, base_name_length)) return false;
636 return (name[base_name_length] == '-' || name[base_name_length] == '.');
637}
638
Alexey Samsonovae4d9ca2012-06-04 14:27:50 +0000639} // namespace __sanitizer
640
Alexey Samsonov46f93952013-04-03 07:24:35 +0000641#endif // SANITIZER_LINUX