1 /* Determine the virtual memory area of a given address.
2 Copyright (C) 2002, 2006, 2008-2009 Bruno Haible <bruno@clisp.org>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19 #include <unistd.h> /* open, close */
20 #include <fcntl.h> /* open */
21 #include <string.h> /* memcpy */
22 #include <sys/types.h>
23 #include <sys/mman.h> /* mmap, munmap */
24 #include <sys/procfs.h> /* PIOC*, prmap_t */
26 #include "stackvma-simple.c"
29 # define sigsegv_get_vma mincore_get_vma
30 # define STATIC static
31 # include "stackvma-mincore.c"
32 # undef sigsegv_get_vma
34 /* Cache for getpagesize(). */
35 static unsigned long pagesize
;
36 /* Initialize pagesize. */
40 pagesize
= getpagesize ();
45 sigsegv_get_vma (unsigned long address
, struct vma_struct
*vma
)
47 char fnamebuf
[6+10+1];
54 # define map_flags MAP_ANON
55 #elif HAVE_MMAP_ANONYMOUS
57 # define map_flags MAP_ANONYMOUS
63 unsigned long auxmap_start
;
64 unsigned long auxmap_end
;
67 unsigned long start
, end
;
68 #if STACK_DIRECTION < 0
75 /* Construct fname = sprintf (fnamebuf+i, "/proc/%u", getpid ()). */
76 fname
= fnamebuf
+ sizeof (fnamebuf
) - 1;
79 unsigned int value
= getpid ();
81 *--fname
= (value
% 10) + '0';
82 while ((value
= value
/ 10) > 0);
85 memcpy (fname
, "/proc/", 6);
87 fd
= open (fname
, O_RDONLY
);
91 if (ioctl (fd
, PIOCNMAP
, &nmaps
) < 0)
94 memneed
= (nmaps
+ 10) * sizeof (prmap_t
);
95 /* Allocate memneed bytes of memory.
96 We cannot use alloca here, because we are low on stack space.
97 We also cannot use malloc here, because a malloc() call may have been
99 So use mmap(), and ignore the resulting VMA. */
100 memneed
= ((memneed
- 1) / pagesize
+ 1) * pagesize
;
101 #if !(HAVE_MMAP_ANON || HAVE_MMAP_ANONYMOUS)
102 zero_fd
= open ("/dev/zero", O_RDONLY
, 0644);
106 auxmap
= (void *) mmap ((void *) 0, memneed
, PROT_READ
| PROT_WRITE
, map_flags
| MAP_PRIVATE
, zero_fd
, 0);
107 #if !(HAVE_MMAP_ANON || HAVE_MMAP_ANONYMOUS)
110 if (auxmap
== (void *) -1)
112 auxmap_start
= (unsigned long) auxmap
;
113 auxmap_end
= auxmap_start
+ memneed
;
114 maps
= (prmap_t
*) auxmap
;
116 if (ioctl (fd
, PIOCMAP
, maps
) < 0)
119 #if STACK_DIRECTION < 0
124 start
= (unsigned long) mp
->pr_vaddr
;
125 end
= start
+ mp
->pr_size
;
126 if (start
== 0 && end
== 0)
129 if (start
<= auxmap_start
&& auxmap_end
- 1 <= end
- 1)
131 /* Consider [start,end-1] \ [auxmap_start,auxmap_end-1]
132 = [start,auxmap_start-1] u [auxmap_end,end-1]. */
133 if (start
!= auxmap_start
)
135 if (address
>= start
&& address
<= auxmap_start
- 1)
140 #if STACK_DIRECTION < 0
144 if (end
!= auxmap_end
)
146 if (address
>= auxmap_end
&& address
<= end
- 1)
151 #if STACK_DIRECTION < 0
158 if (address
>= start
&& address
<= end
- 1)
160 #if STACK_DIRECTION < 0
167 munmap (auxmap
, memneed
);
172 return mincore_get_vma (address
, vma
);
180 #if STACK_DIRECTION < 0
181 vma
->prev_end
= prev
;
183 vma
->next_start
= (unsigned long) mp
->pr_vaddr
;
185 munmap (auxmap
, memneed
);
187 vma
->is_near_this
= simple_is_near_this
;