This source file includes following definitions.
- simple_is_near_this
- simple_is_near_this
- rof_open
- rof_peekchar
- rof_getchar
- rof_scanf_lx
- rof_close
- vma_iterate_proc
- vma_iterate_proc
- vma_iterate_bsd
- vma_iterate
- init_pagesize
- is_mapped
- mapped_range_start
- mapped_range_end
- is_unmapped
- mincore_is_near_this
- mincore_is_near_this
- mincore_get_vma
- callback
- sigsegv_get_vma
- callback
- sigsegv_get_vma
- callback
- sigsegv_get_vma
- init_pagesize
- is_mapped
- mapped_range_start
- mapped_range_end
- is_unmapped
- mquery_is_near_this
- mquery_is_near_this
- sigsegv_get_vma
- sigsegv_get_vma
- sigsegv_get_vma
- init_pagesize
- callback
- vma_iterate
- sigsegv_get_vma
- callback
- sigsegv_get_vma
- callback
- vma_iterate
- sigsegv_get_vma
- sigsegv_get_vma
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22
23
24
25
26
27
28
29
30
31
32
33 #if defined __sun || defined __ANDROID__
34 # undef _FILE_OFFSET_BITS
35 #endif
36
37
38 #include "stackvma.h"
39
40 #include <stdio.h>
41 #include <stdlib.h>
42
43
44
45 #if defined __linux__ || defined __ANDROID__ \
46 || defined __FreeBSD_kernel__ || defined __FreeBSD__ || defined __DragonFly__ \
47 || defined __NetBSD__ \
48 || (defined __APPLE__ && defined __MACH__) \
49 || defined __sgi || defined __sun \
50 || defined __CYGWIN__ || defined __HAIKU__
51
52
53
54
55 # if STACK_DIRECTION < 0
56
57
58
59 static int
60 simple_is_near_this (uintptr_t addr, struct vma_struct *vma)
61 {
62 return (vma->start - addr <= (vma->start - vma->prev_end) / 2);
63 }
64
65 # endif
66 # if STACK_DIRECTION > 0
67
68
69
70 static int
71 simple_is_near_this (uintptr_t addr, struct vma_struct *vma)
72 {
73 return (addr - vma->end < (vma->next_start - vma->end) / 2);
74 }
75
76 # endif
77
78 #endif
79
80
81
82
83 #if defined __linux__ || defined __ANDROID__ \
84 || defined __FreeBSD_kernel__ || defined __FreeBSD__ || defined __DragonFly__ \
85 || defined __NetBSD__ \
86 || defined __CYGWIN__
87
88 # include <errno.h>
89 # include <fcntl.h>
90 # include <stddef.h>
91 # include <unistd.h>
92 # include <sys/types.h>
93 # include <sys/mman.h>
94
95 # if defined __linux__ || defined __ANDROID__
96 # include <limits.h>
97 # endif
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116 # if defined __linux__ || defined __ANDROID__
117
118
119
120
121
122 # define MIN_LEFTOVER (73 + PATH_MAX)
123 # else
124 # define MIN_LEFTOVER 1
125 # endif
126
127 # if MIN_LEFTOVER < 1024
128 # define STACK_ALLOCATED_BUFFER_SIZE 1024
129 # else
130
131
132 # define STACK_ALLOCATED_BUFFER_SIZE 1
133 # endif
134
135 struct rofile
136 {
137 size_t position;
138 size_t filled;
139 int eof_seen;
140
141 char *buffer;
142 char *auxmap;
143 size_t auxmap_length;
144 uintptr_t auxmap_start;
145 uintptr_t auxmap_end;
146 char stack_allocated_buffer[STACK_ALLOCATED_BUFFER_SIZE];
147 };
148
149
150 static int
151 rof_open (struct rofile *rof, const char *filename)
152 {
153 int fd;
154 uintptr_t pagesize;
155 size_t size;
156
157 fd = open (filename, O_RDONLY);
158 if (fd < 0)
159 return -1;
160 rof->position = 0;
161 rof->eof_seen = 0;
162
163 pagesize = 0;
164 rof->buffer = rof->stack_allocated_buffer;
165 size = sizeof (rof->stack_allocated_buffer);
166 rof->auxmap = NULL;
167 rof->auxmap_start = 0;
168 rof->auxmap_end = 0;
169 for (;;)
170 {
171
172 if (size > MIN_LEFTOVER)
173 {
174 int n = read (fd, rof->buffer, size);
175 if (n < 0 && errno == EINTR)
176 goto retry;
177 # if defined __DragonFly__
178 if (!(n < 0 && errno == EFBIG))
179 # endif
180 {
181 if (n <= 0)
182
183 goto fail1;
184 if (n + MIN_LEFTOVER <= size)
185 {
186
187 rof->filled = n;
188 # if defined __linux__ || defined __ANDROID__
189
190
191 for (;;)
192 {
193 n = read (fd, rof->buffer + rof->filled, size - rof->filled);
194 if (n < 0 && errno == EINTR)
195 goto retry;
196 if (n < 0)
197
198 goto fail1;
199 if (n + MIN_LEFTOVER > size - rof->filled)
200
201 break;
202 if (n == 0)
203 {
204
205 close (fd);
206 return 0;
207 }
208 rof->filled += n;
209 }
210 # else
211 close (fd);
212 return 0;
213 # endif
214 }
215 }
216 }
217
218 if (pagesize == 0)
219 {
220 pagesize = getpagesize ();
221 size = pagesize;
222 while (size <= MIN_LEFTOVER)
223 size = 2 * size;
224 }
225 else
226 {
227 size = 2 * size;
228 if (size == 0)
229
230 goto fail1;
231 if (rof->auxmap != NULL)
232 munmap (rof->auxmap, rof->auxmap_length);
233 }
234 rof->auxmap = (void *) mmap ((void *) 0, size, PROT_READ | PROT_WRITE,
235 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
236 if (rof->auxmap == (void *) -1)
237 {
238 close (fd);
239 return -1;
240 }
241 rof->auxmap_length = size;
242 rof->auxmap_start = (uintptr_t) rof->auxmap;
243 rof->auxmap_end = rof->auxmap_start + size;
244 rof->buffer = (char *) rof->auxmap;
245 retry:
246
247 if (lseek (fd, 0, SEEK_SET) < 0)
248 {
249 close (fd);
250 fd = open (filename, O_RDONLY);
251 if (fd < 0)
252 goto fail2;
253 }
254 }
255 fail1:
256 close (fd);
257 fail2:
258 if (rof->auxmap != NULL)
259 munmap (rof->auxmap, rof->auxmap_length);
260 return -1;
261 }
262
263
264
265 static int
266 rof_peekchar (struct rofile *rof)
267 {
268 if (rof->position == rof->filled)
269 {
270 rof->eof_seen = 1;
271 return -1;
272 }
273 return (unsigned char) rof->buffer[rof->position];
274 }
275
276
277 static int
278 rof_getchar (struct rofile *rof)
279 {
280 int c = rof_peekchar (rof);
281 if (c >= 0)
282 rof->position++;
283 return c;
284 }
285
286
287 static int
288 rof_scanf_lx (struct rofile *rof, uintptr_t *valuep)
289 {
290 uintptr_t value = 0;
291 unsigned int numdigits = 0;
292 for (;;)
293 {
294 int c = rof_peekchar (rof);
295 if (c >= '0' && c <= '9')
296 value = (value << 4) + (c - '0');
297 else if (c >= 'A' && c <= 'F')
298 value = (value << 4) + (c - 'A' + 10);
299 else if (c >= 'a' && c <= 'f')
300 value = (value << 4) + (c - 'a' + 10);
301 else
302 break;
303 rof_getchar (rof);
304 numdigits++;
305 }
306 if (numdigits == 0)
307 return -1;
308 *valuep = value;
309 return 0;
310 }
311
312
313 static void
314 rof_close (struct rofile *rof)
315 {
316 if (rof->auxmap != NULL)
317 munmap (rof->auxmap, rof->auxmap_length);
318 }
319
320 #endif
321
322
323
324
325
326
327
328
329 #if defined __linux__ || defined __ANDROID__ \
330 || defined __FreeBSD_kernel__ || defined __FreeBSD__ || defined __DragonFly__ \
331 || defined __NetBSD__ \
332 || defined __CYGWIN__
333
334
335 struct callback_locals;
336 static int callback (struct callback_locals *locals, uintptr_t start, uintptr_t end);
337
338 # if defined __linux__ || defined __ANDROID__ || (defined __FreeBSD_kernel__ && !defined __FreeBSD__) || defined __CYGWIN__
339
340
341
342 static int
343 vma_iterate_proc (struct callback_locals *locals)
344 {
345 struct rofile rof;
346
347
348 if (rof_open (&rof, "/proc/self/maps") >= 0)
349 {
350 uintptr_t auxmap_start = rof.auxmap_start;
351 uintptr_t auxmap_end = rof.auxmap_end;
352
353 for (;;)
354 {
355 uintptr_t start, end;
356 int c;
357
358
359 if (!(rof_scanf_lx (&rof, &start) >= 0
360 && rof_getchar (&rof) == '-'
361 && rof_scanf_lx (&rof, &end) >= 0))
362 break;
363 while (c = rof_getchar (&rof), c != -1 && c != '\n')
364 ;
365
366 if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
367 {
368
369
370 if (start < auxmap_start)
371 if (callback (locals, start, auxmap_start))
372 break;
373 if (auxmap_end - 1 < end - 1)
374 if (callback (locals, auxmap_end, end))
375 break;
376 }
377 else
378 {
379 if (callback (locals, start, end))
380 break;
381 }
382 }
383 rof_close (&rof);
384 return 0;
385 }
386
387 return -1;
388 }
389
390 # elif defined __FreeBSD__ || defined __DragonFly__ || defined __NetBSD__
391
392 static int
393 vma_iterate_proc (struct callback_locals *locals)
394 {
395 struct rofile rof;
396
397
398
399
400
401
402
403
404 if (rof_open (&rof, "/proc/curproc/map") >= 0)
405 {
406 uintptr_t auxmap_start = rof.auxmap_start;
407 uintptr_t auxmap_end = rof.auxmap_end;
408
409 for (;;)
410 {
411 uintptr_t start, end;
412 int c;
413
414
415 if (!(rof_getchar (&rof) == '0'
416 && rof_getchar (&rof) == 'x'
417 && rof_scanf_lx (&rof, &start) >= 0))
418 break;
419 while (c = rof_peekchar (&rof), c == ' ' || c == '\t')
420 rof_getchar (&rof);
421
422 if (!(rof_getchar (&rof) == '0'
423 && rof_getchar (&rof) == 'x'
424 && rof_scanf_lx (&rof, &end) >= 0))
425 break;
426 while (c = rof_getchar (&rof), c != -1 && c != '\n')
427 ;
428
429 if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
430 {
431
432
433 if (start < auxmap_start)
434 if (callback (locals, start, auxmap_start))
435 break;
436 if (auxmap_end - 1 < end - 1)
437 if (callback (locals, auxmap_end, end))
438 break;
439 }
440 else
441 {
442 if (callback (locals, start, end))
443 break;
444 }
445 }
446 rof_close (&rof);
447 return 0;
448 }
449
450 return -1;
451 }
452
453 # endif
454
455 # if (defined __FreeBSD_kernel__ || defined __FreeBSD__) && defined KERN_PROC_VMMAP
456
457 # include <sys/user.h>
458 # include <sys/sysctl.h>
459
460 static int
461 vma_iterate_bsd (struct callback_locals *locals)
462 {
463
464 int info_path[] = { CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid () };
465 size_t len;
466 size_t pagesize;
467 size_t memneed;
468 void *auxmap;
469 unsigned long auxmap_start;
470 unsigned long auxmap_end;
471 char *mem;
472 char *p;
473 char *p_end;
474
475 len = 0;
476 if (sysctl (info_path, 4, NULL, &len, NULL, 0) < 0)
477 return -1;
478
479
480 len = 2 * len + 200;
481
482
483
484
485
486 pagesize = getpagesize ();
487 memneed = len;
488 memneed = ((memneed - 1) / pagesize + 1) * pagesize;
489 auxmap = (void *) mmap ((void *) 0, memneed, PROT_READ | PROT_WRITE,
490 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
491 if (auxmap == (void *) -1)
492 return -1;
493 auxmap_start = (unsigned long) auxmap;
494 auxmap_end = auxmap_start + memneed;
495 mem = (char *) auxmap;
496 if (sysctl (info_path, 4, mem, &len, NULL, 0) < 0)
497 {
498 munmap (auxmap, memneed);
499 return -1;
500 }
501 p = mem;
502 p_end = mem + len;
503 while (p < p_end)
504 {
505 struct kinfo_vmentry *kve = (struct kinfo_vmentry *) p;
506 unsigned long start = kve->kve_start;
507 unsigned long end = kve->kve_end;
508 if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
509 {
510
511
512 if (start < auxmap_start)
513 if (callback (locals, start, auxmap_start))
514 break;
515 if (auxmap_end - 1 < end - 1)
516 if (callback (locals, auxmap_end, end))
517 break;
518 }
519 else
520 {
521 if (callback (locals, start, end))
522 break;
523 }
524 p += kve->kve_structsize;
525 }
526 munmap (auxmap, memneed);
527 return 0;
528 }
529
530 # else
531
532 # define vma_iterate_bsd(locals) (-1)
533
534 # endif
535
536
537
538
539
540
541
542
543
544
545
546
547
548 static int
549 vma_iterate (struct callback_locals *locals)
550 {
551 # if defined __FreeBSD__
552
553
554
555
556
557 int retval = vma_iterate_bsd (locals);
558 if (retval == 0)
559 return 0;
560
561 return vma_iterate_proc (locals);
562 # else
563
564
565 int retval = vma_iterate_proc (locals);
566 if (retval == 0)
567 return 0;
568
569 return vma_iterate_bsd (locals);
570 # endif
571 }
572
573 #endif
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596 #if defined __linux__ || defined __ANDROID__ \
597 || defined __FreeBSD_kernel__ || defined __FreeBSD__ || defined __DragonFly__ \
598 || defined __NetBSD__ \
599 \
600 || defined _AIX || defined __sun
601
602 # include <unistd.h>
603 # include <sys/types.h>
604 # include <sys/mman.h>
605
606
607
608 # ifdef _AIX
609 typedef caddr_t MINCORE_ADDR_T;
610 # else
611 typedef void* MINCORE_ADDR_T;
612 # endif
613
614
615
616 # if __GLIBC__ >= 2 || defined __linux__ || defined __ANDROID__
617 typedef unsigned char pageinfo_t;
618 # else
619 typedef char pageinfo_t;
620 # endif
621
622
623 static uintptr_t pagesize;
624
625
626 static void
627 init_pagesize (void)
628 {
629 pagesize = getpagesize ();
630 }
631
632
633
634 static int
635 is_mapped (uintptr_t addr)
636 {
637 pageinfo_t vec[1];
638 return mincore ((MINCORE_ADDR_T) addr, pagesize, vec) >= 0;
639 }
640
641
642
643
644 static uintptr_t
645 mapped_range_start (uintptr_t addr)
646 {
647
648
649 pageinfo_t vec[1024];
650 uintptr_t stepsize = sizeof (vec);
651
652 for (;;)
653 {
654 uintptr_t max_remaining;
655
656 if (addr == 0)
657 return addr;
658
659 max_remaining = addr / pagesize;
660 if (stepsize > max_remaining)
661 stepsize = max_remaining;
662 if (mincore ((MINCORE_ADDR_T) (addr - stepsize * pagesize),
663 stepsize * pagesize, vec) < 0)
664
665 break;
666
667 addr -= stepsize * pagesize;
668 }
669 for (;;)
670 {
671 uintptr_t halfstepsize1;
672 uintptr_t halfstepsize2;
673
674 if (stepsize == 1)
675 return addr;
676
677
678 halfstepsize1 = (stepsize + 1) / 2;
679 halfstepsize2 = stepsize / 2;
680
681
682 if (mincore ((MINCORE_ADDR_T) (addr - halfstepsize1 * pagesize),
683 halfstepsize1 * pagesize, vec) < 0)
684 stepsize = halfstepsize1;
685 else
686 {
687 addr -= halfstepsize1 * pagesize;
688 stepsize = halfstepsize2;
689 }
690 }
691 }
692
693
694
695
696 static uintptr_t
697 mapped_range_end (uintptr_t addr)
698 {
699
700
701 pageinfo_t vec[1024];
702 uintptr_t stepsize = sizeof (vec);
703
704 addr += pagesize;
705 for (;;)
706 {
707 uintptr_t max_remaining;
708
709 if (addr == 0)
710 return addr;
711
712 max_remaining = (- addr) / pagesize;
713 if (stepsize > max_remaining)
714 stepsize = max_remaining;
715 if (mincore ((MINCORE_ADDR_T) addr, stepsize * pagesize, vec) < 0)
716
717 break;
718
719 addr += stepsize * pagesize;
720 }
721 for (;;)
722 {
723 uintptr_t halfstepsize1;
724 uintptr_t halfstepsize2;
725
726 if (stepsize == 1)
727 return addr;
728
729
730 halfstepsize1 = (stepsize + 1) / 2;
731 halfstepsize2 = stepsize / 2;
732
733
734 if (mincore ((MINCORE_ADDR_T) addr, halfstepsize1 * pagesize, vec) < 0)
735 stepsize = halfstepsize1;
736 else
737 {
738 addr += halfstepsize1 * pagesize;
739 stepsize = halfstepsize2;
740 }
741 }
742 }
743
744
745
746 static int
747 is_unmapped (uintptr_t addr1, uintptr_t addr2)
748 {
749 uintptr_t count;
750 uintptr_t stepsize;
751
752
753 addr1 = (addr1 / pagesize) * pagesize;
754
755 addr2 = ((addr2 / pagesize) + 1) * pagesize;
756
757
758
759
760
761
762
763
764
765
766
767 count = (addr2 - addr1) / pagesize;
768
769 for (stepsize = 1; stepsize < count; )
770 stepsize = 2 * stepsize;
771 for (;;)
772 {
773 uintptr_t addr_stepsize;
774 uintptr_t i;
775 uintptr_t addr;
776
777 stepsize = stepsize / 2;
778 if (stepsize == 0)
779 break;
780 addr_stepsize = stepsize * pagesize;
781 for (i = stepsize, addr = addr1 + addr_stepsize;
782 i < count;
783 i += 2 * stepsize, addr += 2 * addr_stepsize)
784
785 if (is_mapped (addr))
786 return 0;
787 }
788 return 1;
789 }
790
791 # if STACK_DIRECTION < 0
792
793
794
795 static int
796 mincore_is_near_this (uintptr_t addr, struct vma_struct *vma)
797 {
798
799
800
801
802
803
804
805
806 uintptr_t testaddr = addr - (vma->start - addr);
807 if (testaddr > addr)
808 return 0;
809
810 return is_unmapped (testaddr, vma->start - 1);
811 }
812
813 # endif
814 # if STACK_DIRECTION > 0
815
816
817
818 static int
819 mincore_is_near_this (uintptr_t addr, struct vma_struct *vma)
820 {
821
822
823
824
825
826
827
828
829 uintptr_t testaddr = addr + (addr - vma->end);
830 if (testaddr < addr)
831 return 0;
832
833 return is_unmapped (vma->end, testaddr);
834 }
835
836 # endif
837
838 static int
839 mincore_get_vma (uintptr_t address, struct vma_struct *vma)
840 {
841 if (pagesize == 0)
842 init_pagesize ();
843 address = (address / pagesize) * pagesize;
844 vma->start = mapped_range_start (address);
845 vma->end = mapped_range_end (address);
846 vma->is_near_this = mincore_is_near_this;
847 return 0;
848 }
849
850 #endif
851
852
853
854
855
856 #if defined __linux__ || defined __ANDROID__
857
858 struct callback_locals
859 {
860 uintptr_t address;
861 struct vma_struct *vma;
862 # if STACK_DIRECTION < 0
863 uintptr_t prev;
864 # else
865 int stop_at_next_vma;
866 # endif
867 int retval;
868 };
869
870 static int
871 callback (struct callback_locals *locals, uintptr_t start, uintptr_t end)
872 {
873 # if STACK_DIRECTION < 0
874 if (locals->address >= start && locals->address <= end - 1)
875 {
876 locals->vma->start = start;
877 locals->vma->end = end;
878 locals->vma->prev_end = locals->prev;
879 locals->retval = 0;
880 return 1;
881 }
882 locals->prev = end;
883 # else
884 if (locals->stop_at_next_vma)
885 {
886 locals->vma->next_start = start;
887 locals->stop_at_next_vma = 0;
888 return 1;
889 }
890 if (locals->address >= start && locals->address <= end - 1)
891 {
892 locals->vma->start = start;
893 locals->vma->end = end;
894 locals->retval = 0;
895 locals->stop_at_next_vma = 1;
896 return 0;
897 }
898 # endif
899 return 0;
900 }
901
902 int
903 sigsegv_get_vma (uintptr_t address, struct vma_struct *vma)
904 {
905 struct callback_locals locals;
906 locals.address = address;
907 locals.vma = vma;
908 # if STACK_DIRECTION < 0
909 locals.prev = 0;
910 # else
911 locals.stop_at_next_vma = 0;
912 # endif
913 locals.retval = -1;
914
915 vma_iterate (&locals);
916 if (locals.retval == 0)
917 {
918 # if !(STACK_DIRECTION < 0)
919 if (locals.stop_at_next_vma)
920 vma->next_start = 0;
921 # endif
922 vma->is_near_this = simple_is_near_this;
923 return 0;
924 }
925
926 return mincore_get_vma (address, vma);
927 }
928
929
930
931 #elif defined __FreeBSD_kernel__ || defined __FreeBSD__ || defined __DragonFly__
932
933 struct callback_locals
934 {
935 uintptr_t address;
936 struct vma_struct *vma;
937
938
939 uintptr_t curr_start, curr_end;
940 # if STACK_DIRECTION < 0
941 uintptr_t prev_end;
942 # else
943 int stop_at_next_vma;
944 # endif
945 int retval;
946 };
947
948 static int
949 callback (struct callback_locals *locals, uintptr_t start, uintptr_t end)
950 {
951 if (start == locals->curr_end)
952 {
953
954 locals->curr_end = end;
955 return 0;
956 }
957 # if STACK_DIRECTION < 0
958 if (locals->curr_start < locals->curr_end
959 && locals->address >= locals->curr_start
960 && locals->address <= locals->curr_end - 1)
961 {
962 locals->vma->start = locals->curr_start;
963 locals->vma->end = locals->curr_end;
964 locals->vma->prev_end = locals->prev_end;
965 locals->retval = 0;
966 return 1;
967 }
968 locals->prev_end = locals->curr_end;
969 # else
970 if (locals->stop_at_next_vma)
971 {
972 locals->vma->next_start = locals->curr_start;
973 locals->stop_at_next_vma = 0;
974 return 1;
975 }
976 if (locals->curr_start < locals->curr_end
977 && locals->address >= locals->curr_start
978 && locals->address <= locals->curr_end - 1)
979 {
980 locals->vma->start = locals->curr_start;
981 locals->vma->end = locals->curr_end;
982 locals->retval = 0;
983 locals->stop_at_next_vma = 1;
984 return 0;
985 }
986 # endif
987 locals->curr_start = start; locals->curr_end = end;
988 return 0;
989 }
990
991 int
992 sigsegv_get_vma (uintptr_t address, struct vma_struct *vma)
993 {
994 struct callback_locals locals;
995 locals.address = address;
996 locals.vma = vma;
997 locals.curr_start = 0;
998 locals.curr_end = 0;
999 # if STACK_DIRECTION < 0
1000 locals.prev_end = 0;
1001 # else
1002 locals.stop_at_next_vma = 0;
1003 # endif
1004 locals.retval = -1;
1005
1006 vma_iterate (&locals);
1007 if (locals.retval < 0)
1008 {
1009 if (locals.curr_start < locals.curr_end
1010 && address >= locals.curr_start && address <= locals.curr_end - 1)
1011 {
1012 vma->start = locals.curr_start;
1013 vma->end = locals.curr_end;
1014 # if STACK_DIRECTION < 0
1015 vma->prev_end = locals.prev_end;
1016 # else
1017 vma->next_start = 0;
1018 # endif
1019 locals.retval = 0;
1020 }
1021 }
1022 if (locals.retval == 0)
1023 {
1024 # if !(STACK_DIRECTION < 0)
1025 if (locals.stop_at_next_vma)
1026 vma->next_start = 0;
1027 # endif
1028 vma->is_near_this = simple_is_near_this;
1029 return 0;
1030 }
1031
1032
1033
1034 if (!is_mapped (0))
1035
1036 return mincore_get_vma (address, vma);
1037 return -1;
1038 }
1039
1040
1041
1042 #elif defined __NetBSD__
1043
1044 struct callback_locals
1045 {
1046 uintptr_t address;
1047 struct vma_struct *vma;
1048
1049
1050 uintptr_t curr_start, curr_end;
1051 # if STACK_DIRECTION < 0
1052 uintptr_t prev_end;
1053 # else
1054 int stop_at_next_vma;
1055 # endif
1056 int retval;
1057 };
1058
1059 static int
1060 callback (struct callback_locals *locals, uintptr_t start, uintptr_t end)
1061 {
1062 if (start == locals->curr_end)
1063 {
1064
1065 locals->curr_end = end;
1066 return 0;
1067 }
1068 # if STACK_DIRECTION < 0
1069 if (locals->curr_start < locals->curr_end
1070 && locals->address >= locals->curr_start
1071 && locals->address <= locals->curr_end - 1)
1072 {
1073 locals->vma->start = locals->curr_start;
1074 locals->vma->end = locals->curr_end;
1075 locals->vma->prev_end = locals->prev_end;
1076 locals->retval = 0;
1077 return 1;
1078 }
1079 locals->prev_end = locals->curr_end;
1080 # else
1081 if (locals->stop_at_next_vma)
1082 {
1083 locals->vma->next_start = locals->curr_start;
1084 locals->stop_at_next_vma = 0;
1085 return 1;
1086 }
1087 if (locals->curr_start < locals->curr_end
1088 && locals->address >= locals->curr_start
1089 && locals->address <= locals->curr_end - 1)
1090 {
1091 locals->vma->start = locals->curr_start;
1092 locals->vma->end = locals->curr_end;
1093 locals->retval = 0;
1094 locals->stop_at_next_vma = 1;
1095 return 0;
1096 }
1097 # endif
1098 locals->curr_start = start; locals->curr_end = end;
1099 return 0;
1100 }
1101
1102 int
1103 sigsegv_get_vma (uintptr_t address, struct vma_struct *vma)
1104 {
1105 struct callback_locals locals;
1106 locals.address = address;
1107 locals.vma = vma;
1108 locals.curr_start = 0;
1109 locals.curr_end = 0;
1110 # if STACK_DIRECTION < 0
1111 locals.prev_end = 0;
1112 # else
1113 locals.stop_at_next_vma = 0;
1114 # endif
1115 locals.retval = -1;
1116
1117 vma_iterate (&locals);
1118 if (locals.retval < 0)
1119 {
1120 if (locals.curr_start < locals.curr_end
1121 && address >= locals.curr_start && address <= locals.curr_end - 1)
1122 {
1123 vma->start = locals.curr_start;
1124 vma->end = locals.curr_end;
1125 # if STACK_DIRECTION < 0
1126 vma->prev_end = locals.prev_end;
1127 # else
1128 vma->next_start = 0;
1129 # endif
1130 locals.retval = 0;
1131 }
1132 }
1133 if (locals.retval == 0)
1134 {
1135 # if !(STACK_DIRECTION < 0)
1136 if (locals.stop_at_next_vma)
1137 vma->next_start = 0;
1138 # endif
1139 vma->is_near_this = simple_is_near_this;
1140 return 0;
1141 }
1142
1143 return mincore_get_vma (address, vma);
1144 }
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159 #elif defined __OpenBSD__
1160
1161 # include <unistd.h>
1162 # include <sys/types.h>
1163 # include <sys/mman.h>
1164
1165
1166 static uintptr_t pagesize;
1167
1168
1169 static void
1170 init_pagesize (void)
1171 {
1172 pagesize = getpagesize ();
1173 }
1174
1175
1176
1177 static int
1178 is_mapped (uintptr_t addr)
1179 {
1180
1181
1182 if (addr == 0)
1183 return 0;
1184 return mquery ((void *) addr, pagesize, 0, MAP_FIXED, -1, 0) == (void *) -1;
1185 }
1186
1187
1188
1189
1190 static uintptr_t
1191 mapped_range_start (uintptr_t addr)
1192 {
1193 uintptr_t stepsize;
1194 uintptr_t known_unmapped_page;
1195
1196
1197
1198 stepsize = pagesize;
1199 for (;;)
1200 {
1201 uintptr_t hole;
1202
1203 if (addr == 0)
1204 abort ();
1205
1206 if (addr <= stepsize)
1207 {
1208 known_unmapped_page = 0;
1209 break;
1210 }
1211
1212 hole = (uintptr_t) mquery ((void *) (addr - stepsize), pagesize,
1213 0, 0, -1, 0);
1214 if (!(hole == (uintptr_t) (void *) -1 || hole >= addr))
1215 {
1216
1217 known_unmapped_page = hole;
1218 break;
1219 }
1220
1221
1222 addr -= stepsize;
1223
1224 if (2 * stepsize > stepsize && 2 * stepsize < addr)
1225 stepsize = 2 * stepsize;
1226 }
1227
1228
1229
1230
1231 while (stepsize > pagesize && stepsize / 2 >= addr - known_unmapped_page)
1232 stepsize = stepsize / 2;
1233
1234 while (stepsize > pagesize)
1235 {
1236 uintptr_t hole;
1237
1238 stepsize = stepsize / 2;
1239 hole = (uintptr_t) mquery ((void *) (addr - stepsize), pagesize,
1240 0, 0, -1, 0);
1241 if (!(hole == (uintptr_t) (void *) -1 || hole >= addr))
1242
1243 known_unmapped_page = hole;
1244 else
1245
1246 addr -= stepsize;
1247
1248 }
1249
1250 return addr;
1251 }
1252
1253
1254
1255
1256 static uintptr_t
1257 mapped_range_end (uintptr_t addr)
1258 {
1259 uintptr_t end;
1260
1261 if (addr == 0)
1262 abort ();
1263
1264 end = (uintptr_t) mquery ((void *) addr, pagesize, 0, 0, -1, 0);
1265 if (end == (uintptr_t) (void *) -1)
1266 end = 0;
1267 return end;
1268 }
1269
1270
1271
1272 static int
1273 is_unmapped (uintptr_t addr1, uintptr_t addr2)
1274 {
1275
1276 addr1 = (addr1 / pagesize) * pagesize;
1277
1278 addr2 = ((addr2 / pagesize) + 1) * pagesize;
1279
1280
1281
1282 if (addr1 == 0)
1283 addr1 = pagesize;
1284
1285 if (addr1 < addr2)
1286 {
1287 if (mquery ((void *) addr1, addr2 - addr1, 0, MAP_FIXED, -1, 0)
1288 == (void *) -1)
1289
1290 return 0;
1291 else
1292
1293 return 1;
1294 }
1295 return 1;
1296 }
1297
1298 # if STACK_DIRECTION < 0
1299
1300
1301
1302 static int
1303 mquery_is_near_this (uintptr_t addr, struct vma_struct *vma)
1304 {
1305
1306
1307
1308
1309
1310
1311
1312
1313 uintptr_t testaddr = addr - (vma->start - addr);
1314 if (testaddr > addr)
1315 return 0;
1316
1317 return is_unmapped (testaddr, vma->start - 1);
1318 }
1319
1320 # endif
1321 # if STACK_DIRECTION > 0
1322
1323
1324
1325 static int
1326 mquery_is_near_this (uintptr_t addr, struct vma_struct *vma)
1327 {
1328
1329
1330
1331
1332
1333
1334
1335
1336 uintptr_t testaddr = addr + (addr - vma->end);
1337 if (testaddr < addr)
1338 return 0;
1339
1340 return is_unmapped (vma->end, testaddr);
1341 }
1342
1343 # endif
1344
1345 int
1346 sigsegv_get_vma (uintptr_t address, struct vma_struct *vma)
1347 {
1348 if (pagesize == 0)
1349 init_pagesize ();
1350 address = (address / pagesize) * pagesize;
1351 vma->start = mapped_range_start (address);
1352 vma->end = mapped_range_end (address);
1353 vma->is_near_this = mquery_is_near_this;
1354 return 0;
1355 }
1356
1357
1358
1359 #elif (defined __APPLE__ && defined __MACH__)
1360
1361 #include <libc.h>
1362 #include <nlist.h>
1363 #include <mach/mach.h>
1364 #include <mach/machine/vm_param.h>
1365
1366 int
1367 sigsegv_get_vma (uintptr_t req_address, struct vma_struct *vma)
1368 {
1369 uintptr_t prev_address = 0, prev_size = 0;
1370 uintptr_t join_address = 0, join_size = 0;
1371 int more = 1;
1372 vm_address_t address;
1373 vm_size_t size;
1374 task_t task = mach_task_self ();
1375
1376 for (address = VM_MIN_ADDRESS; more; address += size)
1377 {
1378 mach_port_t object_name;
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399 # if defined __aarch64__ || defined __ppc64__ || defined __x86_64__
1400 struct vm_region_basic_info_64 info;
1401 mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
1402
1403 more = (vm_region_64 (task, &address, &size, VM_REGION_BASIC_INFO_64,
1404 (vm_region_info_t)&info, &info_count, &object_name)
1405 == KERN_SUCCESS);
1406 # else
1407 struct vm_region_basic_info info;
1408 mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
1409
1410 more = (vm_region (task, &address, &size, VM_REGION_BASIC_INFO,
1411 (vm_region_info_t)&info, &info_count, &object_name)
1412 == KERN_SUCCESS);
1413 # endif
1414 if (!more)
1415 {
1416 address = join_address + join_size;
1417 size = 0;
1418 }
1419
1420 if ((uintptr_t) address == join_address + join_size)
1421 join_size += size;
1422 else
1423 {
1424 prev_address = join_address;
1425 prev_size = join_size;
1426 join_address = (uintptr_t) address;
1427 join_size = size;
1428 }
1429
1430 if (object_name != MACH_PORT_NULL)
1431 mach_port_deallocate (mach_task_self (), object_name);
1432
1433 # if STACK_DIRECTION < 0
1434 if (join_address <= req_address && join_address + join_size > req_address)
1435 {
1436 vma->start = join_address;
1437 vma->end = join_address + join_size;
1438 vma->prev_end = prev_address + prev_size;
1439 vma->is_near_this = simple_is_near_this;
1440 return 0;
1441 }
1442 # else
1443 if (prev_address <= req_address && prev_address + prev_size > req_address)
1444 {
1445 vma->start = prev_address;
1446 vma->end = prev_address + prev_size;
1447 vma->next_start = join_address;
1448 vma->is_near_this = simple_is_near_this;
1449 return 0;
1450 }
1451 # endif
1452 }
1453
1454 # if STACK_DIRECTION > 0
1455 if (join_address <= req_address && join_address + size > req_address)
1456 {
1457 vma->start = prev_address;
1458 vma->end = prev_address + prev_size;
1459 vma->next_start = ~0UL;
1460 vma->is_near_this = simple_is_near_this;
1461 return 0;
1462 }
1463 # endif
1464
1465 return -1;
1466 }
1467
1468
1469
1470 #elif defined _AIX
1471
1472 int
1473 sigsegv_get_vma (uintptr_t address, struct vma_struct *vma)
1474 {
1475 return mincore_get_vma (address, vma);
1476 }
1477
1478
1479
1480 #elif defined __sgi || defined __sun
1481
1482 # include <errno.h>
1483 # include <fcntl.h>
1484 # include <stddef.h>
1485 # include <unistd.h>
1486 # include <sys/types.h>
1487 # include <sys/mman.h>
1488 # include <sys/stat.h>
1489 # include <string.h>
1490
1491
1492 # define _STRUCTURED_PROC 1
1493 # include <sys/procfs.h>
1494
1495 # if !defined __sun
1496
1497
1498 static uintptr_t pagesize;
1499
1500
1501 static void
1502 init_pagesize (void)
1503 {
1504 pagesize = getpagesize ();
1505 }
1506
1507 # endif
1508
1509 struct callback_locals
1510 {
1511 uintptr_t address;
1512 struct vma_struct *vma;
1513 # if STACK_DIRECTION < 0
1514 uintptr_t prev;
1515 # else
1516 int stop_at_next_vma;
1517 # endif
1518 int retval;
1519 };
1520
1521 static int
1522 callback (struct callback_locals *locals, uintptr_t start, uintptr_t end)
1523 {
1524 # if STACK_DIRECTION < 0
1525 if (locals->address >= start && locals->address <= end - 1)
1526 {
1527 locals->vma->start = start;
1528 locals->vma->end = end;
1529 locals->vma->prev_end = locals->prev;
1530 locals->retval = 0;
1531 return 1;
1532 }
1533 locals->prev = end;
1534 # else
1535 if (locals->stop_at_next_vma)
1536 {
1537 locals->vma->next_start = start;
1538 locals->stop_at_next_vma = 0;
1539 return 1;
1540 }
1541 if (locals->address >= start && locals->address <= end - 1)
1542 {
1543 locals->vma->start = start;
1544 locals->vma->end = end;
1545 locals->retval = 0;
1546 locals->stop_at_next_vma = 1;
1547 return 0;
1548 }
1549 # endif
1550 return 0;
1551 }
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566 static int
1567 vma_iterate (struct callback_locals *locals)
1568 {
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579 # if defined PIOCNMAP && defined PIOCMAP
1580
1581
1582 char fnamebuf[6+10+1];
1583 char *fname;
1584 int fd;
1585 int nmaps;
1586 size_t memneed;
1587 # if HAVE_MAP_ANONYMOUS
1588 # define zero_fd -1
1589 # define map_flags MAP_ANONYMOUS
1590 # else
1591 int zero_fd;
1592 # define map_flags 0
1593 # endif
1594 void *auxmap;
1595 uintptr_t auxmap_start;
1596 uintptr_t auxmap_end;
1597 prmap_t* maps;
1598 prmap_t* mp;
1599
1600 if (pagesize == 0)
1601 init_pagesize ();
1602
1603
1604 fname = fnamebuf + sizeof (fnamebuf) - 1;
1605 *fname = '\0';
1606 {
1607 unsigned int value = getpid ();
1608 do
1609 *--fname = (value % 10) + '0';
1610 while ((value = value / 10) > 0);
1611 }
1612 fname -= 6;
1613 memcpy (fname, "/proc/", 6);
1614
1615 fd = open (fname, O_RDONLY);
1616 if (fd < 0)
1617 return -1;
1618
1619 if (ioctl (fd, PIOCNMAP, &nmaps) < 0)
1620 goto fail2;
1621
1622 memneed = (nmaps + 10) * sizeof (prmap_t);
1623
1624
1625
1626
1627
1628 memneed = ((memneed - 1) / pagesize + 1) * pagesize;
1629 # if !HAVE_MAP_ANONYMOUS
1630 zero_fd = open ("/dev/zero", O_RDONLY, 0644);
1631 if (zero_fd < 0)
1632 goto fail2;
1633 # endif
1634 auxmap = (void *) mmap ((void *) 0, memneed, PROT_READ | PROT_WRITE,
1635 map_flags | MAP_PRIVATE, zero_fd, 0);
1636 # if !HAVE_MAP_ANONYMOUS
1637 close (zero_fd);
1638 # endif
1639 if (auxmap == (void *) -1)
1640 goto fail2;
1641 auxmap_start = (uintptr_t) auxmap;
1642 auxmap_end = auxmap_start + memneed;
1643 maps = (prmap_t *) auxmap;
1644
1645 if (ioctl (fd, PIOCMAP, maps) < 0)
1646 goto fail1;
1647
1648 for (mp = maps;;)
1649 {
1650 uintptr_t start, end;
1651
1652 start = (uintptr_t) mp->pr_vaddr;
1653 end = start + mp->pr_size;
1654 if (start == 0 && end == 0)
1655 break;
1656 mp++;
1657 if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
1658 {
1659
1660
1661 if (start < auxmap_start)
1662 if (callback (locals, start, auxmap_start))
1663 break;
1664 if (auxmap_end - 1 < end - 1)
1665 if (callback (locals, auxmap_end, end))
1666 break;
1667 }
1668 else
1669 {
1670 if (callback (locals, start, end))
1671 break;
1672 }
1673 }
1674 munmap (auxmap, memneed);
1675 close (fd);
1676 return 0;
1677
1678 fail1:
1679 munmap (auxmap, memneed);
1680 fail2:
1681 close (fd);
1682 return -1;
1683
1684 # else
1685
1686
1687
1688
1689
1690
1691
1692 char fnamebuf[6+10+4+1];
1693 char *fname;
1694 int fd;
1695 int nmaps;
1696 size_t memneed;
1697 # if HAVE_MAP_ANONYMOUS
1698 # define zero_fd -1
1699 # define map_flags MAP_ANONYMOUS
1700 # else
1701 int zero_fd;
1702 # define map_flags 0
1703 # endif
1704 void *auxmap;
1705 uintptr_t auxmap_start;
1706 uintptr_t auxmap_end;
1707 prmap_t* maps;
1708 prmap_t* maps_end;
1709 prmap_t* mp;
1710
1711 if (pagesize == 0)
1712 init_pagesize ();
1713
1714
1715 fname = fnamebuf + sizeof (fnamebuf) - 1 - 4;
1716 memcpy (fname, "/map", 4 + 1);
1717 {
1718 unsigned int value = getpid ();
1719 do
1720 *--fname = (value % 10) + '0';
1721 while ((value = value / 10) > 0);
1722 }
1723 fname -= 6;
1724 memcpy (fname, "/proc/", 6);
1725
1726 fd = open (fname, O_RDONLY);
1727 if (fd < 0)
1728 return -1;
1729
1730 {
1731 struct stat statbuf;
1732 if (fstat (fd, &statbuf) < 0)
1733 goto fail2;
1734 nmaps = statbuf.st_size / sizeof (prmap_t);
1735 }
1736
1737 memneed = (nmaps + 10) * sizeof (prmap_t);
1738
1739
1740
1741
1742
1743 memneed = ((memneed - 1) / pagesize + 1) * pagesize;
1744 # if !HAVE_MAP_ANONYMOUS
1745 zero_fd = open ("/dev/zero", O_RDONLY, 0644);
1746 if (zero_fd < 0)
1747 goto fail2;
1748 # endif
1749 auxmap = (void *) mmap ((void *) 0, memneed, PROT_READ | PROT_WRITE,
1750 map_flags | MAP_PRIVATE, zero_fd, 0);
1751 # if !HAVE_MAP_ANONYMOUS
1752 close (zero_fd);
1753 # endif
1754 if (auxmap == (void *) -1)
1755 goto fail2;
1756 auxmap_start = (uintptr_t) auxmap;
1757 auxmap_end = auxmap_start + memneed;
1758 maps = (prmap_t *) auxmap;
1759
1760
1761 {
1762 size_t remaining = memneed;
1763 size_t total_read = 0;
1764 char *ptr = (char *) maps;
1765
1766 do
1767 {
1768 size_t nread = read (fd, ptr, remaining);
1769 if (nread == (size_t)-1)
1770 {
1771 if (errno == EINTR)
1772 continue;
1773 goto fail1;
1774 }
1775 if (nread == 0)
1776
1777 break;
1778 total_read += nread;
1779 ptr += nread;
1780 remaining -= nread;
1781 }
1782 while (remaining > 0);
1783
1784 nmaps = (memneed - remaining) / sizeof (prmap_t);
1785 maps_end = maps + nmaps;
1786 }
1787
1788 for (mp = maps; mp < maps_end; mp++)
1789 {
1790 uintptr_t start, end;
1791
1792 start = (uintptr_t) mp->pr_vaddr;
1793 end = start + mp->pr_size;
1794 if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
1795 {
1796
1797
1798 if (start < auxmap_start)
1799 if (callback (locals, start, auxmap_start))
1800 break;
1801 if (auxmap_end - 1 < end - 1)
1802 if (callback (locals, auxmap_end, end))
1803 break;
1804 }
1805 else
1806 {
1807 if (callback (locals, start, end))
1808 break;
1809 }
1810 }
1811 munmap (auxmap, memneed);
1812 close (fd);
1813 return 0;
1814
1815 fail1:
1816 munmap (auxmap, memneed);
1817 fail2:
1818 close (fd);
1819 return -1;
1820
1821 # endif
1822 }
1823
1824 int
1825 sigsegv_get_vma (uintptr_t address, struct vma_struct *vma)
1826 {
1827 struct callback_locals locals;
1828 locals.address = address;
1829 locals.vma = vma;
1830 # if STACK_DIRECTION < 0
1831 locals.prev = 0;
1832 # else
1833 locals.stop_at_next_vma = 0;
1834 # endif
1835 locals.retval = -1;
1836
1837 vma_iterate (&locals);
1838 if (locals.retval == 0)
1839 {
1840 # if !(STACK_DIRECTION < 0)
1841 if (locals.stop_at_next_vma)
1842 vma->next_start = 0;
1843 # endif
1844 vma->is_near_this = simple_is_near_this;
1845 return 0;
1846 }
1847
1848 # if defined __sun
1849 return mincore_get_vma (address, vma);
1850 # else
1851 return -1;
1852 # endif
1853 }
1854
1855
1856
1857 #elif defined __CYGWIN__
1858
1859 struct callback_locals
1860 {
1861 uintptr_t address;
1862 struct vma_struct *vma;
1863
1864
1865 uintptr_t curr_start, curr_end;
1866 # if STACK_DIRECTION < 0
1867 uintptr_t prev_end;
1868 # else
1869 int stop_at_next_vma;
1870 # endif
1871 int retval;
1872 };
1873
1874 static int
1875 callback (struct callback_locals *locals, uintptr_t start, uintptr_t end)
1876 {
1877 if (start == locals->curr_end)
1878 {
1879
1880 locals->curr_end = end;
1881 return 0;
1882 }
1883 # if STACK_DIRECTION < 0
1884 if (locals->curr_start < locals->curr_end
1885 && locals->address >= locals->curr_start
1886 && locals->address <= locals->curr_end - 1)
1887 {
1888 locals->vma->start = locals->curr_start;
1889 locals->vma->end = locals->curr_end;
1890 locals->vma->prev_end = locals->prev_end;
1891 locals->retval = 0;
1892 return 1;
1893 }
1894 locals->prev_end = locals->curr_end;
1895 # else
1896 if (locals->stop_at_next_vma)
1897 {
1898 locals->vma->next_start = locals->curr_start;
1899 locals->stop_at_next_vma = 0;
1900 return 1;
1901 }
1902 if (locals->curr_start < locals->curr_end
1903 && locals->address >= locals->curr_start
1904 && locals->address <= locals->curr_end - 1)
1905 {
1906 locals->vma->start = locals->curr_start;
1907 locals->vma->end = locals->curr_end;
1908 locals->retval = 0;
1909 locals->stop_at_next_vma = 1;
1910 return 0;
1911 }
1912 # endif
1913 locals->curr_start = start; locals->curr_end = end;
1914 return 0;
1915 }
1916
1917 int
1918 sigsegv_get_vma (uintptr_t address, struct vma_struct *vma)
1919 {
1920 struct callback_locals locals;
1921 locals.address = address;
1922 locals.vma = vma;
1923 locals.curr_start = 0;
1924 locals.curr_end = 0;
1925 # if STACK_DIRECTION < 0
1926 locals.prev_end = 0;
1927 # else
1928 locals.stop_at_next_vma = 0;
1929 # endif
1930 locals.retval = -1;
1931
1932 vma_iterate (&locals);
1933 if (locals.retval < 0)
1934 {
1935 if (locals.curr_start < locals.curr_end
1936 && address >= locals.curr_start && address <= locals.curr_end - 1)
1937 {
1938 vma->start = locals.curr_start;
1939 vma->end = locals.curr_end;
1940 # if STACK_DIRECTION < 0
1941 vma->prev_end = locals.prev_end;
1942 # else
1943 vma->next_start = 0;
1944 # endif
1945 locals.retval = 0;
1946 }
1947 }
1948 if (locals.retval == 0)
1949 {
1950 # if !(STACK_DIRECTION < 0)
1951 if (locals.stop_at_next_vma)
1952 vma->next_start = 0;
1953 # endif
1954 vma->is_near_this = simple_is_near_this;
1955 return 0;
1956 }
1957
1958 return -1;
1959 }
1960
1961
1962
1963 #elif defined __HAIKU__
1964
1965 # include <OS.h>
1966
1967 struct callback_locals
1968 {
1969 uintptr_t address;
1970 struct vma_struct *vma;
1971 # if STACK_DIRECTION < 0
1972 uintptr_t prev;
1973 # else
1974 int stop_at_next_vma;
1975 # endif
1976 int retval;
1977 };
1978
1979 static int
1980 callback (struct callback_locals *locals, uintptr_t start, uintptr_t end)
1981 {
1982 # if STACK_DIRECTION < 0
1983 if (locals->address >= start && locals->address <= end - 1)
1984 {
1985 locals->vma->start = start;
1986 locals->vma->end = end;
1987 locals->vma->prev_end = locals->prev;
1988 locals->retval = 0;
1989 return 1;
1990 }
1991 locals->prev = end;
1992 # else
1993 if (locals->stop_at_next_vma)
1994 {
1995 locals->vma->next_start = start;
1996 locals->stop_at_next_vma = 0;
1997 return 1;
1998 }
1999 if (locals->address >= start && locals->address <= end - 1)
2000 {
2001 locals->vma->start = start;
2002 locals->vma->end = end;
2003 locals->retval = 0;
2004 locals->stop_at_next_vma = 1;
2005 return 0;
2006 }
2007 # endif
2008 return 0;
2009 }
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024 static int
2025 vma_iterate (struct callback_locals *locals)
2026 {
2027 area_info info;
2028 ssize_t cookie;
2029
2030 cookie = 0;
2031 while (get_next_area_info (0, &cookie, &info) == B_OK)
2032 {
2033 uintptr_t start, end;
2034
2035 start = (uintptr_t) info.address;
2036 end = start + info.size;
2037
2038 if (callback (locals, start, end))
2039 break;
2040 }
2041 return 0;
2042 }
2043
2044 int
2045 sigsegv_get_vma (uintptr_t address, struct vma_struct *vma)
2046 {
2047 struct callback_locals locals;
2048 locals.address = address;
2049 locals.vma = vma;
2050 # if STACK_DIRECTION < 0
2051 locals.prev = 0;
2052 # else
2053 locals.stop_at_next_vma = 0;
2054 # endif
2055 locals.retval = -1;
2056
2057 vma_iterate (&locals);
2058 if (locals.retval == 0)
2059 {
2060 # if !(STACK_DIRECTION < 0)
2061 if (locals.stop_at_next_vma)
2062 vma->next_start = 0;
2063 # endif
2064 vma->is_near_this = simple_is_near_this;
2065 return 0;
2066 }
2067 return -1;
2068 }
2069
2070
2071
2072 #else
2073
2074 int
2075 sigsegv_get_vma (uintptr_t address, struct vma_struct *vma)
2076 {
2077
2078 return -1;
2079 }
2080
2081 #endif