//===-- sanitizer_procmaps_bsd.cpp ----------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Information about the process mappings // (FreeBSD and NetBSD-specific parts). //===----------------------------------------------------------------------===// #include "sanitizer_platform.h" #if SANITIZER_FREEBSD || SANITIZER_NETBSD #include "sanitizer_common.h" #include "sanitizer_procmaps.h" // clang-format off #include #include // clang-format on #include #if SANITIZER_FREEBSD #include #endif #include namespace __sanitizer { #if SANITIZER_FREEBSD void GetMemoryProfile(fill_profile_f cb, uptr *stats) { const int Mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()}; struct kinfo_proc *InfoProc; uptr Len = sizeof(*InfoProc); uptr Size = Len; InfoProc = (struct kinfo_proc *)MmapOrDie(Size, "GetMemoryProfile()"); CHECK_EQ( internal_sysctl(Mib, ARRAY_SIZE(Mib), nullptr, (uptr *)InfoProc, &Len, 0), 0); cb(0, InfoProc->ki_rssize * GetPageSizeCached(), false, stats); UnmapOrDie(InfoProc, Size, true); } #elif SANITIZER_NETBSD void GetMemoryProfile(fill_profile_f cb, uptr *stats) { struct kinfo_proc2 *InfoProc; uptr Len = sizeof(*InfoProc); uptr Size = Len; const int Mib[] = {CTL_KERN, KERN_PROC2, KERN_PROC_PID, getpid(), (int)Size, 1}; InfoProc = (struct kinfo_proc2 *)MmapOrDie(Size, "GetMemoryProfile()"); CHECK_EQ( internal_sysctl(Mib, ARRAY_SIZE(Mib), nullptr, (uptr *)InfoProc, &Len, 0), 0); cb(0, InfoProc->p_vm_rssize * GetPageSizeCached(), false, stats); UnmapOrDie(InfoProc, Size, true); } #endif void ReadProcMaps(ProcSelfMapsBuff *proc_maps) { const int Mib[] = { #if SANITIZER_FREEBSD CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid() #elif SANITIZER_NETBSD CTL_VM, VM_PROC, VM_PROC_MAP, getpid(), sizeof(struct kinfo_vmentry) #else #error "not supported" #endif }; uptr Size = 0; int Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), NULL, &Size, NULL, 0); CHECK_EQ(Err, 0); CHECK_GT(Size, 0); size_t MmapedSize = Size * 4 / 3; void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()"); Size = MmapedSize; Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), VmMap, &Size, NULL, 0); CHECK_EQ(Err, 0); proc_maps->data = (char *)VmMap; proc_maps->mmaped_size = MmapedSize; proc_maps->len = Size; } bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) { CHECK(!Error()); // can not fail char *last = data_.proc_self_maps.data + data_.proc_self_maps.len; if (data_.current >= last) return false; const struct kinfo_vmentry *VmEntry = (const struct kinfo_vmentry *)data_.current; segment->start = (uptr)VmEntry->kve_start; segment->end = (uptr)VmEntry->kve_end; segment->offset = (uptr)VmEntry->kve_offset; segment->protection = 0; if ((VmEntry->kve_protection & KVME_PROT_READ) != 0) segment->protection |= kProtectionRead; if ((VmEntry->kve_protection & KVME_PROT_WRITE) != 0) segment->protection |= kProtectionWrite; if ((VmEntry->kve_protection & KVME_PROT_EXEC) != 0) segment->protection |= kProtectionExecute; if (segment->filename != NULL && segment->filename_size > 0) { internal_snprintf(segment->filename, Min(segment->filename_size, (uptr)PATH_MAX), "%s", VmEntry->kve_path); } #if SANITIZER_FREEBSD data_.current += VmEntry->kve_structsize; #else data_.current += sizeof(*VmEntry); #endif return true; } } // namespace __sanitizer #endif