1 //===-- sanitizer_procmaps_bsd.cpp ----------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Information about the process mappings 10 // (FreeBSD and NetBSD-specific parts). 11 //===----------------------------------------------------------------------===// 12 13 #include "sanitizer_platform.h" 14 #if SANITIZER_FREEBSD || SANITIZER_NETBSD 15 #include "sanitizer_common.h" 16 #include "sanitizer_procmaps.h" 17 18 // clang-format off 19 #include <sys/types.h> 20 #include <sys/sysctl.h> 21 // clang-format on 22 #include <unistd.h> 23 #if SANITIZER_FREEBSD 24 #include <sys/user.h> 25 #endif 26 27 #include <limits.h> 28 29 namespace __sanitizer { 30 31 #if SANITIZER_FREEBSD 32 void GetMemoryProfile(fill_profile_f cb, uptr *stats) { 33 const int Mib[] = { 34 CTL_KERN, 35 KERN_PROC, 36 KERN_PROC_PID, 37 getpid() 38 }; 39 40 struct kinfo_proc InfoProc; 41 uptr Len = sizeof(InfoProc); 42 CHECK_EQ(internal_sysctl(Mib, ARRAY_SIZE(Mib), nullptr, (uptr *)&InfoProc, &Len, 0), 0); 43 cb(0, InfoProc.ki_rssize * GetPageSizeCached(), false, stats); 44 } 45 #endif 46 47 void ReadProcMaps(ProcSelfMapsBuff *proc_maps) { 48 const int Mib[] = { 49 #if SANITIZER_FREEBSD 50 CTL_KERN, 51 KERN_PROC, 52 KERN_PROC_VMMAP, 53 getpid() 54 #elif SANITIZER_NETBSD 55 CTL_VM, 56 VM_PROC, 57 VM_PROC_MAP, 58 getpid(), 59 sizeof(struct kinfo_vmentry) 60 #else 61 #error "not supported" 62 #endif 63 }; 64 65 uptr Size = 0; 66 int Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), NULL, &Size, NULL, 0); 67 CHECK_EQ(Err, 0); 68 CHECK_GT(Size, 0); 69 70 size_t MmapedSize = Size * 4 / 3; 71 void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()"); 72 Size = MmapedSize; 73 Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), VmMap, &Size, NULL, 0); 74 CHECK_EQ(Err, 0); 75 proc_maps->data = (char *)VmMap; 76 proc_maps->mmaped_size = MmapedSize; 77 proc_maps->len = Size; 78 } 79 80 bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) { 81 CHECK(!Error()); // can not fail 82 char *last = data_.proc_self_maps.data + data_.proc_self_maps.len; 83 if (data_.current >= last) 84 return false; 85 const struct kinfo_vmentry *VmEntry = 86 (const struct kinfo_vmentry *)data_.current; 87 88 segment->start = (uptr)VmEntry->kve_start; 89 segment->end = (uptr)VmEntry->kve_end; 90 segment->offset = (uptr)VmEntry->kve_offset; 91 92 segment->protection = 0; 93 if ((VmEntry->kve_protection & KVME_PROT_READ) != 0) 94 segment->protection |= kProtectionRead; 95 if ((VmEntry->kve_protection & KVME_PROT_WRITE) != 0) 96 segment->protection |= kProtectionWrite; 97 if ((VmEntry->kve_protection & KVME_PROT_EXEC) != 0) 98 segment->protection |= kProtectionExecute; 99 100 if (segment->filename != NULL && segment->filename_size > 0) { 101 internal_snprintf(segment->filename, 102 Min(segment->filename_size, (uptr)PATH_MAX), "%s", 103 VmEntry->kve_path); 104 } 105 106 #if SANITIZER_FREEBSD 107 data_.current += VmEntry->kve_structsize; 108 #else 109 data_.current += sizeof(*VmEntry); 110 #endif 111 112 return true; 113 } 114 115 } // namespace __sanitizer 116 117 #endif 118