xref: /netbsd-src/external/gpl3/gcc.old/dist/libsanitizer/sanitizer_common/sanitizer_procmaps_bsd.cc (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
1 //===-- sanitizer_procmaps_bsd.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
9 // (FreeBSD, OpenBSD and NetBSD-specific parts).
10 //===----------------------------------------------------------------------===//
11 
12 #include "sanitizer_platform.h"
13 #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD
14 #include "sanitizer_common.h"
15 #if SANITIZER_FREEBSD
16 #include "sanitizer_freebsd.h"
17 #endif
18 #include "sanitizer_procmaps.h"
19 
20 // clang-format off
21 #include <sys/types.h>
22 #include <sys/sysctl.h>
23 // clang-format on
24 #include <unistd.h>
25 #if SANITIZER_FREEBSD
26 #include <sys/user.h>
27 #endif
28 
29 #include <limits.h>
30 #if SANITIZER_OPENBSD
31 #define KVME_PROT_READ KVE_PROT_READ
32 #define KVME_PROT_WRITE KVE_PROT_WRITE
33 #define KVME_PROT_EXEC KVE_PROT_EXEC
34 #endif
35 
36 // Fix 'kinfo_vmentry' definition on FreeBSD prior v9.2 in 32-bit mode.
37 #if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32)
38 #include <osreldate.h>
39 #if __FreeBSD_version <= 902001 // v9.2
40 #define kinfo_vmentry xkinfo_vmentry
41 #endif
42 #endif
43 
44 namespace __sanitizer {
45 
ReadProcMaps(ProcSelfMapsBuff * proc_maps)46 void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
47   const int Mib[] = {
48 #if SANITIZER_FREEBSD
49     CTL_KERN,
50     KERN_PROC,
51     KERN_PROC_VMMAP,
52     getpid()
53 #elif SANITIZER_OPENBSD
54     CTL_KERN,
55     KERN_PROC_VMMAP,
56     getpid()
57 #elif SANITIZER_NETBSD
58     CTL_VM,
59     VM_PROC,
60     VM_PROC_MAP,
61     getpid(),
62     sizeof(struct kinfo_vmentry)
63 #else
64 #error "not supported"
65 #endif
66   };
67 
68   uptr Size = 0;
69   int Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), NULL, &Size, NULL, 0);
70   CHECK_EQ(Err, 0);
71   CHECK_GT(Size, 0);
72 
73 #if !SANITIZER_OPENBSD
74   size_t MmapedSize = Size * 4 / 3;
75   void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()");
76   Size = MmapedSize;
77   Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), VmMap, &Size, NULL, 0);
78   CHECK_EQ(Err, 0);
79   proc_maps->data = (char *)VmMap;
80 #else
81   size_t PageSize = GetPageSize();
82   size_t MmapedSize = Size;
83   MmapedSize = ((MmapedSize - 1) / PageSize + 1) * PageSize;
84   char *Mem = (char *)MmapOrDie(MmapedSize, "ReadProcMaps()");
85   Size = 2 * Size + 10 * sizeof(struct kinfo_vmentry);
86   if (Size > 0x10000)
87     Size = 0x10000;
88   Size = (Size / sizeof(struct kinfo_vmentry)) * sizeof(struct kinfo_vmentry);
89   Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), Mem, &Size, NULL, 0);
90   CHECK_EQ(Err, 0);
91   MmapedSize = Size;
92   proc_maps->data = Mem;
93 #endif
94 
95   proc_maps->mmaped_size = MmapedSize;
96   proc_maps->len = Size;
97 }
98 
Next(MemoryMappedSegment * segment)99 bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
100   char *last = data_.proc_self_maps.data + data_.proc_self_maps.len;
101   if (data_.current >= last)
102     return false;
103   const struct kinfo_vmentry *VmEntry =
104       (const struct kinfo_vmentry *)data_.current;
105 
106   segment->start = (uptr)VmEntry->kve_start;
107   segment->end = (uptr)VmEntry->kve_end;
108   segment->offset = (uptr)VmEntry->kve_offset;
109 
110   segment->protection = 0;
111   if ((VmEntry->kve_protection & KVME_PROT_READ) != 0)
112     segment->protection |= kProtectionRead;
113   if ((VmEntry->kve_protection & KVME_PROT_WRITE) != 0)
114     segment->protection |= kProtectionWrite;
115   if ((VmEntry->kve_protection & KVME_PROT_EXEC) != 0)
116     segment->protection |= kProtectionExecute;
117 
118 #if !SANITIZER_OPENBSD
119   if (segment->filename != NULL && segment->filename_size > 0) {
120     internal_snprintf(segment->filename,
121                       Min(segment->filename_size, (uptr)PATH_MAX), "%s",
122                       VmEntry->kve_path);
123   }
124 #endif
125 
126 #if SANITIZER_FREEBSD
127   data_.current += VmEntry->kve_structsize;
128 #else
129   data_.current += sizeof(*VmEntry);
130 #endif
131 
132   return true;
133 }
134 
135 } // namespace __sanitizer
136 
137 #endif
138