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 33 namespace __sanitizer { 34 35 void 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 67 bool 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