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