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