1 /* Iteration over virtual memory areas.
2 Copyright (C) 2011-2017 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2011.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 #include <errno.h> /* errno */
24 #include <stdlib.h> /* size_t */
25 #include <fcntl.h> /* open, O_RDONLY */
26 #include <unistd.h> /* getpagesize, read, close, getpid */
28 #if defined __sgi || defined __osf__ /* IRIX, OSF/1 */
29 # include <string.h> /* memcpy */
30 # include <sys/types.h>
31 # include <sys/mman.h> /* mmap, munmap */
32 # include <sys/procfs.h> /* PIOC*, prmap_t */
35 #if defined __sun && HAVE_SYS_PROCFS_H /* Solaris */
36 # include <string.h> /* memcpy */
37 # include <sys/types.h>
38 # include <sys/mman.h> /* mmap, munmap */
39 /* Try to use the newer ("structured") /proc filesystem API, if supported. */
40 # define _STRUCTURED_PROC 1
41 # include <sys/procfs.h> /* prmap_t, optionally PIOC* */
44 #if HAVE_PSTAT_GETPROCVM /* HP-UX */
45 # include <sys/pstat.h> /* pstat_getprocvm */
48 #if defined __APPLE__ && defined __MACH__ /* Mac OS X */
49 # include <mach/mach.h>
52 #if (defined _WIN32 || defined __WIN32__) || defined __CYGWIN__ /* Windows */
56 #if defined __BEOS__ || defined __HAIKU__ /* BeOS, Haiku */
60 #if HAVE_MQUERY /* OpenBSD */
61 # include <sys/types.h>
62 # include <sys/mman.h> /* mquery */
65 /* Note: On AIX, there is a /proc/$pic/map file, that contains records of type
66 prmap_t, defined in <sys/procfs.h>. But it lists only the virtual memory
67 areas that are connected to a file, not the anonymous ones. */
70 /* Support for reading text files in the /proc file system. */
72 #if defined __linux__ || defined __FreeBSD__ || defined __NetBSD__ /* || defined __CYGWIN__ */
74 /* Buffered read-only streams.
75 We cannot use <stdio.h> here, because fopen() calls malloc(), and a malloc()
76 call may call mmap() and thus pre-allocate available memory. */
87 /* Open a read-only file stream. */
89 rof_open (struct rofile
*rof
, const char *filename
)
91 int fd
= open (filename
, O_RDONLY
);
101 /* Return the next byte from a read-only file stream without consuming it,
104 rof_peekchar (struct rofile
*rof
)
106 if (rof
->position
== rof
->filled
)
113 int n
= read (rof
->fd
, rof
->buffer
, sizeof (rof
->buffer
));
115 if (n
< 0 && errno
== EINTR
)
128 return (unsigned char) rof
->buffer
[rof
->position
];
131 /* Return the next byte from a read-only file stream, or -1 at EOF. */
133 rof_getchar (struct rofile
*rof
)
135 int c
= rof_peekchar (rof
);
141 /* Parse an unsigned hexadecimal number from a read-only file stream. */
143 rof_scanf_lx (struct rofile
*rof
, unsigned long *valuep
)
145 unsigned long value
= 0;
146 unsigned int numdigits
= 0;
149 int c
= rof_peekchar (rof
);
150 if (c
>= '0' && c
<= '9')
151 value
= (value
<< 4) + (c
- '0');
152 else if (c
>= 'A' && c
<= 'F')
153 value
= (value
<< 4) + (c
- 'A' + 10);
154 else if (c
>= 'a' && c
<= 'f')
155 value
= (value
<< 4) + (c
- 'a' + 10);
167 /* Close a read-only file stream. */
169 rof_close (struct rofile
*rof
)
178 vma_iterate (vma_iterate_callback_fn callback
, void *data
)
180 #if defined __linux__ /* || defined __CYGWIN__ */
185 /* Open the current process' maps file. It describes one VMA per line. */
186 if (rof_open (&rof
, "/proc/self/maps") < 0)
191 unsigned long start
, end
;
194 /* Parse one line. First start and end. */
195 if (!(rof_scanf_lx (&rof
, &start
) >= 0
196 && rof_getchar (&rof
) == '-'
197 && rof_scanf_lx (&rof
, &end
) >= 0))
199 /* Then the flags. */
201 c
= rof_getchar (&rof
);
205 flags
|= VMA_PROT_READ
;
206 c
= rof_getchar (&rof
);
208 flags
|= VMA_PROT_WRITE
;
209 c
= rof_getchar (&rof
);
211 flags
|= VMA_PROT_EXECUTE
;
212 while (c
= rof_getchar (&rof
), c
!= -1 && c
!= '\n')
215 if (callback (data
, start
, end
, flags
))
221 #elif defined __FreeBSD__ || defined __NetBSD__
226 /* Open the current process' maps file. It describes one VMA per line. */
227 if (rof_open (&rof
, "/proc/curproc/map") < 0)
232 unsigned long start
, end
;
235 /* Parse one line. First start. */
236 if (!(rof_getchar (&rof
) == '0'
237 && rof_getchar (&rof
) == 'x'
238 && rof_scanf_lx (&rof
, &start
) >= 0))
240 while (c
= rof_peekchar (&rof
), c
== ' ' || c
== '\t')
243 if (!(rof_getchar (&rof
) == '0'
244 && rof_getchar (&rof
) == 'x'
245 && rof_scanf_lx (&rof
, &end
) >= 0))
247 /* Then the flags. */
249 c
= rof_getchar (&rof
);
253 flags
|= VMA_PROT_READ
;
254 c
= rof_getchar (&rof
);
256 flags
|= VMA_PROT_WRITE
;
257 c
= rof_getchar (&rof
);
259 flags
|= VMA_PROT_EXECUTE
;
260 while (c
= rof_getchar (&rof
), c
!= -1 && c
!= '\n')
263 if (callback (data
, start
, end
, flags
))
269 #elif defined __sgi || defined __osf__ /* IRIX, OSF/1 */
272 char fnamebuf
[6+10+1];
277 # if HAVE_MAP_ANONYMOUS
279 # define map_flags MAP_ANONYMOUS
285 unsigned long auxmap_start
;
286 unsigned long auxmap_end
;
290 pagesize
= getpagesize ();
292 /* Construct fname = sprintf (fnamebuf+i, "/proc/%u", getpid ()). */
293 fname
= fnamebuf
+ sizeof (fnamebuf
) - 1;
296 unsigned int value
= getpid ();
298 *--fname
= (value
% 10) + '0';
299 while ((value
= value
/ 10) > 0);
302 memcpy (fname
, "/proc/", 6);
304 fd
= open (fname
, O_RDONLY
);
308 if (ioctl (fd
, PIOCNMAP
, &nmaps
) < 0)
311 memneed
= (nmaps
+ 10) * sizeof (prmap_t
);
312 /* Allocate memneed bytes of memory.
313 We cannot use alloca here, because not much stack space is guaranteed.
314 We also cannot use malloc here, because a malloc() call may call mmap()
315 and thus pre-allocate available memory.
316 So use mmap(), and ignore the resulting VMA. */
317 memneed
= ((memneed
- 1) / pagesize
+ 1) * pagesize
;
318 # if !HAVE_MAP_ANONYMOUS
319 zero_fd
= open ("/dev/zero", O_RDONLY
, 0644);
323 auxmap
= (void *) mmap ((void *) 0, memneed
, PROT_READ
| PROT_WRITE
,
324 map_flags
| MAP_PRIVATE
, zero_fd
, 0);
325 # if !HAVE_MAP_ANONYMOUS
328 if (auxmap
== (void *) -1)
330 auxmap_start
= (unsigned long) auxmap
;
331 auxmap_end
= auxmap_start
+ memneed
;
332 maps
= (prmap_t
*) auxmap
;
334 if (ioctl (fd
, PIOCMAP
, maps
) < 0)
339 unsigned long start
, end
;
342 start
= (unsigned long) mp
->pr_vaddr
;
343 end
= start
+ mp
->pr_size
;
344 if (start
== 0 && end
== 0)
347 if (mp
->pr_mflags
& MA_READ
)
348 flags
|= VMA_PROT_READ
;
349 if (mp
->pr_mflags
& MA_WRITE
)
350 flags
|= VMA_PROT_WRITE
;
351 if (mp
->pr_mflags
& MA_EXEC
)
352 flags
|= VMA_PROT_EXECUTE
;
354 if (start
<= auxmap_start
&& auxmap_end
- 1 <= end
- 1)
356 /* Consider [start,end-1] \ [auxmap_start,auxmap_end-1]
357 = [start,auxmap_start-1] u [auxmap_end,end-1]. */
358 if (start
< auxmap_start
)
359 if (callback (data
, start
, auxmap_start
, flags
))
361 if (auxmap_end
- 1 < end
- 1)
362 if (callback (data
, auxmap_end
, end
, flags
))
367 if (callback (data
, start
, end
, flags
))
371 munmap (auxmap
, memneed
);
376 munmap (auxmap
, memneed
);
381 #elif defined __sun && HAVE_SYS_PROCFS_H /* Solaris */
383 /* Note: Solaris <sys/procfs.h> defines a different type prmap_t with
384 _STRUCTURED_PROC than without! Here's a table of sizeof(prmap_t):
386 _STRUCTURED_PROC = 0 32 56
387 _STRUCTURED_PROC = 1 96 104
388 Therefore, if the include files provide the newer API, prmap_t has
389 the bigger size, and thus you MUST use the newer API. And if the
390 include files provide the older API, prmap_t has the smaller size,
391 and thus you MUST use the older API. */
393 # if defined PIOCNMAP && defined PIOCMAP
394 /* We must use the older /proc interface. */
397 char fnamebuf
[6+10+1];
402 # if HAVE_MAP_ANONYMOUS
404 # define map_flags MAP_ANONYMOUS
405 # else /* Solaris <= 7 */
410 unsigned long auxmap_start
;
411 unsigned long auxmap_end
;
415 pagesize
= getpagesize ();
417 /* Construct fname = sprintf (fnamebuf+i, "/proc/%u", getpid ()). */
418 fname
= fnamebuf
+ sizeof (fnamebuf
) - 1;
421 unsigned int value
= getpid ();
423 *--fname
= (value
% 10) + '0';
424 while ((value
= value
/ 10) > 0);
427 memcpy (fname
, "/proc/", 6);
429 fd
= open (fname
, O_RDONLY
);
433 if (ioctl (fd
, PIOCNMAP
, &nmaps
) < 0)
436 memneed
= (nmaps
+ 10) * sizeof (prmap_t
);
437 /* Allocate memneed bytes of memory.
438 We cannot use alloca here, because not much stack space is guaranteed.
439 We also cannot use malloc here, because a malloc() call may call mmap()
440 and thus pre-allocate available memory.
441 So use mmap(), and ignore the resulting VMA. */
442 memneed
= ((memneed
- 1) / pagesize
+ 1) * pagesize
;
443 # if !HAVE_MAP_ANONYMOUS
444 zero_fd
= open ("/dev/zero", O_RDONLY
, 0644);
448 auxmap
= (void *) mmap ((void *) 0, memneed
, PROT_READ
| PROT_WRITE
,
449 map_flags
| MAP_PRIVATE
, zero_fd
, 0);
450 # if !HAVE_MAP_ANONYMOUS
453 if (auxmap
== (void *) -1)
455 auxmap_start
= (unsigned long) auxmap
;
456 auxmap_end
= auxmap_start
+ memneed
;
457 maps
= (prmap_t
*) auxmap
;
459 if (ioctl (fd
, PIOCMAP
, maps
) < 0)
464 unsigned long start
, end
;
467 start
= (unsigned long) mp
->pr_vaddr
;
468 end
= start
+ mp
->pr_size
;
469 if (start
== 0 && end
== 0)
472 if (mp
->pr_mflags
& MA_READ
)
473 flags
|= VMA_PROT_READ
;
474 if (mp
->pr_mflags
& MA_WRITE
)
475 flags
|= VMA_PROT_WRITE
;
476 if (mp
->pr_mflags
& MA_EXEC
)
477 flags
|= VMA_PROT_EXECUTE
;
479 if (start
<= auxmap_start
&& auxmap_end
- 1 <= end
- 1)
481 /* Consider [start,end-1] \ [auxmap_start,auxmap_end-1]
482 = [start,auxmap_start-1] u [auxmap_end,end-1]. */
483 if (start
< auxmap_start
)
484 if (callback (data
, start
, auxmap_start
, flags
))
486 if (auxmap_end
- 1 < end
- 1)
487 if (callback (data
, auxmap_end
, end
, flags
))
492 if (callback (data
, start
, end
, flags
))
496 munmap (auxmap
, memneed
);
501 munmap (auxmap
, memneed
);
507 /* We must use the newer /proc interface.
509 https://docs.oracle.com/cd/E23824_01/html/821-1473/proc-4.html
510 The contents of /proc/<pid>/map consists of records of type
511 prmap_t. These are different in 32-bit and 64-bit processes,
512 but here we are fortunately accessing only the current process. */
515 char fnamebuf
[6+10+4+1];
520 # if HAVE_MAP_ANONYMOUS
522 # define map_flags MAP_ANONYMOUS
523 # else /* Solaris <= 7 */
528 unsigned long auxmap_start
;
529 unsigned long auxmap_end
;
534 pagesize
= getpagesize ();
536 /* Construct fname = sprintf (fnamebuf+i, "/proc/%u/map", getpid ()). */
537 fname
= fnamebuf
+ sizeof (fnamebuf
) - 1 - 4;
538 memcpy (fname
, "/map", 4 + 1);
540 unsigned int value
= getpid ();
542 *--fname
= (value
% 10) + '0';
543 while ((value
= value
/ 10) > 0);
546 memcpy (fname
, "/proc/", 6);
548 fd
= open (fname
, O_RDONLY
);
554 if (fstat (fd
, &statbuf
) < 0)
556 nmaps
= statbuf
.st_size
/ sizeof (prmap_t
);
559 memneed
= (nmaps
+ 10) * sizeof (prmap_t
);
560 /* Allocate memneed bytes of memory.
561 We cannot use alloca here, because not much stack space is guaranteed.
562 We also cannot use malloc here, because a malloc() call may call mmap()
563 and thus pre-allocate available memory.
564 So use mmap(), and ignore the resulting VMA. */
565 memneed
= ((memneed
- 1) / pagesize
+ 1) * pagesize
;
566 # if !HAVE_MAP_ANONYMOUS
567 zero_fd
= open ("/dev/zero", O_RDONLY
, 0644);
571 auxmap
= (void *) mmap ((void *) 0, memneed
, PROT_READ
| PROT_WRITE
,
572 map_flags
| MAP_PRIVATE
, zero_fd
, 0);
573 # if !HAVE_MAP_ANONYMOUS
576 if (auxmap
== (void *) -1)
578 auxmap_start
= (unsigned long) auxmap
;
579 auxmap_end
= auxmap_start
+ memneed
;
580 maps
= (prmap_t
*) auxmap
;
582 /* Read up to memneed bytes from fd into maps. */
584 size_t remaining
= memneed
;
585 size_t total_read
= 0;
586 char *ptr
= (char *) maps
;
590 size_t nread
= read (fd
, ptr
, remaining
);
591 if (nread
== (size_t)-1)
604 while (remaining
> 0);
606 nmaps
= (memneed
- remaining
) / sizeof (prmap_t
);
607 maps_end
= maps
+ nmaps
;
610 for (mp
= maps
; mp
< maps_end
; mp
++)
612 unsigned long start
, end
;
615 start
= (unsigned long) mp
->pr_vaddr
;
616 end
= start
+ mp
->pr_size
;
618 if (mp
->pr_mflags
& MA_READ
)
619 flags
|= VMA_PROT_READ
;
620 if (mp
->pr_mflags
& MA_WRITE
)
621 flags
|= VMA_PROT_WRITE
;
622 if (mp
->pr_mflags
& MA_EXEC
)
623 flags
|= VMA_PROT_EXECUTE
;
624 if (start
<= auxmap_start
&& auxmap_end
- 1 <= end
- 1)
626 /* Consider [start,end-1] \ [auxmap_start,auxmap_end-1]
627 = [start,auxmap_start-1] u [auxmap_end,end-1]. */
628 if (start
< auxmap_start
)
629 if (callback (data
, start
, auxmap_start
, flags
))
631 if (auxmap_end
- 1 < end
- 1)
632 if (callback (data
, auxmap_end
, end
, flags
))
637 if (callback (data
, start
, end
, flags
))
641 munmap (auxmap
, memneed
);
646 munmap (auxmap
, memneed
);
653 #elif HAVE_PSTAT_GETPROCVM /* HP-UX */
655 unsigned long pagesize
= getpagesize ();
660 struct pst_vm_status info
;
661 int ret
= pstat_getprocvm (&info
, sizeof (info
), 0, i
);
667 unsigned long start
= info
.pst_vaddr
;
668 unsigned long end
= start
+ info
.pst_length
* pagesize
;
669 unsigned int flags
= 0;
670 if (info
.pst_permission
& PS_PROT_READ
)
671 flags
|= VMA_PROT_READ
;
672 if (info
.pst_permission
& PS_PROT_WRITE
)
673 flags
|= VMA_PROT_WRITE
;
674 if (info
.pst_permission
& PS_PROT_EXECUTE
)
675 flags
|= VMA_PROT_EXECUTE
;
677 if (callback (data
, start
, end
, flags
))
682 #elif defined __APPLE__ && defined __MACH__ /* Mac OS X */
684 task_t task
= mach_task_self ();
685 vm_address_t address
;
688 for (address
= VM_MIN_ADDRESS
;; address
+= size
)
691 mach_port_t object_name
;
693 /* In Mac OS X 10.5, the types vm_address_t, vm_offset_t, vm_size_t have
694 32 bits in 32-bit processes and 64 bits in 64-bit processes. Whereas
695 mach_vm_address_t and mach_vm_size_t are always 64 bits large.
696 Mac OS X 10.5 has three vm_region like methods:
697 - vm_region. It has arguments that depend on whether the current
698 process is 32-bit or 64-bit. When linking dynamically, this
699 function exists only in 32-bit processes. Therefore we use it only
701 - vm_region_64. It has arguments that depend on whether the current
702 process is 32-bit or 64-bit. It interprets a flavor
703 VM_REGION_BASIC_INFO as VM_REGION_BASIC_INFO_64, which is
704 dangerous since 'struct vm_region_basic_info_64' is larger than
705 'struct vm_region_basic_info'; therefore let's write
706 VM_REGION_BASIC_INFO_64 explicitly.
707 - mach_vm_region. It has arguments that are 64-bit always. This
708 function is useful when you want to access the VM of a process
709 other than the current process.
710 In 64-bit processes, we could use vm_region_64 or mach_vm_region.
711 I choose vm_region_64 because it uses the same types as vm_region,
712 resulting in less conditional code. */
713 # if defined __ppc64__ || defined __x86_64__
714 struct vm_region_basic_info_64 info
;
715 mach_msg_type_number_t info_count
= VM_REGION_BASIC_INFO_COUNT_64
;
717 more
= (vm_region_64 (task
, &address
, &size
, VM_REGION_BASIC_INFO_64
,
718 (vm_region_info_t
)&info
, &info_count
, &object_name
)
721 struct vm_region_basic_info info
;
722 mach_msg_type_number_t info_count
= VM_REGION_BASIC_INFO_COUNT
;
724 more
= (vm_region (task
, &address
, &size
, VM_REGION_BASIC_INFO
,
725 (vm_region_info_t
)&info
, &info_count
, &object_name
)
728 if (object_name
!= MACH_PORT_NULL
)
729 mach_port_deallocate (mach_task_self (), object_name
);
733 if (info
.protection
& VM_PROT_READ
)
734 flags
|= VMA_PROT_READ
;
735 if (info
.protection
& VM_PROT_WRITE
)
736 flags
|= VMA_PROT_WRITE
;
737 if (info
.protection
& VM_PROT_EXECUTE
)
738 flags
|= VMA_PROT_EXECUTE
;
739 if (callback (data
, address
, address
+ size
, flags
))
744 #elif (defined _WIN32 || defined __WIN32__) || defined __CYGWIN__
745 /* Windows platform. Use the native Windows API. */
747 MEMORY_BASIC_INFORMATION info
;
748 uintptr_t address
= 0;
750 while (VirtualQuery ((void*)address
, &info
, sizeof(info
)) == sizeof(info
))
752 if (info
.State
!= MEM_FREE
)
753 /* Ignore areas where info.State has the value MEM_RESERVE or,
754 equivalently, info.Protect has the undocumented value 0.
755 This is needed, so that on Cygwin, areas used by malloc() are
756 distinguished from areas reserved for future malloc(). */
757 if (info
.State
!= MEM_RESERVE
)
759 uintptr_t start
, end
;
762 start
= (uintptr_t)info
.BaseAddress
;
763 end
= start
+ info
.RegionSize
;
764 switch (info
.Protect
& ~(PAGE_GUARD
|PAGE_NOCACHE
))
767 flags
= VMA_PROT_READ
;
771 flags
= VMA_PROT_READ
| VMA_PROT_WRITE
;
774 flags
= VMA_PROT_EXECUTE
;
776 case PAGE_EXECUTE_READ
:
777 flags
= VMA_PROT_READ
| VMA_PROT_EXECUTE
;
779 case PAGE_EXECUTE_READWRITE
:
780 case PAGE_EXECUTE_WRITECOPY
:
781 flags
= VMA_PROT_READ
| VMA_PROT_WRITE
| VMA_PROT_EXECUTE
;
789 if (callback (data
, start
, end
, flags
))
792 address
= (uintptr_t)info
.BaseAddress
+ info
.RegionSize
;
796 #elif defined __BEOS__ || defined __HAIKU__
797 /* Use the BeOS specific API. */
803 while (get_next_area_info (0, &cookie
, &info
) == B_OK
)
805 unsigned long start
, end
;
808 start
= (unsigned long) info
.address
;
809 end
= start
+ info
.size
;
811 if (info
.protection
& B_READ_AREA
)
812 flags
|= VMA_PROT_READ
| VMA_PROT_EXECUTE
;
813 if (info
.protection
& B_WRITE_AREA
)
814 flags
|= VMA_PROT_WRITE
;
816 if (callback (data
, start
, end
, flags
))
821 #elif HAVE_MQUERY /* OpenBSD */
825 int /*bool*/ address_known_mapped
;
827 pagesize
= getpagesize ();
828 /* Avoid calling mquery with a NULL first argument, because this argument
829 value has a specific meaning. We know the NULL page is unmapped. */
831 address_known_mapped
= 0;
834 /* Test whether the page at address is mapped. */
835 if (address_known_mapped
836 || mquery ((void *) address
, pagesize
, 0, MAP_FIXED
, -1, 0)
839 /* The page at address is mapped.
840 This is the start of an interval. */
841 uintptr_t start
= address
;
844 /* Find the end of the interval. */
845 end
= (uintptr_t) mquery ((void *) address
, pagesize
, 0, 0, -1, 0);
846 if (end
== (uintptr_t) (void *) -1)
847 end
= 0; /* wrap around */
850 /* It's too complicated to find out about the flags. Just pass 0. */
851 if (callback (data
, start
, end
, 0))
854 if (address
< pagesize
) /* wrap around? */
857 /* Here we know that the page at address is unmapped. */
859 uintptr_t query_size
= pagesize
;
863 /* Query larger and larger blocks, to get through the unmapped address
864 range with few mquery() calls. */
867 if (2 * query_size
> query_size
)
868 query_size
= 2 * query_size
;
869 if (address
+ query_size
- 1 < query_size
) /* wrap around? */
871 address_known_mapped
= 0;
874 if (mquery ((void *) address
, query_size
, 0, MAP_FIXED
, -1, 0)
877 /* Not all the interval [address .. address + query_size - 1]
879 address_known_mapped
= (query_size
== pagesize
);
882 /* The interval [address .. address + query_size - 1] is
884 address
+= query_size
;
886 /* Reduce the query size again, to determine the precise size of the
887 unmapped interval that starts at address. */
888 while (query_size
> pagesize
)
890 query_size
= query_size
/ 2;
891 if (address
+ query_size
- 1 >= query_size
)
893 if (mquery ((void *) address
, query_size
, 0, MAP_FIXED
, -1, 0)
896 /* The interval [address .. address + query_size - 1] is
898 address
+= query_size
;
899 address_known_mapped
= 0;
902 address_known_mapped
= (query_size
== pagesize
);
905 /* Here again query_size = pagesize, and
906 either address + pagesize - 1 < pagesize, or
907 mquery ((void *) address, pagesize, 0, MAP_FIXED, -1, 0) fails.
908 So, the unmapped area ends at address. */
910 if (address
+ pagesize
- 1 < pagesize
) /* wrap around? */
917 /* Not implemented. */
928 /* Output the VMAs of the current process in a format similar to the Linux
929 /proc/$pid/maps file. */
932 vma_iterate_callback (void *data
, uintptr_t start
, uintptr_t end
,
935 printf ("%08lx-%08lx %c%c%c\n",
936 (unsigned long) start
, (unsigned long) end
,
937 flags
& VMA_PROT_READ
? 'r' : '-',
938 flags
& VMA_PROT_WRITE
? 'w' : '-',
939 flags
& VMA_PROT_EXECUTE
? 'x' : '-');
946 vma_iterate (vma_iterate_callback
, NULL
);
948 /* Let the user interactively look at the /proc file system. */