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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Information about the process mappings
10// (FreeBSD and NetBSD-specific parts).
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_platform.h"
14#if SANITIZER_FREEBSD || SANITIZER_NETBSD
15#include "sanitizer_common.h"
16#include "sanitizer_procmaps.h"
17
18// clang-format off
19#include <sys/types.h>
20#include <sys/sysctl.h>
21// clang-format on
22#include <unistd.h>
23#if SANITIZER_FREEBSD
24#include <sys/user.h>
25#endif
26
27#include <limits.h>
28
29namespace __sanitizer {
30
31#if SANITIZER_FREEBSD
32void 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_NETBSD
46void 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, getpid(), Size, 1};
51 InfoProc = (struct kinfo_proc2 *)MmapOrDie(Size, "GetMemoryProfile()");
52 CHECK_EQ(
53 internal_sysctl(Mib, ARRAY_SIZE(Mib), nullptr, (uptr *)InfoProc, &Len, 0),
54 0);
55 cb(0, InfoProc->p_vm_rssize * GetPageSizeCached(), false, stats);
56 UnmapOrDie(InfoProc, Size, true);
57}
58#endif
59
60void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
61 const int Mib[] = {
62#if SANITIZER_FREEBSD
63 CTL_KERN,
64 KERN_PROC,
65 KERN_PROC_VMMAP,
66 getpid()
67#elif SANITIZER_NETBSD
68 CTL_VM,
69 VM_PROC,
70 VM_PROC_MAP,
71 getpid(),
72 sizeof(struct kinfo_vmentry)
73#else
74#error "not supported"
75#endif
76 };
77
78 uptr Size = 0;
79 int Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), NULL, &Size, NULL, 0);
80 CHECK_EQ(Err, 0);
81 CHECK_GT(Size, 0);
82
83 size_t MmapedSize = Size * 4 / 3;
84 void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()");
85 Size = MmapedSize;
86 Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), VmMap, &Size, NULL, 0);
87 CHECK_EQ(Err, 0);
88 proc_maps->data = (char *)VmMap;
89 proc_maps->mmaped_size = MmapedSize;
90 proc_maps->len = Size;
91}
92
93bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
94 CHECK(!Error()); // can not fail
95 char *last = data_.proc_self_maps.data + data_.proc_self_maps.len;
96 if (data_.current >= last)
97 return false;
98 const struct kinfo_vmentry *VmEntry =
99 (const struct kinfo_vmentry *)data_.current;
100
101 segment->start = (uptr)VmEntry->kve_start;
102 segment->end = (uptr)VmEntry->kve_end;
103 segment->offset = (uptr)VmEntry->kve_offset;
104
105 segment->protection = 0;
106 if ((VmEntry->kve_protection & KVME_PROT_READ) != 0)
107 segment->protection |= kProtectionRead;
108 if ((VmEntry->kve_protection & KVME_PROT_WRITE) != 0)
109 segment->protection |= kProtectionWrite;
110 if ((VmEntry->kve_protection & KVME_PROT_EXEC) != 0)
111 segment->protection |= kProtectionExecute;
112
113 if (segment->filename != NULL && segment->filename_size > 0) {
114 internal_snprintf(segment->filename,
115 Min(segment->filename_size, (uptr)PATH_MAX), "%s",
116 VmEntry->kve_path);
117 }
118
119#if SANITIZER_FREEBSD
120 data_.current += VmEntry->kve_structsize;
121#else
122 data_.current += sizeof(*VmEntry);
123#endif
124
125 return true;
126}
127
128} // namespace __sanitizer
129
130#endif
131

source code of compiler-rt/lib/sanitizer_common/sanitizer_procmaps_bsd.cpp