]>
Commit | Line | Data |
---|---|---|
d2ef4bee | 1 | //===-- sanitizer_procmaps_bsd.cc -----------------------------------------===// |
a9586c9c | 2 | // |
3 | // This file is distributed under the University of Illinois Open Source | |
4 | // License. See LICENSE.TXT for details. | |
5 | // | |
6 | //===----------------------------------------------------------------------===// | |
7 | // | |
d2ef4bee | 8 | // Information about the process mappings |
9 | // (FreeBSD, OpenBSD and NetBSD-specific parts). | |
a9586c9c | 10 | //===----------------------------------------------------------------------===// |
11 | ||
12 | #include "sanitizer_platform.h" | |
d2ef4bee | 13 | #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD |
a9586c9c | 14 | #include "sanitizer_common.h" |
36093749 | 15 | #if SANITIZER_FREEBSD |
a9586c9c | 16 | #include "sanitizer_freebsd.h" |
36093749 | 17 | #endif |
a9586c9c | 18 | #include "sanitizer_procmaps.h" |
19 | ||
d2ef4bee | 20 | // clang-format off |
21 | #include <sys/types.h> | |
a9586c9c | 22 | #include <sys/sysctl.h> |
d2ef4bee | 23 | // clang-format on |
24 | #include <unistd.h> | |
36093749 | 25 | #if SANITIZER_FREEBSD |
a9586c9c | 26 | #include <sys/user.h> |
36093749 | 27 | #endif |
a9586c9c | 28 | |
d2ef4bee | 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 | ||
a9586c9c | 36 | // Fix 'kinfo_vmentry' definition on FreeBSD prior v9.2 in 32-bit mode. |
37 | #if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) | |
d2ef4bee | 38 | #include <osreldate.h> |
39 | #if __FreeBSD_version <= 902001 // v9.2 | |
40 | #define kinfo_vmentry xkinfo_vmentry | |
41 | #endif | |
a9586c9c | 42 | #endif |
43 | ||
44 | namespace __sanitizer { | |
45 | ||
46 | void ReadProcMaps(ProcSelfMapsBuff *proc_maps) { | |
36093749 | 47 | const int Mib[] = { |
48 | #if SANITIZER_FREEBSD | |
49 | CTL_KERN, | |
50 | KERN_PROC, | |
51 | KERN_PROC_VMMAP, | |
52 | getpid() | |
d2ef4bee | 53 | #elif SANITIZER_OPENBSD |
54 | CTL_KERN, | |
55 | KERN_PROC_VMMAP, | |
56 | getpid() | |
57 | #elif SANITIZER_NETBSD | |
36093749 | 58 | CTL_VM, |
59 | VM_PROC, | |
60 | VM_PROC_MAP, | |
61 | getpid(), | |
62 | sizeof(struct kinfo_vmentry) | |
d2ef4bee | 63 | #else |
64 | #error "not supported" | |
36093749 | 65 | #endif |
66 | }; | |
67 | ||
d2ef4bee | 68 | uptr Size = 0; |
69 | int Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), NULL, &Size, NULL, 0); | |
a9586c9c | 70 | CHECK_EQ(Err, 0); |
71 | CHECK_GT(Size, 0); | |
72 | ||
d2ef4bee | 73 | #if !SANITIZER_OPENBSD |
a9586c9c | 74 | size_t MmapedSize = Size * 4 / 3; |
75 | void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()"); | |
76 | Size = MmapedSize; | |
d2ef4bee | 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); | |
a9586c9c | 90 | CHECK_EQ(Err, 0); |
d2ef4bee | 91 | MmapedSize = Size; |
92 | proc_maps->data = Mem; | |
93 | #endif | |
a9586c9c | 94 | |
a9586c9c | 95 | proc_maps->mmaped_size = MmapedSize; |
96 | proc_maps->len = Size; | |
97 | } | |
98 | ||
36093749 | 99 | bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) { |
100 | char *last = data_.proc_self_maps.data + data_.proc_self_maps.len; | |
d2ef4bee | 101 | if (data_.current >= last) |
102 | return false; | |
103 | const struct kinfo_vmentry *VmEntry = | |
104 | (const struct kinfo_vmentry *)data_.current; | |
36093749 | 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; | |
a9586c9c | 111 | if ((VmEntry->kve_protection & KVME_PROT_READ) != 0) |
36093749 | 112 | segment->protection |= kProtectionRead; |
a9586c9c | 113 | if ((VmEntry->kve_protection & KVME_PROT_WRITE) != 0) |
36093749 | 114 | segment->protection |= kProtectionWrite; |
a9586c9c | 115 | if ((VmEntry->kve_protection & KVME_PROT_EXEC) != 0) |
36093749 | 116 | segment->protection |= kProtectionExecute; |
a9586c9c | 117 | |
d2ef4bee | 118 | #if !SANITIZER_OPENBSD |
36093749 | 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); | |
a9586c9c | 123 | } |
d2ef4bee | 124 | #endif |
a9586c9c | 125 | |
36093749 | 126 | #if SANITIZER_FREEBSD |
127 | data_.current += VmEntry->kve_structsize; | |
128 | #else | |
129 | data_.current += sizeof(*VmEntry); | |
130 | #endif | |
a9586c9c | 131 | |
132 | return true; | |
133 | } | |
134 | ||
d2ef4bee | 135 | } // namespace __sanitizer |
a9586c9c | 136 | |
d2ef4bee | 137 | #endif |