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 44namespace __sanitizer { 45 46void 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 99bool 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