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 #if SANITIZER_FREEBSD 17 #include "sanitizer_freebsd.h" 18 #endif 19 #include "sanitizer_procmaps.h" 20 21 // clang-format off 22 #include <sys/types.h> 23 #include <sys/sysctl.h> 24 // clang-format on 25 #include <unistd.h> 26 #if SANITIZER_FREEBSD 27 #include <sys/user.h> 28 #endif 29 30 #include <limits.h> 31 32 // Fix 'kinfo_vmentry' definition on FreeBSD prior v9.2 in 32-bit mode. 33 #if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) 34 #include <osreldate.h> 35 #if __FreeBSD_version <= 902001 // v9.2 36 #define kinfo_vmentry xkinfo_vmentry 37 #endif 38 #endif 39 40 namespace __sanitizer { 41 42 void ReadProcMaps(ProcSelfMapsBuff *proc_maps) { 43 const int Mib[] = { 44 #if SANITIZER_FREEBSD 45 CTL_KERN, 46 KERN_PROC, 47 KERN_PROC_VMMAP, 48 getpid() 49 #elif SANITIZER_NETBSD 50 CTL_VM, 51 VM_PROC, 52 VM_PROC_MAP, 53 getpid(), 54 sizeof(struct kinfo_vmentry) 55 #else 56 #error "not supported" 57 #endif 58 }; 59 60 uptr Size = 0; 61 int Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), NULL, &Size, NULL, 0); 62 CHECK_EQ(Err, 0); 63 CHECK_GT(Size, 0); 64 65 size_t MmapedSize = Size * 4 / 3; 66 void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()"); 67 Size = MmapedSize; 68 Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), VmMap, &Size, NULL, 0); 69 CHECK_EQ(Err, 0); 70 proc_maps->data = (char *)VmMap; 71 proc_maps->mmaped_size = MmapedSize; 72 proc_maps->len = Size; 73 } 74 75 bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) { 76 CHECK(!Error()); // can not fail 77 char *last = data_.proc_self_maps.data + data_.proc_self_maps.len; 78 if (data_.current >= last) 79 return false; 80 const struct kinfo_vmentry *VmEntry = 81 (const struct kinfo_vmentry *)data_.current; 82 83 segment->start = (uptr)VmEntry->kve_start; 84 segment->end = (uptr)VmEntry->kve_end; 85 segment->offset = (uptr)VmEntry->kve_offset; 86 87 segment->protection = 0; 88 if ((VmEntry->kve_protection & KVME_PROT_READ) != 0) 89 segment->protection |= kProtectionRead; 90 if ((VmEntry->kve_protection & KVME_PROT_WRITE) != 0) 91 segment->protection |= kProtectionWrite; 92 if ((VmEntry->kve_protection & KVME_PROT_EXEC) != 0) 93 segment->protection |= kProtectionExecute; 94 95 if (segment->filename != NULL && segment->filename_size > 0) { 96 internal_snprintf(segment->filename, 97 Min(segment->filename_size, (uptr)PATH_MAX), "%s", 98 VmEntry->kve_path); 99 } 100 101 #if SANITIZER_FREEBSD 102 data_.current += VmEntry->kve_structsize; 103 #else 104 data_.current += sizeof(*VmEntry); 105 #endif 106 107 return true; 108 } 109 110 } // namespace __sanitizer 111 112 #endif 113