1*68d75effSDimitry Andric //===-- sanitizer_posix.cpp -----------------------------------------------===// 2*68d75effSDimitry Andric // 3*68d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*68d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*68d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*68d75effSDimitry Andric // 7*68d75effSDimitry Andric //===----------------------------------------------------------------------===// 8*68d75effSDimitry Andric // 9*68d75effSDimitry Andric // This file is shared between AddressSanitizer and ThreadSanitizer 10*68d75effSDimitry Andric // run-time libraries and implements POSIX-specific functions from 11*68d75effSDimitry Andric // sanitizer_posix.h. 12*68d75effSDimitry Andric //===----------------------------------------------------------------------===// 13*68d75effSDimitry Andric 14*68d75effSDimitry Andric #include "sanitizer_platform.h" 15*68d75effSDimitry Andric 16*68d75effSDimitry Andric #if SANITIZER_POSIX 17*68d75effSDimitry Andric 18*68d75effSDimitry Andric #include "sanitizer_common.h" 19*68d75effSDimitry Andric #include "sanitizer_file.h" 20*68d75effSDimitry Andric #include "sanitizer_flags.h" 21*68d75effSDimitry Andric #include "sanitizer_libc.h" 22*68d75effSDimitry Andric #include "sanitizer_posix.h" 23*68d75effSDimitry Andric #include "sanitizer_procmaps.h" 24*68d75effSDimitry Andric 25*68d75effSDimitry Andric #include <errno.h> 26*68d75effSDimitry Andric #include <fcntl.h> 27*68d75effSDimitry Andric #include <signal.h> 28*68d75effSDimitry Andric #include <sys/mman.h> 29*68d75effSDimitry Andric 30*68d75effSDimitry Andric #if SANITIZER_FREEBSD 31*68d75effSDimitry Andric // The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before 32*68d75effSDimitry Andric // that, it was never implemented. So just define it to zero. 33*68d75effSDimitry Andric #undef MAP_NORESERVE 34*68d75effSDimitry Andric #define MAP_NORESERVE 0 35*68d75effSDimitry Andric #endif 36*68d75effSDimitry Andric 37*68d75effSDimitry Andric namespace __sanitizer { 38*68d75effSDimitry Andric 39*68d75effSDimitry Andric // ------------- sanitizer_common.h 40*68d75effSDimitry Andric uptr GetMmapGranularity() { 41*68d75effSDimitry Andric return GetPageSize(); 42*68d75effSDimitry Andric } 43*68d75effSDimitry Andric 44*68d75effSDimitry Andric void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) { 45*68d75effSDimitry Andric size = RoundUpTo(size, GetPageSizeCached()); 46*68d75effSDimitry Andric uptr res = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE, 47*68d75effSDimitry Andric MAP_PRIVATE | MAP_ANON, mem_type); 48*68d75effSDimitry Andric int reserrno; 49*68d75effSDimitry Andric if (UNLIKELY(internal_iserror(res, &reserrno))) 50*68d75effSDimitry Andric ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno, raw_report); 51*68d75effSDimitry Andric IncreaseTotalMmap(size); 52*68d75effSDimitry Andric return (void *)res; 53*68d75effSDimitry Andric } 54*68d75effSDimitry Andric 55*68d75effSDimitry Andric void UnmapOrDie(void *addr, uptr size) { 56*68d75effSDimitry Andric if (!addr || !size) return; 57*68d75effSDimitry Andric uptr res = internal_munmap(addr, size); 58*68d75effSDimitry Andric if (UNLIKELY(internal_iserror(res))) { 59*68d75effSDimitry Andric Report("ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p\n", 60*68d75effSDimitry Andric SanitizerToolName, size, size, addr); 61*68d75effSDimitry Andric CHECK("unable to unmap" && 0); 62*68d75effSDimitry Andric } 63*68d75effSDimitry Andric DecreaseTotalMmap(size); 64*68d75effSDimitry Andric } 65*68d75effSDimitry Andric 66*68d75effSDimitry Andric void *MmapOrDieOnFatalError(uptr size, const char *mem_type) { 67*68d75effSDimitry Andric size = RoundUpTo(size, GetPageSizeCached()); 68*68d75effSDimitry Andric uptr res = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE, 69*68d75effSDimitry Andric MAP_PRIVATE | MAP_ANON, mem_type); 70*68d75effSDimitry Andric int reserrno; 71*68d75effSDimitry Andric if (UNLIKELY(internal_iserror(res, &reserrno))) { 72*68d75effSDimitry Andric if (reserrno == ENOMEM) 73*68d75effSDimitry Andric return nullptr; 74*68d75effSDimitry Andric ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno); 75*68d75effSDimitry Andric } 76*68d75effSDimitry Andric IncreaseTotalMmap(size); 77*68d75effSDimitry Andric return (void *)res; 78*68d75effSDimitry Andric } 79*68d75effSDimitry Andric 80*68d75effSDimitry Andric // We want to map a chunk of address space aligned to 'alignment'. 81*68d75effSDimitry Andric // We do it by mapping a bit more and then unmapping redundant pieces. 82*68d75effSDimitry Andric // We probably can do it with fewer syscalls in some OS-dependent way. 83*68d75effSDimitry Andric void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment, 84*68d75effSDimitry Andric const char *mem_type) { 85*68d75effSDimitry Andric CHECK(IsPowerOfTwo(size)); 86*68d75effSDimitry Andric CHECK(IsPowerOfTwo(alignment)); 87*68d75effSDimitry Andric uptr map_size = size + alignment; 88*68d75effSDimitry Andric uptr map_res = (uptr)MmapOrDieOnFatalError(map_size, mem_type); 89*68d75effSDimitry Andric if (UNLIKELY(!map_res)) 90*68d75effSDimitry Andric return nullptr; 91*68d75effSDimitry Andric uptr map_end = map_res + map_size; 92*68d75effSDimitry Andric uptr res = map_res; 93*68d75effSDimitry Andric if (!IsAligned(res, alignment)) { 94*68d75effSDimitry Andric res = (map_res + alignment - 1) & ~(alignment - 1); 95*68d75effSDimitry Andric UnmapOrDie((void*)map_res, res - map_res); 96*68d75effSDimitry Andric } 97*68d75effSDimitry Andric uptr end = res + size; 98*68d75effSDimitry Andric if (end != map_end) 99*68d75effSDimitry Andric UnmapOrDie((void*)end, map_end - end); 100*68d75effSDimitry Andric return (void*)res; 101*68d75effSDimitry Andric } 102*68d75effSDimitry Andric 103*68d75effSDimitry Andric void *MmapNoReserveOrDie(uptr size, const char *mem_type) { 104*68d75effSDimitry Andric size = RoundUpTo(size, GetPageSizeCached()); 105*68d75effSDimitry Andric uptr p = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE, 106*68d75effSDimitry Andric MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, mem_type); 107*68d75effSDimitry Andric int reserrno; 108*68d75effSDimitry Andric if (UNLIKELY(internal_iserror(p, &reserrno))) 109*68d75effSDimitry Andric ReportMmapFailureAndDie(size, mem_type, "allocate noreserve", reserrno); 110*68d75effSDimitry Andric IncreaseTotalMmap(size); 111*68d75effSDimitry Andric return (void *)p; 112*68d75effSDimitry Andric } 113*68d75effSDimitry Andric 114*68d75effSDimitry Andric static void *MmapFixedImpl(uptr fixed_addr, uptr size, bool tolerate_enomem, 115*68d75effSDimitry Andric const char *name) { 116*68d75effSDimitry Andric size = RoundUpTo(size, GetPageSizeCached()); 117*68d75effSDimitry Andric fixed_addr = RoundDownTo(fixed_addr, GetPageSizeCached()); 118*68d75effSDimitry Andric uptr p = MmapNamed((void *)fixed_addr, size, PROT_READ | PROT_WRITE, 119*68d75effSDimitry Andric MAP_PRIVATE | MAP_ANON | MAP_FIXED, name); 120*68d75effSDimitry Andric int reserrno; 121*68d75effSDimitry Andric if (UNLIKELY(internal_iserror(p, &reserrno))) { 122*68d75effSDimitry Andric if (tolerate_enomem && reserrno == ENOMEM) 123*68d75effSDimitry Andric return nullptr; 124*68d75effSDimitry Andric char mem_type[40]; 125*68d75effSDimitry Andric internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx", 126*68d75effSDimitry Andric fixed_addr); 127*68d75effSDimitry Andric ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno); 128*68d75effSDimitry Andric } 129*68d75effSDimitry Andric IncreaseTotalMmap(size); 130*68d75effSDimitry Andric return (void *)p; 131*68d75effSDimitry Andric } 132*68d75effSDimitry Andric 133*68d75effSDimitry Andric void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name) { 134*68d75effSDimitry Andric return MmapFixedImpl(fixed_addr, size, false /*tolerate_enomem*/, name); 135*68d75effSDimitry Andric } 136*68d75effSDimitry Andric 137*68d75effSDimitry Andric void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size, const char *name) { 138*68d75effSDimitry Andric return MmapFixedImpl(fixed_addr, size, true /*tolerate_enomem*/, name); 139*68d75effSDimitry Andric } 140*68d75effSDimitry Andric 141*68d75effSDimitry Andric bool MprotectNoAccess(uptr addr, uptr size) { 142*68d75effSDimitry Andric return 0 == internal_mprotect((void*)addr, size, PROT_NONE); 143*68d75effSDimitry Andric } 144*68d75effSDimitry Andric 145*68d75effSDimitry Andric bool MprotectReadOnly(uptr addr, uptr size) { 146*68d75effSDimitry Andric return 0 == internal_mprotect((void *)addr, size, PROT_READ); 147*68d75effSDimitry Andric } 148*68d75effSDimitry Andric 149*68d75effSDimitry Andric #if !SANITIZER_MAC 150*68d75effSDimitry Andric void MprotectMallocZones(void *addr, int prot) {} 151*68d75effSDimitry Andric #endif 152*68d75effSDimitry Andric 153*68d75effSDimitry Andric fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *errno_p) { 154*68d75effSDimitry Andric if (ShouldMockFailureToOpen(filename)) 155*68d75effSDimitry Andric return kInvalidFd; 156*68d75effSDimitry Andric int flags; 157*68d75effSDimitry Andric switch (mode) { 158*68d75effSDimitry Andric case RdOnly: flags = O_RDONLY; break; 159*68d75effSDimitry Andric case WrOnly: flags = O_WRONLY | O_CREAT | O_TRUNC; break; 160*68d75effSDimitry Andric case RdWr: flags = O_RDWR | O_CREAT; break; 161*68d75effSDimitry Andric } 162*68d75effSDimitry Andric fd_t res = internal_open(filename, flags, 0660); 163*68d75effSDimitry Andric if (internal_iserror(res, errno_p)) 164*68d75effSDimitry Andric return kInvalidFd; 165*68d75effSDimitry Andric return ReserveStandardFds(res); 166*68d75effSDimitry Andric } 167*68d75effSDimitry Andric 168*68d75effSDimitry Andric void CloseFile(fd_t fd) { 169*68d75effSDimitry Andric internal_close(fd); 170*68d75effSDimitry Andric } 171*68d75effSDimitry Andric 172*68d75effSDimitry Andric bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read, 173*68d75effSDimitry Andric error_t *error_p) { 174*68d75effSDimitry Andric uptr res = internal_read(fd, buff, buff_size); 175*68d75effSDimitry Andric if (internal_iserror(res, error_p)) 176*68d75effSDimitry Andric return false; 177*68d75effSDimitry Andric if (bytes_read) 178*68d75effSDimitry Andric *bytes_read = res; 179*68d75effSDimitry Andric return true; 180*68d75effSDimitry Andric } 181*68d75effSDimitry Andric 182*68d75effSDimitry Andric bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written, 183*68d75effSDimitry Andric error_t *error_p) { 184*68d75effSDimitry Andric uptr res = internal_write(fd, buff, buff_size); 185*68d75effSDimitry Andric if (internal_iserror(res, error_p)) 186*68d75effSDimitry Andric return false; 187*68d75effSDimitry Andric if (bytes_written) 188*68d75effSDimitry Andric *bytes_written = res; 189*68d75effSDimitry Andric return true; 190*68d75effSDimitry Andric } 191*68d75effSDimitry Andric 192*68d75effSDimitry Andric void *MapFileToMemory(const char *file_name, uptr *buff_size) { 193*68d75effSDimitry Andric fd_t fd = OpenFile(file_name, RdOnly); 194*68d75effSDimitry Andric CHECK(fd != kInvalidFd); 195*68d75effSDimitry Andric uptr fsize = internal_filesize(fd); 196*68d75effSDimitry Andric CHECK_NE(fsize, (uptr)-1); 197*68d75effSDimitry Andric CHECK_GT(fsize, 0); 198*68d75effSDimitry Andric *buff_size = RoundUpTo(fsize, GetPageSizeCached()); 199*68d75effSDimitry Andric uptr map = internal_mmap(nullptr, *buff_size, PROT_READ, MAP_PRIVATE, fd, 0); 200*68d75effSDimitry Andric return internal_iserror(map) ? nullptr : (void *)map; 201*68d75effSDimitry Andric } 202*68d75effSDimitry Andric 203*68d75effSDimitry Andric void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset) { 204*68d75effSDimitry Andric uptr flags = MAP_SHARED; 205*68d75effSDimitry Andric if (addr) flags |= MAP_FIXED; 206*68d75effSDimitry Andric uptr p = internal_mmap(addr, size, PROT_READ | PROT_WRITE, flags, fd, offset); 207*68d75effSDimitry Andric int mmap_errno = 0; 208*68d75effSDimitry Andric if (internal_iserror(p, &mmap_errno)) { 209*68d75effSDimitry Andric Printf("could not map writable file (%d, %lld, %zu): %zd, errno: %d\n", 210*68d75effSDimitry Andric fd, (long long)offset, size, p, mmap_errno); 211*68d75effSDimitry Andric return nullptr; 212*68d75effSDimitry Andric } 213*68d75effSDimitry Andric return (void *)p; 214*68d75effSDimitry Andric } 215*68d75effSDimitry Andric 216*68d75effSDimitry Andric static inline bool IntervalsAreSeparate(uptr start1, uptr end1, 217*68d75effSDimitry Andric uptr start2, uptr end2) { 218*68d75effSDimitry Andric CHECK(start1 <= end1); 219*68d75effSDimitry Andric CHECK(start2 <= end2); 220*68d75effSDimitry Andric return (end1 < start2) || (end2 < start1); 221*68d75effSDimitry Andric } 222*68d75effSDimitry Andric 223*68d75effSDimitry Andric // FIXME: this is thread-unsafe, but should not cause problems most of the time. 224*68d75effSDimitry Andric // When the shadow is mapped only a single thread usually exists (plus maybe 225*68d75effSDimitry Andric // several worker threads on Mac, which aren't expected to map big chunks of 226*68d75effSDimitry Andric // memory). 227*68d75effSDimitry Andric bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) { 228*68d75effSDimitry Andric MemoryMappingLayout proc_maps(/*cache_enabled*/true); 229*68d75effSDimitry Andric if (proc_maps.Error()) 230*68d75effSDimitry Andric return true; // and hope for the best 231*68d75effSDimitry Andric MemoryMappedSegment segment; 232*68d75effSDimitry Andric while (proc_maps.Next(&segment)) { 233*68d75effSDimitry Andric if (segment.start == segment.end) continue; // Empty range. 234*68d75effSDimitry Andric CHECK_NE(0, segment.end); 235*68d75effSDimitry Andric if (!IntervalsAreSeparate(segment.start, segment.end - 1, range_start, 236*68d75effSDimitry Andric range_end)) 237*68d75effSDimitry Andric return false; 238*68d75effSDimitry Andric } 239*68d75effSDimitry Andric return true; 240*68d75effSDimitry Andric } 241*68d75effSDimitry Andric 242*68d75effSDimitry Andric void DumpProcessMap() { 243*68d75effSDimitry Andric MemoryMappingLayout proc_maps(/*cache_enabled*/true); 244*68d75effSDimitry Andric const sptr kBufSize = 4095; 245*68d75effSDimitry Andric char *filename = (char*)MmapOrDie(kBufSize, __func__); 246*68d75effSDimitry Andric MemoryMappedSegment segment(filename, kBufSize); 247*68d75effSDimitry Andric Report("Process memory map follows:\n"); 248*68d75effSDimitry Andric while (proc_maps.Next(&segment)) { 249*68d75effSDimitry Andric Printf("\t%p-%p\t%s\n", (void *)segment.start, (void *)segment.end, 250*68d75effSDimitry Andric segment.filename); 251*68d75effSDimitry Andric } 252*68d75effSDimitry Andric Report("End of process memory map.\n"); 253*68d75effSDimitry Andric UnmapOrDie(filename, kBufSize); 254*68d75effSDimitry Andric } 255*68d75effSDimitry Andric 256*68d75effSDimitry Andric const char *GetPwd() { 257*68d75effSDimitry Andric return GetEnv("PWD"); 258*68d75effSDimitry Andric } 259*68d75effSDimitry Andric 260*68d75effSDimitry Andric bool IsPathSeparator(const char c) { 261*68d75effSDimitry Andric return c == '/'; 262*68d75effSDimitry Andric } 263*68d75effSDimitry Andric 264*68d75effSDimitry Andric bool IsAbsolutePath(const char *path) { 265*68d75effSDimitry Andric return path != nullptr && IsPathSeparator(path[0]); 266*68d75effSDimitry Andric } 267*68d75effSDimitry Andric 268*68d75effSDimitry Andric void ReportFile::Write(const char *buffer, uptr length) { 269*68d75effSDimitry Andric SpinMutexLock l(mu); 270*68d75effSDimitry Andric ReopenIfNecessary(); 271*68d75effSDimitry Andric internal_write(fd, buffer, length); 272*68d75effSDimitry Andric } 273*68d75effSDimitry Andric 274*68d75effSDimitry Andric bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end) { 275*68d75effSDimitry Andric MemoryMappingLayout proc_maps(/*cache_enabled*/false); 276*68d75effSDimitry Andric InternalScopedString buff(kMaxPathLength); 277*68d75effSDimitry Andric MemoryMappedSegment segment(buff.data(), kMaxPathLength); 278*68d75effSDimitry Andric while (proc_maps.Next(&segment)) { 279*68d75effSDimitry Andric if (segment.IsExecutable() && 280*68d75effSDimitry Andric internal_strcmp(module, segment.filename) == 0) { 281*68d75effSDimitry Andric *start = segment.start; 282*68d75effSDimitry Andric *end = segment.end; 283*68d75effSDimitry Andric return true; 284*68d75effSDimitry Andric } 285*68d75effSDimitry Andric } 286*68d75effSDimitry Andric return false; 287*68d75effSDimitry Andric } 288*68d75effSDimitry Andric 289*68d75effSDimitry Andric uptr SignalContext::GetAddress() const { 290*68d75effSDimitry Andric auto si = static_cast<const siginfo_t *>(siginfo); 291*68d75effSDimitry Andric return (uptr)si->si_addr; 292*68d75effSDimitry Andric } 293*68d75effSDimitry Andric 294*68d75effSDimitry Andric bool SignalContext::IsMemoryAccess() const { 295*68d75effSDimitry Andric auto si = static_cast<const siginfo_t *>(siginfo); 296*68d75effSDimitry Andric return si->si_signo == SIGSEGV; 297*68d75effSDimitry Andric } 298*68d75effSDimitry Andric 299*68d75effSDimitry Andric int SignalContext::GetType() const { 300*68d75effSDimitry Andric return static_cast<const siginfo_t *>(siginfo)->si_signo; 301*68d75effSDimitry Andric } 302*68d75effSDimitry Andric 303*68d75effSDimitry Andric const char *SignalContext::Describe() const { 304*68d75effSDimitry Andric switch (GetType()) { 305*68d75effSDimitry Andric case SIGFPE: 306*68d75effSDimitry Andric return "FPE"; 307*68d75effSDimitry Andric case SIGILL: 308*68d75effSDimitry Andric return "ILL"; 309*68d75effSDimitry Andric case SIGABRT: 310*68d75effSDimitry Andric return "ABRT"; 311*68d75effSDimitry Andric case SIGSEGV: 312*68d75effSDimitry Andric return "SEGV"; 313*68d75effSDimitry Andric case SIGBUS: 314*68d75effSDimitry Andric return "BUS"; 315*68d75effSDimitry Andric case SIGTRAP: 316*68d75effSDimitry Andric return "TRAP"; 317*68d75effSDimitry Andric } 318*68d75effSDimitry Andric return "UNKNOWN SIGNAL"; 319*68d75effSDimitry Andric } 320*68d75effSDimitry Andric 321*68d75effSDimitry Andric fd_t ReserveStandardFds(fd_t fd) { 322*68d75effSDimitry Andric CHECK_GE(fd, 0); 323*68d75effSDimitry Andric if (fd > 2) 324*68d75effSDimitry Andric return fd; 325*68d75effSDimitry Andric bool used[3]; 326*68d75effSDimitry Andric internal_memset(used, 0, sizeof(used)); 327*68d75effSDimitry Andric while (fd <= 2) { 328*68d75effSDimitry Andric used[fd] = true; 329*68d75effSDimitry Andric fd = internal_dup(fd); 330*68d75effSDimitry Andric } 331*68d75effSDimitry Andric for (int i = 0; i <= 2; ++i) 332*68d75effSDimitry Andric if (used[i]) 333*68d75effSDimitry Andric internal_close(i); 334*68d75effSDimitry Andric return fd; 335*68d75effSDimitry Andric } 336*68d75effSDimitry Andric 337*68d75effSDimitry Andric bool ShouldMockFailureToOpen(const char *path) { 338*68d75effSDimitry Andric return common_flags()->test_only_emulate_no_memorymap && 339*68d75effSDimitry Andric internal_strncmp(path, "/proc/", 6) == 0; 340*68d75effSDimitry Andric } 341*68d75effSDimitry Andric 342*68d75effSDimitry Andric #if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_GO 343*68d75effSDimitry Andric int GetNamedMappingFd(const char *name, uptr size, int *flags) { 344*68d75effSDimitry Andric if (!common_flags()->decorate_proc_maps || !name) 345*68d75effSDimitry Andric return -1; 346*68d75effSDimitry Andric char shmname[200]; 347*68d75effSDimitry Andric CHECK(internal_strlen(name) < sizeof(shmname) - 10); 348*68d75effSDimitry Andric internal_snprintf(shmname, sizeof(shmname), "/dev/shm/%zu [%s]", 349*68d75effSDimitry Andric internal_getpid(), name); 350*68d75effSDimitry Andric int fd = ReserveStandardFds( 351*68d75effSDimitry Andric internal_open(shmname, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, S_IRWXU)); 352*68d75effSDimitry Andric CHECK_GE(fd, 0); 353*68d75effSDimitry Andric int res = internal_ftruncate(fd, size); 354*68d75effSDimitry Andric CHECK_EQ(0, res); 355*68d75effSDimitry Andric res = internal_unlink(shmname); 356*68d75effSDimitry Andric CHECK_EQ(0, res); 357*68d75effSDimitry Andric *flags &= ~(MAP_ANON | MAP_ANONYMOUS); 358*68d75effSDimitry Andric return fd; 359*68d75effSDimitry Andric } 360*68d75effSDimitry Andric #else 361*68d75effSDimitry Andric int GetNamedMappingFd(const char *name, uptr size, int *flags) { 362*68d75effSDimitry Andric return -1; 363*68d75effSDimitry Andric } 364*68d75effSDimitry Andric #endif 365*68d75effSDimitry Andric 366*68d75effSDimitry Andric #if SANITIZER_ANDROID 367*68d75effSDimitry Andric #define PR_SET_VMA 0x53564d41 368*68d75effSDimitry Andric #define PR_SET_VMA_ANON_NAME 0 369*68d75effSDimitry Andric void DecorateMapping(uptr addr, uptr size, const char *name) { 370*68d75effSDimitry Andric if (!common_flags()->decorate_proc_maps || !name) 371*68d75effSDimitry Andric return; 372*68d75effSDimitry Andric internal_prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, addr, size, (uptr)name); 373*68d75effSDimitry Andric } 374*68d75effSDimitry Andric #else 375*68d75effSDimitry Andric void DecorateMapping(uptr addr, uptr size, const char *name) { 376*68d75effSDimitry Andric } 377*68d75effSDimitry Andric #endif 378*68d75effSDimitry Andric 379*68d75effSDimitry Andric uptr MmapNamed(void *addr, uptr length, int prot, int flags, const char *name) { 380*68d75effSDimitry Andric int fd = GetNamedMappingFd(name, length, &flags); 381*68d75effSDimitry Andric uptr res = internal_mmap(addr, length, prot, flags, fd, 0); 382*68d75effSDimitry Andric if (!internal_iserror(res)) 383*68d75effSDimitry Andric DecorateMapping(res, length, name); 384*68d75effSDimitry Andric return res; 385*68d75effSDimitry Andric } 386*68d75effSDimitry Andric 387*68d75effSDimitry Andric 388*68d75effSDimitry Andric } // namespace __sanitizer 389*68d75effSDimitry Andric 390*68d75effSDimitry Andric #endif // SANITIZER_POSIX 391