• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*--------------------------------------------------------------------*/
3 /*--- The address space manager.              pub_core_aspacemgr.h ---*/
4 /*--------------------------------------------------------------------*/
5 
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9 
10    Copyright (C) 2000-2012 Julian Seward
11       jseward@acm.org
12 
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.
17 
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.
22 
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
26    02111-1307, USA.
27 
28    The GNU General Public License is contained in the file COPYING.
29 */
30 
31 #ifndef __PUB_CORE_ASPACEMGR_H
32 #define __PUB_CORE_ASPACEMGR_H
33 
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
39 // THIS.
40 //--------------------------------------------------------------------
41 
42 #include "pub_tool_aspacemgr.h"
43 
44 //--------------------------------------------------------------
45 // Definition of address-space segments
46 
47 /* types SegKind, ShrinkMode and NSegment are described in
48    the tool-visible header file, not here. */
49 
50 
51 //--------------------------------------------------------------
52 // Initialisation
53 
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.
57 
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 for the client's stack. */
62 extern Addr VG_(am_startup) ( Addr sp_at_startup );
63 
64 
65 //--------------------------------------------------------------
66 // Querying current status
67 
68 /* Finds the segment containing 'a'.  Only returns file/anon/resvn
69    segments.  This returns a 'NSegment const *' - a pointer to
70    readonly data. */
71 // Is in tool-visible header file.
72 // extern NSegment const * VG_(am_find_nsegment) ( Addr a );
73 
74 /* Find the next segment along from 'here', if it is a file/anon/resvn
75    segment. */
76 extern NSegment const* VG_(am_next_nsegment) ( NSegment* here, Bool fwds );
77 
78 /* Is the area [start .. start+len-1] validly accessible by the
79    client with at least the permissions 'prot' ?  To find out
80    simply if said area merely belongs to the client, pass
81    VKI_PROT_NONE as 'prot'.  Will return False if any part of the
82    area does not belong to the client or does not have at least
83    the stated permissions. */
84 // Is in tool-visible header file.
85 // extern Bool VG_(am_is_valid_for_client)
86 //   ( Addr start, SizeT len, UInt prot );
87 
88 /* Variant of VG_(am_is_valid_for_client) which allows free areas to
89    be consider part of the client's addressable space.  It also
90    considers reservations to be allowable, since from the client's
91    point of view they don't exist. */
92 extern Bool VG_(am_is_valid_for_client_or_free_or_resvn)
93    ( Addr start, SizeT len, UInt prot );
94 
95 /* Trivial fn: return the total amount of space in anonymous mappings,
96    both for V and the client.  Is used for printing stats in
97    out-of-memory messages. */
98 extern ULong VG_(am_get_anonsize_total)( void );
99 
100 /* Show the segment array on the debug log, at given loglevel. */
101 extern void VG_(am_show_nsegments) ( Int logLevel, HChar* who );
102 
103 /* Get the filename corresponding to this segment, if known and if it
104    has one.  The returned name's storage cannot be assumed to be
105    persistent, so the caller should immediately copy the name
106    elsewhere.  This may return NULL if the file name is not known or
107    for arbitrary other implementation-dependent reasons, so callers
108    need to be able to handle a NULL return value. */
109 // Is in tool-visible header file.
110 // extern HChar* VG_(am_get_filename)( NSegment* );
111 
112 /* VG_(am_get_segment_starts) is also part of this section, but its
113    prototype is tool-visible, hence not in this header file. */
114 
115 /* Sanity check: check that Valgrind and the kernel agree on the
116    address space layout.  Prints offending segments and call point if
117    a discrepancy is detected, but does not abort the system.  Returned
118    Bool is False if a discrepancy was found. */
119 
120 extern Bool VG_(am_do_sync_check) ( const HChar* fn,
121                                     const HChar* file, Int line );
122 
123 //--------------------------------------------------------------
124 // Functions pertaining to the central query-notify mechanism
125 // used to handle mmap/munmap/mprotect resulting from client
126 // syscalls.
127 
128 /* Describes a request for VG_(am_get_advisory). */
129 typedef
130    struct {
131       enum { MFixed, MHint, MAny } rkind;
132       Addr start;
133       Addr len;
134    }
135    MapRequest;
136 
137 /* Query aspacem to ask where a mapping should go.  On success, the
138    advised placement is returned, and *ok is set to True.  On failure,
139    zero is returned and *ok is set to False.  Note that *ok must be
140    consulted by the caller to establish success or failure; that
141    cannot be established reliably from the returned value.  If *ok is
142    set to False, it means aspacem has vetoed the mapping, and so the
143    caller should not proceed with it. */
144 extern Addr VG_(am_get_advisory)
145    ( MapRequest* req, Bool forClient, /*OUT*/Bool* ok );
146 
147 /* Convenience wrapper for VG_(am_get_advisory) for client floating or
148    fixed requests.  If start is zero, a floating request is issued; if
149    nonzero, a fixed request at that address is issued.  Same comments
150    about return values apply. */
151 extern Addr VG_(am_get_advisory_client_simple)
152    ( Addr start, SizeT len, /*OUT*/Bool* ok );
153 
154 /* Returns True if [start, start + len - 1] is covered by a single
155    free segment, otherwise returns False.
156    This allows to check the following case:
157    VG_(am_get_advisory_client_simple) (first arg == 0, meaning
158    this-or-nothing) is too lenient, and may allow us to trash
159    the next segment along.  So make very sure that the proposed
160    new area really is free.  This is perhaps overly
161    conservative, but it fixes #129866. */
162 extern Bool VG_(am_covered_by_single_free_segment)
163    ( Addr start, SizeT len);
164 
165 /* Notifies aspacem that the client completed an mmap successfully.
166    The segment array is updated accordingly.  If the returned Bool is
167    True, the caller should immediately discard translations from the
168    specified address range. */
169 extern Bool VG_(am_notify_client_mmap)
170    ( Addr a, SizeT len, UInt prot, UInt flags, Int fd, Off64T offset );
171 
172 /* Notifies aspacem that the client completed a shmat 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_shmat)( Addr a, SizeT len, UInt prot );
177 
178 /* Notifies aspacem that an mprotect was completed successfully.  The
179    segment array is updated accordingly.  Note, as with
180    VG_(am_notify_munmap), it is not the job of this function to reject
181    stupid mprotects, for example the client doing mprotect of
182    non-client areas.  Such requests should be intercepted earlier, by
183    the syscall wrapper for mprotect.  This function merely records
184    whatever it is told.  If the returned Bool is True, the caller
185    should immediately discard translations from the specified address
186    range. */
187 extern Bool VG_(am_notify_mprotect)( Addr start, SizeT len, UInt prot );
188 
189 /* Notifies aspacem that an munmap completed successfully.  The
190    segment array is updated accordingly.  As with
191    VG_(am_notify_munmap), we merely record the given info, and don't
192    check it for sensibleness.  If the returned Bool is True, the
193    caller should immediately discard translations from the specified
194    address range. */
195 extern Bool VG_(am_notify_munmap)( Addr start, SizeT len );
196 
197 /* Hand a raw mmap to the kernel, without aspacem updating the segment
198    array.  THIS FUNCTION IS DANGEROUS -- it will cause aspacem's view
199    of the address space to diverge from that of the kernel.  DO NOT
200    USE IT UNLESS YOU UNDERSTAND the request-notify model used by
201    aspacem.  In short, DO NOT USE THIS FUNCTION. */
202 extern SysRes VG_(am_do_mmap_NO_NOTIFY)
203    ( Addr start, SizeT length, UInt prot, UInt flags, Int fd, Off64T offset);
204 
205 
206 //--------------------------------------------------------------
207 // Dealing with mappings which do not arise directly from the
208 // simulation of the client.  These are typically used for
209 // loading the client and building its stack/data segment, before
210 // execution begins.  Also for V's own administrative use.
211 
212 /* --- --- --- map, unmap, protect  --- --- --- */
213 
214 /* Map a file at a fixed address for the client, and update the
215    segment array accordingly. */
216 extern SysRes VG_(am_mmap_file_fixed_client)
217    ( Addr start, SizeT length, UInt prot, Int fd, Off64T offset );
218 extern SysRes VG_(am_mmap_named_file_fixed_client)
219    ( Addr start, SizeT length, UInt prot, Int fd, Off64T offset, const HChar *name );
220 
221 /* Map anonymously at a fixed address for the client, and update
222    the segment array accordingly. */
223 extern SysRes VG_(am_mmap_anon_fixed_client)
224    ( Addr start, SizeT length, UInt prot );
225 
226 
227 /* Map anonymously at an unconstrained address for the client, and
228    update the segment array accordingly.  */
229 extern SysRes VG_(am_mmap_anon_float_client) ( SizeT length, Int prot );
230 
231 /* Similarly, acquire new address space for the client but with
232    considerable restrictions on what can be done with it: (1) the
233    actual protections may exceed those stated in 'prot', (2) the
234    area's protections cannot be later changed using any form of
235    mprotect, and (3) the area cannot be freed using any form of
236    munmap.  On Linux this behaves the same as
237    VG_(am_mmap_anon_float_client).  On AIX5 this *may* allocate memory
238    by using sbrk, so as to make use of large pages on AIX. */
239 extern SysRes VG_(am_sbrk_anon_float_client) ( SizeT length, Int prot );
240 
241 
242 /* Map anonymously at an unconstrained address for V, and update the
243    segment array accordingly.  This is fundamentally how V allocates
244    itself more address space when needed. */
245 extern SysRes VG_(am_mmap_anon_float_valgrind)( SizeT cszB );
246 
247 /* Same comments apply as per VG_(am_sbrk_anon_float_client).  On
248    Linux this behaves the same as VG_(am_mmap_anon_float_valgrind). */
249 extern SysRes VG_(am_sbrk_anon_float_valgrind)( SizeT cszB );
250 
251 
252 /* Map privately a file at an unconstrained address for V, and update the
253    segment array accordingly.  This is used by V for transiently
254    mapping in object files to read their debug info.  */
255 extern SysRes VG_(am_mmap_file_float_valgrind)
256    ( SizeT length, UInt prot, Int fd, Off64T offset );
257 
258 /* Map shared a file at an unconstrained address for V, and update the
259    segment array accordingly.  This is used by V for communicating
260    with vgdb.  */
261 extern SysRes VG_(am_shared_mmap_file_float_valgrind)
262    ( SizeT length, UInt prot, Int fd, Off64T offset );
263 
264 /* Unmap the given address range and update the segment array
265    accordingly.  This fails if the range isn't valid for the client.
266    If *need_discard is True after a successful return, the caller
267    should immediately discard translations from the specified address
268    range. */
269 extern SysRes VG_(am_munmap_client)( /*OUT*/Bool* need_discard,
270                                      Addr start, SizeT length );
271 
272 /* Let (start,len) denote an area within a single Valgrind-owned
273   segment (anon or file).  Change the ownership of [start, start+len)
274   to the client instead.  Fails if (start,len) does not denote a
275   suitable segment. */
276 extern Bool VG_(am_change_ownership_v_to_c)( Addr start, SizeT len );
277 
278 /* 'seg' must be NULL or have been obtained from
279    VG_(am_find_nsegment), and still valid.  If non-NULL, and if it
280    denotes a SkAnonC (anonymous client mapping) area, set the .isCH
281    (is-client-heap) flag for that area.  Otherwise do nothing.
282    (Bizarre interface so that the same code works for both Linux and
283    AIX and does not impose inefficiencies on the Linux version.) */
284 extern void VG_(am_set_segment_isCH_if_SkAnonC)( NSegment* seg );
285 
286 /* Same idea as VG_(am_set_segment_isCH_if_SkAnonC), except set the
287    segment's hasT bit (has-cached-code) if this is SkFileC or SkAnonC
288    segment. */
289 extern void VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( NSegment* );
290 
291 /* --- --- --- reservations --- --- --- */
292 
293 /* Create a reservation from START .. START+LENGTH-1, with the given
294    ShrinkMode.  When checking whether the reservation can be created,
295    also ensure that at least abs(EXTRA) extra free bytes will remain
296    above (> 0) or below (< 0) the reservation.
297 
298    The reservation will only be created if it, plus the extra-zone,
299    falls entirely within a single free segment.  The returned Bool
300    indicates whether the creation succeeded. */
301 extern Bool VG_(am_create_reservation)
302    ( Addr start, SizeT length, ShrinkMode smode, SSizeT extra );
303 
304 /* Let SEG be an anonymous client mapping.  This fn extends the
305    mapping by DELTA bytes, taking the space from a reservation section
306    which must be adjacent.  If DELTA is positive, the segment is
307    extended forwards in the address space, and the reservation must be
308    the next one along.  If DELTA is negative, the segment is extended
309    backwards in the address space and the reservation must be the
310    previous one.  DELTA must be page aligned.  abs(DELTA) must not
311    exceed the size of the reservation segment minus one page, that is,
312    the reservation segment after the operation must be at least one
313    page long. */
314 extern Bool VG_(am_extend_into_adjacent_reservation_client)
315    ( NSegment* seg, SSizeT delta );
316 
317 /* --- --- --- resizing/move a mapping --- --- --- */
318 
319 /* Let SEG be a client mapping (anonymous or file).  This fn extends
320    the mapping forwards only by DELTA bytes, and trashes whatever was
321    in the new area.  Fails if SEG is not a single client mapping or if
322    the new area is not accessible to the client.  Fails if DELTA is
323    not page aligned.  *seg is invalid after a successful return.  If
324    *need_discard is True after a successful return, the caller should
325    immediately discard translations from the new area. */
326 extern Bool VG_(am_extend_map_client)( /*OUT*/Bool* need_discard,
327                                        NSegment* seg, SizeT delta );
328 
329 /* Remap the old address range to the new address range.  Fails if any
330    parameter is not page aligned, if the either size is zero, if any
331    wraparound is implied, if the old address range does not fall
332    entirely within a single segment, if the new address range overlaps
333    with the old one, or if the old address range is not a valid client
334    mapping.  If *need_discard is True after a successful return, the
335    caller should immediately discard translations from both specified
336    address ranges.  */
337 extern Bool VG_(am_relocate_nooverlap_client)( /*OUT*/Bool* need_discard,
338                                                Addr old_addr, SizeT old_len,
339                                                Addr new_addr, SizeT new_len );
340 
341 //--------------------------------------------------------------
342 // Valgrind (non-client) thread stacks.  V itself runs on such
343 // stacks.  The address space manager provides and suitably
344 // protects such stacks.
345 
346 #if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
347     || defined(VGP_mips32_linux)
348 # define VG_STACK_GUARD_SZB  65536  // 1 or 16 pages
349 # define VG_STACK_ACTIVE_SZB (4096 * 256) // 1Mb
350 #else
351 # define VG_STACK_GUARD_SZB  8192   // 2 pages
352 # define VG_STACK_ACTIVE_SZB (4096 * 256) // 1Mb
353 #endif
354 
355 typedef
356    struct {
357       HChar bytes[VG_STACK_GUARD_SZB
358                   + VG_STACK_ACTIVE_SZB
359                   + VG_STACK_GUARD_SZB];
360    }
361    VgStack;
362 
363 
364 /* Allocate and initialise a VgStack (anonymous client space).
365    Protect the stack active area and the guard areas appropriately.
366    Returns NULL on failure, else the address of the bottom of the
367    stack.  On success, also sets *initial_sp to what the stack pointer
368    should be set to. */
369 
370 extern VgStack* VG_(am_alloc_VgStack)( /*OUT*/Addr* initial_sp );
371 
372 /* Figure out how many bytes of the stack's active area have not been
373    used.  Used for estimating if we are close to overflowing it.  If
374    the free area is larger than 'limit', just return 'limit'. */
375 extern SizeT VG_(am_get_VgStack_unused_szB)( VgStack* stack, SizeT limit );
376 
377 // DDD: this is ugly
378 #if defined(VGO_darwin)
379 typedef
380    struct {
381       Bool   is_added;  // Added or removed seg?
382       Addr   start;
383       SizeT  end;
384       UInt   prot;      // Not used for removed segs.
385       Off64T offset;    // Not used for removed segs.
386    }
387    ChangedSeg;
388 
389 extern Bool VG_(get_changed_segments)(
390       const HChar* when, const HChar* where, /*OUT*/ChangedSeg* css,
391       Int css_size, /*OUT*/Int* css_used);
392 #endif
393 
394 #endif   // __PUB_CORE_ASPACEMGR_H
395 
396 /*--------------------------------------------------------------------*/
397 /*--- end                                                          ---*/
398 /*--------------------------------------------------------------------*/
399