132 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// Information about the process mappings10// (FreeBSD and NetBSD-specific parts).11//===----------------------------------------------------------------------===//12 13#include "sanitizer_platform.h"14#if SANITIZER_FREEBSD || SANITIZER_NETBSD15#include "sanitizer_common.h"16#include "sanitizer_procmaps.h"17 18// clang-format off19#include <sys/types.h>20#include <sys/sysctl.h>21// clang-format on22#include <unistd.h>23#if SANITIZER_FREEBSD24#include <sys/user.h>25#endif26 27#include <limits.h>28 29namespace __sanitizer {30 31#if SANITIZER_FREEBSD32void GetMemoryProfile(fill_profile_f cb, uptr *stats) {33 const int Mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()};34 35 struct kinfo_proc *InfoProc;36 uptr Len = sizeof(*InfoProc);37 uptr Size = Len;38 InfoProc = (struct kinfo_proc *)MmapOrDie(Size, "GetMemoryProfile()");39 CHECK_EQ(40 internal_sysctl(Mib, ARRAY_SIZE(Mib), nullptr, (uptr *)InfoProc, &Len, 0),41 0);42 cb(0, InfoProc->ki_rssize * GetPageSizeCached(), false, stats);43 UnmapOrDie(InfoProc, Size, true);44}45#elif SANITIZER_NETBSD46void GetMemoryProfile(fill_profile_f cb, uptr *stats) {47 struct kinfo_proc2 *InfoProc;48 uptr Len = sizeof(*InfoProc);49 uptr Size = Len;50 const int Mib[] = {CTL_KERN, KERN_PROC2, KERN_PROC_PID,51 getpid(), (int)Size, 1};52 InfoProc = (struct kinfo_proc2 *)MmapOrDie(Size, "GetMemoryProfile()");53 CHECK_EQ(54 internal_sysctl(Mib, ARRAY_SIZE(Mib), nullptr, (uptr *)InfoProc, &Len, 0),55 0);56 cb(0, InfoProc->p_vm_rssize * GetPageSizeCached(), false, stats);57 UnmapOrDie(InfoProc, Size, true);58}59#endif60 61void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {62 const int Mib[] = {63#if SANITIZER_FREEBSD64 CTL_KERN,65 KERN_PROC,66 KERN_PROC_VMMAP,67 getpid()68#elif SANITIZER_NETBSD69 CTL_VM,70 VM_PROC,71 VM_PROC_MAP,72 getpid(),73 sizeof(struct kinfo_vmentry)74#else75#error "not supported"76#endif77 };78 79 uptr Size = 0;80 int Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), NULL, &Size, NULL, 0);81 CHECK_EQ(Err, 0);82 CHECK_GT(Size, 0);83 84 size_t MmapedSize = Size * 4 / 3;85 void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()");86 Size = MmapedSize;87 Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), VmMap, &Size, NULL, 0);88 CHECK_EQ(Err, 0);89 proc_maps->data = (char *)VmMap;90 proc_maps->mmaped_size = MmapedSize;91 proc_maps->len = Size;92}93 94bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {95 CHECK(!Error()); // can not fail96 char *last = data_.proc_self_maps.data + data_.proc_self_maps.len;97 if (data_.current >= last)98 return false;99 const struct kinfo_vmentry *VmEntry =100 (const struct kinfo_vmentry *)data_.current;101 102 segment->start = (uptr)VmEntry->kve_start;103 segment->end = (uptr)VmEntry->kve_end;104 segment->offset = (uptr)VmEntry->kve_offset;105 106 segment->protection = 0;107 if ((VmEntry->kve_protection & KVME_PROT_READ) != 0)108 segment->protection |= kProtectionRead;109 if ((VmEntry->kve_protection & KVME_PROT_WRITE) != 0)110 segment->protection |= kProtectionWrite;111 if ((VmEntry->kve_protection & KVME_PROT_EXEC) != 0)112 segment->protection |= kProtectionExecute;113 114 if (segment->filename != NULL && segment->filename_size > 0) {115 internal_snprintf(segment->filename,116 Min(segment->filename_size, (uptr)PATH_MAX), "%s",117 VmEntry->kve_path);118 }119 120#if SANITIZER_FREEBSD121 data_.current += VmEntry->kve_structsize;122#else123 data_.current += sizeof(*VmEntry);124#endif125 126 return true;127}128 129} // namespace __sanitizer130 131#endif132