2 /*--------------------------------------------------------------------*/
3 /*--- The address space manager. pub_core_aspacemgr.h ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2000-2013 Julian Seward
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 The GNU General Public License is contained in the file COPYING.
31 #ifndef __PUB_CORE_ASPACEMGR_H
32 #define __PUB_CORE_ASPACEMGR_H
34 //--------------------------------------------------------------------
35 // PURPOSE: This module deals with management of the entire process
36 // address space. Almost everything depends upon it, including dynamic
37 // memory management. Hence this module is almost completely
38 // standalone; the only module it uses is m_debuglog. DO NOT CHANGE
40 //--------------------------------------------------------------------
42 #include "pub_tool_aspacemgr.h"
44 //--------------------------------------------------------------
45 // Definition of address-space segments
47 /* types SegKind, ShrinkMode and NSegment are described in
48 the tool-visible header file, not here. */
51 //--------------------------------------------------------------
54 /* Initialise the address space manager, setting up the initial
55 segment list, and reading /proc/self/maps into it. This must
56 be called before any other function.
58 Takes a pointer to the SP at the time V gained control. This is
59 taken to be the highest usable address (more or less). Based on
60 that (and general consultation of tea leaves, etc) return a
61 suggested end address (highest addressable byte) for the client's stack. */
62 extern Addr
VG_(am_startup
) ( Addr sp_at_startup
);
65 //--------------------------------------------------------------
66 // Querying current status
68 /* Finds the segment containing 'a'. Only returns file/anon/resvn
69 segments. This returns a 'NSegment const *' - a pointer to
71 // Is in tool-visible header file.
72 // extern NSegment const * VG_(am_find_nsegment) ( Addr a );
74 /* Find the next segment along from 'here', if it is a file/anon/resvn
76 extern NSegment
const* VG_(am_next_nsegment
) ( const NSegment
* here
,
79 /* Is the area [start .. start+len-1] validly accessible by the
80 client with at least the permissions 'prot' ? To find out
81 simply if said area merely belongs to the client, pass
82 VKI_PROT_NONE as 'prot'. Will return False if any part of the
83 area does not belong to the client or does not have at least
84 the stated permissions. */
85 // Is in tool-visible header file.
86 // extern Bool VG_(am_is_valid_for_client)
87 // ( Addr start, SizeT len, UInt prot );
89 /* Same as VG_(am_is_valid_for_client) but for valgrind :
90 test if memory is addressable by valgrind with at least
91 the protection 'prot'. */
92 extern Bool
VG_(am_is_valid_for_valgrind
)
93 ( Addr start
, SizeT len
, UInt prot
);
95 /* Variant of VG_(am_is_valid_for_client) which allows free areas to
96 be consider part of the client's addressable space. It also
97 considers reservations to be allowable, since from the client's
98 point of view they don't exist. */
99 extern Bool
VG_(am_is_valid_for_client_or_free_or_resvn
)
100 ( Addr start
, SizeT len
, UInt prot
);
102 /* Trivial fn: return the total amount of space in anonymous mappings,
103 both for V and the client. Is used for printing stats in
104 out-of-memory messages. */
105 extern ULong
VG_(am_get_anonsize_total
)( void );
107 /* Show the segment array on the debug log, at given loglevel. */
108 extern void VG_(am_show_nsegments
) ( Int logLevel
, const HChar
* who
);
110 /* Get the filename corresponding to this segment, if known and if it
111 has one. The returned name's storage cannot be assumed to be
112 persistent, so the caller should immediately copy the name
113 elsewhere. This may return NULL if the file name is not known or
114 for arbitrary other implementation-dependent reasons, so callers
115 need to be able to handle a NULL return value. */
116 // Is in tool-visible header file.
117 // extern HChar* VG_(am_get_filename)( NSegment* );
119 /* VG_(am_get_segment_starts) is also part of this section, but its
120 prototype is tool-visible, hence not in this header file. */
122 /* Sanity check: check that Valgrind and the kernel agree on the
123 address space layout. Prints offending segments and call point if
124 a discrepancy is detected, but does not abort the system. Returned
125 Bool is False if a discrepancy was found. */
127 extern Bool
VG_(am_do_sync_check
) ( const HChar
* fn
,
128 const HChar
* file
, Int line
);
130 //--------------------------------------------------------------
131 // Functions pertaining to the central query-notify mechanism
132 // used to handle mmap/munmap/mprotect resulting from client
135 /* Describes a request for VG_(am_get_advisory). */
138 enum { MFixed
, MHint
, MAny
} rkind
;
144 /* Query aspacem to ask where a mapping should go. On success, the
145 advised placement is returned, and *ok is set to True. On failure,
146 zero is returned and *ok is set to False. Note that *ok must be
147 consulted by the caller to establish success or failure; that
148 cannot be established reliably from the returned value. If *ok is
149 set to False, it means aspacem has vetoed the mapping, and so the
150 caller should not proceed with it. */
151 extern Addr
VG_(am_get_advisory
)
152 ( const MapRequest
* req
, Bool forClient
, /*OUT*/Bool
* ok
);
154 /* Convenience wrapper for VG_(am_get_advisory) for client floating or
155 fixed requests. If start is zero, a floating request is issued; if
156 nonzero, a fixed request at that address is issued. Same comments
157 about return values apply. */
158 extern Addr
VG_(am_get_advisory_client_simple
)
159 ( Addr start
, SizeT len
, /*OUT*/Bool
* ok
);
161 /* Returns True if [start, start + len - 1] is covered by a single
162 free segment, otherwise returns False.
163 This allows to check the following case:
164 VG_(am_get_advisory_client_simple) (first arg == 0, meaning
165 this-or-nothing) is too lenient, and may allow us to trash
166 the next segment along. So make very sure that the proposed
167 new area really is free. This is perhaps overly
168 conservative, but it fixes #129866. */
169 extern Bool
VG_(am_covered_by_single_free_segment
)
170 ( Addr start
, SizeT len
);
172 /* Notifies aspacem that the client completed an mmap successfully.
173 The segment array is updated accordingly. If the returned Bool is
174 True, the caller should immediately discard translations from the
175 specified address range. */
176 extern Bool
VG_(am_notify_client_mmap
)
177 ( Addr a
, SizeT len
, UInt prot
, UInt flags
, Int fd
, Off64T offset
);
179 /* Notifies aspacem that the client completed a shmat successfully.
180 The segment array is updated accordingly. If the returned Bool is
181 True, the caller should immediately discard translations from the
182 specified address range. */
183 extern Bool
VG_(am_notify_client_shmat
)( Addr a
, SizeT len
, UInt prot
);
185 /* Notifies aspacem that an mprotect was completed successfully. The
186 segment array is updated accordingly. Note, as with
187 VG_(am_notify_munmap), it is not the job of this function to reject
188 stupid mprotects, for example the client doing mprotect of
189 non-client areas. Such requests should be intercepted earlier, by
190 the syscall wrapper for mprotect. This function merely records
191 whatever it is told. If the returned Bool is True, the caller
192 should immediately discard translations from the specified address
194 extern Bool
VG_(am_notify_mprotect
)( Addr start
, SizeT len
, UInt prot
);
196 /* Notifies aspacem that an munmap completed successfully. The
197 segment array is updated accordingly. As with
198 VG_(am_notify_munmap), we merely record the given info, and don't
199 check it for sensibleness. If the returned Bool is True, the
200 caller should immediately discard translations from the specified
202 extern Bool
VG_(am_notify_munmap
)( Addr start
, SizeT len
);
204 /* Hand a raw mmap to the kernel, without aspacem updating the segment
205 array. THIS FUNCTION IS DANGEROUS -- it will cause aspacem's view
206 of the address space to diverge from that of the kernel. DO NOT
207 USE IT UNLESS YOU UNDERSTAND the request-notify model used by
208 aspacem. In short, DO NOT USE THIS FUNCTION. */
209 extern SysRes
VG_(am_do_mmap_NO_NOTIFY
)
210 ( Addr start
, SizeT length
, UInt prot
, UInt flags
, Int fd
, Off64T offset
);
213 //--------------------------------------------------------------
214 // Dealing with mappings which do not arise directly from the
215 // simulation of the client. These are typically used for
216 // loading the client and building its stack/data segment, before
217 // execution begins. Also for V's own administrative use.
219 /* --- --- --- map, unmap, protect --- --- --- */
221 /* Map a file at a fixed address for the client, and update the
222 segment array accordingly. */
223 extern SysRes
VG_(am_mmap_file_fixed_client
)
224 ( Addr start
, SizeT length
, UInt prot
, Int fd
, Off64T offset
);
225 extern SysRes
VG_(am_mmap_named_file_fixed_client
)
226 ( Addr start
, SizeT length
, UInt prot
, Int fd
, Off64T offset
, const HChar
*name
);
228 /* Map anonymously at a fixed address for the client, and update
229 the segment array accordingly. */
230 extern SysRes
VG_(am_mmap_anon_fixed_client
)
231 ( Addr start
, SizeT length
, UInt prot
);
234 /* Map anonymously at an unconstrained address for the client, and
235 update the segment array accordingly. */
236 extern SysRes
VG_(am_mmap_anon_float_client
) ( SizeT length
, Int prot
);
238 /* Map anonymously at an unconstrained address for V, and update the
239 segment array accordingly. This is fundamentally how V allocates
240 itself more address space when needed. */
241 extern SysRes
VG_(am_mmap_anon_float_valgrind
)( SizeT cszB
);
243 /* Map privately a file at an unconstrained address for V, and update the
244 segment array accordingly. This is used by V for transiently
245 mapping in object files to read their debug info. */
246 extern SysRes
VG_(am_mmap_file_float_valgrind
)
247 ( SizeT length
, UInt prot
, Int fd
, Off64T offset
);
249 /* Map shared a file at an unconstrained address for V, and update the
250 segment array accordingly. This is used by V for communicating
252 extern SysRes
VG_(am_shared_mmap_file_float_valgrind
)
253 ( SizeT length
, UInt prot
, Int fd
, Off64T offset
);
255 /* Unmap the given address range and update the segment array
256 accordingly. This fails if the range isn't valid for the client.
257 If *need_discard is True after a successful return, the caller
258 should immediately discard translations from the specified address
260 extern SysRes
VG_(am_munmap_client
)( /*OUT*/Bool
* need_discard
,
261 Addr start
, SizeT length
);
263 /* Let (start,len) denote an area within a single Valgrind-owned
264 segment (anon or file). Change the ownership of [start, start+len)
265 to the client instead. Fails if (start,len) does not denote a
267 extern Bool
VG_(am_change_ownership_v_to_c
)( Addr start
, SizeT len
);
269 /* 'seg' must be NULL or have been obtained from
270 VG_(am_find_nsegment), and still valid. If non-NULL, and if it
271 denotes a SkAnonC (anonymous client mapping) area, set the .isCH
272 (is-client-heap) flag for that area. Otherwise do nothing.
273 (Bizarre interface so that the same code works for both Linux and
274 AIX and does not impose inefficiencies on the Linux version.) */
275 extern void VG_(am_set_segment_isCH_if_SkAnonC
)( const NSegment
* seg
);
277 /* Same idea as VG_(am_set_segment_isCH_if_SkAnonC), except set the
278 segment's hasT bit (has-cached-code) if this is SkFileC or SkAnonC
280 extern void VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC
)( const NSegment
* );
282 /* --- --- --- reservations --- --- --- */
284 /* Create a reservation from START .. START+LENGTH-1, with the given
285 ShrinkMode. When checking whether the reservation can be created,
286 also ensure that at least abs(EXTRA) extra free bytes will remain
287 above (> 0) or below (< 0) the reservation.
289 The reservation will only be created if it, plus the extra-zone,
290 falls entirely within a single free segment. The returned Bool
291 indicates whether the creation succeeded. */
292 extern Bool
VG_(am_create_reservation
)
293 ( Addr start
, SizeT length
, ShrinkMode smode
, SSizeT extra
);
295 /* Let SEG be an anonymous client mapping. This fn extends the
296 mapping by DELTA bytes, taking the space from a reservation section
297 which must be adjacent. If DELTA is positive, the segment is
298 extended forwards in the address space, and the reservation must be
299 the next one along. If DELTA is negative, the segment is extended
300 backwards in the address space and the reservation must be the
301 previous one. DELTA must be page aligned. abs(DELTA) must not
302 exceed the size of the reservation segment minus one page, that is,
303 the reservation segment after the operation must be at least one
305 extern Bool
VG_(am_extend_into_adjacent_reservation_client
)
306 ( const NSegment
* seg
, SSizeT delta
);
308 /* --- --- --- resizing/move a mapping --- --- --- */
310 /* Let SEG be a client mapping (anonymous or file). This fn extends
311 the mapping forwards only by DELTA bytes, and trashes whatever was
312 in the new area. Fails if SEG is not a single client mapping or if
313 the new area is not accessible to the client. Fails if DELTA is
314 not page aligned. *seg is invalid after a successful return. If
315 *need_discard is True after a successful return, the caller should
316 immediately discard translations from the new area. */
317 extern Bool
VG_(am_extend_map_client
)( /*OUT*/Bool
* need_discard
,
318 const NSegment
* seg
, SizeT delta
);
320 /* Remap the old address range to the new address range. Fails if any
321 parameter is not page aligned, if the either size is zero, if any
322 wraparound is implied, if the old address range does not fall
323 entirely within a single segment, if the new address range overlaps
324 with the old one, or if the old address range is not a valid client
325 mapping. If *need_discard is True after a successful return, the
326 caller should immediately discard translations from both specified
328 extern Bool
VG_(am_relocate_nooverlap_client
)( /*OUT*/Bool
* need_discard
,
329 Addr old_addr
, SizeT old_len
,
330 Addr new_addr
, SizeT new_len
);
332 //--------------------------------------------------------------
333 // Valgrind (non-client) thread stacks. V itself runs on such
334 // stacks. The address space manager provides and suitably
335 // protects such stacks.
337 #if defined(VGP_ppc32_linux) \
338 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
339 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
340 || defined(VGP_arm64_linux)
341 # define VG_STACK_GUARD_SZB 65536 // 1 or 16 pages
342 # define VG_STACK_ACTIVE_SZB (4096 * 256) // 1Mb
344 # define VG_STACK_GUARD_SZB 8192 // 2 pages
345 # define VG_STACK_ACTIVE_SZB (4096 * 256) // 1Mb
350 HChar bytes
[VG_STACK_GUARD_SZB
351 + VG_STACK_ACTIVE_SZB
352 + VG_STACK_GUARD_SZB
];
357 /* Allocate and initialise a VgStack (anonymous valgrind space).
358 Protect the stack active area and the guard areas appropriately.
359 Returns NULL on failure, else the address of the bottom of the
360 stack. On success, also sets *initial_sp to what the stack pointer
363 extern VgStack
* VG_(am_alloc_VgStack
)( /*OUT*/Addr
* initial_sp
);
365 /* Figure out how many bytes of the stack's active area have not been
366 used. Used for estimating if we are close to overflowing it. If
367 the free area is larger than 'limit', just return 'limit'. */
368 extern SizeT
VG_(am_get_VgStack_unused_szB
)( const VgStack
* stack
,
372 #if defined(VGO_darwin)
375 Bool is_added
; // Added or removed seg?
378 UInt prot
; // Not used for removed segs.
379 Off64T offset
; // Not used for removed segs.
383 extern Bool
VG_(get_changed_segments
)(
384 const HChar
* when
, const HChar
* where
, /*OUT*/ChangedSeg
* css
,
385 Int css_size
, /*OUT*/Int
* css_used
);
388 #endif // __PUB_CORE_ASPACEMGR_H
390 /*--------------------------------------------------------------------*/
392 /*--------------------------------------------------------------------*/