Home | History | Annotate | Download | only in coregrind
      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-2013 Julian Seward
     11       jseward (at) 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) ( const NSegment* here,
     77                                                Bool fwds );
     78 
     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 );
     88 
     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 );
     94 
     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 );
    101 
    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 );
    106 
    107 /* Show the segment array on the debug log, at given loglevel. */
    108 extern void VG_(am_show_nsegments) ( Int logLevel, const HChar* who );
    109 
    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* );
    118 
    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. */
    121 
    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. */
    126 
    127 extern Bool VG_(am_do_sync_check) ( const HChar* fn,
    128                                     const HChar* file, Int line );
    129 
    130 //--------------------------------------------------------------
    131 // Functions pertaining to the central query-notify mechanism
    132 // used to handle mmap/munmap/mprotect resulting from client
    133 // syscalls.
    134 
    135 /* Describes a request for VG_(am_get_advisory). */
    136 typedef
    137    struct {
    138       enum { MFixed, MHint, MAny } rkind;
    139       Addr start;
    140       Addr len;
    141    }
    142    MapRequest;
    143 
    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    ( MapRequest* req, Bool forClient, /*OUT*/Bool* ok );
    153 
    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 );
    160 
    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);
    171 
    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 );
    178 
    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 );
    184 
    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
    193    range. */
    194 extern Bool VG_(am_notify_mprotect)( Addr start, SizeT len, UInt prot );
    195 
    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
    201    address range. */
    202 extern Bool VG_(am_notify_munmap)( Addr start, SizeT len );
    203 
    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);
    211 
    212 
    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.
    218 
    219 /* --- --- --- map, unmap, protect  --- --- --- */
    220 
    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 );
    227 
    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 );
    232 
    233 
    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 );
    237 
    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 );
    242 
    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 );
    248 
    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
    251    with vgdb.  */
    252 extern SysRes VG_(am_shared_mmap_file_float_valgrind)
    253    ( SizeT length, UInt prot, Int fd, Off64T offset );
    254 
    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
    259    range. */
    260 extern SysRes VG_(am_munmap_client)( /*OUT*/Bool* need_discard,
    261                                      Addr start, SizeT length );
    262 
    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
    266   suitable segment. */
    267 extern Bool VG_(am_change_ownership_v_to_c)( Addr start, SizeT len );
    268 
    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 );
    276 
    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
    279    segment. */
    280 extern void VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( const NSegment* );
    281 
    282 /* --- --- --- reservations --- --- --- */
    283 
    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.
    288 
    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 );
    294 
    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
    304    page long. */
    305 extern Bool VG_(am_extend_into_adjacent_reservation_client)
    306    ( const NSegment* seg, SSizeT delta );
    307 
    308 /* --- --- --- resizing/move a mapping --- --- --- */
    309 
    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 );
    319 
    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
    327    address ranges.  */
    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 );
    331 
    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.
    336 
    337 #if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
    338     || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
    339     || defined(VGP_arm64_linux)
    340 # define VG_STACK_GUARD_SZB  65536  // 1 or 16 pages
    341 # define VG_STACK_ACTIVE_SZB (4096 * 256) // 1Mb
    342 #else
    343 # define VG_STACK_GUARD_SZB  8192   // 2 pages
    344 # define VG_STACK_ACTIVE_SZB (4096 * 256) // 1Mb
    345 #endif
    346 
    347 typedef
    348    struct {
    349       HChar bytes[VG_STACK_GUARD_SZB
    350                   + VG_STACK_ACTIVE_SZB
    351                   + VG_STACK_GUARD_SZB];
    352    }
    353    VgStack;
    354 
    355 
    356 /* Allocate and initialise a VgStack (anonymous valgrind space).
    357    Protect the stack active area and the guard areas appropriately.
    358    Returns NULL on failure, else the address of the bottom of the
    359    stack.  On success, also sets *initial_sp to what the stack pointer
    360    should be set to. */
    361 
    362 extern VgStack* VG_(am_alloc_VgStack)( /*OUT*/Addr* initial_sp );
    363 
    364 /* Figure out how many bytes of the stack's active area have not been
    365    used.  Used for estimating if we are close to overflowing it.  If
    366    the free area is larger than 'limit', just return 'limit'. */
    367 extern SizeT VG_(am_get_VgStack_unused_szB)( VgStack* stack, SizeT limit );
    368 
    369 // DDD: this is ugly
    370 #if defined(VGO_darwin)
    371 typedef
    372    struct {
    373       Bool   is_added;  // Added or removed seg?
    374       Addr   start;
    375       SizeT  end;
    376       UInt   prot;      // Not used for removed segs.
    377       Off64T offset;    // Not used for removed segs.
    378    }
    379    ChangedSeg;
    380 
    381 extern Bool VG_(get_changed_segments)(
    382       const HChar* when, const HChar* where, /*OUT*/ChangedSeg* css,
    383       Int css_size, /*OUT*/Int* css_used);
    384 #endif
    385 
    386 #endif   // __PUB_CORE_ASPACEMGR_H
    387 
    388 /*--------------------------------------------------------------------*/
    389 /*--- end                                                          ---*/
    390 /*--------------------------------------------------------------------*/
    391