1 //===-- sanitizer_procmaps_bsd.cc -----------------------------------------===// 2 // 3 // This file is distributed under the University of Illinois Open Source 4 // License. See LICENSE.TXT for details. 5 // 6 //===----------------------------------------------------------------------===// 7 // 8 // Information about the process mappings 9 // (FreeBSD, OpenBSD and NetBSD-specific parts). 10 //===----------------------------------------------------------------------===// 11 12 #include "sanitizer_platform.h" 13 #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD 14 #include "sanitizer_common.h" 15 #if SANITIZER_FREEBSD 16 #include "sanitizer_freebsd.h" 17 #endif 18 #include "sanitizer_procmaps.h" 19 20 // clang-format off 21 #include <sys/types.h> 22 #include <sys/sysctl.h> 23 // clang-format on 24 #include <unistd.h> 25 #if SANITIZER_FREEBSD 26 #include <sys/user.h> 27 #endif 28 29 #include <limits.h> 30 #if SANITIZER_OPENBSD 31 #define KVME_PROT_READ KVE_PROT_READ 32 #define KVME_PROT_WRITE KVE_PROT_WRITE 33 #define KVME_PROT_EXEC KVE_PROT_EXEC 34 #endif 35 36 // Fix 'kinfo_vmentry' definition on FreeBSD prior v9.2 in 32-bit mode. 37 #if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) 38 #include <osreldate.h> 39 #if __FreeBSD_version <= 902001 // v9.2 40 #define kinfo_vmentry xkinfo_vmentry 41 #endif 42 #endif 43 44 namespace __sanitizer { 45 46 void ReadProcMaps(ProcSelfMapsBuff *proc_maps) { 47 const int Mib[] = { 48 #if SANITIZER_FREEBSD 49 CTL_KERN, 50 KERN_PROC, 51 KERN_PROC_VMMAP, 52 getpid() 53 #elif SANITIZER_OPENBSD 54 CTL_KERN, 55 KERN_PROC_VMMAP, 56 getpid() 57 #elif SANITIZER_NETBSD 58 CTL_VM, 59 VM_PROC, 60 VM_PROC_MAP, 61 getpid(), 62 sizeof(struct kinfo_vmentry) 63 #else 64 #error "not supported" 65 #endif 66 }; 67 68 uptr Size = 0; 69 int Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), NULL, &Size, NULL, 0); 70 CHECK_EQ(Err, 0); 71 CHECK_GT(Size, 0); 72 73 #if !SANITIZER_OPENBSD 74 size_t MmapedSize = Size * 4 / 3; 75 void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()"); 76 Size = MmapedSize; 77 Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), VmMap, &Size, NULL, 0); 78 CHECK_EQ(Err, 0); 79 proc_maps->data = (char *)VmMap; 80 #else 81 size_t PageSize = GetPageSize(); 82 size_t MmapedSize = Size; 83 MmapedSize = ((MmapedSize - 1) / PageSize + 1) * PageSize; 84 char *Mem = (char *)MmapOrDie(MmapedSize, "ReadProcMaps()"); 85 Size = 2 * Size + 10 * sizeof(struct kinfo_vmentry); 86 if (Size > 0x10000) 87 Size = 0x10000; 88 Size = (Size / sizeof(struct kinfo_vmentry)) * sizeof(struct kinfo_vmentry); 89 Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), Mem, &Size, NULL, 0); 90 CHECK_EQ(Err, 0); 91 MmapedSize = Size; 92 proc_maps->data = Mem; 93 #endif 94 95 proc_maps->mmaped_size = MmapedSize; 96 proc_maps->len = Size; 97 } 98 99 bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) { 100 char *last = data_.proc_self_maps.data + data_.proc_self_maps.len; 101 if (data_.current >= last) 102 return false; 103 const struct kinfo_vmentry *VmEntry = 104 (const struct kinfo_vmentry *)data_.current; 105 106 segment->start = (uptr)VmEntry->kve_start; 107 segment->end = (uptr)VmEntry->kve_end; 108 segment->offset = (uptr)VmEntry->kve_offset; 109 110 segment->protection = 0; 111 if ((VmEntry->kve_protection & KVME_PROT_READ) != 0) 112 segment->protection |= kProtectionRead; 113 if ((VmEntry->kve_protection & KVME_PROT_WRITE) != 0) 114 segment->protection |= kProtectionWrite; 115 if ((VmEntry->kve_protection & KVME_PROT_EXEC) != 0) 116 segment->protection |= kProtectionExecute; 117 118 #if !SANITIZER_OPENBSD 119 if (segment->filename != NULL && segment->filename_size > 0) { 120 internal_snprintf(segment->filename, 121 Min(segment->filename_size, (uptr)PATH_MAX), "%s", 122 VmEntry->kve_path); 123 } 124 #endif 125 126 #if SANITIZER_FREEBSD 127 data_.current += VmEntry->kve_structsize; 128 #else 129 data_.current += sizeof(*VmEntry); 130 #endif 131 132 return true; 133 } 134 135 } // namespace __sanitizer 136 137 #endif 138