This source file includes following definitions.
- rof_open
- rof_peekchar
- rof_getchar
- rof_scanf_lx
- rof_close
- vma_iterate_proc
- vma_iterate_proc
- vma_iterate_proc
- vma_iterate_proc
- vma_iterate_bsd
- vma_iterate_bsd
- vma_iterate_bsd
- vma_iterate_bsd
- vma_iterate
- vma_iterate_callback
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #include <config.h>
19
20
21
22
23
24
25
26
27
28
29
30
31 #if defined __sun || defined __ANDROID__
32 # undef _FILE_OFFSET_BITS
33 #endif
34
35
36 #include "vma-iter.h"
37
38 #include <errno.h>
39 #include <stdlib.h>
40 #include <fcntl.h>
41 #include <unistd.h>
42
43 #if defined __linux__ || defined __ANDROID__
44 # include <limits.h>
45 #endif
46
47 #if defined __linux__ || defined __ANDROID__ || defined __FreeBSD_kernel__ || defined __FreeBSD__ || defined __DragonFly__ || defined __NetBSD__ || defined __minix
48 # include <sys/types.h>
49 # include <sys/mman.h>
50 #endif
51 #if defined __minix
52 # include <string.h>
53 #endif
54
55 #if defined __FreeBSD__ || defined __FreeBSD_kernel__
56 # include <sys/types.h>
57 # include <sys/mman.h>
58 # include <sys/user.h>
59 # include <sys/sysctl.h>
60 #endif
61 #if defined __NetBSD__ || defined __OpenBSD__
62 # include <sys/types.h>
63 # include <sys/mman.h>
64 # include <sys/sysctl.h>
65 #endif
66
67 #if defined __sgi || defined __osf__
68 # include <string.h>
69 # include <sys/types.h>
70 # include <sys/mman.h>
71 # include <sys/procfs.h>
72 #endif
73
74 #if defined __sun
75 # include <string.h>
76 # include <sys/types.h>
77 # include <sys/mman.h>
78
79 # define _STRUCTURED_PROC 1
80 # include <sys/procfs.h>
81 #endif
82
83 #if HAVE_PSTAT_GETPROCVM
84 # include <sys/pstat.h>
85 #endif
86
87 #if defined __APPLE__ && defined __MACH__
88 # include <mach/mach.h>
89 #endif
90
91 #if defined __GNU__
92 # include <mach/mach.h>
93 #endif
94
95 #if defined _WIN32 || defined __CYGWIN__
96 # include <windows.h>
97 #endif
98
99 #if defined __BEOS__ || defined __HAIKU__
100 # include <OS.h>
101 #endif
102
103 #if HAVE_MQUERY
104 # include <sys/types.h>
105 # include <sys/mman.h>
106 #endif
107
108
109
110
111
112
113
114
115 #if defined __linux__ || defined __ANDROID__ || defined __FreeBSD_kernel__ || defined __FreeBSD__ || defined __DragonFly__ || defined __NetBSD__ || defined __minix
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132 # if defined __linux__ || defined __ANDROID__
133
134
135
136
137
138 # define MIN_LEFTOVER (73 + PATH_MAX)
139 # else
140 # define MIN_LEFTOVER 1
141 # endif
142
143 # ifdef TEST
144
145 # define STACK_ALLOCATED_BUFFER_SIZE 32
146 # else
147 # if MIN_LEFTOVER < 1024
148 # define STACK_ALLOCATED_BUFFER_SIZE 1024
149 # else
150
151 # define STACK_ALLOCATED_BUFFER_SIZE 1
152 # endif
153 # endif
154
155 struct rofile
156 {
157 size_t position;
158 size_t filled;
159 int eof_seen;
160
161 char *buffer;
162 char *auxmap;
163 size_t auxmap_length;
164 unsigned long auxmap_start;
165 unsigned long auxmap_end;
166 char stack_allocated_buffer[STACK_ALLOCATED_BUFFER_SIZE];
167 };
168
169
170 static int
171 rof_open (struct rofile *rof, const char *filename)
172 {
173 int fd;
174 unsigned long pagesize;
175 size_t size;
176
177 fd = open (filename, O_RDONLY | O_CLOEXEC);
178 if (fd < 0)
179 return -1;
180 rof->position = 0;
181 rof->eof_seen = 0;
182
183 pagesize = 0;
184 rof->buffer = rof->stack_allocated_buffer;
185 size = sizeof (rof->stack_allocated_buffer);
186 rof->auxmap = NULL;
187 rof->auxmap_start = 0;
188 rof->auxmap_end = 0;
189 for (;;)
190 {
191
192 if (size > MIN_LEFTOVER)
193 {
194 int n = read (fd, rof->buffer, size);
195 if (n < 0 && errno == EINTR)
196 goto retry;
197 # if defined __DragonFly__
198 if (!(n < 0 && errno == EFBIG))
199 # endif
200 {
201 if (n <= 0)
202
203 goto fail1;
204 if (n + MIN_LEFTOVER <= size)
205 {
206
207 rof->filled = n;
208 # if defined __linux__ || defined __ANDROID__
209
210
211 for (;;)
212 {
213 n = read (fd, rof->buffer + rof->filled, size - rof->filled);
214 if (n < 0 && errno == EINTR)
215 goto retry;
216 if (n < 0)
217
218 goto fail1;
219 if (n + MIN_LEFTOVER > size - rof->filled)
220
221 break;
222 if (n == 0)
223 {
224
225 close (fd);
226 return 0;
227 }
228 rof->filled += n;
229 }
230 # else
231 close (fd);
232 return 0;
233 # endif
234 }
235 }
236 }
237
238 if (pagesize == 0)
239 {
240 pagesize = getpagesize ();
241 size = pagesize;
242 while (size <= MIN_LEFTOVER)
243 size = 2 * size;
244 }
245 else
246 {
247 size = 2 * size;
248 if (size == 0)
249
250 goto fail1;
251 if (rof->auxmap != NULL)
252 munmap (rof->auxmap, rof->auxmap_length);
253 }
254 rof->auxmap = (void *) mmap ((void *) 0, size, PROT_READ | PROT_WRITE,
255 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
256 if (rof->auxmap == (void *) -1)
257 {
258 close (fd);
259 return -1;
260 }
261 rof->auxmap_length = size;
262 rof->auxmap_start = (unsigned long) rof->auxmap;
263 rof->auxmap_end = rof->auxmap_start + size;
264 rof->buffer = (char *) rof->auxmap;
265 retry:
266
267 if (lseek (fd, 0, SEEK_SET) < 0)
268 {
269 close (fd);
270 fd = open (filename, O_RDONLY | O_CLOEXEC);
271 if (fd < 0)
272 goto fail2;
273 }
274 }
275 fail1:
276 close (fd);
277 fail2:
278 if (rof->auxmap != NULL)
279 munmap (rof->auxmap, rof->auxmap_length);
280 return -1;
281 }
282
283
284
285 static int
286 rof_peekchar (struct rofile *rof)
287 {
288 if (rof->position == rof->filled)
289 {
290 rof->eof_seen = 1;
291 return -1;
292 }
293 return (unsigned char) rof->buffer[rof->position];
294 }
295
296
297 static int
298 rof_getchar (struct rofile *rof)
299 {
300 int c = rof_peekchar (rof);
301 if (c >= 0)
302 rof->position++;
303 return c;
304 }
305
306
307 static int
308 rof_scanf_lx (struct rofile *rof, unsigned long *valuep)
309 {
310 unsigned long value = 0;
311 unsigned int numdigits = 0;
312 for (;;)
313 {
314 int c = rof_peekchar (rof);
315 if (c >= '0' && c <= '9')
316 value = (value << 4) + (c - '0');
317 else if (c >= 'A' && c <= 'F')
318 value = (value << 4) + (c - 'A' + 10);
319 else if (c >= 'a' && c <= 'f')
320 value = (value << 4) + (c - 'a' + 10);
321 else
322 break;
323 rof_getchar (rof);
324 numdigits++;
325 }
326 if (numdigits == 0)
327 return -1;
328 *valuep = value;
329 return 0;
330 }
331
332
333 static void
334 rof_close (struct rofile *rof)
335 {
336 if (rof->auxmap != NULL)
337 munmap (rof->auxmap, rof->auxmap_length);
338 }
339
340 #endif
341
342
343
344
345 #if defined __linux__ || defined __ANDROID__ || (defined __FreeBSD_kernel__ && !defined __FreeBSD__)
346
347
348
349 static int
350 vma_iterate_proc (vma_iterate_callback_fn callback, void *data)
351 {
352 struct rofile rof;
353
354
355 if (rof_open (&rof, "/proc/self/maps") >= 0)
356 {
357 unsigned long auxmap_start = rof.auxmap_start;
358 unsigned long auxmap_end = rof.auxmap_end;
359
360 for (;;)
361 {
362 unsigned long start, end;
363 unsigned int flags;
364 int c;
365
366
367 if (!(rof_scanf_lx (&rof, &start) >= 0
368 && rof_getchar (&rof) == '-'
369 && rof_scanf_lx (&rof, &end) >= 0))
370 break;
371
372 do
373 c = rof_getchar (&rof);
374 while (c == ' ');
375 flags = 0;
376 if (c == 'r')
377 flags |= VMA_PROT_READ;
378 c = rof_getchar (&rof);
379 if (c == 'w')
380 flags |= VMA_PROT_WRITE;
381 c = rof_getchar (&rof);
382 if (c == 'x')
383 flags |= VMA_PROT_EXECUTE;
384 while (c = rof_getchar (&rof), c != -1 && c != '\n')
385 ;
386
387 if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
388 {
389
390
391 if (start < auxmap_start)
392 if (callback (data, start, auxmap_start, flags))
393 break;
394 if (auxmap_end - 1 < end - 1)
395 if (callback (data, auxmap_end, end, flags))
396 break;
397 }
398 else
399 {
400 if (callback (data, start, end, flags))
401 break;
402 }
403 }
404 rof_close (&rof);
405 return 0;
406 }
407
408 return -1;
409 }
410
411 #elif defined __FreeBSD__ || defined __DragonFly__ || defined __NetBSD__
412
413 static int
414 vma_iterate_proc (vma_iterate_callback_fn callback, void *data)
415 {
416 struct rofile rof;
417
418
419 if (rof_open (&rof, "/proc/curproc/map") >= 0)
420 {
421 unsigned long auxmap_start = rof.auxmap_start;
422 unsigned long auxmap_end = rof.auxmap_end;
423
424 for (;;)
425 {
426 unsigned long start, end;
427 unsigned int flags;
428 int c;
429
430
431 if (!(rof_getchar (&rof) == '0'
432 && rof_getchar (&rof) == 'x'
433 && rof_scanf_lx (&rof, &start) >= 0))
434 break;
435 while (c = rof_peekchar (&rof), c == ' ' || c == '\t')
436 rof_getchar (&rof);
437
438 if (!(rof_getchar (&rof) == '0'
439 && rof_getchar (&rof) == 'x'
440 && rof_scanf_lx (&rof, &end) >= 0))
441 break;
442 # if defined __FreeBSD__ || defined __DragonFly__
443
444 do
445 c = rof_getchar (&rof);
446 while (c == ' ');
447 do
448 c = rof_getchar (&rof);
449 while (c != -1 && c != '\n' && c != ' ');
450
451 do
452 c = rof_getchar (&rof);
453 while (c == ' ');
454 do
455 c = rof_getchar (&rof);
456 while (c != -1 && c != '\n' && c != ' ');
457
458 do
459 c = rof_getchar (&rof);
460 while (c == ' ');
461 do
462 c = rof_getchar (&rof);
463 while (c != -1 && c != '\n' && c != ' ');
464 # endif
465
466 do
467 c = rof_getchar (&rof);
468 while (c == ' ');
469 flags = 0;
470 if (c == 'r')
471 flags |= VMA_PROT_READ;
472 c = rof_getchar (&rof);
473 if (c == 'w')
474 flags |= VMA_PROT_WRITE;
475 c = rof_getchar (&rof);
476 if (c == 'x')
477 flags |= VMA_PROT_EXECUTE;
478 while (c = rof_getchar (&rof), c != -1 && c != '\n')
479 ;
480
481 if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
482 {
483
484
485 if (start < auxmap_start)
486 if (callback (data, start, auxmap_start, flags))
487 break;
488 if (auxmap_end - 1 < end - 1)
489 if (callback (data, auxmap_end, end, flags))
490 break;
491 }
492 else
493 {
494 if (callback (data, start, end, flags))
495 break;
496 }
497 }
498 rof_close (&rof);
499 return 0;
500 }
501
502 return -1;
503 }
504
505 #elif defined __minix
506
507 static int
508 vma_iterate_proc (vma_iterate_callback_fn callback, void *data)
509 {
510 char fnamebuf[6+10+4+1];
511 char *fname;
512 struct rofile rof;
513
514
515 fname = fnamebuf + sizeof (fnamebuf) - (4 + 1);
516 memcpy (fname, "/map", 4 + 1);
517 {
518 unsigned int value = getpid ();
519 do
520 *--fname = (value % 10) + '0';
521 while ((value = value / 10) > 0);
522 }
523 fname -= 6;
524 memcpy (fname, "/proc/", 6);
525
526
527 if (rof_open (&rof, fname) >= 0)
528 {
529 unsigned long auxmap_start = rof.auxmap_start;
530 unsigned long auxmap_end = rof.auxmap_end;
531
532 for (;;)
533 {
534 unsigned long start, end;
535 unsigned int flags;
536 int c;
537
538
539 if (!(rof_scanf_lx (&rof, &start) >= 0
540 && rof_getchar (&rof) == '-'
541 && rof_scanf_lx (&rof, &end) >= 0))
542 break;
543
544 do
545 c = rof_getchar (&rof);
546 while (c == ' ');
547 flags = 0;
548 if (c == 'r')
549 flags |= VMA_PROT_READ;
550 c = rof_getchar (&rof);
551 if (c == 'w')
552 flags |= VMA_PROT_WRITE;
553 c = rof_getchar (&rof);
554 if (c == 'x')
555 flags |= VMA_PROT_EXECUTE;
556 while (c = rof_getchar (&rof), c != -1 && c != '\n')
557 ;
558
559 if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
560 {
561
562
563 if (start < auxmap_start)
564 if (callback (data, start, auxmap_start, flags))
565 break;
566 if (auxmap_end - 1 < end - 1)
567 if (callback (data, auxmap_end, end, flags))
568 break;
569 }
570 else
571 {
572 if (callback (data, start, end, flags))
573 break;
574 }
575 }
576 rof_close (&rof);
577 return 0;
578 }
579
580 return -1;
581 }
582
583 #else
584
585 static inline int
586 vma_iterate_proc (vma_iterate_callback_fn callback, void *data)
587 {
588 return -1;
589 }
590
591 #endif
592
593
594
595
596 #if (defined __FreeBSD__ || defined __FreeBSD_kernel__) && defined KERN_PROC_VMMAP
597
598 static int
599 vma_iterate_bsd (vma_iterate_callback_fn callback, void *data)
600 {
601
602 int info_path[] = { CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid () };
603 size_t len;
604 size_t pagesize;
605 size_t memneed;
606 void *auxmap;
607 unsigned long auxmap_start;
608 unsigned long auxmap_end;
609 char *mem;
610 char *p;
611 char *p_end;
612
613 len = 0;
614 if (sysctl (info_path, 4, NULL, &len, NULL, 0) < 0)
615 return -1;
616
617
618 len = 2 * len + 200;
619
620
621
622
623
624 pagesize = getpagesize ();
625 memneed = len;
626 memneed = ((memneed - 1) / pagesize + 1) * pagesize;
627 auxmap = (void *) mmap ((void *) 0, memneed, PROT_READ | PROT_WRITE,
628 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
629 if (auxmap == (void *) -1)
630 return -1;
631 auxmap_start = (unsigned long) auxmap;
632 auxmap_end = auxmap_start + memneed;
633 mem = (char *) auxmap;
634 if (sysctl (info_path, 4, mem, &len, NULL, 0) < 0)
635 {
636 munmap (auxmap, memneed);
637 return -1;
638 }
639 p = mem;
640 p_end = mem + len;
641 while (p < p_end)
642 {
643 struct kinfo_vmentry *kve = (struct kinfo_vmentry *) p;
644 unsigned long start = kve->kve_start;
645 unsigned long end = kve->kve_end;
646 unsigned int flags = 0;
647 if (kve->kve_protection & KVME_PROT_READ)
648 flags |= VMA_PROT_READ;
649 if (kve->kve_protection & KVME_PROT_WRITE)
650 flags |= VMA_PROT_WRITE;
651 if (kve->kve_protection & KVME_PROT_EXEC)
652 flags |= VMA_PROT_EXECUTE;
653 if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
654 {
655
656
657 if (start < auxmap_start)
658 if (callback (data, start, auxmap_start, flags))
659 break;
660 if (auxmap_end - 1 < end - 1)
661 if (callback (data, auxmap_end, end, flags))
662 break;
663 }
664 else
665 {
666 if (callback (data, start, end, flags))
667 break;
668 }
669 p += kve->kve_structsize;
670 }
671 munmap (auxmap, memneed);
672 return 0;
673 }
674
675 #elif defined __NetBSD__ && defined VM_PROC_MAP
676
677 static int
678 vma_iterate_bsd (vma_iterate_callback_fn callback, void *data)
679 {
680
681 unsigned int entry_size =
682
683
684
685 offsetof (struct kinfo_vmentry, kve_path);
686 int info_path[] = { CTL_VM, VM_PROC, VM_PROC_MAP, getpid (), entry_size };
687 size_t len;
688 size_t pagesize;
689 size_t memneed;
690 void *auxmap;
691 unsigned long auxmap_start;
692 unsigned long auxmap_end;
693 char *mem;
694 char *p;
695 char *p_end;
696
697 len = 0;
698 if (sysctl (info_path, 5, NULL, &len, NULL, 0) < 0)
699 return -1;
700
701
702 len = 2 * len + 10 * entry_size;
703
704 if (len > 0x100000)
705 len = 0x100000;
706
707
708 len = (len / entry_size) * entry_size;
709
710
711
712
713
714 pagesize = getpagesize ();
715 memneed = len;
716 memneed = ((memneed - 1) / pagesize + 1) * pagesize;
717 auxmap = (void *) mmap ((void *) 0, memneed, PROT_READ | PROT_WRITE,
718 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
719 if (auxmap == (void *) -1)
720 return -1;
721 auxmap_start = (unsigned long) auxmap;
722 auxmap_end = auxmap_start + memneed;
723 mem = (char *) auxmap;
724 if (sysctl (info_path, 5, mem, &len, NULL, 0) < 0
725 || len > 0x100000 - entry_size)
726 {
727
728 munmap (auxmap, memneed);
729 return -1;
730 }
731 p = mem;
732 p_end = mem + len;
733 while (p < p_end)
734 {
735 struct kinfo_vmentry *kve = (struct kinfo_vmentry *) p;
736 unsigned long start = kve->kve_start;
737 unsigned long end = kve->kve_end;
738 unsigned int flags = 0;
739 if (kve->kve_protection & KVME_PROT_READ)
740 flags |= VMA_PROT_READ;
741 if (kve->kve_protection & KVME_PROT_WRITE)
742 flags |= VMA_PROT_WRITE;
743 if (kve->kve_protection & KVME_PROT_EXEC)
744 flags |= VMA_PROT_EXECUTE;
745 if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
746 {
747
748
749 if (start < auxmap_start)
750 if (callback (data, start, auxmap_start, flags))
751 break;
752 if (auxmap_end - 1 < end - 1)
753 if (callback (data, auxmap_end, end, flags))
754 break;
755 }
756 else
757 {
758 if (callback (data, start, end, flags))
759 break;
760 }
761 p += entry_size;
762 }
763 munmap (auxmap, memneed);
764 return 0;
765 }
766
767 #elif defined __OpenBSD__ && defined KERN_PROC_VMMAP
768
769 static int
770 vma_iterate_bsd (vma_iterate_callback_fn callback, void *data)
771 {
772
773 int info_path[] = { CTL_KERN, KERN_PROC_VMMAP, getpid () };
774 size_t len;
775 size_t pagesize;
776 size_t memneed;
777 void *auxmap;
778 unsigned long auxmap_start;
779 unsigned long auxmap_end;
780 char *mem;
781 char *p;
782 char *p_end;
783
784 len = 0;
785 if (sysctl (info_path, 3, NULL, &len, NULL, 0) < 0)
786 return -1;
787
788
789 len = 2 * len + 10 * sizeof (struct kinfo_vmentry);
790
791 if (len > 0x10000)
792 len = 0x10000;
793
794
795 len = (len / sizeof (struct kinfo_vmentry)) * sizeof (struct kinfo_vmentry);
796
797
798
799
800
801 pagesize = getpagesize ();
802 memneed = len;
803 memneed = ((memneed - 1) / pagesize + 1) * pagesize;
804 auxmap = (void *) mmap ((void *) 0, memneed, PROT_READ | PROT_WRITE,
805 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
806 if (auxmap == (void *) -1)
807 return -1;
808 auxmap_start = (unsigned long) auxmap;
809 auxmap_end = auxmap_start + memneed;
810 mem = (char *) auxmap;
811 if (sysctl (info_path, 3, mem, &len, NULL, 0) < 0
812 || len > 0x10000 - sizeof (struct kinfo_vmentry))
813 {
814
815 munmap (auxmap, memneed);
816 return -1;
817 }
818 p = mem;
819 p_end = mem + len;
820 while (p < p_end)
821 {
822 struct kinfo_vmentry *kve = (struct kinfo_vmentry *) p;
823 unsigned long start = kve->kve_start;
824 unsigned long end = kve->kve_end;
825 unsigned int flags = 0;
826 if (kve->kve_protection & KVE_PROT_READ)
827 flags |= VMA_PROT_READ;
828 if (kve->kve_protection & KVE_PROT_WRITE)
829 flags |= VMA_PROT_WRITE;
830 if (kve->kve_protection & KVE_PROT_EXEC)
831 flags |= VMA_PROT_EXECUTE;
832 if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
833 {
834
835
836 if (start < auxmap_start)
837 if (callback (data, start, auxmap_start, flags))
838 break;
839 if (auxmap_end - 1 < end - 1)
840 if (callback (data, auxmap_end, end, flags))
841 break;
842 }
843 else
844 {
845 if (start != end)
846 if (callback (data, start, end, flags))
847 break;
848 }
849 p += sizeof (struct kinfo_vmentry);
850 }
851 munmap (auxmap, memneed);
852 return 0;
853 }
854
855 #else
856
857 static inline int
858 vma_iterate_bsd (vma_iterate_callback_fn callback, void *data)
859 {
860 return -1;
861 }
862
863 #endif
864
865
866 int
867 vma_iterate (vma_iterate_callback_fn callback, void *data)
868 {
869 #if defined __linux__ || defined __ANDROID__ || defined __FreeBSD_kernel__ || defined __FreeBSD__ || defined __DragonFly__ || defined __NetBSD__ || defined __minix
870
871 # if defined __FreeBSD__
872
873
874
875
876
877 int retval = vma_iterate_bsd (callback, data);
878 if (retval == 0)
879 return 0;
880
881 return vma_iterate_proc (callback, data);
882 # else
883
884
885 int retval = vma_iterate_proc (callback, data);
886 if (retval == 0)
887 return 0;
888
889 return vma_iterate_bsd (callback, data);
890 # endif
891
892 #elif defined __sgi || defined __osf__
893
894 size_t pagesize;
895 char fnamebuf[6+10+1];
896 char *fname;
897 int fd;
898 int nmaps;
899 size_t memneed;
900 # if HAVE_MAP_ANONYMOUS
901 # define zero_fd -1
902 # define map_flags MAP_ANONYMOUS
903 # else
904 int zero_fd;
905 # define map_flags 0
906 # endif
907 void *auxmap;
908 unsigned long auxmap_start;
909 unsigned long auxmap_end;
910 prmap_t* maps;
911 prmap_t* mp;
912
913 pagesize = getpagesize ();
914
915
916 fname = fnamebuf + sizeof (fnamebuf) - 1;
917 *fname = '\0';
918 {
919 unsigned int value = getpid ();
920 do
921 *--fname = (value % 10) + '0';
922 while ((value = value / 10) > 0);
923 }
924 fname -= 6;
925 memcpy (fname, "/proc/", 6);
926
927 fd = open (fname, O_RDONLY | O_CLOEXEC);
928 if (fd < 0)
929 return -1;
930
931 if (ioctl (fd, PIOCNMAP, &nmaps) < 0)
932 goto fail2;
933
934 memneed = (nmaps + 10) * sizeof (prmap_t);
935
936
937
938
939
940 memneed = ((memneed - 1) / pagesize + 1) * pagesize;
941 # if !HAVE_MAP_ANONYMOUS
942 zero_fd = open ("/dev/zero", O_RDONLY | O_CLOEXEC, 0644);
943 if (zero_fd < 0)
944 goto fail2;
945 # endif
946 auxmap = (void *) mmap ((void *) 0, memneed, PROT_READ | PROT_WRITE,
947 map_flags | MAP_PRIVATE, zero_fd, 0);
948 # if !HAVE_MAP_ANONYMOUS
949 close (zero_fd);
950 # endif
951 if (auxmap == (void *) -1)
952 goto fail2;
953 auxmap_start = (unsigned long) auxmap;
954 auxmap_end = auxmap_start + memneed;
955 maps = (prmap_t *) auxmap;
956
957 if (ioctl (fd, PIOCMAP, maps) < 0)
958 goto fail1;
959
960 for (mp = maps;;)
961 {
962 unsigned long start, end;
963 unsigned int flags;
964
965 start = (unsigned long) mp->pr_vaddr;
966 end = start + mp->pr_size;
967 if (start == 0 && end == 0)
968 break;
969 flags = 0;
970 if (mp->pr_mflags & MA_READ)
971 flags |= VMA_PROT_READ;
972 if (mp->pr_mflags & MA_WRITE)
973 flags |= VMA_PROT_WRITE;
974 if (mp->pr_mflags & MA_EXEC)
975 flags |= VMA_PROT_EXECUTE;
976 mp++;
977 if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
978 {
979
980
981 if (start < auxmap_start)
982 if (callback (data, start, auxmap_start, flags))
983 break;
984 if (auxmap_end - 1 < end - 1)
985 if (callback (data, auxmap_end, end, flags))
986 break;
987 }
988 else
989 {
990 if (callback (data, start, end, flags))
991 break;
992 }
993 }
994 munmap (auxmap, memneed);
995 close (fd);
996 return 0;
997
998 fail1:
999 munmap (auxmap, memneed);
1000 fail2:
1001 close (fd);
1002 return -1;
1003
1004 #elif defined __sun
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016 # if defined PIOCNMAP && defined PIOCMAP
1017
1018
1019 size_t pagesize;
1020 char fnamebuf[6+10+1];
1021 char *fname;
1022 int fd;
1023 int nmaps;
1024 size_t memneed;
1025 # if HAVE_MAP_ANONYMOUS
1026 # define zero_fd -1
1027 # define map_flags MAP_ANONYMOUS
1028 # else
1029 int zero_fd;
1030 # define map_flags 0
1031 # endif
1032 void *auxmap;
1033 unsigned long auxmap_start;
1034 unsigned long auxmap_end;
1035 prmap_t* maps;
1036 prmap_t* mp;
1037
1038 pagesize = getpagesize ();
1039
1040
1041 fname = fnamebuf + sizeof (fnamebuf) - 1;
1042 *fname = '\0';
1043 {
1044 unsigned int value = getpid ();
1045 do
1046 *--fname = (value % 10) + '0';
1047 while ((value = value / 10) > 0);
1048 }
1049 fname -= 6;
1050 memcpy (fname, "/proc/", 6);
1051
1052 fd = open (fname, O_RDONLY | O_CLOEXEC);
1053 if (fd < 0)
1054 return -1;
1055
1056 if (ioctl (fd, PIOCNMAP, &nmaps) < 0)
1057 goto fail2;
1058
1059 memneed = (nmaps + 10) * sizeof (prmap_t);
1060
1061
1062
1063
1064
1065 memneed = ((memneed - 1) / pagesize + 1) * pagesize;
1066 # if !HAVE_MAP_ANONYMOUS
1067 zero_fd = open ("/dev/zero", O_RDONLY | O_CLOEXEC, 0644);
1068 if (zero_fd < 0)
1069 goto fail2;
1070 # endif
1071 auxmap = (void *) mmap ((void *) 0, memneed, PROT_READ | PROT_WRITE,
1072 map_flags | MAP_PRIVATE, zero_fd, 0);
1073 # if !HAVE_MAP_ANONYMOUS
1074 close (zero_fd);
1075 # endif
1076 if (auxmap == (void *) -1)
1077 goto fail2;
1078 auxmap_start = (unsigned long) auxmap;
1079 auxmap_end = auxmap_start + memneed;
1080 maps = (prmap_t *) auxmap;
1081
1082 if (ioctl (fd, PIOCMAP, maps) < 0)
1083 goto fail1;
1084
1085 for (mp = maps;;)
1086 {
1087 unsigned long start, end;
1088 unsigned int flags;
1089
1090 start = (unsigned long) mp->pr_vaddr;
1091 end = start + mp->pr_size;
1092 if (start == 0 && end == 0)
1093 break;
1094 flags = 0;
1095 if (mp->pr_mflags & MA_READ)
1096 flags |= VMA_PROT_READ;
1097 if (mp->pr_mflags & MA_WRITE)
1098 flags |= VMA_PROT_WRITE;
1099 if (mp->pr_mflags & MA_EXEC)
1100 flags |= VMA_PROT_EXECUTE;
1101 mp++;
1102 if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
1103 {
1104
1105
1106 if (start < auxmap_start)
1107 if (callback (data, start, auxmap_start, flags))
1108 break;
1109 if (auxmap_end - 1 < end - 1)
1110 if (callback (data, auxmap_end, end, flags))
1111 break;
1112 }
1113 else
1114 {
1115 if (callback (data, start, end, flags))
1116 break;
1117 }
1118 }
1119 munmap (auxmap, memneed);
1120 close (fd);
1121 return 0;
1122
1123 fail1:
1124 munmap (auxmap, memneed);
1125 fail2:
1126 close (fd);
1127 return -1;
1128
1129 # else
1130
1131
1132
1133
1134
1135
1136
1137 size_t pagesize;
1138 char fnamebuf[6+10+4+1];
1139 char *fname;
1140 int fd;
1141 int nmaps;
1142 size_t memneed;
1143 # if HAVE_MAP_ANONYMOUS
1144 # define zero_fd -1
1145 # define map_flags MAP_ANONYMOUS
1146 # else
1147 int zero_fd;
1148 # define map_flags 0
1149 # endif
1150 void *auxmap;
1151 unsigned long auxmap_start;
1152 unsigned long auxmap_end;
1153 prmap_t* maps;
1154 prmap_t* maps_end;
1155 prmap_t* mp;
1156
1157 pagesize = getpagesize ();
1158
1159
1160 fname = fnamebuf + sizeof (fnamebuf) - 1 - 4;
1161 memcpy (fname, "/map", 4 + 1);
1162 {
1163 unsigned int value = getpid ();
1164 do
1165 *--fname = (value % 10) + '0';
1166 while ((value = value / 10) > 0);
1167 }
1168 fname -= 6;
1169 memcpy (fname, "/proc/", 6);
1170
1171 fd = open (fname, O_RDONLY | O_CLOEXEC);
1172 if (fd < 0)
1173 return -1;
1174
1175 {
1176 struct stat statbuf;
1177 if (fstat (fd, &statbuf) < 0)
1178 goto fail2;
1179 nmaps = statbuf.st_size / sizeof (prmap_t);
1180 }
1181
1182 memneed = (nmaps + 10) * sizeof (prmap_t);
1183
1184
1185
1186
1187
1188 memneed = ((memneed - 1) / pagesize + 1) * pagesize;
1189 # if !HAVE_MAP_ANONYMOUS
1190 zero_fd = open ("/dev/zero", O_RDONLY | O_CLOEXEC, 0644);
1191 if (zero_fd < 0)
1192 goto fail2;
1193 # endif
1194 auxmap = (void *) mmap ((void *) 0, memneed, PROT_READ | PROT_WRITE,
1195 map_flags | MAP_PRIVATE, zero_fd, 0);
1196 # if !HAVE_MAP_ANONYMOUS
1197 close (zero_fd);
1198 # endif
1199 if (auxmap == (void *) -1)
1200 goto fail2;
1201 auxmap_start = (unsigned long) auxmap;
1202 auxmap_end = auxmap_start + memneed;
1203 maps = (prmap_t *) auxmap;
1204
1205
1206 {
1207 size_t remaining = memneed;
1208 size_t total_read = 0;
1209 char *ptr = (char *) maps;
1210
1211 do
1212 {
1213 size_t nread = read (fd, ptr, remaining);
1214 if (nread == (size_t)-1)
1215 {
1216 if (errno == EINTR)
1217 continue;
1218 goto fail1;
1219 }
1220 if (nread == 0)
1221
1222 break;
1223 total_read += nread;
1224 ptr += nread;
1225 remaining -= nread;
1226 }
1227 while (remaining > 0);
1228
1229 nmaps = (memneed - remaining) / sizeof (prmap_t);
1230 maps_end = maps + nmaps;
1231 }
1232
1233 for (mp = maps; mp < maps_end; mp++)
1234 {
1235 unsigned long start, end;
1236 unsigned int flags;
1237
1238 start = (unsigned long) mp->pr_vaddr;
1239 end = start + mp->pr_size;
1240 flags = 0;
1241 if (mp->pr_mflags & MA_READ)
1242 flags |= VMA_PROT_READ;
1243 if (mp->pr_mflags & MA_WRITE)
1244 flags |= VMA_PROT_WRITE;
1245 if (mp->pr_mflags & MA_EXEC)
1246 flags |= VMA_PROT_EXECUTE;
1247 if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
1248 {
1249
1250
1251 if (start < auxmap_start)
1252 if (callback (data, start, auxmap_start, flags))
1253 break;
1254 if (auxmap_end - 1 < end - 1)
1255 if (callback (data, auxmap_end, end, flags))
1256 break;
1257 }
1258 else
1259 {
1260 if (callback (data, start, end, flags))
1261 break;
1262 }
1263 }
1264 munmap (auxmap, memneed);
1265 close (fd);
1266 return 0;
1267
1268 fail1:
1269 munmap (auxmap, memneed);
1270 fail2:
1271 close (fd);
1272 return -1;
1273
1274 # endif
1275
1276 #elif HAVE_PSTAT_GETPROCVM
1277
1278 unsigned long pagesize = getpagesize ();
1279 int i;
1280
1281 for (i = 0; ; i++)
1282 {
1283 struct pst_vm_status info;
1284 int ret = pstat_getprocvm (&info, sizeof (info), 0, i);
1285 if (ret < 0)
1286 return -1;
1287 if (ret == 0)
1288 break;
1289 {
1290 unsigned long start = info.pst_vaddr;
1291 unsigned long end = start + info.pst_length * pagesize;
1292 unsigned int flags = 0;
1293 if (info.pst_permission & PS_PROT_READ)
1294 flags |= VMA_PROT_READ;
1295 if (info.pst_permission & PS_PROT_WRITE)
1296 flags |= VMA_PROT_WRITE;
1297 if (info.pst_permission & PS_PROT_EXECUTE)
1298 flags |= VMA_PROT_EXECUTE;
1299
1300 if (callback (data, start, end, flags))
1301 break;
1302 }
1303 }
1304
1305 #elif defined __APPLE__ && defined __MACH__
1306
1307 task_t task = mach_task_self ();
1308 vm_address_t address;
1309 vm_size_t size;
1310
1311 for (address = VM_MIN_ADDRESS;; address += size)
1312 {
1313 int more;
1314 mach_port_t object_name;
1315 unsigned int flags;
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336 # if defined __aarch64__ || defined __ppc64__ || defined __x86_64__
1337 struct vm_region_basic_info_64 info;
1338 mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
1339
1340 more = (vm_region_64 (task, &address, &size, VM_REGION_BASIC_INFO_64,
1341 (vm_region_info_t)&info, &info_count, &object_name)
1342 == KERN_SUCCESS);
1343 # else
1344 struct vm_region_basic_info info;
1345 mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
1346
1347 more = (vm_region (task, &address, &size, VM_REGION_BASIC_INFO,
1348 (vm_region_info_t)&info, &info_count, &object_name)
1349 == KERN_SUCCESS);
1350 # endif
1351 if (object_name != MACH_PORT_NULL)
1352 mach_port_deallocate (mach_task_self (), object_name);
1353 if (!more)
1354 break;
1355 flags = 0;
1356 if (info.protection & VM_PROT_READ)
1357 flags |= VMA_PROT_READ;
1358 if (info.protection & VM_PROT_WRITE)
1359 flags |= VMA_PROT_WRITE;
1360 if (info.protection & VM_PROT_EXECUTE)
1361 flags |= VMA_PROT_EXECUTE;
1362 if (callback (data, address, address + size, flags))
1363 break;
1364 }
1365 return 0;
1366
1367 #elif defined __GNU__
1368
1369
1370
1371
1372
1373
1374
1375 task_t task = mach_task_self ();
1376 vm_address_t address;
1377 vm_size_t size;
1378
1379 for (address = 0;; address += size)
1380 {
1381 vm_prot_t protection;
1382 vm_prot_t max_protection;
1383 vm_inherit_t inheritance;
1384 boolean_t shared;
1385 memory_object_name_t object_name;
1386 vm_offset_t offset;
1387 unsigned int flags;
1388
1389 if (!(vm_region (task, &address, &size, &protection, &max_protection,
1390 &inheritance, &shared, &object_name, &offset)
1391 == KERN_SUCCESS))
1392 break;
1393 mach_port_deallocate (task, object_name);
1394 flags = 0;
1395 if (protection & VM_PROT_READ)
1396 flags |= VMA_PROT_READ;
1397 if (protection & VM_PROT_WRITE)
1398 flags |= VMA_PROT_WRITE;
1399 if (protection & VM_PROT_EXECUTE)
1400 flags |= VMA_PROT_EXECUTE;
1401 if (callback (data, address, address + size, flags))
1402 break;
1403 }
1404 return 0;
1405
1406 #elif defined _WIN32 || defined __CYGWIN__
1407
1408
1409 MEMORY_BASIC_INFORMATION info;
1410 uintptr_t address = 0;
1411
1412 while (VirtualQuery ((void*)address, &info, sizeof(info)) == sizeof(info))
1413 {
1414 if (info.State != MEM_FREE)
1415
1416
1417
1418
1419 if (info.State != MEM_RESERVE)
1420 {
1421 uintptr_t start, end;
1422 unsigned int flags;
1423
1424 start = (uintptr_t)info.BaseAddress;
1425 end = start + info.RegionSize;
1426 switch (info.Protect & ~(PAGE_GUARD|PAGE_NOCACHE))
1427 {
1428 case PAGE_READONLY:
1429 flags = VMA_PROT_READ;
1430 break;
1431 case PAGE_READWRITE:
1432 case PAGE_WRITECOPY:
1433 flags = VMA_PROT_READ | VMA_PROT_WRITE;
1434 break;
1435 case PAGE_EXECUTE:
1436 flags = VMA_PROT_EXECUTE;
1437 break;
1438 case PAGE_EXECUTE_READ:
1439 flags = VMA_PROT_READ | VMA_PROT_EXECUTE;
1440 break;
1441 case PAGE_EXECUTE_READWRITE:
1442 case PAGE_EXECUTE_WRITECOPY:
1443 flags = VMA_PROT_READ | VMA_PROT_WRITE | VMA_PROT_EXECUTE;
1444 break;
1445 case PAGE_NOACCESS:
1446 default:
1447 flags = 0;
1448 break;
1449 }
1450
1451 if (callback (data, start, end, flags))
1452 break;
1453 }
1454 address = (uintptr_t)info.BaseAddress + info.RegionSize;
1455 }
1456 return 0;
1457
1458 #elif defined __BEOS__ || defined __HAIKU__
1459
1460
1461 area_info info;
1462 ssize_t cookie;
1463
1464 cookie = 0;
1465 while (get_next_area_info (0, &cookie, &info) == B_OK)
1466 {
1467 unsigned long start, end;
1468 unsigned int flags;
1469
1470 start = (unsigned long) info.address;
1471 end = start + info.size;
1472 flags = 0;
1473 if (info.protection & B_READ_AREA)
1474 flags |= VMA_PROT_READ | VMA_PROT_EXECUTE;
1475 if (info.protection & B_WRITE_AREA)
1476 flags |= VMA_PROT_WRITE;
1477
1478 if (callback (data, start, end, flags))
1479 break;
1480 }
1481 return 0;
1482
1483 #elif HAVE_MQUERY
1484
1485 # if defined __OpenBSD__
1486
1487
1488 {
1489 int retval = vma_iterate_bsd (callback, data);
1490 if (retval == 0)
1491 return 0;
1492 }
1493 # endif
1494
1495 {
1496 uintptr_t pagesize;
1497 uintptr_t address;
1498 int address_known_mapped;
1499
1500 pagesize = getpagesize ();
1501
1502
1503 address = pagesize;
1504 address_known_mapped = 0;
1505 for (;;)
1506 {
1507
1508 if (address_known_mapped
1509 || mquery ((void *) address, pagesize, 0, MAP_FIXED, -1, 0)
1510 == (void *) -1)
1511 {
1512
1513
1514 uintptr_t start = address;
1515 uintptr_t end;
1516
1517
1518 end = (uintptr_t) mquery ((void *) address, pagesize, 0, 0, -1, 0);
1519 if (end == (uintptr_t) (void *) -1)
1520 end = 0;
1521 address = end;
1522
1523
1524
1525 if (callback (data, start, end, 0))
1526 break;
1527
1528 if (address < pagesize)
1529 break;
1530 }
1531
1532 {
1533 uintptr_t query_size = pagesize;
1534
1535 address += pagesize;
1536
1537
1538
1539 for (;;)
1540 {
1541 if (2 * query_size > query_size)
1542 query_size = 2 * query_size;
1543 if (address + query_size - 1 < query_size)
1544 {
1545 address_known_mapped = 0;
1546 break;
1547 }
1548 if (mquery ((void *) address, query_size, 0, MAP_FIXED, -1, 0)
1549 == (void *) -1)
1550 {
1551
1552
1553 address_known_mapped = (query_size == pagesize);
1554 break;
1555 }
1556
1557
1558 address += query_size;
1559 }
1560
1561
1562 while (query_size > pagesize)
1563 {
1564 query_size = query_size / 2;
1565 if (address + query_size - 1 >= query_size)
1566 {
1567 if (mquery ((void *) address, query_size, 0, MAP_FIXED, -1, 0)
1568 != (void *) -1)
1569 {
1570
1571
1572 address += query_size;
1573 address_known_mapped = 0;
1574 }
1575 else
1576 address_known_mapped = (query_size == pagesize);
1577 }
1578 }
1579
1580
1581
1582
1583 }
1584 if (address + pagesize - 1 < pagesize)
1585 break;
1586 }
1587 return 0;
1588 }
1589
1590 #else
1591
1592
1593 return -1;
1594
1595 #endif
1596 }
1597
1598
1599 #ifdef TEST
1600
1601 #include <stdio.h>
1602
1603
1604
1605
1606 static int
1607 vma_iterate_callback (void *data, uintptr_t start, uintptr_t end,
1608 unsigned int flags)
1609 {
1610 printf ("%08lx-%08lx %c%c%c\n",
1611 (unsigned long) start, (unsigned long) end,
1612 flags & VMA_PROT_READ ? 'r' : '-',
1613 flags & VMA_PROT_WRITE ? 'w' : '-',
1614 flags & VMA_PROT_EXECUTE ? 'x' : '-');
1615 return 0;
1616 }
1617
1618 int
1619 main ()
1620 {
1621 vma_iterate (vma_iterate_callback, NULL);
1622
1623
1624 sleep (10);
1625
1626 return 0;
1627 }
1628
1629
1630
1631
1632
1633
1634
1635 #endif