168d75effSDimitry Andric //===-- sanitizer_posix.cpp -----------------------------------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is shared between AddressSanitizer and ThreadSanitizer 1068d75effSDimitry Andric // run-time libraries and implements POSIX-specific functions from 1168d75effSDimitry Andric // sanitizer_posix.h. 1268d75effSDimitry Andric //===----------------------------------------------------------------------===// 1368d75effSDimitry Andric 1468d75effSDimitry Andric #include "sanitizer_platform.h" 1568d75effSDimitry Andric 1668d75effSDimitry Andric #if SANITIZER_POSIX 1768d75effSDimitry Andric 1868d75effSDimitry Andric #include "sanitizer_common.h" 1968d75effSDimitry Andric #include "sanitizer_file.h" 2068d75effSDimitry Andric #include "sanitizer_flags.h" 2168d75effSDimitry Andric #include "sanitizer_libc.h" 2268d75effSDimitry Andric #include "sanitizer_posix.h" 2368d75effSDimitry Andric #include "sanitizer_procmaps.h" 2468d75effSDimitry Andric 2568d75effSDimitry Andric #include <errno.h> 2668d75effSDimitry Andric #include <fcntl.h> 2768d75effSDimitry Andric #include <signal.h> 2868d75effSDimitry Andric #include <sys/mman.h> 2968d75effSDimitry Andric 3068d75effSDimitry Andric #if SANITIZER_FREEBSD 3168d75effSDimitry Andric // The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before 3268d75effSDimitry Andric // that, it was never implemented. So just define it to zero. 3368d75effSDimitry Andric #undef MAP_NORESERVE 3468d75effSDimitry Andric #define MAP_NORESERVE 0 3568d75effSDimitry Andric #endif 3668d75effSDimitry Andric 3768d75effSDimitry Andric namespace __sanitizer { 3868d75effSDimitry Andric 3968d75effSDimitry Andric // ------------- sanitizer_common.h 4068d75effSDimitry Andric uptr GetMmapGranularity() { 4168d75effSDimitry Andric return GetPageSize(); 4268d75effSDimitry Andric } 4368d75effSDimitry Andric 4468d75effSDimitry Andric void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) { 4568d75effSDimitry Andric size = RoundUpTo(size, GetPageSizeCached()); 4668d75effSDimitry Andric uptr res = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE, 4768d75effSDimitry Andric MAP_PRIVATE | MAP_ANON, mem_type); 4868d75effSDimitry Andric int reserrno; 4968d75effSDimitry Andric if (UNLIKELY(internal_iserror(res, &reserrno))) 5068d75effSDimitry Andric ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno, raw_report); 5168d75effSDimitry Andric IncreaseTotalMmap(size); 5268d75effSDimitry Andric return (void *)res; 5368d75effSDimitry Andric } 5468d75effSDimitry Andric 5568d75effSDimitry Andric void UnmapOrDie(void *addr, uptr size) { 5668d75effSDimitry Andric if (!addr || !size) return; 5768d75effSDimitry Andric uptr res = internal_munmap(addr, size); 5868d75effSDimitry Andric if (UNLIKELY(internal_iserror(res))) { 5968d75effSDimitry Andric Report("ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p\n", 6068d75effSDimitry Andric SanitizerToolName, size, size, addr); 6168d75effSDimitry Andric CHECK("unable to unmap" && 0); 6268d75effSDimitry Andric } 6368d75effSDimitry Andric DecreaseTotalMmap(size); 6468d75effSDimitry Andric } 6568d75effSDimitry Andric 6668d75effSDimitry Andric void *MmapOrDieOnFatalError(uptr size, const char *mem_type) { 6768d75effSDimitry Andric size = RoundUpTo(size, GetPageSizeCached()); 6868d75effSDimitry Andric uptr res = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE, 6968d75effSDimitry Andric MAP_PRIVATE | MAP_ANON, mem_type); 7068d75effSDimitry Andric int reserrno; 7168d75effSDimitry Andric if (UNLIKELY(internal_iserror(res, &reserrno))) { 7268d75effSDimitry Andric if (reserrno == ENOMEM) 7368d75effSDimitry Andric return nullptr; 7468d75effSDimitry Andric ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno); 7568d75effSDimitry Andric } 7668d75effSDimitry Andric IncreaseTotalMmap(size); 7768d75effSDimitry Andric return (void *)res; 7868d75effSDimitry Andric } 7968d75effSDimitry Andric 8068d75effSDimitry Andric // We want to map a chunk of address space aligned to 'alignment'. 8168d75effSDimitry Andric // We do it by mapping a bit more and then unmapping redundant pieces. 8268d75effSDimitry Andric // We probably can do it with fewer syscalls in some OS-dependent way. 8368d75effSDimitry Andric void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment, 8468d75effSDimitry Andric const char *mem_type) { 8568d75effSDimitry Andric CHECK(IsPowerOfTwo(size)); 8668d75effSDimitry Andric CHECK(IsPowerOfTwo(alignment)); 8768d75effSDimitry Andric uptr map_size = size + alignment; 8868d75effSDimitry Andric uptr map_res = (uptr)MmapOrDieOnFatalError(map_size, mem_type); 8968d75effSDimitry Andric if (UNLIKELY(!map_res)) 9068d75effSDimitry Andric return nullptr; 9168d75effSDimitry Andric uptr map_end = map_res + map_size; 9268d75effSDimitry Andric uptr res = map_res; 9368d75effSDimitry Andric if (!IsAligned(res, alignment)) { 9468d75effSDimitry Andric res = (map_res + alignment - 1) & ~(alignment - 1); 9568d75effSDimitry Andric UnmapOrDie((void*)map_res, res - map_res); 9668d75effSDimitry Andric } 9768d75effSDimitry Andric uptr end = res + size; 9868d75effSDimitry Andric if (end != map_end) 9968d75effSDimitry Andric UnmapOrDie((void*)end, map_end - end); 10068d75effSDimitry Andric return (void*)res; 10168d75effSDimitry Andric } 10268d75effSDimitry Andric 10368d75effSDimitry Andric void *MmapNoReserveOrDie(uptr size, const char *mem_type) { 10468d75effSDimitry Andric size = RoundUpTo(size, GetPageSizeCached()); 10568d75effSDimitry Andric uptr p = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE, 10668d75effSDimitry Andric MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, mem_type); 10768d75effSDimitry Andric int reserrno; 10868d75effSDimitry Andric if (UNLIKELY(internal_iserror(p, &reserrno))) 10968d75effSDimitry Andric ReportMmapFailureAndDie(size, mem_type, "allocate noreserve", reserrno); 11068d75effSDimitry Andric IncreaseTotalMmap(size); 11168d75effSDimitry Andric return (void *)p; 11268d75effSDimitry Andric } 11368d75effSDimitry Andric 11468d75effSDimitry Andric static void *MmapFixedImpl(uptr fixed_addr, uptr size, bool tolerate_enomem, 11568d75effSDimitry Andric const char *name) { 11668d75effSDimitry Andric size = RoundUpTo(size, GetPageSizeCached()); 11768d75effSDimitry Andric fixed_addr = RoundDownTo(fixed_addr, GetPageSizeCached()); 11868d75effSDimitry Andric uptr p = MmapNamed((void *)fixed_addr, size, PROT_READ | PROT_WRITE, 11968d75effSDimitry Andric MAP_PRIVATE | MAP_ANON | MAP_FIXED, name); 12068d75effSDimitry Andric int reserrno; 12168d75effSDimitry Andric if (UNLIKELY(internal_iserror(p, &reserrno))) { 12268d75effSDimitry Andric if (tolerate_enomem && reserrno == ENOMEM) 12368d75effSDimitry Andric return nullptr; 12468d75effSDimitry Andric char mem_type[40]; 12568d75effSDimitry Andric internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx", 12668d75effSDimitry Andric fixed_addr); 12768d75effSDimitry Andric ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno); 12868d75effSDimitry Andric } 12968d75effSDimitry Andric IncreaseTotalMmap(size); 13068d75effSDimitry Andric return (void *)p; 13168d75effSDimitry Andric } 13268d75effSDimitry Andric 13368d75effSDimitry Andric void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name) { 13468d75effSDimitry Andric return MmapFixedImpl(fixed_addr, size, false /*tolerate_enomem*/, name); 13568d75effSDimitry Andric } 13668d75effSDimitry Andric 13768d75effSDimitry Andric void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size, const char *name) { 13868d75effSDimitry Andric return MmapFixedImpl(fixed_addr, size, true /*tolerate_enomem*/, name); 13968d75effSDimitry Andric } 14068d75effSDimitry Andric 14168d75effSDimitry Andric bool MprotectNoAccess(uptr addr, uptr size) { 14268d75effSDimitry Andric return 0 == internal_mprotect((void*)addr, size, PROT_NONE); 14368d75effSDimitry Andric } 14468d75effSDimitry Andric 14568d75effSDimitry Andric bool MprotectReadOnly(uptr addr, uptr size) { 14668d75effSDimitry Andric return 0 == internal_mprotect((void *)addr, size, PROT_READ); 14768d75effSDimitry Andric } 14868d75effSDimitry Andric 14968d75effSDimitry Andric #if !SANITIZER_MAC 15068d75effSDimitry Andric void MprotectMallocZones(void *addr, int prot) {} 15168d75effSDimitry Andric #endif 15268d75effSDimitry Andric 15368d75effSDimitry Andric fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *errno_p) { 15468d75effSDimitry Andric if (ShouldMockFailureToOpen(filename)) 15568d75effSDimitry Andric return kInvalidFd; 15668d75effSDimitry Andric int flags; 15768d75effSDimitry Andric switch (mode) { 15868d75effSDimitry Andric case RdOnly: flags = O_RDONLY; break; 15968d75effSDimitry Andric case WrOnly: flags = O_WRONLY | O_CREAT | O_TRUNC; break; 16068d75effSDimitry Andric case RdWr: flags = O_RDWR | O_CREAT; break; 16168d75effSDimitry Andric } 16268d75effSDimitry Andric fd_t res = internal_open(filename, flags, 0660); 16368d75effSDimitry Andric if (internal_iserror(res, errno_p)) 16468d75effSDimitry Andric return kInvalidFd; 16568d75effSDimitry Andric return ReserveStandardFds(res); 16668d75effSDimitry Andric } 16768d75effSDimitry Andric 16868d75effSDimitry Andric void CloseFile(fd_t fd) { 16968d75effSDimitry Andric internal_close(fd); 17068d75effSDimitry Andric } 17168d75effSDimitry Andric 17268d75effSDimitry Andric bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read, 17368d75effSDimitry Andric error_t *error_p) { 17468d75effSDimitry Andric uptr res = internal_read(fd, buff, buff_size); 17568d75effSDimitry Andric if (internal_iserror(res, error_p)) 17668d75effSDimitry Andric return false; 17768d75effSDimitry Andric if (bytes_read) 17868d75effSDimitry Andric *bytes_read = res; 17968d75effSDimitry Andric return true; 18068d75effSDimitry Andric } 18168d75effSDimitry Andric 18268d75effSDimitry Andric bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written, 18368d75effSDimitry Andric error_t *error_p) { 18468d75effSDimitry Andric uptr res = internal_write(fd, buff, buff_size); 18568d75effSDimitry Andric if (internal_iserror(res, error_p)) 18668d75effSDimitry Andric return false; 18768d75effSDimitry Andric if (bytes_written) 18868d75effSDimitry Andric *bytes_written = res; 18968d75effSDimitry Andric return true; 19068d75effSDimitry Andric } 19168d75effSDimitry Andric 19268d75effSDimitry Andric void *MapFileToMemory(const char *file_name, uptr *buff_size) { 19368d75effSDimitry Andric fd_t fd = OpenFile(file_name, RdOnly); 19468d75effSDimitry Andric CHECK(fd != kInvalidFd); 19568d75effSDimitry Andric uptr fsize = internal_filesize(fd); 19668d75effSDimitry Andric CHECK_NE(fsize, (uptr)-1); 19768d75effSDimitry Andric CHECK_GT(fsize, 0); 19868d75effSDimitry Andric *buff_size = RoundUpTo(fsize, GetPageSizeCached()); 19968d75effSDimitry Andric uptr map = internal_mmap(nullptr, *buff_size, PROT_READ, MAP_PRIVATE, fd, 0); 20068d75effSDimitry Andric return internal_iserror(map) ? nullptr : (void *)map; 20168d75effSDimitry Andric } 20268d75effSDimitry Andric 20368d75effSDimitry Andric void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset) { 20468d75effSDimitry Andric uptr flags = MAP_SHARED; 20568d75effSDimitry Andric if (addr) flags |= MAP_FIXED; 20668d75effSDimitry Andric uptr p = internal_mmap(addr, size, PROT_READ | PROT_WRITE, flags, fd, offset); 20768d75effSDimitry Andric int mmap_errno = 0; 20868d75effSDimitry Andric if (internal_iserror(p, &mmap_errno)) { 20968d75effSDimitry Andric Printf("could not map writable file (%d, %lld, %zu): %zd, errno: %d\n", 21068d75effSDimitry Andric fd, (long long)offset, size, p, mmap_errno); 21168d75effSDimitry Andric return nullptr; 21268d75effSDimitry Andric } 21368d75effSDimitry Andric return (void *)p; 21468d75effSDimitry Andric } 21568d75effSDimitry Andric 21668d75effSDimitry Andric static inline bool IntervalsAreSeparate(uptr start1, uptr end1, 21768d75effSDimitry Andric uptr start2, uptr end2) { 21868d75effSDimitry Andric CHECK(start1 <= end1); 21968d75effSDimitry Andric CHECK(start2 <= end2); 22068d75effSDimitry Andric return (end1 < start2) || (end2 < start1); 22168d75effSDimitry Andric } 22268d75effSDimitry Andric 22368d75effSDimitry Andric // FIXME: this is thread-unsafe, but should not cause problems most of the time. 22468d75effSDimitry Andric // When the shadow is mapped only a single thread usually exists (plus maybe 22568d75effSDimitry Andric // several worker threads on Mac, which aren't expected to map big chunks of 22668d75effSDimitry Andric // memory). 22768d75effSDimitry Andric bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) { 22868d75effSDimitry Andric MemoryMappingLayout proc_maps(/*cache_enabled*/true); 22968d75effSDimitry Andric if (proc_maps.Error()) 23068d75effSDimitry Andric return true; // and hope for the best 23168d75effSDimitry Andric MemoryMappedSegment segment; 23268d75effSDimitry Andric while (proc_maps.Next(&segment)) { 23368d75effSDimitry Andric if (segment.start == segment.end) continue; // Empty range. 23468d75effSDimitry Andric CHECK_NE(0, segment.end); 23568d75effSDimitry Andric if (!IntervalsAreSeparate(segment.start, segment.end - 1, range_start, 23668d75effSDimitry Andric range_end)) 23768d75effSDimitry Andric return false; 23868d75effSDimitry Andric } 23968d75effSDimitry Andric return true; 24068d75effSDimitry Andric } 24168d75effSDimitry Andric 24268d75effSDimitry Andric void DumpProcessMap() { 24368d75effSDimitry Andric MemoryMappingLayout proc_maps(/*cache_enabled*/true); 24468d75effSDimitry Andric const sptr kBufSize = 4095; 24568d75effSDimitry Andric char *filename = (char*)MmapOrDie(kBufSize, __func__); 24668d75effSDimitry Andric MemoryMappedSegment segment(filename, kBufSize); 24768d75effSDimitry Andric Report("Process memory map follows:\n"); 24868d75effSDimitry Andric while (proc_maps.Next(&segment)) { 24968d75effSDimitry Andric Printf("\t%p-%p\t%s\n", (void *)segment.start, (void *)segment.end, 25068d75effSDimitry Andric segment.filename); 25168d75effSDimitry Andric } 25268d75effSDimitry Andric Report("End of process memory map.\n"); 25368d75effSDimitry Andric UnmapOrDie(filename, kBufSize); 25468d75effSDimitry Andric } 25568d75effSDimitry Andric 25668d75effSDimitry Andric const char *GetPwd() { 25768d75effSDimitry Andric return GetEnv("PWD"); 25868d75effSDimitry Andric } 25968d75effSDimitry Andric 26068d75effSDimitry Andric bool IsPathSeparator(const char c) { 26168d75effSDimitry Andric return c == '/'; 26268d75effSDimitry Andric } 26368d75effSDimitry Andric 26468d75effSDimitry Andric bool IsAbsolutePath(const char *path) { 26568d75effSDimitry Andric return path != nullptr && IsPathSeparator(path[0]); 26668d75effSDimitry Andric } 26768d75effSDimitry Andric 26868d75effSDimitry Andric void ReportFile::Write(const char *buffer, uptr length) { 26968d75effSDimitry Andric SpinMutexLock l(mu); 27068d75effSDimitry Andric ReopenIfNecessary(); 27168d75effSDimitry Andric internal_write(fd, buffer, length); 27268d75effSDimitry Andric } 27368d75effSDimitry Andric 27468d75effSDimitry Andric bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end) { 27568d75effSDimitry Andric MemoryMappingLayout proc_maps(/*cache_enabled*/false); 27668d75effSDimitry Andric InternalScopedString buff(kMaxPathLength); 27768d75effSDimitry Andric MemoryMappedSegment segment(buff.data(), kMaxPathLength); 27868d75effSDimitry Andric while (proc_maps.Next(&segment)) { 27968d75effSDimitry Andric if (segment.IsExecutable() && 28068d75effSDimitry Andric internal_strcmp(module, segment.filename) == 0) { 28168d75effSDimitry Andric *start = segment.start; 28268d75effSDimitry Andric *end = segment.end; 28368d75effSDimitry Andric return true; 28468d75effSDimitry Andric } 28568d75effSDimitry Andric } 28668d75effSDimitry Andric return false; 28768d75effSDimitry Andric } 28868d75effSDimitry Andric 28968d75effSDimitry Andric uptr SignalContext::GetAddress() const { 29068d75effSDimitry Andric auto si = static_cast<const siginfo_t *>(siginfo); 29168d75effSDimitry Andric return (uptr)si->si_addr; 29268d75effSDimitry Andric } 29368d75effSDimitry Andric 29468d75effSDimitry Andric bool SignalContext::IsMemoryAccess() const { 29568d75effSDimitry Andric auto si = static_cast<const siginfo_t *>(siginfo); 29668d75effSDimitry Andric return si->si_signo == SIGSEGV; 29768d75effSDimitry Andric } 29868d75effSDimitry Andric 29968d75effSDimitry Andric int SignalContext::GetType() const { 30068d75effSDimitry Andric return static_cast<const siginfo_t *>(siginfo)->si_signo; 30168d75effSDimitry Andric } 30268d75effSDimitry Andric 30368d75effSDimitry Andric const char *SignalContext::Describe() const { 30468d75effSDimitry Andric switch (GetType()) { 30568d75effSDimitry Andric case SIGFPE: 30668d75effSDimitry Andric return "FPE"; 30768d75effSDimitry Andric case SIGILL: 30868d75effSDimitry Andric return "ILL"; 30968d75effSDimitry Andric case SIGABRT: 31068d75effSDimitry Andric return "ABRT"; 31168d75effSDimitry Andric case SIGSEGV: 31268d75effSDimitry Andric return "SEGV"; 31368d75effSDimitry Andric case SIGBUS: 31468d75effSDimitry Andric return "BUS"; 31568d75effSDimitry Andric case SIGTRAP: 31668d75effSDimitry Andric return "TRAP"; 31768d75effSDimitry Andric } 31868d75effSDimitry Andric return "UNKNOWN SIGNAL"; 31968d75effSDimitry Andric } 32068d75effSDimitry Andric 32168d75effSDimitry Andric fd_t ReserveStandardFds(fd_t fd) { 32268d75effSDimitry Andric CHECK_GE(fd, 0); 32368d75effSDimitry Andric if (fd > 2) 32468d75effSDimitry Andric return fd; 32568d75effSDimitry Andric bool used[3]; 32668d75effSDimitry Andric internal_memset(used, 0, sizeof(used)); 32768d75effSDimitry Andric while (fd <= 2) { 32868d75effSDimitry Andric used[fd] = true; 32968d75effSDimitry Andric fd = internal_dup(fd); 33068d75effSDimitry Andric } 33168d75effSDimitry Andric for (int i = 0; i <= 2; ++i) 33268d75effSDimitry Andric if (used[i]) 33368d75effSDimitry Andric internal_close(i); 33468d75effSDimitry Andric return fd; 33568d75effSDimitry Andric } 33668d75effSDimitry Andric 33768d75effSDimitry Andric bool ShouldMockFailureToOpen(const char *path) { 33868d75effSDimitry Andric return common_flags()->test_only_emulate_no_memorymap && 33968d75effSDimitry Andric internal_strncmp(path, "/proc/", 6) == 0; 34068d75effSDimitry Andric } 34168d75effSDimitry Andric 34268d75effSDimitry Andric #if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_GO 34368d75effSDimitry Andric int GetNamedMappingFd(const char *name, uptr size, int *flags) { 34468d75effSDimitry Andric if (!common_flags()->decorate_proc_maps || !name) 34568d75effSDimitry Andric return -1; 34668d75effSDimitry Andric char shmname[200]; 34768d75effSDimitry Andric CHECK(internal_strlen(name) < sizeof(shmname) - 10); 34868d75effSDimitry Andric internal_snprintf(shmname, sizeof(shmname), "/dev/shm/%zu [%s]", 34968d75effSDimitry Andric internal_getpid(), name); 350*5ffd83dbSDimitry Andric int o_cloexec = 0; 351*5ffd83dbSDimitry Andric #if defined(O_CLOEXEC) 352*5ffd83dbSDimitry Andric o_cloexec = O_CLOEXEC; 353*5ffd83dbSDimitry Andric #endif 35468d75effSDimitry Andric int fd = ReserveStandardFds( 355*5ffd83dbSDimitry Andric internal_open(shmname, O_RDWR | O_CREAT | O_TRUNC | o_cloexec, S_IRWXU)); 35668d75effSDimitry Andric CHECK_GE(fd, 0); 357*5ffd83dbSDimitry Andric if (!o_cloexec) { 358*5ffd83dbSDimitry Andric int res = fcntl(fd, F_SETFD, FD_CLOEXEC); 359*5ffd83dbSDimitry Andric CHECK_EQ(0, res); 360*5ffd83dbSDimitry Andric } 36168d75effSDimitry Andric int res = internal_ftruncate(fd, size); 36268d75effSDimitry Andric CHECK_EQ(0, res); 36368d75effSDimitry Andric res = internal_unlink(shmname); 36468d75effSDimitry Andric CHECK_EQ(0, res); 36568d75effSDimitry Andric *flags &= ~(MAP_ANON | MAP_ANONYMOUS); 36668d75effSDimitry Andric return fd; 36768d75effSDimitry Andric } 36868d75effSDimitry Andric #else 36968d75effSDimitry Andric int GetNamedMappingFd(const char *name, uptr size, int *flags) { 37068d75effSDimitry Andric return -1; 37168d75effSDimitry Andric } 37268d75effSDimitry Andric #endif 37368d75effSDimitry Andric 37468d75effSDimitry Andric #if SANITIZER_ANDROID 37568d75effSDimitry Andric #define PR_SET_VMA 0x53564d41 37668d75effSDimitry Andric #define PR_SET_VMA_ANON_NAME 0 37768d75effSDimitry Andric void DecorateMapping(uptr addr, uptr size, const char *name) { 37868d75effSDimitry Andric if (!common_flags()->decorate_proc_maps || !name) 37968d75effSDimitry Andric return; 38068d75effSDimitry Andric internal_prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, addr, size, (uptr)name); 38168d75effSDimitry Andric } 38268d75effSDimitry Andric #else 38368d75effSDimitry Andric void DecorateMapping(uptr addr, uptr size, const char *name) { 38468d75effSDimitry Andric } 38568d75effSDimitry Andric #endif 38668d75effSDimitry Andric 38768d75effSDimitry Andric uptr MmapNamed(void *addr, uptr length, int prot, int flags, const char *name) { 38868d75effSDimitry Andric int fd = GetNamedMappingFd(name, length, &flags); 38968d75effSDimitry Andric uptr res = internal_mmap(addr, length, prot, flags, fd, 0); 39068d75effSDimitry Andric if (!internal_iserror(res)) 39168d75effSDimitry Andric DecorateMapping(res, length, name); 39268d75effSDimitry Andric return res; 39368d75effSDimitry Andric } 39468d75effSDimitry Andric 39568d75effSDimitry Andric 39668d75effSDimitry Andric } // namespace __sanitizer 39768d75effSDimitry Andric 39868d75effSDimitry Andric #endif // SANITIZER_POSIX 399