1 //===-- sanitizer_linux.cc ------------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is shared between AddressSanitizer and ThreadSanitizer
9 // run-time libraries and implements linux-specific functions from
11 //===----------------------------------------------------------------------===//
13 #include "sanitizer_platform.h"
16 #include "sanitizer_common.h"
17 #include "sanitizer_internal_defs.h"
18 #include "sanitizer_libc.h"
19 #include "sanitizer_linux.h"
20 #include "sanitizer_mutex.h"
21 #include "sanitizer_placement_new.h"
22 #include "sanitizer_procmaps.h"
23 #include "sanitizer_stacktrace.h"
24 #include "sanitizer_symbolizer.h"
26 #include <asm/param.h>
30 #if !SANITIZER_ANDROID
36 #include <sys/ptrace.h>
37 #include <sys/resource.h>
39 #include <sys/syscall.h>
41 #include <sys/types.h>
45 #if !SANITIZER_ANDROID
46 #include <sys/signal.h>
50 struct kernel_timeval
{
55 // <linux/futex.h> is broken on some linux distributions.
56 const int FUTEX_WAIT
= 0;
57 const int FUTEX_WAKE
= 1;
59 // Are we using 32-bit or 64-bit syscalls?
60 // x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
61 // but it still needs to use 64-bit syscalls.
62 #if defined(__x86_64__) || SANITIZER_WORDSIZE == 64
63 # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
65 # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
68 namespace __sanitizer
{
71 #include "sanitizer_syscall_linux_x86_64.inc"
73 #include "sanitizer_syscall_generic.inc"
76 // --------------- sanitizer_libc.h
77 uptr
internal_mmap(void *addr
, uptr length
, int prot
, int flags
,
79 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
80 return internal_syscall(__NR_mmap
, (uptr
)addr
, length
, prot
, flags
, fd
, offset
);
82 return internal_syscall(__NR_mmap2
, addr
, length
, prot
, flags
, fd
, offset
);
86 uptr
internal_munmap(void *addr
, uptr length
) {
87 return internal_syscall(__NR_munmap
, (uptr
)addr
, length
);
90 uptr
internal_close(fd_t fd
) {
91 return internal_syscall(__NR_close
, fd
);
94 uptr
internal_open(const char *filename
, int flags
) {
95 return internal_syscall(__NR_open
, (uptr
)filename
, flags
);
98 uptr
internal_open(const char *filename
, int flags
, u32 mode
) {
99 return internal_syscall(__NR_open
, (uptr
)filename
, flags
, mode
);
102 uptr
OpenFile(const char *filename
, bool write
) {
103 return internal_open(filename
,
104 write
? O_WRONLY
| O_CREAT
/*| O_CLOEXEC*/ : O_RDONLY
, 0660);
107 uptr
internal_read(fd_t fd
, void *buf
, uptr count
) {
109 HANDLE_EINTR(res
, (sptr
)internal_syscall(__NR_read
, fd
, (uptr
)buf
, count
));
113 uptr
internal_write(fd_t fd
, const void *buf
, uptr count
) {
115 HANDLE_EINTR(res
, (sptr
)internal_syscall(__NR_write
, fd
, (uptr
)buf
, count
));
119 #if !SANITIZER_LINUX_USES_64BIT_SYSCALLS
120 static void stat64_to_stat(struct stat64
*in
, struct stat
*out
) {
121 internal_memset(out
, 0, sizeof(*out
));
122 out
->st_dev
= in
->st_dev
;
123 out
->st_ino
= in
->st_ino
;
124 out
->st_mode
= in
->st_mode
;
125 out
->st_nlink
= in
->st_nlink
;
126 out
->st_uid
= in
->st_uid
;
127 out
->st_gid
= in
->st_gid
;
128 out
->st_rdev
= in
->st_rdev
;
129 out
->st_size
= in
->st_size
;
130 out
->st_blksize
= in
->st_blksize
;
131 out
->st_blocks
= in
->st_blocks
;
132 out
->st_atime
= in
->st_atime
;
133 out
->st_mtime
= in
->st_mtime
;
134 out
->st_ctime
= in
->st_ctime
;
135 out
->st_ino
= in
->st_ino
;
139 uptr
internal_stat(const char *path
, void *buf
) {
140 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
141 return internal_syscall(__NR_stat
, (uptr
)path
, (uptr
)buf
);
144 int res
= internal_syscall(__NR_stat64
, path
, &buf64
);
145 stat64_to_stat(&buf64
, (struct stat
*)buf
);
150 uptr
internal_lstat(const char *path
, void *buf
) {
151 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
152 return internal_syscall(__NR_lstat
, (uptr
)path
, (uptr
)buf
);
155 int res
= internal_syscall(__NR_lstat64
, path
, &buf64
);
156 stat64_to_stat(&buf64
, (struct stat
*)buf
);
161 uptr
internal_fstat(fd_t fd
, void *buf
) {
162 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
163 return internal_syscall(__NR_fstat
, fd
, (uptr
)buf
);
166 int res
= internal_syscall(__NR_fstat64
, fd
, &buf64
);
167 stat64_to_stat(&buf64
, (struct stat
*)buf
);
172 uptr
internal_filesize(fd_t fd
) {
174 if (internal_fstat(fd
, &st
))
176 return (uptr
)st
.st_size
;
179 uptr
internal_dup2(int oldfd
, int newfd
) {
180 return internal_syscall(__NR_dup2
, oldfd
, newfd
);
183 uptr
internal_readlink(const char *path
, char *buf
, uptr bufsize
) {
184 return internal_syscall(__NR_readlink
, (uptr
)path
, (uptr
)buf
, bufsize
);
187 uptr
internal_unlink(const char *path
) {
188 return internal_syscall(__NR_unlink
, (uptr
)path
);
191 uptr
internal_sched_yield() {
192 return internal_syscall(__NR_sched_yield
);
195 void internal__exit(int exitcode
) {
196 internal_syscall(__NR_exit_group
, exitcode
);
197 Die(); // Unreachable.
200 uptr
internal_execve(const char *filename
, char *const argv
[],
201 char *const envp
[]) {
202 return internal_syscall(__NR_execve
, (uptr
)filename
, (uptr
)argv
, (uptr
)envp
);
205 // ----------------- sanitizer_common.h
206 bool FileExists(const char *filename
) {
208 if (internal_stat(filename
, &st
))
210 // Sanity check: filename is a regular file.
211 return S_ISREG(st
.st_mode
);
215 return internal_syscall(__NR_gettid
);
219 kernel_timeval tv
= {};
220 internal_syscall(__NR_gettimeofday
, (uptr
)&tv
, 0);
221 return (u64
)tv
.tv_sec
* 1000*1000*1000 + tv
.tv_usec
* 1000;
224 // Like getenv, but reads env directly from /proc and does not use libc.
225 // This function should be called first inside __asan_init.
226 const char *GetEnv(const char *name
) {
227 static char *environ
;
233 len
= ReadFileToBuffer("/proc/self/environ",
234 &environ
, &environ_size
, 1 << 26);
236 if (!environ
|| len
== 0) return 0;
237 uptr namelen
= internal_strlen(name
);
238 const char *p
= environ
;
239 while (*p
!= '\0') { // will happen at the \0\0 that terminates the buffer
240 // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
242 (char*)internal_memchr(p
, '\0', len
- (p
- environ
));
243 if (endp
== 0) // this entry isn't NUL terminated
245 else if (!internal_memcmp(p
, name
, namelen
) && p
[namelen
] == '=') // Match.
246 return p
+ namelen
+ 1; // point after =
249 return 0; // Not found.
253 SANITIZER_WEAK_ATTRIBUTE
extern void *__libc_stack_end
;
257 static void ReadNullSepFileToArray(const char *path
, char ***arr
,
261 *arr
= (char **)MmapOrDie(arr_size
* sizeof(char *), "NullSepFileArray");
262 ReadFileToBuffer(path
, &buff
, &buff_size
, 1024 * 1024);
265 for (count
= 1, i
= 1; ; i
++) {
267 if (buff
[i
+1] == 0) break;
268 (*arr
)[count
] = &buff
[i
+1];
269 CHECK_LE(count
, arr_size
- 1); // FIXME: make this more flexible.
277 static void GetArgsAndEnv(char*** argv
, char*** envp
) {
279 if (&__libc_stack_end
) {
281 uptr
* stack_end
= (uptr
*)__libc_stack_end
;
282 int argc
= *stack_end
;
283 *argv
= (char**)(stack_end
+ 1);
284 *envp
= (char**)(stack_end
+ argc
+ 2);
287 static const int kMaxArgv
= 2000, kMaxEnvp
= 2000;
288 ReadNullSepFileToArray("/proc/self/cmdline", argv
, kMaxArgv
);
289 ReadNullSepFileToArray("/proc/self/environ", envp
, kMaxEnvp
);
296 GetArgsAndEnv(&argv
, &envp
);
297 uptr rv
= internal_execve("/proc/self/exe", argv
, envp
);
299 CHECK_EQ(internal_iserror(rv
, &rverrno
), true);
300 Printf("execve failed, errno %d\n", rverrno
);
304 void PrepareForSandboxing() {
305 // Some kinds of sandboxes may forbid filesystem access, so we won't be able
306 // to read the file mappings from /proc/self/maps. Luckily, neither the
307 // process will be able to load additional libraries, so it's fine to use the
309 MemoryMappingLayout::CacheMemoryMappings();
310 // Same for /proc/self/exe in the symbolizer.
312 getSymbolizer()->PrepareForSandboxing();
316 // ----------------- sanitizer_procmaps.h
317 // Linker initialized.
318 ProcSelfMapsBuff
MemoryMappingLayout::cached_proc_self_maps_
;
319 StaticSpinMutex
MemoryMappingLayout::cache_lock_
; // Linker initialized.
321 MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled
) {
322 proc_self_maps_
.len
=
323 ReadFileToBuffer("/proc/self/maps", &proc_self_maps_
.data
,
324 &proc_self_maps_
.mmaped_size
, 1 << 26);
326 if (proc_self_maps_
.mmaped_size
== 0) {
328 CHECK_GT(proc_self_maps_
.len
, 0);
331 CHECK_GT(proc_self_maps_
.mmaped_size
, 0);
334 // FIXME: in the future we may want to cache the mappings on demand only.
336 CacheMemoryMappings();
339 MemoryMappingLayout::~MemoryMappingLayout() {
340 // Only unmap the buffer if it is different from the cached one. Otherwise
341 // it will be unmapped when the cache is refreshed.
342 if (proc_self_maps_
.data
!= cached_proc_self_maps_
.data
) {
343 UnmapOrDie(proc_self_maps_
.data
, proc_self_maps_
.mmaped_size
);
347 void MemoryMappingLayout::Reset() {
348 current_
= proc_self_maps_
.data
;
352 void MemoryMappingLayout::CacheMemoryMappings() {
353 SpinMutexLock
l(&cache_lock_
);
354 // Don't invalidate the cache if the mappings are unavailable.
355 ProcSelfMapsBuff old_proc_self_maps
;
356 old_proc_self_maps
= cached_proc_self_maps_
;
357 cached_proc_self_maps_
.len
=
358 ReadFileToBuffer("/proc/self/maps", &cached_proc_self_maps_
.data
,
359 &cached_proc_self_maps_
.mmaped_size
, 1 << 26);
360 if (cached_proc_self_maps_
.mmaped_size
== 0) {
361 cached_proc_self_maps_
= old_proc_self_maps
;
363 if (old_proc_self_maps
.mmaped_size
) {
364 UnmapOrDie(old_proc_self_maps
.data
,
365 old_proc_self_maps
.mmaped_size
);
370 void MemoryMappingLayout::LoadFromCache() {
371 SpinMutexLock
l(&cache_lock_
);
372 if (cached_proc_self_maps_
.data
) {
373 proc_self_maps_
= cached_proc_self_maps_
;
377 // Parse a hex value in str and update str.
378 static uptr
ParseHex(char **str
) {
381 for (s
= *str
; ; s
++) {
384 if (c
>= '0' && c
<= '9')
386 else if (c
>= 'a' && c
<= 'f')
388 else if (c
>= 'A' && c
<= 'F')
398 static bool IsOneOf(char c
, char c1
, char c2
) {
399 return c
== c1
|| c
== c2
;
402 static bool IsDecimal(char c
) {
403 return c
>= '0' && c
<= '9';
406 static bool IsHex(char c
) {
407 return (c
>= '0' && c
<= '9')
408 || (c
>= 'a' && c
<= 'f');
411 static uptr
ReadHex(const char *p
) {
413 for (; IsHex(p
[0]); p
++) {
414 if (p
[0] >= '0' && p
[0] <= '9')
415 v
= v
* 16 + p
[0] - '0';
417 v
= v
* 16 + p
[0] - 'a' + 10;
422 static uptr
ReadDecimal(const char *p
) {
424 for (; IsDecimal(p
[0]); p
++)
425 v
= v
* 10 + p
[0] - '0';
430 bool MemoryMappingLayout::Next(uptr
*start
, uptr
*end
, uptr
*offset
,
431 char filename
[], uptr filename_size
,
433 char *last
= proc_self_maps_
.data
+ proc_self_maps_
.len
;
434 if (current_
>= last
) return false;
436 if (!start
) start
= &dummy
;
437 if (!end
) end
= &dummy
;
438 if (!offset
) offset
= &dummy
;
439 char *next_line
= (char*)internal_memchr(current_
, '\n', last
- current_
);
442 // Example: 08048000-08056000 r-xp 00000000 03:0c 64593 /foo/bar
443 *start
= ParseHex(¤t_
);
444 CHECK_EQ(*current_
++, '-');
445 *end
= ParseHex(¤t_
);
446 CHECK_EQ(*current_
++, ' ');
447 uptr local_protection
= 0;
448 CHECK(IsOneOf(*current_
, '-', 'r'));
449 if (*current_
++ == 'r')
450 local_protection
|= kProtectionRead
;
451 CHECK(IsOneOf(*current_
, '-', 'w'));
452 if (*current_
++ == 'w')
453 local_protection
|= kProtectionWrite
;
454 CHECK(IsOneOf(*current_
, '-', 'x'));
455 if (*current_
++ == 'x')
456 local_protection
|= kProtectionExecute
;
457 CHECK(IsOneOf(*current_
, 's', 'p'));
458 if (*current_
++ == 's')
459 local_protection
|= kProtectionShared
;
461 *protection
= local_protection
;
463 CHECK_EQ(*current_
++, ' ');
464 *offset
= ParseHex(¤t_
);
465 CHECK_EQ(*current_
++, ' ');
467 CHECK_EQ(*current_
++, ':');
469 CHECK_EQ(*current_
++, ' ');
470 while (IsDecimal(*current_
))
472 // Qemu may lack the trailing space.
473 // http://code.google.com/p/address-sanitizer/issues/detail?id=160
474 // CHECK_EQ(*current_++, ' ');
476 while (current_
< next_line
&& *current_
== ' ')
478 // Fill in the filename.
480 while (current_
< next_line
) {
481 if (filename
&& i
< filename_size
- 1)
482 filename
[i
++] = *current_
;
485 if (filename
&& i
< filename_size
)
487 current_
= next_line
+ 1;
491 // Gets the object name and the offset by walking MemoryMappingLayout.
492 bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr
, uptr
*offset
,
496 return IterateForObjectNameAndOffset(addr
, offset
, filename
, filename_size
,
500 void GetMemoryProfile(fill_profile_f cb
, uptr
*stats
, uptr stats_size
) {
503 uptr smaps_len
= ReadFileToBuffer("/proc/self/smaps",
504 &smaps
, &smaps_cap
, 64<<20);
507 const char *pos
= smaps
;
508 while (pos
< smaps
+ smaps_len
) {
510 start
= ReadHex(pos
);
511 for (; *pos
!= '/' && *pos
> '\n'; pos
++) {}
513 } else if (internal_strncmp(pos
, "Rss:", 4) == 0) {
514 for (; *pos
< '0' || *pos
> '9'; pos
++) {}
515 uptr rss
= ReadDecimal(pos
) * 1024;
516 cb(start
, rss
, file
, stats
, stats_size
);
518 while (*pos
++ != '\n') {}
520 UnmapOrDie(smaps
, smaps_cap
);
529 BlockingMutex::BlockingMutex(LinkerInitialized
) {
533 BlockingMutex::BlockingMutex() {
534 internal_memset(this, 0, sizeof(*this));
537 void BlockingMutex::Lock() {
538 atomic_uint32_t
*m
= reinterpret_cast<atomic_uint32_t
*>(&opaque_storage_
);
539 if (atomic_exchange(m
, MtxLocked
, memory_order_acquire
) == MtxUnlocked
)
541 while (atomic_exchange(m
, MtxSleeping
, memory_order_acquire
) != MtxUnlocked
)
542 internal_syscall(__NR_futex
, (uptr
)m
, FUTEX_WAIT
, MtxSleeping
, 0, 0, 0);
545 void BlockingMutex::Unlock() {
546 atomic_uint32_t
*m
= reinterpret_cast<atomic_uint32_t
*>(&opaque_storage_
);
547 u32 v
= atomic_exchange(m
, MtxUnlocked
, memory_order_relaxed
);
548 CHECK_NE(v
, MtxUnlocked
);
549 if (v
== MtxSleeping
)
550 internal_syscall(__NR_futex
, (uptr
)m
, FUTEX_WAKE
, 1, 0, 0, 0);
553 void BlockingMutex::CheckLocked() {
554 atomic_uint32_t
*m
= reinterpret_cast<atomic_uint32_t
*>(&opaque_storage_
);
555 CHECK_NE(MtxUnlocked
, atomic_load(m
, memory_order_relaxed
));
558 // ----------------- sanitizer_linux.h
559 // The actual size of this structure is specified by d_reclen.
560 // Note that getdents64 uses a different structure format. We only provide the
561 // 32-bit syscall here.
562 struct linux_dirent
{
565 unsigned short d_reclen
;
570 uptr
internal_ptrace(int request
, int pid
, void *addr
, void *data
) {
571 return internal_syscall(__NR_ptrace
, request
, pid
, (uptr
)addr
, (uptr
)data
);
574 uptr
internal_waitpid(int pid
, int *status
, int options
) {
575 return internal_syscall(__NR_wait4
, pid
, (uptr
)status
, options
, 0 /* rusage */);
578 uptr
internal_getpid() {
579 return internal_syscall(__NR_getpid
);
582 uptr
internal_getppid() {
583 return internal_syscall(__NR_getppid
);
586 uptr
internal_getdents(fd_t fd
, struct linux_dirent
*dirp
, unsigned int count
) {
587 return internal_syscall(__NR_getdents
, fd
, (uptr
)dirp
, count
);
590 uptr
internal_lseek(fd_t fd
, OFF_T offset
, int whence
) {
591 return internal_syscall(__NR_lseek
, fd
, offset
, whence
);
594 uptr
internal_prctl(int option
, uptr arg2
, uptr arg3
, uptr arg4
, uptr arg5
) {
595 return internal_syscall(__NR_prctl
, option
, arg2
, arg3
, arg4
, arg5
);
598 uptr
internal_sigaltstack(const struct sigaltstack
*ss
,
599 struct sigaltstack
*oss
) {
600 return internal_syscall(__NR_sigaltstack
, (uptr
)ss
, (uptr
)oss
);
603 // ThreadLister implementation.
604 ThreadLister::ThreadLister(int pid
)
609 entry_((struct linux_dirent
*)buffer_
.data()),
611 char task_directory_path
[80];
612 internal_snprintf(task_directory_path
, sizeof(task_directory_path
),
613 "/proc/%d/task/", pid
);
614 uptr openrv
= internal_open(task_directory_path
, O_RDONLY
| O_DIRECTORY
);
615 if (internal_iserror(openrv
)) {
617 Report("Can't open /proc/%d/task for reading.\n", pid
);
620 descriptor_
= openrv
;
624 int ThreadLister::GetNextTID() {
629 if ((char *)entry_
>= &buffer_
[bytes_read_
] && !GetDirectoryEntries())
631 if (entry_
->d_ino
!= 0 && entry_
->d_name
[0] >= '0' &&
632 entry_
->d_name
[0] <= '9') {
633 // Found a valid tid.
634 tid
= (int)internal_atoll(entry_
->d_name
);
636 entry_
= (struct linux_dirent
*)(((char *)entry_
) + entry_
->d_reclen
);
641 void ThreadLister::Reset() {
642 if (error_
|| descriptor_
< 0)
644 internal_lseek(descriptor_
, 0, SEEK_SET
);
647 ThreadLister::~ThreadLister() {
648 if (descriptor_
>= 0)
649 internal_close(descriptor_
);
652 bool ThreadLister::error() { return error_
; }
654 bool ThreadLister::GetDirectoryEntries() {
655 CHECK_GE(descriptor_
, 0);
656 CHECK_NE(error_
, true);
657 bytes_read_
= internal_getdents(descriptor_
,
658 (struct linux_dirent
*)buffer_
.data(),
660 if (internal_iserror(bytes_read_
)) {
661 Report("Can't read directory entries from /proc/%d/task.\n", pid_
);
664 } else if (bytes_read_
== 0) {
667 entry_
= (struct linux_dirent
*)buffer_
.data();
672 #if defined(__x86_64__) || defined(__i386__)
673 return EXEC_PAGESIZE
;
675 return sysconf(_SC_PAGESIZE
); // EXEC_PAGESIZE may not be trustworthy.
679 static char proc_self_exe_cache_str
[kMaxPathLength
];
680 static uptr proc_self_exe_cache_len
= 0;
682 uptr
ReadBinaryName(/*out*/char *buf
, uptr buf_len
) {
683 uptr module_name_len
= internal_readlink(
684 "/proc/self/exe", buf
, buf_len
);
686 if (internal_iserror(module_name_len
, &readlink_error
)) {
687 if (proc_self_exe_cache_len
) {
688 // If available, use the cached module name.
689 CHECK_LE(proc_self_exe_cache_len
, buf_len
);
690 internal_strncpy(buf
, proc_self_exe_cache_str
, buf_len
);
691 module_name_len
= internal_strlen(proc_self_exe_cache_str
);
693 // We can't read /proc/self/exe for some reason, assume the name of the
694 // binary is unknown.
695 Report("WARNING: readlink(\"/proc/self/exe\") failed with errno %d, "
696 "some stack frames may not be symbolized\n", readlink_error
);
697 module_name_len
= internal_snprintf(buf
, buf_len
, "/proc/self/exe");
699 CHECK_LT(module_name_len
, buf_len
);
700 buf
[module_name_len
] = '\0';
702 return module_name_len
;
705 void CacheBinaryName() {
706 if (!proc_self_exe_cache_len
) {
707 proc_self_exe_cache_len
=
708 ReadBinaryName(proc_self_exe_cache_str
, kMaxPathLength
);
712 // Match full names of the form /path/to/base_name{-,.}*
713 bool LibraryNameIs(const char *full_name
, const char *base_name
) {
714 const char *name
= full_name
;
716 while (*name
!= '\0') name
++;
717 while (name
> full_name
&& *name
!= '/') name
--;
718 if (*name
== '/') name
++;
719 uptr base_name_length
= internal_strlen(base_name
);
720 if (internal_strncmp(name
, base_name
, base_name_length
)) return false;
721 return (name
[base_name_length
] == '-' || name
[base_name_length
] == '.');
724 #if !SANITIZER_ANDROID
725 // Call cb for each region mapped by map.
726 void ForEachMappedRegion(link_map
*map
, void (*cb
)(const void *, uptr
)) {
727 typedef ElfW(Phdr
) Elf_Phdr
;
728 typedef ElfW(Ehdr
) Elf_Ehdr
;
729 char *base
= (char *)map
->l_addr
;
730 Elf_Ehdr
*ehdr
= (Elf_Ehdr
*)base
;
731 char *phdrs
= base
+ ehdr
->e_phoff
;
732 char *phdrs_end
= phdrs
+ ehdr
->e_phnum
* ehdr
->e_phentsize
;
734 // Find the segment with the minimum base so we can "relocate" the p_vaddr
735 // fields. Typically ET_DYN objects (DSOs) have base of zero and ET_EXEC
736 // objects have a non-zero base.
737 uptr preferred_base
= (uptr
)-1;
738 for (char *iter
= phdrs
; iter
!= phdrs_end
; iter
+= ehdr
->e_phentsize
) {
739 Elf_Phdr
*phdr
= (Elf_Phdr
*)iter
;
740 if (phdr
->p_type
== PT_LOAD
&& preferred_base
> (uptr
)phdr
->p_vaddr
)
741 preferred_base
= (uptr
)phdr
->p_vaddr
;
744 // Compute the delta from the real base to get a relocation delta.
745 sptr delta
= (uptr
)base
- preferred_base
;
746 // Now we can figure out what the loader really mapped.
747 for (char *iter
= phdrs
; iter
!= phdrs_end
; iter
+= ehdr
->e_phentsize
) {
748 Elf_Phdr
*phdr
= (Elf_Phdr
*)iter
;
749 if (phdr
->p_type
== PT_LOAD
) {
750 uptr seg_start
= phdr
->p_vaddr
+ delta
;
751 uptr seg_end
= seg_start
+ phdr
->p_memsz
;
752 // None of these values are aligned. We consider the ragged edges of the
753 // load command as defined, since they are mapped from the file.
754 seg_start
= RoundDownTo(seg_start
, GetPageSizeCached());
755 seg_end
= RoundUpTo(seg_end
, GetPageSizeCached());
756 cb((void *)seg_start
, seg_end
- seg_start
);
762 #if defined(__x86_64__)
763 // We cannot use glibc's clone wrapper, because it messes with the child
764 // task's TLS. It writes the PID and TID of the child task to its thread
765 // descriptor, but in our case the child task shares the thread descriptor with
766 // the parent (because we don't know how to allocate a new thread
767 // descriptor to keep glibc happy). So the stock version of clone(), when
768 // used with CLONE_VM, would end up corrupting the parent's thread descriptor.
769 uptr
internal_clone(int (*fn
)(void *), void *child_stack
, int flags
, void *arg
,
770 int *parent_tidptr
, void *newtls
, int *child_tidptr
) {
772 if (!fn
|| !child_stack
)
774 CHECK_EQ(0, (uptr
)child_stack
% 16);
775 child_stack
= (char *)child_stack
- 2 * sizeof(unsigned long long);
776 ((unsigned long long *)child_stack
)[0] = (uptr
)fn
;
777 ((unsigned long long *)child_stack
)[1] = (uptr
)arg
;
778 register void *r8
__asm__ ("r8") = newtls
;
779 register int *r10
__asm__ ("r10") = child_tidptr
;
780 __asm__
__volatile__(
781 /* %rax = syscall(%rax = __NR_clone,
783 * %rsi = child_stack,
784 * %rdx = parent_tidptr,
786 * %r10 = child_tidptr)
794 "testq %%rax,%%rax\n"
797 /* In the child. Terminate unwind chain. */
799 ".cfi_undefined %%rip;\n"
802 /* Call "fn(arg)". */
807 /* Call _exit(%rax). */
812 /* Return to parent. */
815 : "a"(__NR_clone
), "i"(__NR_exit
),
821 : "rsp", "memory", "r11", "rcx");
824 #endif // defined(__x86_64__)
825 } // namespace __sanitizer
827 #endif // SANITIZER_LINUX